前言
最近使用tmux+vim开发中遇到一个问题那就是能不能使用命令直接打开我的项目存放根目录 然后在该命令后面使用tab自动补全想要的目录名(项目文件夹名) 然后在指定的那个文件夹(补全后的那个项目文件夹)直接打开 我的tmux脚本(也可以是vim直接打开文件)。
比如 我输入myobj 然后按tab 会直接出现 我的项目文件夹 “项目1 项目2 …” 然后自动补全回车自动打开项目。tmux脚本网上一大把 这里就不发出来了。由于本人觉得自动补全比较有难度,所以下面把我的方案分享给大家。
先看结果
shell自动补全大法,拿去不谢!
1、创建 obj_complete.sh文件 填写内容如下
complete -F _myobj_complete_func myobj
_myobj_complete_func() {
COMPREPLY=()
command_name="${COMP_WORDS[COMP_CWORD]}" #注意这里不能使用$1获取只能用 ${COMP_WORDS[COMP_CWORD]}
completion_txt="text formal"
COMPREPLY=($(compgen -W "${completion_txt}" -- ${command_name}))
return 0
}
2、执行 source ./obj_complete.sh
3、输入 myobj (myobj后面要有一个空格才有效)按[tab][tab] 即可看到如下效果 注意这里的myobj是注册到了全局即使没有myobj这个命令也有效,但是直接回车会报myoba: command not found 但是补全功能是有效的
再探究竟
命令详解
complete -F _myobj_complete_func myobj
complete | -F | _myobj_complete_func | myobj |
执行complete方法 | 使用-F参数 | 调用_myobj_complete_func函数 | 传入myobj参数 |
complete参数
参数 | 类型 | 说明 |
---|---|---|
-o | bashdefault | 如果没有生成补全条目,就使用bash默认的其它补全。 |
-o | default | 如果没有生成补全条目,就使用“readline”默认的文件名补全。 |
-o | dirnames | 如果没有生成补全条目,就进行目录名补全。 |
-o | filenames | 告诉“readline”生成文件名,以便进行与文件名相关的处理,例如在目录名后面加上斜杠,引用特殊字符,去掉行尾的空格,目的是用于shell函数。 |
-o | noquote | 告诉“readline”不引用文件名,默认会进行引用。 |
-o | nospace | 告诉“readline”在补全的名称后不添加空格,默认添加空格。 |
-o | plusdirs | 生成补全条目之后,还会进行目录名补全并把结果添加到其它动作得到的结果中。 |
-A | alias | 别名,同选项“-a”。 |
-A | arrayvar | 数组变量名。 |
-A | binding | “readline”键绑定名。 |
-A | builtin | shell内建命令名,同选项“-b”。 |
-A | command | 命令名,同选项“-c”。 |
-A | directory | 目录名,同选项“-d”。 |
-A | disabled | 不可用的shell内建命令名。 |
-A | enabled | 可用的shell内建命令名。 |
-A | export | 导出的shell变量名,同选项“-e”。 |
-A | file | 文件名,同选项“-f”。 |
-A | function | shell函数名。 |
-A | group | 组名,同选项“-g”。 |
-A | helptopic | 内建命令help支持的帮助主题。 |
-A | hostname | 主机名,从shell环境变量HOSTFILE中获取。 |
-A | job | 作业名,同选项“-j”。 |
-A | keyword | shell保留字,同选项“-k”。 |
-A | running | 正在运行的作业名。 |
-A | service | 服务名,同选项“-s”。 |
-A | setopt | 内建命令set的选项“-o”可用的参数。 |
-A | shopt | 内建命令shopt可接受的选项名。 |
-A | signal | 信号名。 |
-A | stopped | 暂停的作业名。 |
-A | user | 用户名,同选项“-u”。 |
-A | variable | 所有的shell变量名,同选项“-v”。 |
-C | command | 在子shell中执行命令,并把其结果作为补全条目。 |
-F | function | 我们现在用的 在当前的shell环境中执行函数function,执行时,参数“$1”表示那个参数正在进行补全的命令名,参数“$2”表示补全的名称,参数“$3”表示补全的名称前面的单词,表示结束执行时,从数组变量COMPREPLY中获取补全条目。 |
-G | globpat | 使用文件名扩展模式globpat进行扩展以生成可能的补全条目。 |
-P | prefix | 在所有的选项应用到补全结果后,在结果前添加前缀prefix。 |
-S | suffix | 在所有的选项应用到补全结果后,在结果后添加后缀suffix。 |
-W | wordlist | 使用特殊变量IFS中的字符拆分单词列表wordlist,并扩展拆分后的每个单词,结果中与待补全单词匹配的条目就是补全条目。 |
-X | filterpat | filterpat是进行文件名扩展时使用的模式,它作用于通过前面的选项和参数生成的补全列表,并把每个与过滤模式匹配的条目删除,模式中前导的叹号表示否定,这时会删除与过滤模式不匹配的条目。 |
COMPREPLY=($(compgen -W "${completion_txt}" -- ${command_name}))
COMPREPLY | compgen | -W | “${completion_txt}” | ${command_name} |
将执行的结果赋值给环境变量COMPREPLY | 执行compgen命令 | 使用compgen的-W参数 | 补全的字符串集合 | 唤起补全的命令名称 |
compgen 参数说明
参数 | 类型 | 说明 |
---|---|---|
-F | function | 执行shell 函数,函数中生成COMPREPLY作为候选的补全结果 |
-C | command | 将 command 命令的执行结果作为候选的补全 结果 |
-G | pattern | 将匹配 pattern的文件名作为候选的补全结果 |
-W | wordlist | 我们现在用的 分割 wordlist 中的单词,作为候选的补全结果 |
-p | [name] | 列出当前所有的补全命令 |
-r | [name] | 删除某个补全命令 |
内置变量
变量名 | 说明 | 变量类型 |
---|---|---|
COMP_WORDS | 存放当前命令行中输入的所有单词 | Array |
COMP_CWORD | 当前输入的单词在COMP_WORDS中的索引 | Int |
COMPREPLY | 候选的补全结果 | Array |
COMP_WORDBREAKS | 单词之间的分隔符 | String |
COMP_LINE | 当前的命令行输入字符 | String |
COMP_POINT | 光标在当前命令行的哪个位置 | Int |
注意
如需【参数不同时出现】请参考如下博客:
linux shell中的命令自动补全(compgen complete)与 命令行参数解析
这种方法只针对当前终端会话有效,如果关闭终端打开其他终端即刻失效。
如果想要全局生效请自行研究如何添加到系统环境变量中。