Skip to content

Commit a203253

Browse files
committed
Fix zsh for DirectiveNoSpace and DirectiveNoFileComp
Fixes #1211 When handling ShellCompDirectiveNoSpace we must still properly handle descriptions. To do so we cannot simply use 'compadd', but must use zsh's '_describe' function. Also, when handling ShellCompDirectiveNoSpace we cannot assume that only a single completion will be given to the script. In fact, ValidArgsFunction can return multiple completions, even if they don't match the 'toComplete' argument prefix. Therefore, we cannot use the number of completions received in the completion script to determine if we should activate the "no space" directive. Instead, we can leave it all to the '_describe' function. Fixes #1212 When handling ShellCompDirectiveNoFileComp we cannot base ourself on the script receiving no valid completion. In fact, ValidArgsFunction can return multiple completions, even if they don't match the 'toComplete' argument prefix at all. Therefore, we cannot use the number of completions received by the completion script to determine if we should activate the "no file comp" directive. Instead, we can check if the '_describe' function has found any completions. Finally, it is important for the script to return the return code of the called zsh functions (_describe, _arguments). This tells zsh if completions were found or not, which if not, will trigger different matching attempts, such as matching what the user typed with the the content of possible completions (instead of just as the prefix). Signed-off-by: Marc Khouzam <[email protected]>
1 parent b97b5ea commit a203253

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

custom_completions.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,6 @@ func (c *Command) initCompleteCmd(args []string) {
149149
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
150150
}
151151

152-
if directive >= shellCompDirectiveMaxValue {
153-
directive = ShellCompDirectiveDefault
154-
}
155-
156152
// As the last printout, print the completion directive for the completion script to parse.
157153
// The directive integer must be that last character following a single colon (:).
158154
// The completion script expects :<directive>

zsh_completions.go

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ _%[1]s()
9595
local shellCompDirectiveFilterFileExt=%[6]d
9696
local shellCompDirectiveFilterDirs=%[7]d
9797
98-
local lastParam lastChar flagPrefix requestComp out directive compCount comp lastComp
98+
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
9999
local -a completions
100100
101101
__%[1]s_debug "\n========= starting completion logic =========="
@@ -163,7 +163,6 @@ _%[1]s()
163163
return
164164
fi
165165
166-
compCount=0
167166
while IFS='\n' read -r comp; do
168167
if [ -n "$comp" ]; then
169168
# If requested, completions are returned with a description.
@@ -175,13 +174,17 @@ _%[1]s()
175174
local tab=$(printf '\t')
176175
comp=${comp//$tab/:}
177176
178-
((compCount++))
179177
__%[1]s_debug "Adding completion: ${comp}"
180178
completions+=${comp}
181179
lastComp=$comp
182180
fi
183181
done < <(printf "%%s\n" "${out[@]}")
184182
183+
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
184+
__%[1]s_debug "Activating nospace."
185+
noSpace="-S ''"
186+
fi
187+
185188
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
186189
# File extension filtering
187190
local filteringCmd
@@ -208,25 +211,40 @@ _%[1]s()
208211
__%[1]s_debug "Listing directories in ."
209212
fi
210213
214+
local result
211215
_arguments '*:dirname:_files -/'" ${flagPrefix}"
216+
result=$?
212217
if [ -n "$subdir" ]; then
213218
popd >/dev/null 2>&1
214219
fi
215-
elif [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ] && [ ${compCount} -eq 1 ]; then
216-
__%[1]s_debug "Activating nospace."
217-
# We can use compadd here as there is no description when
218-
# there is only one completion.
219-
compadd -S '' "${lastComp}"
220-
elif [ ${compCount} -eq 0 ]; then
221-
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
222-
__%[1]s_debug "deactivating file completion"
220+
return $result
221+
else
222+
__%[1]s_debug "Calling _describe"
223+
if eval _describe "completions" completions $flagPrefix $noSpace; then
224+
__%[1]s_debug "_describe found some completions"
225+
226+
# Return the success of having called _describe
227+
return 0
223228
else
224-
# Perform file completion
225-
__%[1]s_debug "activating file completion"
226-
_arguments '*:filename:_files'" ${flagPrefix}"
229+
__%[1]s_debug "_describe did not find completions."
230+
__%[1]s_debug "Checking if we should do file completion."
231+
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
232+
__%[1]s_debug "deactivating file completion"
233+
234+
# We must return an error code here to let zsh know that there were no
235+
# completions found by _describe; this is what will trigger other
236+
# matching algorithms to attempt to find completions.
237+
# For example zsh can match letters in the middle of words.
238+
return 1
239+
else
240+
# Perform file completion
241+
__%[1]s_debug "Activating file completion"
242+
243+
# We must return the result of this command, so it must be the
244+
# last command, or else we must store its result to return it.
245+
_arguments '*:filename:_files'" ${flagPrefix}"
246+
fi
227247
fi
228-
else
229-
_describe "completions" completions $(echo $flagPrefix)
230248
fi
231249
}
232250

0 commit comments

Comments
 (0)