Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement completion NoMatching #1833

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions completions.go
Expand Up @@ -77,6 +77,9 @@ const (
// obtain the same behavior but only for flags.
ShellCompDirectiveFilterDirs

// ShellCompDirectiveNoMatching indicates that the provided completions will be
// passed to the user as-is, without additional matching (zsh and fish only).
ShellCompDirectiveNoMatching
// ===========================================================================

// All directives using iota should be above this one.
Expand Down Expand Up @@ -159,6 +162,9 @@ func (d ShellCompDirective) string() string {
if d&ShellCompDirectiveFilterDirs != 0 {
directives = append(directives, "ShellCompDirectiveFilterDirs")
}
if d&ShellCompDirectiveNoMatching != 0 {
directives = append(directives, "ShellCompDirectiveNoMatching")
}
if len(directives) == 0 {
directives = append(directives, "ShellCompDirectiveDefault")
}
Expand Down
21 changes: 14 additions & 7 deletions fish_completions.go
Expand Up @@ -53,7 +53,7 @@ function __%[1]s_perform_completion
__%[1]s_debug "last arg: $lastArg"

# Disable ActiveHelp which is not supported for fish shell
set -l requestComp "%[9]s=0 $args[1] %[3]s $args[2..-1] $lastArg"
set -l requestComp "%[10]s=0 $args[1] %[3]s $args[2..-1] $lastArg"

__%[1]s_debug "Calling $requestComp"
set -l results (eval $requestComp 2> /dev/null)
Expand Down Expand Up @@ -119,6 +119,7 @@ function __%[1]s_prepare_completions
set -l shellCompDirectiveNoFileComp %[6]d
set -l shellCompDirectiveFilterFileExt %[7]d
set -l shellCompDirectiveFilterDirs %[8]d
set -l shellCompDirectiveNoMatching %[9]d

if test -z "$directive"
set directive 0
Expand All @@ -141,19 +142,24 @@ function __%[1]s_prepare_completions

set -l nospace (math (math --scale 0 $directive / $shellCompDirectiveNoSpace) %% 2)
set -l nofiles (math (math --scale 0 $directive / $shellCompDirectiveNoFileComp) %% 2)
set -l nomatching (math (math --scale 0 $directive / $shellCompDirectiveNoMatching) %% 2)

__%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
__%[1]s_debug "nospace: $nospace, nofiles: $nofiles, nomatching: $nomatching"

# If we want to prevent a space, or if file completion is NOT disabled,
# we need to count the number of valid completions.
# To do so, we will filter on prefix as the completions we have received
# may not already be filtered so as to allow fish to match on different
# criteria than the prefix.
if test $nospace -ne 0; or test $nofiles -eq 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a special case which the comment may not have made very clear.

Let's take file completion. We only want to trigger file completion if there are no other completions available (from the point of view of the user). This is not normally what fish does, but it is how the other shells behave so we decided to standardize on that.

However, if the program does not filter on prefix (to allow fuzzy matching), it will always return some completions and we will not be able to know if fish will match any of them or not; so, we would not know if there are no real completions and couldn't tell if we should trigger file completion. Therefore, in this case, we turn off fuzzy matching and explicitly match on prefix; if there are no completions left, we know to turn on file completion.

A similar scenario applies to the nospace directive. You can refer to #1249 for details.

This means that in this case, we cannot do fuzzy completion, or it would break the request from the program to do file completion and/or nospace completion.

I don't know if that was clear, so don't hesitate to ask for clarification.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum I see, what do you suggest changing the logic to in that case ?

set -l prefix (commandline -t | string escape --style=regex)
__%[1]s_debug "prefix: $prefix"

set -l completions (string match -r -- "^$prefix.*" $__%[1]s_comp_results)
if test $nomatching -ne 0
set -l completions $__%[1]s_comp_results
else
set -l prefix (commandline -t | string escape --style=regex)
__%[1]s_debug "prefix: $prefix"

set -l completions (string match -r -- "^$prefix.*" $__%[1]s_comp_results)
end
set --global __%[1]s_comp_results $completions
__%[1]s_debug "Filtered completions are: $__%[1]s_comp_results"

Expand Down Expand Up @@ -211,7 +217,8 @@ complete -c %[2]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'

`, nameForVar, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, activeHelpEnvVar(name)))
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveNoMatching,
activeHelpEnvVar(name)))
}

// GenFishCompletion generates fish completion file and writes to the passed writer.
Expand Down
15 changes: 11 additions & 4 deletions zsh_completions.go
Expand Up @@ -108,8 +108,9 @@ _%[1]s()
local shellCompDirectiveNoFileComp=%[5]d
local shellCompDirectiveFilterFileExt=%[6]d
local shellCompDirectiveFilterDirs=%[7]d
local shellCompDirectiveNoMatching=%[8]d

local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace
local lastParam lastChar flagPrefix requestComp out directive comp lastComp noSpace noMatching
local -a completions

__%[1]s_debug "\n========= starting completion logic =========="
Expand Down Expand Up @@ -177,7 +178,7 @@ _%[1]s()
return
fi

local activeHelpMarker="%[8]s"
local activeHelpMarker="%[9]s"
local endIndex=${#activeHelpMarker}
local startIndex=$((${#activeHelpMarker}+1))
local hasActiveHelp=0
Expand Down Expand Up @@ -261,8 +262,14 @@ _%[1]s()
fi
return $result
else
if [ $((directive & shellCompDirectiveNoMatching)) -ne 0 ]; then
__heph_debug "Activating no matching."
compstate[insert]=automenu
noMatching="-U -o nosort"
fi

__%[1]s_debug "Calling _describe"
if eval _describe "completions" completions $flagPrefix $noSpace; then
if eval _describe "completions" completions $noMatching $flagPrefix $noSpace; then
__%[1]s_debug "_describe found some completions"

# Return the success of having called _describe
Expand Down Expand Up @@ -296,6 +303,6 @@ if [ "$funcstack[1]" = "_%[1]s" ]; then
fi
`, name, compCmd,
ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs, ShellCompDirectiveNoMatching,
activeHelpMarker))
}