mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-28 05:43:11 +00:00
__fish_complete_suffix: enable fuzzy completion, simplify
fish's internal completion logic is much smarter than the globbing in this function, so let's just reuse "complete -C", and filter directories and files with the given suffix. Thanks to @Kratacoa for reporting on Gitter. Using "complete -C" works well no prefix is given. Since in this repository only the openocd completions pass a prefix, I left the prefix-case as is. It could probably be improved and simplified as well. The prefix argument was introduced to avoid cd's side effects inside a completion. Using cd is tempting though because it would allow to use the same logic as without a prefix.
This commit is contained in:
parent
0dd334ee46
commit
93cb0e2abb
1 changed files with 41 additions and 33 deletions
|
@ -48,40 +48,48 @@ function __fish_complete_suffix -d "Complete using files"
|
|||
end
|
||||
end
|
||||
|
||||
# Strip leading ./ as it confuses the detection of base and suffix
|
||||
# It is conditionally re-added below.
|
||||
set base $prefix(string replace -r '^("\')?\\./' '' -- $comp | string trim -c '\'"') # " make emacs syntax highlighting happy
|
||||
|
||||
set -l all
|
||||
set -l dirs
|
||||
# If $comp is "./ma" and the file is "main.py", we'll catch that case here,
|
||||
# but complete.cpp will not consider it a match, so we have to output the
|
||||
# correct form.
|
||||
|
||||
# Also do directory completion, since there might be files with the correct
|
||||
# suffix in a subdirectory.
|
||||
set all $base*
|
||||
set all (string match -r -- ".*"(string escape --style=regex -- $suff) $all)
|
||||
if not string match -qr '/$' -- $suff
|
||||
set dirs $base*/
|
||||
|
||||
# The problem is that we now have each directory included twice in the output,
|
||||
# once as `dir` and once as `dir/`. The runtime here is O(n) for n directories
|
||||
# in the output, but hopefully since we have only one level (no nested results)
|
||||
# it should be fast. The alternative is to shell out to `sort` and remove any
|
||||
# duplicate results, but it would have to be a huge `n` to make up for the fork
|
||||
# overhead.
|
||||
for dir in $dirs
|
||||
set all (string match -v (string match -r '(.*)/$' -- $dir)[2] -- $all)
|
||||
end
|
||||
end
|
||||
|
||||
set files $all $dirs
|
||||
if string match -qr '^\\./' -- $comp
|
||||
set files ./$files
|
||||
# Simple and common case: no prefix, just complete normally and filter out unwanted suffixes.
|
||||
if test -z $prefix
|
||||
set -l suffix (string escape --style=regex -- $suff)
|
||||
# Use normal file completions. Any valid command works here as, as long as it has no
|
||||
# user-defined completions. The builtin ":" should work.
|
||||
set files (complete -C ": $comp" | string match -r "^.*(?:$suffix|/)\$")
|
||||
else
|
||||
# "Escape" files starting with a literal dash `-` with a `./`
|
||||
set files (string replace -r -- "^-" "./-" $files)
|
||||
# Strip leading ./ as it confuses the detection of base and suffix
|
||||
# It is conditionally re-added below.
|
||||
set base $prefix(string replace -r '^("\')?\\./' '' -- $comp | string trim -c '\'"') # " make emacs syntax highlighting happy
|
||||
|
||||
set -l all
|
||||
set -l dirs
|
||||
# If $comp is "./ma" and the file is "main.py", we'll catch that case here,
|
||||
# but complete.cpp will not consider it a match, so we have to output the
|
||||
# correct form.
|
||||
|
||||
# Also do directory completion, since there might be files with the correct
|
||||
# suffix in a subdirectory.
|
||||
set all $base*
|
||||
set all (string match -r -- ".*"(string escape --style=regex -- $suff) $all)
|
||||
if not string match -qr '/$' -- $suff
|
||||
set dirs $base*/
|
||||
|
||||
# The problem is that we now have each directory included twice in the output,
|
||||
# once as `dir` and once as `dir/`. The runtime here is O(n) for n directories
|
||||
# in the output, but hopefully since we have only one level (no nested results)
|
||||
# it should be fast. The alternative is to shell out to `sort` and remove any
|
||||
# duplicate results, but it would have to be a huge `n` to make up for the fork
|
||||
# overhead.
|
||||
for dir in $dirs
|
||||
set all (string match -v (string match -r '(.*)/$' -- $dir)[2] -- $all)
|
||||
end
|
||||
end
|
||||
|
||||
set files $all $dirs
|
||||
if string match -qr '^\\./' -- $comp
|
||||
set files ./$files
|
||||
else
|
||||
# "Escape" files starting with a literal dash `-` with a `./`
|
||||
set files (string replace -r -- "^-" "./-" $files)
|
||||
end
|
||||
end
|
||||
|
||||
if set -q files[1]
|
||||
|
|
Loading…
Reference in a new issue