Skip to content

Commit b0919a0

Browse files
authored
Merge pull request #1114 from carapace-sh/bash-fix-homedir-space
bash: fix path containing space with `~` prefix
2 parents 546cbd9 + d0a0896 commit b0919a0

File tree

2 files changed

+31
-14
lines changed

2 files changed

+31
-14
lines changed

complete.go

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func complete(cmd *cobra.Command, args []string) (string, error) {
2727
case "bash": // TODO what about oil and such?
2828
LOG.Printf("COMP_LINE is %#v", os.Getenv("COMP_LINE"))
2929
LOG.Printf("COMP_POINT is %#v", os.Getenv("COMP_POINT"))
30+
LOG.Printf("COMP_WORDBREAKS is %#v", os.Getenv("COMP_WORDBREAKS"))
3031
var err error
3132
args, err = bash.Patch(args) // handle redirects
3233
LOG.Printf("patching args to %#v", args)

internal/shell/bash/action.go

+30-14
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,36 @@ var sanitizer = strings.NewReplacer(
1414
"\t", ``,
1515
)
1616

17-
var valueReplacer = strings.NewReplacer(
17+
var escapingQuotedReplacer = strings.NewReplacer(
1818
`\`, `\\`,
1919
`"`, `\"`,
2020
`$`, `\$`,
2121
"`", "\\`",
2222
)
2323

24+
var escapingReplacer = strings.NewReplacer(
25+
`\`, `\\`,
26+
`&`, `\&`,
27+
`<`, `\<`,
28+
`>`, `\>`,
29+
"`", "\\`",
30+
`'`, `\'`,
31+
`"`, `\"`,
32+
`{`, `\{`,
33+
`}`, `\}`,
34+
`$`, `\$`,
35+
`#`, `\#`,
36+
`|`, `\|`,
37+
`?`, `\?`,
38+
`(`, `\(`,
39+
`)`, `\)`,
40+
`;`, `\;`,
41+
` `, `\ `,
42+
`[`, `\[`,
43+
`]`, `\]`,
44+
`*`, `\*`,
45+
)
46+
2447
var displayReplacer = strings.NewReplacer(
2548
`${`, `\\\${`,
2649
)
@@ -81,19 +104,11 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu
81104
nospace = nospace || meta.Nospace.Matches(val.Value)
82105

83106
vals[index] = sanitizer.Replace(val.Value)
84-
if requiresQuoting(vals[index]) {
85-
vals[index] = valueReplacer.Replace(vals[index])
86-
switch {
87-
case strings.HasPrefix(vals[index], "~"): // assume homedir expansion
88-
if splitted := strings.SplitAfterN(vals[index], "/", 2); len(splitted) == 2 {
89-
vals[index] = fmt.Sprintf(`%v"%v"`, splitted[0], splitted[1])
90-
} else {
91-
// TODO homedir expansion won't work this way, but shouldn't reach this point anyway.
92-
vals[index] = fmt.Sprintf(`~"%v"`, strings.TrimPrefix(vals[index], "~"))
93-
}
94-
default:
95-
vals[index] = fmt.Sprintf(`"%v"`, vals[index])
96-
}
107+
switch {
108+
case strings.HasPrefix(vals[index], "~"): // assume homedir expansion
109+
vals[index] = escapingReplacer.Replace(vals[index])
110+
case requiresQuoting(vals[index]):
111+
vals[index] = fmt.Sprintf(`"%v"`, escapingQuotedReplacer.Replace(vals[index]))
97112
}
98113
} else {
99114
nospace = true
@@ -111,6 +126,7 @@ func ActionRawValues(currentWord string, meta common.Meta, values common.RawValu
111126

112127
func requiresQuoting(s string) bool {
113128
chars := " \t\r\n`" + `[]{}()<>;|$&:*#`
129+
chars += `'"`
114130
chars += os.Getenv("COMP_WORDBREAKS")
115131
chars += `\`
116132
return strings.ContainsAny(s, chars)

0 commit comments

Comments
 (0)