diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 11d692483..7accb82ac 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -251,6 +251,7 @@ Completions - Lots of improvements to completions. - Improvements to the manpage completion generator (:issue:`7086`). - Significant performance improvements to completion of the available commands (:issue:`7153`). +- ``__fish_complete_suffix`` completes any file but sorts files with matching suffix first (:issue:`7040`). Previously, it only completed files with matching suffix. Deprecations and removed features --------------------------------- diff --git a/doc_src/completions.rst b/doc_src/completions.rst index b4624780d..4731af5ef 100644 --- a/doc_src/completions.rst +++ b/doc_src/completions.rst @@ -83,7 +83,7 @@ Functions beginning with the string ``__fish_print_`` print a newline separated - ``__fish_complete_pids`` prints a list of all processes IDs with the command name as description. -- ``__fish_complete_suffix SUFFIX`` performs file completion allowing only files ending in SUFFIX, with an optional description. +- ``__fish_complete_suffix SUFFIX`` performs file completion but sorts files ending in SUFFIX first. This is useful in conjunction with ``complete --keep-order``. - ``__fish_complete_users`` prints a list of all users with their full name as description. diff --git a/share/functions/__fish_complete_suffix.fish b/share/functions/__fish_complete_suffix.fish index 5d0402dd8..37bef4648 100644 --- a/share/functions/__fish_complete_suffix.fish +++ b/share/functions/__fish_complete_suffix.fish @@ -1,10 +1,11 @@ # -# Find files that complete $argv[1], has the suffix $argv[2], and -# output them as completions with the optional description $argv[3] 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. -# +# 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. function __fish_complete_suffix -d "Complete using files" @@ -48,17 +49,21 @@ function __fish_complete_suffix -d "Complete using files" end end - # Simple and common case: no prefix, just complete normally and filter out unwanted suffixes. + # 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) # Use normal file completions. - set files (complete -C "__fish_command_without_completions $comp" | string match -r "^.*(?:$suffix|/)\$") + set files (complete -C "__fish_command_without_completions $comp") + set -l files_with_suffix (string match -r -- "^.*$suffix\$" $files) + set -l directories (string match -r -- '^.*/$' $files) + set files $files_with_suffix $directories $files else # 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 files_with_suffix 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 @@ -67,7 +72,7 @@ function __fish_complete_suffix -d "Complete using files" # 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) + set files_with_suffix (string match -r -- ".*"(string escape --style=regex -- $suff) $all) if not string match -qr '/$' -- $suff set dirs $base*/ @@ -82,7 +87,7 @@ function __fish_complete_suffix -d "Complete using files" end end - set files $all $dirs + set files $files_with_suffix $dirs $all if string match -qr '^\\./' -- $comp set files ./$files else