基于文件扩展名的fish选项卡完成

huangapple go评论112阅读模式
英文:

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 "/").

huangapple
  • 本文由 发表于 2023年6月26日 12:01:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76553442.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定