get_line.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package ask
  3. import (
  4. "fmt"
  5. "io"
  6. "os"
  7. "path/filepath"
  8. "time"
  9. "kitty/tools/tui/loop"
  10. "kitty/tools/tui/readline"
  11. "kitty/tools/utils"
  12. )
  13. var _ = fmt.Print
  14. func get_line(o *Options) (result string, err error) {
  15. lp, err := loop.New(loop.NoAlternateScreen, loop.NoRestoreColors)
  16. if err != nil {
  17. return
  18. }
  19. cwd, _ := os.Getwd()
  20. ropts := readline.RlInit{Prompt: o.Prompt}
  21. if o.Name != "" {
  22. base := filepath.Join(utils.CacheDir(), "ask")
  23. ropts.HistoryPath = filepath.Join(base, o.Name+".history.json")
  24. os.MkdirAll(base, 0o755)
  25. }
  26. rl := readline.New(lp, ropts)
  27. if o.Default != "" {
  28. rl.SetText(o.Default)
  29. }
  30. lp.OnInitialize = func() (string, error) {
  31. rl.Start()
  32. return "", nil
  33. }
  34. lp.OnFinalize = func() string { rl.End(); return "" }
  35. lp.OnResumeFromStop = func() error {
  36. rl.Start()
  37. return nil
  38. }
  39. lp.OnResize = rl.OnResize
  40. lp.OnKeyEvent = func(event *loop.KeyEvent) error {
  41. if event.MatchesPressOrRepeat("ctrl+c") {
  42. return fmt.Errorf("Canceled by user")
  43. }
  44. err := rl.OnKeyEvent(event)
  45. if err != nil {
  46. if err == io.EOF {
  47. lp.Quit(0)
  48. return nil
  49. }
  50. if err == readline.ErrAcceptInput {
  51. hi := readline.HistoryItem{Timestamp: time.Now(), Cmd: rl.AllText(), ExitCode: 0, Cwd: cwd}
  52. rl.AddHistoryItem(hi)
  53. result = rl.AllText()
  54. lp.Quit(0)
  55. return nil
  56. }
  57. return err
  58. }
  59. if event.Handled {
  60. rl.Redraw()
  61. return nil
  62. }
  63. return nil
  64. }
  65. lp.OnText = func(text string, from_key_event, in_bracketed_paste bool) error {
  66. err := rl.OnText(text, from_key_event, in_bracketed_paste)
  67. if err == nil {
  68. rl.Redraw()
  69. }
  70. return err
  71. }
  72. err = lp.Run()
  73. rl.Shutdown()
  74. if err != nil {
  75. return "", err
  76. }
  77. ds := lp.DeathSignalName()
  78. if ds != "" {
  79. return "", fmt.Errorf("Killed by signal: %s", ds)
  80. }
  81. return
  82. }