shell.go

 1package util
 2
 3import (
 4	"context"
 5	"errors"
 6	"os/exec"
 7
 8	tea "charm.land/bubbletea/v2"
 9	"mvdan.cc/sh/v3/shell"
10)
11
12// 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
14// arguments while preserving TTY handling for terminal editors.
15func ExecShell(ctx context.Context, cmdStr string, callback tea.ExecCallback) tea.Cmd {
16	fields, err := shell.Fields(cmdStr, nil)
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}