diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index e8c836e3..4c7915c2 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -1451,8 +1451,6 @@ call. \fBfzf --bind "enter:become(vim {})"\fR -\fBbecome(...)\fR is not supported on Windows. - .SS RELOAD INPUT \fBreload(...)\fR action is used to dynamically update the input list diff --git a/src/options.go b/src/options.go index a3666efe..66e0554e 100644 --- a/src/options.go +++ b/src/options.go @@ -1329,10 +1329,6 @@ func parseActionList(masked string, original string, prevActions []*action, putA actions = append(actions, &action{t: t, a: actionArg}) } switch t { - case actBecome: - if util.IsWindows() { - exit("become action is not supported on Windows") - } case actUnbind, actRebind: parseKeyChordsImpl(actionArg, spec[0:offset]+" target required", exit) case actChangePreviewWindow: diff --git a/src/terminal.go b/src/terminal.go index 3a5bf794..8d114e1b 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -7,7 +7,6 @@ import ( "io" "math" "os" - "os/exec" "os/signal" "regexp" "sort" @@ -3376,27 +3375,21 @@ func (t *Terminal) Loop() { valid, list := t.buildPlusList(a.a, false) if valid { command := t.replacePlaceholder(a.a, false, string(t.input), list) - shell := os.Getenv("SHELL") - if len(shell) == 0 { - shell = "sh" - } - shellPath, err := exec.LookPath(shell) - if err == nil { - t.tui.Close() - if t.history != nil { - t.history.append(string(t.input)) - } - /* - FIXME: It is not at all clear why this is required. - The following command will report 'not a tty', unless we open - /dev/tty *twice* after closing the standard input for 'reload' - in Reader.terminate(). - : | fzf --bind 'start:reload:ls' --bind 'enter:become:tty' - */ - tui.TtyIn() - util.SetStdin(tui.TtyIn()) - syscall.Exec(shellPath, []string{shell, "-c", command}, os.Environ()) + t.tui.Close() + if t.history != nil { + t.history.append(string(t.input)) } + + /* + FIXME: It is not at all clear why this is required. + The following command will report 'not a tty', unless we open + /dev/tty *twice* after closing the standard input for 'reload' + in Reader.terminate(). + + while : | fzf --bind 'start:reload:ls' --bind 'load:become:tty'; do echo; done + */ + tui.TtyIn() + t.executor.Become(tui.TtyIn(), t.environ(), command) } case actExecute, actExecuteSilent: t.executeCommand(a.a, false, a.t == actExecuteSilent, false, false) diff --git a/src/util/util_unix.go b/src/util/util_unix.go index 190cc694..e1e086d4 100644 --- a/src/util/util_unix.go +++ b/src/util/util_unix.go @@ -56,6 +56,16 @@ func (x *Executor) QuoteEntry(entry string) string { return "'" + x.escaper.Replace(entry) + "'" } +func (x *Executor) Become(stdin *os.File, environ []string, command string) { + SetStdin(stdin) + shellPath, err := exec.LookPath(x.shell) + if err == nil { + shellPath = x.shell + } + args := append([]string{shellPath}, append(x.args, command)...) + syscall.Exec(shellPath, args, environ) +} + // KillCommand kills the process for the given command func KillCommand(cmd *exec.Cmd) error { return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) diff --git a/src/util/util_windows.go b/src/util/util_windows.go index 8f73c47e..8a831c01 100644 --- a/src/util/util_windows.go +++ b/src/util/util_windows.go @@ -64,6 +64,21 @@ func (x *Executor) ExecCommand(command string, setpgid bool) *exec.Cmd { return cmd } +func (x *Executor) Become(stdin *os.File, environ []string, command string) { + cmd := x.ExecCommand(command, false) + cmd.Stdin = stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Env = environ + err := cmd.Run() + if err != nil { + if exitError, ok := err.(*exec.ExitError); ok { + Exit(exitError.ExitCode()) + } + } + Exit(0) +} + func (x *Executor) QuoteEntry(entry string) string { if strings.Contains(x.shell, "cmd") { // backslash escaping is done here for applications