shell自动补全功能:bash和zsh;zsh启动优化

时间:2024-03-06 17:10:54

首要一点:shell有多种,比如bash、zsh、csh、ksh、sh、tcsh等

因此,制作自动补全功能时,要先搞清楚,你使用的是哪种shell,各个shell制作方法是不同的,网上大部分介绍的是关于bash的。

定义补全脚本后,要重新打开终端或者先执行下脚本:source

 

一、bash:

涉及命令:

补全命令complete、筛选命令compgen、修改补全命令设置compopt

内置变量:

通过这些变量,可以获得当前命令的内容、位置等信息,以便判断下面应该出现的提示命令的内容

除了上面三个命令外,Bash还有几个内置变量来辅助补全功能,如下: 

 

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

 

帮助信息:

man complete

补全脚本位置(Mac):

每打开一个新的shell,都会把这个目录下的脚本执行一遍

/usr/local/etc/bash_completion.d

代码解读:

_god()
{
    COMPREPLY=()  # 为数组,名字必须是COMPREPLY,在给COMPREPLY赋值之前,最好将它重置清空,避免被其它补全函数干扰
    local cur prev
    _get_comp_words_by_ref cur prev
    COMPREPLY=( $( compgen -W \'xiaomi noops blog\' -- "$cur" ) )
    return 0
} 
complete -F _god god

 

_god()
{
    COMPREPLY=(xiaomi noops blog)
    return 0
}
complete -F _god god

 

查看已经有的命令补全:complete

 

最简单的使用方式:
complete -W "192.168.1.1 192.168.1.2" ssh
这样在输入ssh 后,按tab可以提示+补全IP地址

 

参考:

https://mp.weixin.qq.com/s/nSje0zhcP2vAmBAH05g64w

http://noops.me/?p=1114 

https://linux.cn/article-6301-1.html

 

二、zsh:

涉及命令:compctl

内置变量:没有bash的那些内置的变量,但是有个内置read函数,可以获取当前出现指令集、当前的指令内容、前一个指令内容等信息。

 

帮助信息:

通过这条命令查找zsh的内置函数,找到read的用法:

man zshbuiltins

read函数所用参数解释:

-A     The first name is taken as the name of an array and all words are assigned to it.
-n     Together with -c, the number of the word the cursor is on is read.  With -l, the index of the character the cursor is on is read.  Note that the command name is word number 1, not word  0,  and
       that when the cursor is at the end of the line, its character index is the length of the line plus one.
-c
-l     These flags are allowed only if called inside a function used for completion (specified with the -K flag to compctl).  If the -c flag is given, the words of the current command are read. If the
       -l flag is given, the whole line is assigned as a scalar.  If both flags are present, -l is used and -c is ignored.

 

man zsh

补全脚本位置(Mac):每个新的shell终端都会把这个脚本执行一遍,所以内容太多,一是占用内存,而是新的terminal启动慢

~/.zshrc

 

代码解读:执行下面这段代码,终端执行proxy命令,就可以看到提示信息

_proxy(){
    local cur cword words  # 定义变量,cur表示当前光标下的单词
    read -cn cword  # 所有指令集
    read -Ac words  # 当前指令的索引值
    cur="$words[$cword-1]" # 当前指令值
    if [ $cur = "proxy" ]  # 根据当前不同指令返回对应的提示信息
    then
        reply=(start stop restart connect route help)  # 必须是值reply,返回提示信息内容
    elif [ $cur = "route" ]
    then
        reply=(add delete)
    else
        reply=()
    fi
}
compctl -K _proxy proxy   # -K 表示使用函数

 

参考:

https://github.com/johan/zsh/blob/master/Misc/compctl-examples

 

在.zshrc里加入如下语句:意思大概是自动加载fpath路径下的各种函数,比如自动补全函数。

fpath=(/usr/local/share/zsh-completions $fpath)
autoload -Uz compinit && compinit -u
autoload -U +X bashcompinit && bashcompinit

另外autoload/compinit/bashcompinit是zsh的builtin函数,可以使用man zshbuiltins查看帮助

三、brew search comple

这种模糊搜索可以查到很多工具的命令自动补全脚本:比如pip、bash、docker、zsh等

 

brew info bash-completion查看安装信息

四、python shell的自动补全

五、zsh启动优化

查看zsh启动时间:2.37s,还是很长的,是否可以优化到0.x秒,这样感觉就没有卡顿

time zsh -i -c exit
zsh -i -c exit  2.37s user 1.25s system 98% cpu 3.663 total