uiutil.go 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. // Package uiutil provides utility functions for UI message handling.
  2. // TODO: Move to internal/ui/<appropriate_location> once the new UI migration
  3. // is finalized.
  4. package uiutil
  5. import (
  6. "context"
  7. "errors"
  8. "log/slog"
  9. "os/exec"
  10. "time"
  11. tea "charm.land/bubbletea/v2"
  12. "mvdan.cc/sh/v3/shell"
  13. )
  14. type Cursor interface {
  15. Cursor() *tea.Cursor
  16. }
  17. func CmdHandler(msg tea.Msg) tea.Cmd {
  18. return func() tea.Msg {
  19. return msg
  20. }
  21. }
  22. func ReportError(err error) tea.Cmd {
  23. slog.Error("Error reported", "error", err)
  24. return CmdHandler(InfoMsg{
  25. Type: InfoTypeError,
  26. Msg: err.Error(),
  27. })
  28. }
  29. type InfoType int
  30. const (
  31. InfoTypeInfo InfoType = iota
  32. InfoTypeSuccess
  33. InfoTypeWarn
  34. InfoTypeError
  35. InfoTypeUpdate
  36. )
  37. func ReportInfo(info string) tea.Cmd {
  38. return CmdHandler(InfoMsg{
  39. Type: InfoTypeInfo,
  40. Msg: info,
  41. })
  42. }
  43. func ReportWarn(warn string) tea.Cmd {
  44. return CmdHandler(InfoMsg{
  45. Type: InfoTypeWarn,
  46. Msg: warn,
  47. })
  48. }
  49. type (
  50. InfoMsg struct {
  51. Type InfoType
  52. Msg string
  53. TTL time.Duration
  54. }
  55. ClearStatusMsg struct{}
  56. )
  57. // ExecShell parses a shell command string and executes it with exec.Command.
  58. // Uses shell.Fields for proper handling of shell syntax like quotes and
  59. // arguments while preserving TTY handling for terminal editors.
  60. func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
  61. fields, err := shell.Fields(cmdStr, nil)
  62. if err != nil {
  63. return ReportError(err)
  64. }
  65. if len(fields) == 0 {
  66. return ReportError(errors.New("empty command"))
  67. }
  68. cmd := exec.CommandContext(ctx, fields[0], fields[1:]...)
  69. return tea.ExecProcess(cmd, callback)
  70. }