「Bash」- 自动补全功能 | Bash Completion

该笔记将记录:在 Bash 中,与自动补全(Bash Completion)有关的内容,以及相关问题处理;

描述

Bash Completion,是个 Bash 特性(其他 Shell 也支持),只需轻点几下 TAB 即可实现复杂的命令行选项提示,而无需我们输出复杂、冗长的命令。

文档 | https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html

原理

因为大多数的 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 函数;

应用

通过 TAB 实现自动补全。

改进

如何扩展 Bash 自动补全

默认的自动补全功能有限,基本上只有命令、路径、目录的补全,但是可以扩展自动补全功能,使其支持命令行选项的扩展。

在终端下,命令 CMD 自动补全提示功能(<TAB><TAB>)在 Bash Completion 软件包中;

这个就不介绍如何扩展自动补全,有兴趣可以参考以下两篇文章:
1)An introduction to bash completion: part 1
2)An introduction to bash completion: part 2

一来没有遇到去完善自动补全的必要,二来我们有 Bash Completion 软件包;

sftp 能否使用补全功能?

为了回答「sftp 能否使用补全功能?」这个问题才重新整理了这篇文章。下面是问题的内容:

在 ssh 下,以及 windows 的 powershell、macOS 的 terminal,都是可以按 tab 键自动补全的,那 sftp 为什么没有这个功能,还是说被隐藏了?有没有可能让它加入这个功能?

下面是我们当时的回答:

在终端里的自动补全功能,它是由所使用的 Shell 提供的,而不是由软件自身提供:

在 macOS 中,Terminal 加载的 Shell 是 Bash,而自动补全功能则是由 Bash 提供的,而不是由什么 sftp 提供的;

在 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 能否使用补全功能?
Wikipedia/Tab key
.inputrc, TAB and CTRL-i
Control codes – converting to ASCII, Hex or Decimal
How does bash tab completion work?