完成没有根的文件名,只有扩展名(隐藏文件)
Completion for filenames without root, only extension (hidden files)
我正在尝试为一个命令编写完成,该命令采用没有 root/base 部分的文件名,只有扩展名(例如“foo/.ext”)。隐藏文件。 (具体来说,direnv 的“.envrc”。)
在 fish 的安装中有几个示例可以使用
__fish_complete_suffix for files that have a root and extension, such as 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`
我正在尝试为一个命令编写完成,该命令采用没有 root/base 部分的文件名,只有扩展名(例如“foo/.ext”)。隐藏文件。 (具体来说,direnv 的“.envrc”。)
在 fish 的安装中有几个示例可以使用 __fish_complete_suffix for files that have a root and extension, such as 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`