summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2017-10-02 11:36:19 -0400
committerJunegunn Choi <junegunn.c@gmail.com>2017-10-14 15:26:37 +0900
commitc4185e81e86e339ae2c18e5d9b596b7992ec179b (patch)
tree13877428693578f3e65adcfff08d7f0329f128d9 /src
parent0580fe9046d038c359645f6e7ed99acfa45b2190 (diff)
downloadfzf-c4185e81e86e339ae2c18e5d9b596b7992ec179b.tar.gz
Fix ExecCommandWith for cmd.exe in Windows (#1072)
Close #1018 Run the command as is in cmd.exe with no parsing and escaping. Explicity set cmd.SysProcAttr so execCommand does not escape the command. Technically, the command should be escaped with ^ for special characters, including ". This allows cmd.exe commands to be chained together. See https://github.com/neovim/neovim/pull/7343#issuecomment-333350201 This commit also updates quoteEntry to use strings.Replace instead of strconv.Quote which escapes more than \ and ".
Diffstat (limited to 'src')
-rw-r--r--src/terminal.go11
-rw-r--r--src/terminal_test.go19
-rw-r--r--src/util/util_windows.go14
3 files changed, 36 insertions, 8 deletions
diff --git a/src/terminal.go b/src/terminal.go
index 7813680a..98d837c8 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -1103,9 +1103,18 @@ func keyMatch(key int, event tui.Event) bool {
event.Type == tui.Mouse && key == tui.DoubleClick && event.MouseEvent.Double
}
+func quoteEntryCmd(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
+ })
+}
+
func quoteEntry(entry string) string {
if util.IsWindows() {
- return strconv.Quote(strings.Replace(entry, "\"", "\\\"", -1))
+ return quoteEntryCmd(entry)
}
return "'" + strings.Replace(entry, "'", "'\\''", -1) + "'"
}
diff --git a/src/terminal_test.go b/src/terminal_test.go
index d42d2b82..60f2b1ad 100644
--- a/src/terminal_test.go
+++ b/src/terminal_test.go
@@ -91,3 +91,22 @@ func TestReplacePlaceholder(t *testing.T) {
result = replacePlaceholder("echo {}/{1}/{3}/{2..3}", true, Delimiter{regex: regex}, false, "query", items1)
check("echo ' foo'\\''bar baz'/'f'/'r b'/''\\''bar b'")
}
+
+func TestQuoteEntryCmd(t *testing.T) {
+ tests := map[string]string{
+ `"`: `^"\^"^"`,
+ `\`: `^"\\^"`,
+ `\"`: `^"\\\^"^"`,
+ `"\\\"`: `^"\^"\\\\\\\^"^"`,
+ `&|<>()@^%!`: `^"^&^|^<^>^(^)^@^^^%^!^"`,
+ `%USERPROFILE%`: `^"^%USERPROFILE^%^"`,
+ `C:\Program Files (x86)\`: `^"C:\\Program Files ^(x86^)\\^"`,
+ }
+
+ for input, expected := range tests {
+ escaped := quoteEntryCmd(input)
+ if escaped != expected {
+ t.Errorf("Input: %s, expected: %s, actual %s", input, expected, escaped)
+ }
+ }
+}
diff --git a/src/util/util_windows.go b/src/util/util_windows.go
index 493f4d7f..86409fde 100644
--- a/src/util/util_windows.go
+++ b/src/util/util_windows.go
@@ -6,8 +6,6 @@ import (
"os"
"os/exec"
"syscall"
-
- "github.com/mattn/go-shellwords"
)
// ExecCommand executes the given command with cmd
@@ -18,11 +16,13 @@ func ExecCommand(command string) *exec.Cmd {
// ExecCommandWith executes the given command with cmd. _shell parameter is
// ignored on Windows.
func ExecCommandWith(_shell string, command string) *exec.Cmd {
- args, _ := shellwords.Parse(command)
- allArgs := make([]string, len(args)+1)
- allArgs[0] = "/c"
- copy(allArgs[1:], args)
- return exec.Command("cmd", allArgs...)
+ cmd := exec.Command("cmd")
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ HideWindow: false,
+ CmdLine: fmt.Sprintf(` /s /c "%s"`, command),
+ CreationFlags: 0,
+ }
+ return cmd
}
// IsWindows returns true on Windows