mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-06-07 10:01:14 -03:00
Fixes #8924 via __fish_complete_suffix overhaul
Before: * hand write arg parse * only accepts one suffix After: * use `arg_parse` to parse args * accepts multi suffixes Closes #9611.
This commit is contained in:
committed by
Mahmoud Al-Qudsi
parent
dea18b34aa
commit
aa65856ee0
@@ -1,10 +1,5 @@
|
||||
function __fish_complete_docutils -d "Completions for Docutils common options" -a cmd
|
||||
complete -x -c $cmd -k -a "
|
||||
(
|
||||
__fish_complete_suffix .rst
|
||||
__fish_complete_suffix .txt
|
||||
)
|
||||
"
|
||||
complete -x -c $cmd -k -a "(__fish_complete_suffix .rst .txt)"
|
||||
|
||||
# General Docutils Options
|
||||
complete -c $cmd -l title -d "Specify the docs title"
|
||||
|
||||
@@ -1,79 +1,52 @@
|
||||
# Find files ending in any of the non-switch arguments and output them as completions.
|
||||
# * --description provides the description that should be part of each generated completion,
|
||||
# * --prefix=DIR makes __fish_complete_suffix behave as if it were called in DIR rather than $PWD
|
||||
# * --complete=PREFIX only lists files that begin with PREFIX
|
||||
#
|
||||
# Find files that complete $argv[1], has the suffix $argv[2], and output them
|
||||
# as completions with the optional description $argv[3]. Then, also output
|
||||
# completions for the files that don't have the suffix, so you want to use
|
||||
# "complete -k" on the output. Both $argv[1] and $argv[3] are optional,
|
||||
# if only one is specified, it is assumed to be the argument to complete. If
|
||||
# $argv[4] is present, it is treated as a prefix for the path, i.e. in lieu
|
||||
# of $PWD.
|
||||
|
||||
# Files matching the above preconditions are printed first then other, non-matching files
|
||||
# are printed for fallback purposes. As such, it is imperative that `complete` calls that
|
||||
# shell out to `__fish_complete_suffix` are made with a `-k` switch to ensure sort order
|
||||
# is preserved.
|
||||
function __fish_complete_suffix -d "Complete using files"
|
||||
set -l _flag_prefix ""
|
||||
set -l _flag_complete (commandline -ct)
|
||||
|
||||
# Variable declarations
|
||||
argparse 'prefix=' 'description=' 'complete=' -- $argv
|
||||
|
||||
set -l comp
|
||||
set -l suff
|
||||
set -l desc
|
||||
set -l files
|
||||
set -l prefix ""
|
||||
|
||||
switch (count $argv)
|
||||
|
||||
case 1
|
||||
set comp (commandline -ct)
|
||||
set suff $argv
|
||||
set desc ""
|
||||
|
||||
case 2
|
||||
set comp $argv[1]
|
||||
set suff $argv[2]
|
||||
set desc ""
|
||||
|
||||
case 3
|
||||
set comp $argv[1]
|
||||
set suff $argv[2]
|
||||
set desc $argv[3]
|
||||
|
||||
case 4
|
||||
set comp $argv[1]
|
||||
set suff $argv[2]
|
||||
set desc $argv[3]
|
||||
set prefix $argv[4]
|
||||
|
||||
# Only directories are supported as prefixes, and to use the same logic
|
||||
# for both absolute prefixed paths and relative non-prefixed paths, $prefix
|
||||
# must terminate in a `/` if it is present, so it can be unconditionally
|
||||
# prefixed to any path to get the desired result.
|
||||
if not string match -qr '/$' $prefix
|
||||
set prefix $prefix/
|
||||
end
|
||||
end
|
||||
set -l suff (string escape --style=regex -- $argv)
|
||||
|
||||
# Simple and common case: no prefix, just complete normally and sort matching files first.
|
||||
if test -z $prefix
|
||||
set -l suffix (string escape --style=regex -- $suff)
|
||||
if test -z $_flag_prefix
|
||||
# Use normal file completions.
|
||||
set files (complete -C "__fish_command_without_completions $comp")
|
||||
set -l files_with_suffix (string match -r -- "^.*$suffix\$" $files)
|
||||
set files (complete -C "__fish_command_without_completions $_flag_complete")
|
||||
set -l files_with_suffix (string match -r -- (string join "|" "^.*"$suff\$) $files)
|
||||
set -l directories (string match -r -- '^.*/$' $files)
|
||||
set files $files_with_suffix $directories $files
|
||||
else
|
||||
# Only directories are supported as prefixes, and to use the same logic
|
||||
# for both absolute prefixed paths and relative non-prefixed paths, $_flag_prefix
|
||||
# must terminate in a `/` if it is present, so it can be unconditionally
|
||||
# prefixed to any path to get the desired result.
|
||||
if not string match -qr '/$' $_flag_prefix
|
||||
set _flag_prefix $_flag_prefix/
|
||||
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 base $_flag_prefix(string replace -r '^("\')?\\./' '' -- $_flag_complete | string trim -c '\'"') # " make emacs syntax highlighting happy
|
||||
|
||||
set -l all
|
||||
set -l files_with_suffix
|
||||
set -l dirs
|
||||
# If $comp is "./ma" and the file is "main.py", we'll catch that case here,
|
||||
# If $_flag_complete 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 files_with_suffix (string match -r -- ".*"(string escape --style=regex -- $suff) $all)
|
||||
if not string match -qr '/$' -- $suff
|
||||
set files_with_suffix (string match -r -- (string join "|" ".*"$suff) $all)
|
||||
if not string match -qr '/$' -- $argv
|
||||
set dirs $base*/
|
||||
|
||||
# The problem is that we now have each directory included twice in the output,
|
||||
@@ -88,7 +61,7 @@ function __fish_complete_suffix -d "Complete using files"
|
||||
end
|
||||
|
||||
set files $files_with_suffix $dirs $all
|
||||
if string match -qr '^\\./' -- $comp
|
||||
if string match -qr '^\\./' -- $_flag_complete
|
||||
set files ./$files
|
||||
else
|
||||
# "Escape" files starting with a literal dash `-` with a `./`
|
||||
@@ -97,14 +70,14 @@ function __fish_complete_suffix -d "Complete using files"
|
||||
end
|
||||
|
||||
if set -q files[1]
|
||||
if string match -qr -- . "$desc"
|
||||
set desc "\t$desc"
|
||||
if string match -qr -- . "$_flag_description"
|
||||
set _flag_description "\t$_flag_description"
|
||||
end
|
||||
if string match -qr -- . "$prefix"
|
||||
set prefix (string escape --style=regex -- $prefix)
|
||||
if string match -qr -- . "$_flag_prefix"
|
||||
set prefix (string escape --style=regex -- $_flag_prefix)
|
||||
set files (string replace -r -- "^$prefix" "" $files)
|
||||
end
|
||||
printf "%s$desc\n" $files
|
||||
printf "%s$_flag_description\n" $files
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user