on main help sign in
Revert "fix(editor): fix opening `$EDITOR` when it contains arguments… (#1519)
commit9b1ec537337706c42683d081b8a67ebc3f00cd8d authorAyman Bagabas <ayman.bagabas@gmail.com> dateWed 26 Nov 2025, 17:08 (1 year ago) parent64637e5
2 files changed+7−64
internal/tui/components/chat/editor/editor.go+7−6 internal/tui/util/shell.go−58
internal/tui/components/chat/editor/editor.go+7−6
@@ -6,6 +6,7 @@ import (
66 "math/rand"
77 "net/http"
88 "os"
9+ "os/exec"
910 "path/filepath"
1011 "runtime"
1112 "slices"
@@ -95,7 +96,7 @@ type OpenEditorMsg struct {
9596func (m *editorCmp) openEditor(value string) tea.Cmd {
9697 editor := os.Getenv("EDITOR")
9798 if editor == "" {
98− // Use platform-appropriate default editor.
99+ // Use platform-appropriate default editor
99100 if runtime.GOOS == "windows" {
100101 editor = "notepad"
101102 } else {
@@ -111,11 +112,11 @@ func (m *editorCmp) openEditor(value string) tea.Cmd {
111112 if _, err := tmpfile.WriteString(value); err != nil {
112113 return util.ReportError(err)
113114 }
114−
115− // Build the full shell command with the file argument.
116− cmdStr := fmt.Sprintf("%s %s", editor, tmpfile.Name())
117−
118− return util.ExecShell(context.TODO(), cmdStr, func(err error) tea.Msg {
115+ c := exec.CommandContext(context.TODO(), editor, tmpfile.Name())
116+ c.Stdin = os.Stdin
117+ c.Stdout = os.Stdout
118+ c.Stderr = os.Stderr
119+ return tea.ExecProcess(c, func(err error) tea.Msg {
119120 if err != nil {
120121 return util.ReportError(err)
121122 }
internal/tui/util/shell.godeleted−58
@@ -1,58 +0,0 @@
1−package util
2−
3−import (
4− "context"
5− "io"
6− "strings"
7−
8− tea "charm.land/bubbletea/v2"
9− "mvdan.cc/sh/v3/interp"
10− "mvdan.cc/sh/v3/syntax"
11−)
12−
13−// shellCommand wraps a shell interpreter to implement tea.ExecCommand.
14−type shellCommand struct {
15− ctx context.Context
16− file *syntax.File
17− stdin io.Reader
18− stdout io.Writer
19− stderr io.Writer
20−}
21−
22−func (s *shellCommand) SetStdin(r io.Reader) {
23− s.stdin = r
24−}
25−
26−func (s *shellCommand) SetStdout(w io.Writer) {
27− s.stdout = w
28−}
29−
30−func (s *shellCommand) SetStderr(w io.Writer) {
31− s.stderr = w
32−}
33−
34−func (s *shellCommand) Run() error {
35− runner, err := interp.New(
36− interp.StdIO(s.stdin, s.stdout, s.stderr),
37− )
38− if err != nil {
39− return err
40− }
41− return runner.Run(s.ctx, s.file)
42−}
43−
44−// ExecShell executes a shell command string using tea.Exec.
45−// The command is parsed and executed via mvdan.cc/sh/v3/interp, allowing
46−// proper handling of shell syntax like quotes and arguments.
47−func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
48− parsed, err := syntax.NewParser().Parse(strings.NewReader(cmdStr), "")
49− if err != nil {
50− return ReportError(err)
51− }
52−
53− cmd := &shellCommand{
54− ctx: ctx,
55− file: parsed,
56− }
57− return tea.Exec(cmd, callback)
58−}