on main help sign in
refactor(tui): move ExecShell to uiutil package
7fd14ffAyman Bagabas
internal/tui/util/shell.go+2−13
@@ -2,25 +2,14 @@ package util
2
2
3import (
3import (
4 "context"
4 "context"
5− "errors"
6− "os/exec"
7
5
8 tea "charm.land/bubbletea/v2"
6 tea "charm.land/bubbletea/v2"
9− "mvdan.cc/sh/v3/shell"
7+ "github.com/charmbracelet/crush/internal/uiutil"
10)
8)
11
9
12// ExecShell parses a shell command string and executes it with exec.Command.
10// ExecShell parses a shell command string and executes it with exec.Command.
13// Uses shell.Fields for proper handling of shell syntax like quotes and
11// Uses shell.Fields for proper handling of shell syntax like quotes and
14// arguments while preserving TTY handling for terminal editors.
12// arguments while preserving TTY handling for terminal editors.
15func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
13func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
16− fields, err := shell.Fields(cmdStr, nil)
14+ return uiutil.ExecShell(ctx, cmdStr, callback)
17− if err != nil {
18− return ReportError(err)
19− }
20− if len(fields) == 0 {
21− return ReportError(errors.New("empty command"))
22− }
23−
24− cmd := exec.CommandContext(ctx, fields[0], fields[1:]...)
25− return tea.ExecProcess(cmd, callback)
26}
15}
internal/uiutil/uiutil.go+20
@@ -4,10 +4,14 @@
4package uiutil
4package uiutil
5
5
6import (
6import (
7+ "context"
8+ "errors"
7 "log/slog"
9 "log/slog"
10+ "os/exec"
8 "time"
11 "time"
9
12
10 tea "charm.land/bubbletea/v2"
13 tea "charm.land/bubbletea/v2"
14+ "mvdan.cc/sh/v3/shell"
11)
15)
12
16
13type Cursor interface {
17type Cursor interface {
@@ -60,3 +64,19 @@ type (
60 }
64 }
61 ClearStatusMsg struct{}
65 ClearStatusMsg struct{}
62)
66)
67+
68+// ExecShell parses a shell command string and executes it with exec.Command.
69+// Uses shell.Fields for proper handling of shell syntax like quotes and
70+// arguments while preserving TTY handling for terminal editors.
71+func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
72+ fields, err := shell.Fields(cmdStr, nil)
73+ if err != nil {
74+ return ReportError(err)
75+ }
76+ if len(fields) == 0 {
77+ return ReportError(errors.New("empty command"))
78+ }
79+
80+ cmd := exec.CommandContext(ctx, fields[0], fields[1:]...)
81+ return tea.ExecProcess(cmd, callback)
82+}