#自动补全 的教程

看到一片很有用的文章,就直接摘抄下来了,原网址在这
注:本文有些我个人理解,可能会有错误,若有人发现望告知纠正。

知识点梳理:
内置补全变量表:

变量名 功能
COMP_WORDS 类型为数组,存放当前命令行中输入的所有单词
COMPREPLY 类型为数组,候选的补全结果
COMP_WORDBREAKS 类型为字符串,表示单词之间的分隔符
COMP_LINE 类型为字符串,表示当前的命令行输入字符
COMP_POINT 类型为整数,表示光标在当前命令行的哪个位置

[示例代码0]

# 脚本1: vtb.bash
_vtb()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "mea aqua alice" -- $cur) )
}
complete -F _vtb vtb
个人笔记

vtb.bash 这个文件名看起来作用有点像 ~/.bashrc ?
虽然我不知道这个文件的专业说法叫什么,但「alias」指令创建的快捷方式貌似就写在「~/.bashrc」里面
感觉像是记录指令快捷方式的文件(指 ~/.bashrc 文件)

[使用方式0]

> chmod +x vtb.bash
> source vtb.bash
> vtb <TAB> <TAB>
alice  aqua   mea
> vtb a <TAB> <TAB>
alice  aqua

代码拆解分析:

代码compgen -W

脚本1(就是「示例代码0」)_vtb函数中,我们首先定义了cur(个人吐槽:老是会想到「curl」指令怎么办)变量用于获取当前光标所在位置的单词,将其作为参数传递给compgen -W命令。该命令接受两个参数,定义与使用方式如下:
[示例代码1]

# compgen -W <word_list> <comp_word>
> compgen -W "aqua alice mea" -- a  # 省略‘--’则不会输出多行
aqua
alice

compgen命令的作用是完成候选词的筛选-W模式代表从<word_list>中获得候选词,然后通过<comp_word>参数对候选词进行筛选,最后我们将筛选得到的结果存入COMPREPLY数组中。

个人笔记

看起来compgen -W后面跟的就是自动补全的列表,用空格分隔(吐槽:好像一句废话,上面有写)

代码complete -F

我们在脚本1中使用了complete命令的-F模式让vtb命令能够获取_vtb函数中的候选补全结果COMPREPLY,其本质就是完成候选词的绑定。我们先以简单的-W模式为例进行讲解,其定义与使用方式如下:
[使用方式1]

# complete -W <word_list> <comp_cmd>
> complete -W "aa ab cd" test_comp
> test_comp <TAB> <TAB>
aa    ab    cd
> test_comp a <TAB> <TAB>
aa    ab

complete命令可以给<comp_cmd>绑定候选词列表,根据不同的命令模式(-F -W -C -G)会有不同的构建候选词列表的方式。-W模式通过字符串构建候选词列表,而-F模式需要使用COMPREPLY构造候选词列表,其定义与使用方式如下:

complete -F <func_name> <comp_cmd>     # 绑定候选词列表
<comp_cmd> <comp_word> <TAB> <TAB>     # 筛选候选词列表

该命令可以实现<func_name><comp_cmd>的绑定,<func_name>函数中必须通过COMPREPLY构造候选词列表,而是否使用compgen或其他方式进行候选词筛选取决于业务逻辑。相比于其他模式,-F模式能够提供更灵活的自动补全策略,以脚本1为例,我们通过组合使用compgencomplete和内置补全变量实现了类似-W模式的功能。

个人笔记

1.看起来这应该是个终端窗口,前面的>就是下一行指令(那是不是换成$会更好?)(吐槽:我闲的没事干分析这个干嘛?)
2.complete -W是和字符串绑定(助记:W=Word);complete -F是和函数绑定(助记:F=Function)
(注:如何与函数绑定是「示例代码0」,在最上面)

疑问

1.「示例代码0」的文件名一定是 vtb.bash 吗?修改了会对程序的运行有什么影响吗?
2.在「示例代码1」中第二行的第一个符号>有什么作用?

1 个赞
  1. 文件名就是命令名,可以根据自己的喜好命名,修改了之后相应的complete -F 绑定的命令名也要修改,出于代码可读性的原因,相应的补全函数名也要修改。
  2. 这个>大概只是一种指示(给读者看的),表示这一行是由用户输入的命令。

顺便说一句,使用bash-completion提供的api来编写自动补全效果更好。