mirror of
https://github.com/spf13/cobra
synced 2024-12-28 07:17:06 +00:00
Fix zsh for DirectiveNoSpace and DirectiveNoFileComp (#1213)
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 <marc.khouzam@montreal.ca>
This commit is contained in:
parent
2d94892a8b
commit
95d23d24ff
2 changed files with 35 additions and 21 deletions
|
@ -175,10 +175,6 @@ func (c *Command) initCompleteCmd(args []string) {
|
|||
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
|
||||
}
|
||||
|
||||
if directive >= shellCompDirectiveMaxValue {
|
||||
directive = ShellCompDirectiveDefault
|
||||
}
|
||||
|
||||
// As the last printout, print the completion directive for the completion script to parse.
|
||||
// The directive integer must be that last character following a single colon (:).
|
||||
// The completion script expects :<directive>
|
||||
|
|
|
@ -95,7 +95,7 @@ _%[1]s()
|
|||
local shellCompDirectiveFilterFileExt=%[6]d
|
||||
local shellCompDirectiveFilterDirs=%[7]d
|
||||
|
||||
local lastParam lastChar flagPrefix requestComp out directive compCount comp lastComp
|
||||
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
|
||||
local -a completions
|
||||
|
||||
__%[1]s_debug "\n========= starting completion logic =========="
|
||||
|
@ -163,7 +163,6 @@ _%[1]s()
|
|||
return
|
||||
fi
|
||||
|
||||
compCount=0
|
||||
while IFS='\n' read -r comp; do
|
||||
if [ -n "$comp" ]; then
|
||||
# If requested, completions are returned with a description.
|
||||
|
@ -175,13 +174,17 @@ _%[1]s()
|
|||
local tab=$(printf '\t')
|
||||
comp=${comp//$tab/:}
|
||||
|
||||
((compCount++))
|
||||
__%[1]s_debug "Adding completion: ${comp}"
|
||||
completions+=${comp}
|
||||
lastComp=$comp
|
||||
fi
|
||||
done < <(printf "%%s\n" "${out[@]}")
|
||||
|
||||
if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
|
||||
__%[1]s_debug "Activating nospace."
|
||||
noSpace="-S ''"
|
||||
fi
|
||||
|
||||
if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
|
||||
# File extension filtering
|
||||
local filteringCmd
|
||||
|
@ -208,25 +211,40 @@ _%[1]s()
|
|||
__%[1]s_debug "Listing directories in ."
|
||||
fi
|
||||
|
||||
local result
|
||||
_arguments '*:dirname:_files -/'" ${flagPrefix}"
|
||||
result=$?
|
||||
if [ -n "$subdir" ]; then
|
||||
popd >/dev/null 2>&1
|
||||
fi
|
||||
elif [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ] && [ ${compCount} -eq 1 ]; then
|
||||
__%[1]s_debug "Activating nospace."
|
||||
# We can use compadd here as there is no description when
|
||||
# there is only one completion.
|
||||
compadd -S '' "${lastComp}"
|
||||
elif [ ${compCount} -eq 0 ]; then
|
||||
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||
__%[1]s_debug "deactivating file completion"
|
||||
else
|
||||
# Perform file completion
|
||||
__%[1]s_debug "activating file completion"
|
||||
_arguments '*:filename:_files'" ${flagPrefix}"
|
||||
fi
|
||||
return $result
|
||||
else
|
||||
_describe "completions" completions $(echo $flagPrefix)
|
||||
__%[1]s_debug "Calling _describe"
|
||||
if eval _describe "completions" completions $flagPrefix $noSpace; then
|
||||
__%[1]s_debug "_describe found some completions"
|
||||
|
||||
# Return the success of having called _describe
|
||||
return 0
|
||||
else
|
||||
__%[1]s_debug "_describe did not find completions."
|
||||
__%[1]s_debug "Checking if we should do file completion."
|
||||
if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
|
||||
__%[1]s_debug "deactivating file completion"
|
||||
|
||||
# We must return an error code here to let zsh know that there were no
|
||||
# completions found by _describe; this is what will trigger other
|
||||
# matching algorithms to attempt to find completions.
|
||||
# For example zsh can match letters in the middle of words.
|
||||
return 1
|
||||
else
|
||||
# Perform file completion
|
||||
__%[1]s_debug "Activating file completion"
|
||||
|
||||
# We must return the result of this command, so it must be the
|
||||
# last command, or else we must store its result to return it.
|
||||
_arguments '*:filename:_files'" ${flagPrefix}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue