Skip to content

Commit cd17686

Browse files
apcha-oaistainless-app[bot]
authored andcommitted
Fix bash completion filename quoting (#216)
1 parent 0357e08 commit cd17686

2 files changed

Lines changed: 86 additions & 1 deletion

File tree

internal/autocomplete/autocomplete_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package autocomplete
22

33
import (
4+
"os/exec"
5+
"strings"
46
"testing"
57

68
"github.com/stretchr/testify/assert"
@@ -155,6 +157,89 @@ func TestGetCompletions_FileFlagBehavior(t *testing.T) {
155157
assert.Empty(t, result.Completions)
156158
}
157159

160+
func TestBashCompletionFileCandidatesUseFilenameQuoting(t *testing.T) {
161+
t.Parallel()
162+
163+
bash, err := exec.LookPath("bash")
164+
if err != nil {
165+
t.Skip("bash is not available")
166+
}
167+
168+
completionScript, err := shellCompletions[CompletionStyleBash](&cli.Command{}, "openai")
169+
if !assert.NoError(t, err) {
170+
return
171+
}
172+
173+
probe := `
174+
cd "$1" || exit 1
175+
touch '$(printf autocomplete-marker > completion-output)'
176+
177+
if ! type mapfile >/dev/null 2>&1; then
178+
mapfile() {
179+
if [[ "$1" == "-t" ]]; then
180+
shift
181+
fi
182+
if [[ "$1" != "COMPREPLY" ]]; then
183+
return 2
184+
fi
185+
186+
COMPREPLY=()
187+
local line
188+
while IFS= read -r line; do
189+
COMPREPLY+=("$line")
190+
done
191+
}
192+
fi
193+
194+
openai() {
195+
return 10
196+
}
197+
198+
` + completionScript + `
199+
200+
printf 'spec:%s\n' "$(complete -p openai)"
201+
202+
COMP_WORDS=(openai files create --file '@$(')
203+
COMP_CWORD=4
204+
__openai_bash_autocomplete
205+
printf 'forced:%s\n' "${COMPREPLY[0]}"
206+
207+
COMP_WORDS=(openai upload '$(')
208+
COMP_CWORD=2
209+
__openai_bash_autocomplete
210+
printf 'file:%s\n' "${COMPREPLY[0]}"
211+
212+
if [[ -e completion-output ]]; then
213+
printf 'unexpected completion-output file\n'
214+
exit 1
215+
fi
216+
`
217+
218+
cmd := exec.Command(bash, "-c", probe, "bash-completion-probe", t.TempDir())
219+
out, err := cmd.CombinedOutput()
220+
output := string(out)
221+
222+
if !assert.NoError(t, err, output) {
223+
return
224+
}
225+
assert.Contains(t, output, "spec:complete -o filenames -F __openai_bash_autocomplete openai")
226+
assert.Contains(t, output, "forced:@$(printf autocomplete-marker > completion-output)")
227+
assert.Contains(t, output, "file:$(printf autocomplete-marker > completion-output)")
228+
assert.NotContains(t, output, "unexpected completion-output file")
229+
}
230+
231+
func TestBashCompletionScriptDoesNotRegisterPlainCompletion(t *testing.T) {
232+
t.Parallel()
233+
234+
completionScript, err := shellCompletions[CompletionStyleBash](&cli.Command{}, "openai")
235+
if !assert.NoError(t, err) {
236+
return
237+
}
238+
239+
assert.Contains(t, completionScript, "complete -o filenames -F __openai_bash_autocomplete openai")
240+
assert.False(t, strings.Contains(completionScript, "\ncomplete -F __openai_bash_autocomplete openai"))
241+
}
242+
158243
func TestGetCompletions_NonBoolFlagValue(t *testing.T) {
159244
t.Parallel()
160245

internal/autocomplete/shellscripts/bash_autocomplete.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,4 @@ ____APPNAME___bash_autocomplete() {
5656
fi
5757
}
5858

59-
complete -F ____APPNAME___bash_autocomplete __APPNAME__
59+
complete -o filenames -F ____APPNAME___bash_autocomplete __APPNAME__

0 commit comments

Comments
 (0)