关于bash的自动完成
为了庆祝新博客落成,先来发篇技术类文章。
这篇文章是我9月17日写的。因为写了以后没地方发,所以极大的推动了现在这个博客Feelyblog 2.0的编码进度。
Bash中的Tab自动补全
今天在开发一个命令行工具,由于子命令很多,我又懒得记。平常自己是Tab党嘛,那么如何让自己的命令行工具支持Tab自动补全呢。
bash中有两个内置命令,complete
和compgen
,前者用于给bash注册补全函数,后者用于从输入片段和列表中找出匹配的补全选项。
所以要做bash补全的话,只需要写一个补全函数,用complete
命令指定,然后把这个脚本扔到/etc/bash_completion.d/
下面就可以了。
compgen
在说这个脚本怎么写之前,我们先来说下compgen
这个命令。
1 | compgen -W "create clean delete drop" -- "d" |
所以compgen
最基本的用法就是 compgen -W "候选词列表" -- "待补全词"
有种情况特别常用,就是需要补全的内容是文件。这种用法如下:
1 | compgen -f -- "待补全词" |
complete
这个命令就特别简单了,用法如下
1 | complete -F 补全函数 待补全命令 |
比如说我写了一个bash函数名称为 _foo()
,我的命令行工具叫 foo1
和foo
,都要用这个补全函数,于是我就可以这么定义:
1 | complete -F _foo foo1 foo |
补全函数
前面两个命令说完了接下来就轮到重点了。如何写这个补全函数。
其实这里是有一些系统预定义好的一些变量的:
COMP_WORDS
数组,存放当前命令行中输入的所有单词;COMP_CWORD
整数,当前光标下输入的单词位于COMP_WORDS
数组中的索引COMPREPLY
数组,候选的补全结果COMP_WORDBREAKS
字符串,表示单词之间的分隔符COMP_LINE
字符串,表示当前的命令行输入
简单的说就是我们根据上下文和compgen
计算出需要的补全结果,赋值给COMPREPLY
数组,然后return 0
就可以了。
下面是一个例子:
假设我的命令行工具是这样的:
foo {create|clean|delete|help|version} --参数名 参数值
create 的时候可用的参数: --name
标题 -c, --config
配置文件 -y, --assumeyes
忽略询问
clean,delete 的时候可用的参数: --name
标题
help,version 直接输出并退出,没有二级参数
1 | function _a() { |
把上面这个文件保存成foo后存到/etc/bash_completion.d
去就可以了。
当然一般的方法是链接过去。这样不需要你计算机里有多个这个脚本的副本。
当然如果这个工具更加复杂,也可以写出更加复杂的补全脚本来。
如果安装了git可以打开/etc/bash_completion.d/git
文件,这是git的补全脚本,当然也相当复杂。