summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRashil Gandhi <46838874+rashil2000@users.noreply.github.com>2021-10-22 21:39:47 +0530
committerGitHub <noreply@github.com>2021-10-23 01:09:47 +0900
commit84a47f71029992fe804e506a6128643bffbb598c (patch)
tree7aef3711567f5303b1077ec6ca9e656436f36a2e
parent97ae8afb6f83b545eac530a689d7b3d46e20eec1 (diff)
downloadfzf-84a47f71029992fe804e506a6128643bffbb598c.tar.gz
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
-rw-r--r--src/terminal_windows.go27
-rw-r--r--src/util/util_windows.go39
2 files changed, 53 insertions, 13 deletions
diff --git a/src/terminal_windows.go b/src/terminal_windows.go
index d4262b65..7ba64dff 100644
--- a/src/terminal_windows.go
+++ b/src/terminal_windows.go
@@ -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) + "'"
+ }
}
diff --git a/src/util/util_windows.go b/src/util/util_windows.go
index a4af20dd..8a85a072 100644
--- a/src/util/util_windows.go
+++ b/src/util/util_windows.go
@@ -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