简介
项目路径
- https://github.com/scop/bash-completion/
本文描述的内容可能因为
bash
版本差异, 执行会有细微差异;
什么是补全
补全规则
补全规则选择
补全规则生成候选项
生成集合: 根据拼写一截的补全; 比如
git sta
就有补全stage stash status
;根据sta
过滤;-f -d
生成集合会被FIGNORE
过滤;比如
-G "*.sh"
, 这个就是文件扩张生成当前目录下sh
结尾的文件; 不会被sta
这种影响, 会全部纳入; 但是受到FIGNORE
的影响;
-W "hello world $PATH"
, 进行bash
的扩张后生成的字符串, 再进行bash
分词规则生成字符串集合;git sta
会从过滤集合中过滤前缀sta
的集合;-W
某些场景完全可以替代; 差距就是是否需要对集合过滤;
-F -C
: 会生成变量;COMP_LINE, COMP_POINT, COMP_KEY, COMP_TYPE
;-F
还会生成COMP_WORDS, COMP_CWORD
; 入参:$1
指令名,$2
补全名, 如sta
;$3
不全名前一个单词, 比如git sta
,sta
前一个就是git
; 无过滤规则; 即生成的所有都纳入候选, 需指令提供者或函数提供者根据输入参数进行过滤;
-F
优先: 是shell
函数; 可以通过compgen -A function
查看当前环境下的函数定义; 当然一般是局部自定义的;-F
指定的function
一般结合compgen, comopt
使用; 返回集合通过COMREPLY
数组, 即一般使用COMPREPLY=( hello world )
;
-C
次之: 基本和-F
相同, 除了没有COMP_WORDS, COMP_CWORD
; 输出到标准输出的字符集按\n
进行分词, 生成结果集; 可以结合\
使用;过滤规则:
&
被替代为sta
; 可以用\&
保持愿意;!
则是取反;shopt nocasematch
可以按照不区分大小写匹配;complete -G "*" -X "!&*" todo
; 完全匹配的会被删除; 保留不匹配的;补充
-o
选项;
- 如果前面没有任何匹配集合, 且规则指定了
-o dirnames
; 会将当前目录下的文件夹名纳入匹配, 并过滤; 但是如果有匹配集合这个选项就不会生效;- 指定了
-o plusdirs
; 会将目录纳入集合; 和-o dirnames
区别在于,-o plusdirs
一定会生效;complete -W "hello" -o plusdirs todo
;如果上面的
complete
指定的规则;bash completion,Readline
的补齐规则会被禁用; 可以通过-o bashdefault
开启bash complettion
,-o default
开启Readline completion
作为补充手段, 这个是没有任何生成集合的时候才会生效, 有就不会生效;如果有
compspec
是目录, 会补全/
; 可以通过一些手段规避;complete -W "hello $(find . -maxdepth 1 -mindepth 1 -type d -printf "%f\n")" todo
;compgen -d
生成的也没有后缀;补充: 动态加载规则
- 一般都是一次性的加载; 但是当我们
-F
的返回值是124
的时候, 会重新加载当前指令的complete
; 即返回124
表示当前指令的规则发生了变化;_completion_loader() { . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124 } complete -D -F _completion_loader -o bashdefault -o default
- 默认规则, 用于动态生成某个指令的规则; 即使用了指令并触发才生成;
指令: compgen, complete, compopt
compgen
格式:
compgen [option] [word]
- 这个是手动触发; 即模拟
complete
;option
是可以是complete
的所有选项, 除了-r, -p
;-F -C
在这里也不太好用; 因为相关参数没有设置;word
用于过滤; 即git sta
案例; 可以理解为sta
就是这里的word
参与过滤; 没有就不过滤; 返回所有;- 具体使用参见后面案例
compopt
格式:
compopt [-o option] [-DEI] [+o option] [name]
, 即控制某个指令的选项开关; 不修改其他规则;
-o option
: 打开某个选项;+o option
: 关闭某个选项;name
: 指定具体指令, 未指定表示当前指令;[-DEI]
: 指定是name
忽略;
complete
complete [-abcdefgjksuv] [-o comp-option] [-DEI] [-A action] [-G globpat] [-W wordlist]