问题描述
我正在尝试为一个命令编写一个完成,该命令的文件名没有根/基本部分,只有扩展名(例如“foo/.ext”)。隐藏文件。 (特别是 direnv 的“.envrc”。)
在fish的安装中有几个例子可以使用 __fish_complete_suffix 用于具有根 和 扩展名的文件,例如 fish 本身:
complete -c fish -k -x -a "(__fish_complete_suffix .fish)"
# completions/foo.fish
complete -c foo -k -x -a "(__fish_complete_suffix .bar)"
# functions/foo.fish
function foo
echo $argv
end
> mkdir -p a/b; touch a/1.bar a/2.bar a/.bar
> foo a/<TAB>
a/1.bar a/2.bar a/b/
有没有办法用这个或其他一些功能来实现这一点?
解决方法
fish doesn't add hidden files to the list of completions unless the token being completed 已经以“.
”开头。
您应该能够编写满足您要求的自定义完成,但不幸的是 long-standing bug 使这变得不可能。
,我在这上面花了太多时间,它可能过于复杂,可能需要优化和简化,但它几乎适用于所有情况。一个没有的情况是@Zanchey 提到的突出错误。
# completions/foo.fish
complete -c foo -k -x -a "(__fish_complete_dotfile_or_subdirectories .bar)"
function __fish_complete_dotfile_or_subdirectories -d "Complete dotfile or directories"
set -l token
set -l suffix
switch (count $argv)
case 1
set token (commandline -ct)
set suffix $argv
case 2
set token $argv[1]
set suffix $argv[2]
end
set -l suffix_len (string length $suffix)
# trim leading . from suffix if present
if test (string sub -l 1 $suffix) = "."
set suffix_len (math $suffix_len - 1)
set suffix (string sub -l $suffix_len -s "-"$suffix_len $suffix)
end
set -l root_name (string split -rm 1 "/" $token)
set -l root $root_name[1..-2]"/"
set -l name $root_name[-1]
# build regex
# $suffix = foo -> '^(?:|\.|\.f|\.fo|\.foo)$'
# $suffix = bar -> '^(?:|\.|\.b|\.ba|\.bar)$'
set -l re (
echo -n "^(?:|\."
for i in (seq $suffix_len)
echo -n "|\."(string sub -l $i $suffix)
end
echo ')$'
)
if string match -qr $re "$name"
set -l i
if test -n "$root"
set i (printf "%s.%s" $root $suffix)
else
set i (printf ".%s" $suffix)
end
if test -f "$i"
printf "%s\n" $i
end
end
# all subdirs except . and ..
for i in (complete -C "nonexistentcommand $token" |
string match -er '[^\.]/$')
printf "%s\n" $i
end
end
*(complete -C ...
行 inspiration)
> mkdir -p a/{.a1,.a2,b1,b2,.b3,.b4} c
> touch .bar .baz a/.bar a/.baz a/foo.bar c/.bar
> tree -aF
.
├── a/
│ ├── .a1/
│ ├── .a2/
│ ├── b1/
│ ├── b2/
│ ├── .b3/
│ ├── .b4/
│ ├── .bar
│ ├── .baz
│ └── foo.bar
├── .bar
├── .baz
└── c/
└── .bar
> foo <TAB>
> __fish_complete_dotfile_or_subdirectories "" bar
.bar # .bar is included ...
a/
c/
> foo <TAB>
a/ c/ # ... but is not here because of the long-standing bug
> foo .<TAB> # completes to `foo .bar`
> foo ./<TAB>
./.bar ./a/ ./c/ # now it's included
> foo ./.<TAB> # completes to `foo ./.bar`
> foo a<TAB> # completes to `foo a/`
> foo a/<TAB>
a/.bar a/b1/ a/b2/
> foo a/.<TAB>
a/.bar a/.a1/ a/.a2/ a/.b3/ a/.b4/
> foo a/.b<TAB>
a/.bar a/.b3/ a/.b4/
> foo a/.ba<TAB> # completes to `foo a/.bar`
> foo c<TAB> # completes to `foo c/`
> foo c/<TAB> # completes to `foo c/.bar`