「Bash」- 自动补全功能(Bash Completion)

问题描述

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

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

解决方案

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

以 Bash 为例

因为大多数的 Shell 都是差不多的,实现上有很多类似的地方。我们平时主要使用的 Shell 也是 Bash,所以就说说 Bash 吧;

必须指出的是TAB键通常发送 ASCII 的Control-I字符。因为控制字符Control-ITAB键的 ASCII 值是对应的都是9,所以你在终端中按下TAB键的效果和Ctrl-I的效果是一样的;

Control-I字符绑定在compete函数上。这一点可以通过bind -p | grep -F '\C-i‘命令看到。bindcomplete都是 Bash 中内建的函数,可以使用help bindhelp 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 能否使用补全功能?」这个问题才重新整理了这篇文章。下面是问题的内容:

在 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 能否使用补全功能?
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?