问题描述
Bash Completion,是个 Bash 特性(其他 Shell 也支持),只需轻点几下 TAB 即可实现复杂的命令行选项提示,而无需我们输出复杂、冗长的命令。
该笔记将记录:在 Bash 中,与自动补全(Bash Completion)有关的内容,以及相关问题处理。
解决方案
以 Bash 为例
因为大多数的Shell都是差不多的,实现上有很多类似的地方。我们平时主要使用的 Shell 也是 Bash,所以就说说 Bash 吧。
必须指出的是TAB键通常发送ASCII的Control-I字符。因为控制字符Control-I和TAB键的ASCII值是对应的都是9,所以你在终端中按下TAB键的效果和Ctrl-I的效果是一样的。
而Control-I字符绑定在compete函数上。这一点可以通过bind -p | grep -F '\C-i‘命令看到。bind和complete都是Bash中内建的函数,可以使用help bind和help complete命令查看手册。实际上complete是自动补全的关键,当你去看「GitHub/scop/bash-completion/completions/」中的自动补全脚本的时候,你会发现大量的compete -F调用,后面会介绍Bash Completion是什么。
所以,当你按下 TAB 键时,向 Bash 发送了 Control-I 字符,收到该字符后 Bash 执行 complete 函数。
如何扩展 Bash 自动补全
默认的自动补全功能有限,基本上只有命令、路径、目录的补全,但是可以扩展自动补全功能,使其支持命令行选项的扩展。
这个就不介绍如何扩展自动补全,有兴趣可以参考以下两篇文章:
1)An introduction to bash completion: part 1
2)An introduction to bash completion: part 2
一来没有遇到去完善自动补全的必要,二来我们有 Bash Completion 软件包。
关于 Bash Completion 软件
默认的自动补全仅能进行简单的自动补全,比如文件目录路径。该软件包扩展 Bash 的自动补全功能,它能满足我们的大多数需要。
项目地址:scop/bash-completion: Programmable completion functions for bash
安装方法:1)参考源码目录下的 README.md 文件;2)或者直接使用包管理器安装(各个 Linux 发行版已经包含该软件包,但是版本可能较旧)
常见问题汇总
我们应该将第三方补全脚本安装到哪里?
根据官方文档,我们能够:
1)保存在 ~/.local/share/bash-completion/completions/ 目录中;
2)也可以在 ~/.bash_completion 中添加自定义脚本;
sftp能否使用补全功能?
为了回答「sftp能否使用补全功能?」这个问题才重新整理了这篇文章。下面是问题的内容:
下面是我们当时的回答:
在终端里的自动补全功能,它是由所使用的Shell提供的,而不是由软件自身提供:
在Windows中,我们没了解过PowerShell,但是我们推侧道理是一样的。因为,如果自动补全是软件实现的,那每个软件作者都要实现自动补全功能,在按TAB键的时候,处理程序逻辑,这……所以,我们才觉得道理是一样的。(在说这段话的时候,我们搜索到了「How to make PowerShell tab completion work like Bash」一文,所以基本可以断定是PowerShell提供的自动补全功能)
在Linux下,这就不用说了,所使用的Shell也是Bash、Dash之类的,与在macOS下的情况是类似的。
还有一点,“在ssh下”,当SSH到远程主机(假设是Linux系统)后,实际上的自动补全是由远程主机Shell(可能是Bash、Dash等等)提供的,这时的自动补全和本地的Shell没啥关系了。
(当然,大多数情况是这样的。但是,如果软件作者非要自己实现自动补全功能,那我们还能说啥……)
如果想让 Bash 支持 sftp 的自动补全,那么需要:
1)自己扩展Bash的自动补全(参考下面「如何扩展Bash的自动补全」部分的指引);
2)或者到「GitHub/bash-complete」项目里提需求;
3)或者自己完善「GitHub/bash-complete/completions/ssh」文件,这个文件提供了对sftp的支持。
参考文献
知乎/sftp能否使用补全功能?
Bash Completion Homepage
An easy bash completion tutorial?
GitHub/scop/bash-completion
Wikipedia/Tab key
.inputrc, TAB and CTRL-i
Control codes – converting to ASCII, Hex or Decimal
How does bash tab completion work?