Respect SHELL env var on Windows (#2641)

This makes fzf respect SHELL environment variable on Windows, like it does on *nix, whenever defined.

Close #2638
This commit is contained in:
Rashil Gandhi 2021-10-22 21:39:47 +05:30 committed by GitHub
parent 97ae8afb6f
commit 84a47f7102
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 13 deletions

View File

@ -21,10 +21,25 @@ func notifyOnCont(resizeChan chan<- os.Signal) {
}
func quoteEntry(entry string) string {
escaped := strings.Replace(entry, `\`, `\\`, -1)
escaped = `"` + strings.Replace(escaped, `"`, `\"`, -1) + `"`
r, _ := regexp.Compile(`[&|<>()@^%!"]`)
return r.ReplaceAllStringFunc(escaped, func(match string) string {
return "^" + match
})
shell := os.Getenv("SHELL")
if len(shell) == 0 {
shell = "cmd"
}
if strings.Contains(shell, "cmd") {
// backslash escaping is done here for applications
// (see ripgrep test case in terminal_test.go#TestWindowsCommands)
escaped := strings.Replace(entry, `\`, `\\`, -1)
escaped = `"` + strings.Replace(escaped, `"`, `\"`, -1) + `"`
// caret is the escape character for cmd shell
r, _ := regexp.Compile(`[&|<>()@^%!"]`)
return r.ReplaceAllStringFunc(escaped, func(match string) string {
return "^" + match
})
} else if strings.Contains(shell, "pwsh") || strings.Contains(shell, "powershell") {
escaped := strings.Replace(entry, `"`, `""`, -1)
return "'" + strings.Replace(escaped, "'", "''", -1) + "'"
} else {
return "'" + strings.Replace(entry, "'", "'\\''", -1) + "'"
}
}

View File

@ -6,23 +6,48 @@ import (
"fmt"
"os"
"os/exec"
"strings"
"syscall"
)
// ExecCommand executes the given command with cmd
// ExecCommand executes the given command with $SHELL
func ExecCommand(command string, setpgid bool) *exec.Cmd {
return ExecCommandWith("cmd", command, setpgid)
shell := os.Getenv("SHELL")
if len(shell) == 0 {
shell = "cmd"
} else if strings.Contains(shell, "/") {
out, err := exec.Command("cygpath", "-w", shell).Output()
if err == nil {
shell = strings.Trim(string(out), "\n")
}
}
return ExecCommandWith(shell, command, setpgid)
}
// ExecCommandWith executes the given command with cmd. _shell parameter is
// ignored on Windows.
// ExecCommandWith executes the given command with the specified shell
// FIXME: setpgid is unused. We set it in the Unix implementation so that we
// can kill preview process with its child processes at once.
func ExecCommandWith(_shell string, command string, setpgid bool) *exec.Cmd {
cmd := exec.Command("cmd")
// NOTE: For "powershell", we should ideally set output encoding to UTF8,
// but it is left as is now because no adverse effect has been observed.
func ExecCommandWith(shell string, command string, setpgid bool) *exec.Cmd {
var commandline string
if strings.Contains(shell, "cmd") {
commandline = fmt.Sprintf(` /v:on/s/c "%s"`, command)
} else if strings.Contains(shell, "pwsh") || strings.Contains(shell, "powershell") {
commandline = fmt.Sprintf(` -NoProfile -Command "& { %s }"`, command)
}
if len(commandline) == 0 {
cmd := exec.Command(shell, "-c", command)
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: false,
CreationFlags: 0,
}
return cmd
}
cmd := exec.Command(shell)
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: false,
CmdLine: fmt.Sprintf(` /v:on/s/c "%s"`, command),
CmdLine: commandline,
CreationFlags: 0,
}
return cmd