mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-26 10:43:47 +08:00
c2970f9618
This runs build_tools/style.fish, which runs clang-format on C++, fish_indent on fish and (new) black on python. If anything is wrong with the formatting, we should fix the tools, but automated formatting is worth it.
108 lines
3.7 KiB
Fish
108 lines
3.7 KiB
Fish
#
|
|
# 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.
|
|
#
|
|
|
|
function __fish_complete_suffix -d "Complete using files"
|
|
|
|
# Variable declarations
|
|
|
|
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
|
|
|
|
# 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
|
|
# echo "base: $base" > /dev/tty
|
|
# echo "suffix: $suff" > /dev/tty
|
|
|
|
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. `eval` is used since $suff may be passed in
|
|
# as {.foo,.bar} and we want to expand that.
|
|
eval "set all $base*$suff"
|
|
if not string match -qr '/$' -- $suff
|
|
eval "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
|
|
end
|
|
|
|
# Another problem is that expanded paths are not matched, either.
|
|
# So an expression like $HOME/foo*.zip will expand to /home/rdahl/foo-bar.zip
|
|
# but that no longer matches the expression at the command line.
|
|
if string match -qr '[${}*~]' -- $comp
|
|
set -l expanded
|
|
eval "set expanded $comp"
|
|
set files (string replace -- $expanded $comp $files)
|
|
end
|
|
|
|
if set -q files[1]
|
|
if string match -qr -- . "$desc"
|
|
set desc "\t$desc"
|
|
end
|
|
if string match -qr -- . "$prefix"
|
|
# Ideally, only replace in the beginning of the string, but we have no
|
|
# way of doing a pcre2 escape so we can use a regex replace instead
|
|
set files (string replace $prefix "" $files)
|
|
end
|
|
printf "%s$desc\n" $files #| sort -u
|
|
end
|
|
|
|
end
|