fish 自动补全子命令
fish 自动补全子命令
之前在 「创建 fish shell 自动补全文件」 中介绍了如何创建 fish 的补全文件,实现对命令的友好补全提示。通过形如 complete -c <command> -a ["参数列表"]
的脚本来实现的。
比如 complete -c myprog -a "yes no"
可在输入 myprog
后通过 TAB 唤起提示:
$ myprog<tab>
no yes
但如果 <comamnd>
包含子命令时,则需要麻烦些。比如拿 git commit
来说,为了实现在输入该命令时提示一些信息,实测如下形式是不行的:
complete -c git-commit -a "yes no"
complete -c "git commit" -a "yes no"
同时,想要实现 git commit -m<TAB>
在进行 git 提交时,进行一些提示,除了需要解决上面子命令判定的问题,还需要判定这里的 -m
参数。
判断子命令
查看 fish 在 GitHub 的仓库可发现,在 fish-shell/share/functions/
目录下提供了很多工具方法, 通过 __fish_seen_subcommand_from
配合 complete
的 -n
参数可实现子命令的判定。
该工具方法需要结合 -n
(condition)参数,指定一段 shell 脚本,当脚本返回 0 时所指定的自动补全才生效。
complete -f -c git -n '__fish_seen_subcommand_from commit' -a 'test' -d "the test command will appear after commit"
上述脚本实现的效果,是在输入 git commit
之后,TAB 会触发 test
命令的自动补全,当且仅当 git
后跟的是 commit
这个子命令。
-s
-l
的用法
一般命令会需要带参数,这些参数或是通过 -
加缩写或 --
加完整的参数名称提供。通过 -s
(short)、 -l
(long) 便可指定命令需要补全的参数名称。
complete -f -c git -n '__fish_seen_subcommand_from commit' -s m --l message -d "specify the commit message"
complete -f -c git -n '__fish_seen_subcommand_from commit' -s f --l foo -d "argument foo"
complete -f -c git -n '__fish_seen_subcommand_from commit' -s b --l bar -d "argument bar"
complete -f -c git -n '__fish_seen_subcommand_from commit' -s b --l baz -d "argument baz"
complete -f -c git -n '__fish_seen_subcommand_from commit' -s b --l quz -d "argument quz"
上述脚本实现的效果是,在输入 git commit -<TAB>
后,参数列表会作为候选补全列出来:
$ git commit -
-b --quz (argument quz) -m --message (specify the commit message) --baz (argument baz)
-f --foo (argument foo) --bar (argument bar)
可以看到,默认情况下,这些参数按字母顺序进行了重排,可通过 -k
(keep order) 来保持书写时指定的顺序。-k
参数对于 -a
指定的命令也适用。
判定参数
通过 __fish_seen_argument
工具方法,可判定输入的命令后有没有跟指定参数。
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'build' -d "Changes that affect the build system or \r\ntexternal dependencies (example scopes: gulp, broccoli, npm)"
这里判定参数的写法,和前面 -s
-l
中介绍的一致。
上述脚本实现的效果是,当输入 git commit -m<TAB>
时会自动补上 build
命令。
到这里就完成了子命令和参数的判定。接下来,就可以用于一些实用的场景,比如 Angular 的提交消息规定了如下的形式:
<type>(<scope>): <short summary>
其中 <type>
包含如下可选值:
- build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
- ci: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
- docs: Documentation only changes
- feat: A new feature
- fix: A bug fix
- perf: A code change that improves performance
- refactor: A code change that neither fixes a bug nor adds a feature
- test: Adding missing tests or correcting existing tests
可通过前面介绍的方法,将这里的 type 在进行 git commit 时给提示出来。
实现 Angular commit type 的自动提示
最后,实现这一效果的脚本大概是这样子:
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'build' -d "Changes that affect the build system or \r\ntexternal dependencies (example scopes: gulp, broccoli, npm)"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'ci' -d "Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'docs' -d "Documentation only changes"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'feat' -d "A new feature"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'fix' -d "A bug fix"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'perf' -d "A code change that improves performance"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'refactor' -d "A code change that neither fixes a bug nor adds a feature"
complete -k -f -c git -n '__fish_seen_subcommand_from commit; and __fish_seen_argument -s m -l message' -a 'test' -d "Adding missing tests or correcting existing tests"
相关仓库 👉 wayou/angular-commit-complete。