自定义Bash自动完成

Bash的自动完成功能很爽,它不知道免掉我多少记忆的负担,节约了多少键盘操作。 但是对于我们自己写的脚本也能够利用它的自动完成功能吗?回答是肯定的。下面以几个例子来说明。

程序员需要记忆很多东西,bash, vi, screen, svn都有很多命令和快捷键,偏偏我的记忆力不行,不时查看cheatsheet,每次都cd到某个目录,从一大堆文件中找到那个文件,然后再打开,这个过程显然很烦琐。所以我写了一个脚本,叫做quickref,它接收一个参数,例如bash, vi,然后就会打开对应的cheatsheet。
quickref:
#!/bin/bash

case $1 in
	bash)
		exo-open ~/dropbox/cheatsheets/bash/bash_cheat_sheet.pdf
		;;
	vi)
		exo-open ~/dropbox/cheatsheets/vi_cheat_sheet.pdf
		;;
	# more...
esac

exo-open是xubuntu下的命令,它自动用文件关联的应用程序打开, 例如, pdf文件就会用evince打开。ubuntu下对应的命令是gnome-open。

如果只有bash, vi的cheatsheet,一切不成问题,但是当列表越来越长,问题就来,你不知道你的命令能够接受哪些参数,输入命令时你得考虑,我该输入什么呢?可能还得来回折腾几次,最坏的情况,你可能需要查看源代码才能确定你到底能输入什么。你可以将它们显示在出错消息中,这样可以节省一些功夫,但总不太好。我们可以利用Bash的自动完成功能,我不再担心会输入错误。

我们直接来看怎么做,建立一个文件quickref_completion, 输入以下内容:
_quickref_completion()
{
	local cur
	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	COMPREPLY=($( compgen -W 'bash vi' -- $cur ))

	return 0
}
complete -F _quickref_completion quickref

然后执行命令". quickref_complection",然后再在bash下输入"quickref ",然后再按Tab(或许得按两次Tab),你会发现bash自动列出所有匹配的結果,下面是我的机器上的显示結果:
$ quickref
bash  vi
$ quickref

怎么实现的呢?其实很简单,_quickref_completion函数用来完成主要的功能,前三行用来得到用户当前的输入,全部补全的結果放在COMPREPLY数组中。这里补全的功能由compgen命令来完成,它完成的功能就是从单词列表中选出匹配给定前缀的所有单词,你最后在命令行下测试一下:
$ compgen -W "find fine hello"
find
fine
hello
$ compgen -W "find fine hello" fi
find
fine

最后complete命令用来注册自动补全函数,第一个参数就是自动补全的函数,后面的参数是应用这个补全函数的所有命令。执行quickref_completion的操作最好放在bashrc中去。

再一个例子,我经常用到命令"sudo apt-get install"命令,所以我给它定义了一个别名:"alias pkginstall='sudo apt-get install'",但这样不好的是,你不能再利用apt-get install的自动完成功能。另外我也定义了别名"alias pkgremove='sudo apt-get remove", 我为它们写了自动补全的函数:
_pkginstall_completion()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	COMPREPLY=( $( apt-cache pkgnames -- $cur ) )
}
complete -F _pkginstall_completion pkginstall

_pkgremove_completion()
{
	local cur

	COMPREPLY=()
	cur=${COMP_WORDS[COMP_CWORD]}
	COMPREPLY=( $( dpkg -l | awk '{ print $2 }' | grep "^${cur}" ) )
}
complete -F _pkgremove_completion pkgremove

代码就不再解释了,很简单,至于用到的命令,不熟悉的在命令行下试试就知道了。

当然这里所介绍的只是十分简单,但于我已经够用了,至少到目前为止是这样。但要完成更加复杂的功能,例如对于不同的选项,使用不同的命令完成,例如apt-get install和apt-get remove的自动补全就不一样,你可能需要参考其它文章。/etc/complete.d/目录下有很多补全函数的实现,你可以拿来看一下。也可能参考官方文章 Programmable-Completion.

你可能感兴趣的:(SVN,F#,ubuntu,脚本,bash)