英文:
fish tab completion based on file extension
问题
在fish中是否可以实现类似以下bash命令的tab自动补全功能:
complete -f -X '!*.bar' foo
英文:
I have a command foo
that can only run *.bar
files. I would like to implement tab completion for foo
such that only *.bar
files are listed as options. In bash, this would look like:
complete -f -X '!*.bar' foo
Is it possible to do this in fish?
答案1
得分: 4
根据文件扩展名完成可能是一个吸引人的陷阱。你认为你想要它,但大多数情况下它是错误的。大多数通常使用特定扩展名的文件的程序也会愉快地与其他文件一起工作,如果它们不工作,那就是一个奇怪的限制,可以轻松地移除。
如果你将完成限制在特定的扩展名上,然后需要没有这种扩展名的文件,那将很难使用。
Fish提供了一个名为__fish_complete_suffix
的辅助函数,它会首先排序所需的扩展名。你可以像这样使用它:
complete -c patch -s i -l input -x -k -a "(__fish_complete_suffix .patch .diff)";
这告诉Fish要完成patch
命令的-i
或--input
选项,该选项需要一个参数,但不是通过Fish的内置文件完成(这是-x
标志),并保持完成的顺序(-k
/--keep-order
)。要生成完成,它运行了__fish_complete_suffix .patch .diff
,这会首先对.patch和.diff文件进行排序。
你可以根据你的命令进行调整:
complete -c foo -x -k -a "( __fish_complete_suffix .bar)";
如果你确信你的命令需要文件名为".bar",你也可以使用类似下面的方法自己生成完成:
complete -c foo -f -a '(complete -C"'' $(commandline -ct)" | string match -re "(?:/|.bar)$")';
这告诉Fish禁用内置的文件完成(-f
),然后匹配以".bar"或"/"结尾的文件(通过手动运行文件完成来完成命令''
),这样你就可以得到可能包含".bar"文件的目录。你也可以尝试在任何地方匹配.bar文件,但通常这是非常昂贵的 - 想象一下如果你尝试在文件系统根目录("/"的$PWD)中运行这个命令。
英文:
Completing based on file extension is an attractive nuisance. You think you want it, but most of the time it is wrong. Most programs that typically use files with a specific extension will also happily work with others, and if they don't that's a weird restriction that could just as well be removed.
And if you restrict your completions to a specific extension and then need files without that's awkward to use.
Fish ships a helper function called __fish_complete_suffix
that instead sorts the wanted extensions first. You would use it like this:
complete -c patch -s i -l input -x -k -a "(__fish_complete_suffix .patch .diff)"
This tells fish to complete the command patch
with a -i
or --input
option which requires an argument but not via fish's builtin file completion (that's the -x
flag), and keeps whatever order the completions were generated in (-k
/--keep-order
). To generate the completions, it runs __fish_complete_suffix .patch .diff
, which sorts .patch and .diff files first.
You could adapt this to your command with:
complete -c foo -x -k -a "( __fish_complete_suffix .bar)"
If you really are sure that your command needs the file to be called ".bar", you can also generate this yourself with something like
complete -c foo -f -a '(complete -C"\'\' $(commandline -ct)" | string match -re "(?:/|.bar)$")'
This tells fish to disable the builtin file completions (-f
), and then matches files (by running the file completions by hand by asking it to complete the command ''
) ending in ".bar" or "/", so you get directories that might contain ".bar" files. You could also try to match .bar files everywhere, but that's prohibitively expensive typically - imagine if you try to run this in the filesystem root ($PWD of "/").
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论