linux 怎么自动提示命令行,命令行自动补全原理

命令行自动补全原理

概述

bash 自动补全

测试补全的脚本

参数自动补全

自定义补全

zsh 自动补全

参数自动补全

自定义补全

总结

概述

虽然CLI(命令行)类型的工具由于其高效,易定制的特性为很多人所喜爱(也包括我自己), 但是,相对于GUI工具,CLI工具给人的直观感觉就是不容易使用,如果看到工具中大量的参数说明后,更让人望而却步。

因此,如果在自己命令行工具中加入 自动补全 的功能,就可以极大的提高工具的易用性,还可以保留命令行工具原有的高效。 这里所说的 自动补全 不仅仅是补全那些固定的参数(这些意义不大),更多的是补全动态的内容。

本篇主要介绍两种主流的 shell(bash 和 zsh)中,如何实现命令行工具的补全。

bash 自动补全

测试补全的脚本

简单编写一个测试脚本用来测试后面的自动补全:

#!/bin/bash

# filename: cli-test.sh

UPCASE=false

DATE=""

usage() {

echo "USAGE:"

echo "cli-test "

echo " -h : print help"

echo " -u : print info upcase"

echo " -p : print info"

echo " -d : date in print info"

}

print() {

if $UPCASE

then

echo -n $1 | tr a-z A-Z

else

echo -n $1

fi

if [ "$DATE" != ""]

then

echo " date:$DATE"

else

echo ""

fi

}

while getopts "hup:d:" opt; do

case "$opt"in

h)

usage

exit 0

;;

u)

UPCASE=true

;;

d)

DATE=$OPTARG

;;

p)

print $OPTARG

;;

esac

done

测试上面的脚本如下:

bash-3.2$ chmod +x cli-test.sh

bash-3.2$ ./cli-test.sh -h

USAGE:

cli-test

-h : print help

-u : print info upcase

-p : print info

-d : date in print info

bash-3.2$ ./cli-test.sh -p hello

hellobash-3.2$ ./cli-test.sh -p hello

hello

bash-3.2$ ./cli-test.sh -u -p hello

HELLO

bash-3.2$ ./cli-test.sh -u -d 2016-10-13 -p hello

HELLO date: 2016-10-13

参数自动补全

参数的补全一般来说比较简单,因为一个命令行工具的参数一般都是固定的。 下面的参数补全脚本是针对 上面的 测试补全的脚本 cli-test.sh

_complete_func() {

local cur prev opts base

COMPREPLY=()

cur="${COMP_WORDS[COMP_CWORD]}"

prev="${COMP_WORDS[COMP_CWORD-1]}"

opts="-h -u -d -p"

if [[ ${cur} == -*]] ; then

COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )

return 0

fi

}

complete -F _complete_func cli-test.sh

让自动补全脚本生效的方法如下:

bash-3.2$ source bash_complete # 使自动补全脚本生效

bash-3.2$ ./cli-test.sh - # 这里输入 - 之后,再输入2次就可以把所有能补全的参数列出来

自定义补全

上面的补全是补全固定的参数,简单,但是用处也不大,用户记不住的其实就是那些会变的参数内容。 下面尝试动态补全 cli-test.sh 的参数 -d 的内容(内容是当前日期以及前3天和后三天的日期) 修改 bash_complete 脚本如下:

_complete_func() {

local cur prev opts base

COMPREPLY=()

cur="${COMP_WORDS[COMP_CWORD]}"

prev="${COMP_WORDS[COMP_CWORD-1]}"

if [[ ${cur} == -*]] ; then

opts="-h -u -d -p"

COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )

else

opts=$( _complete_d_option )

COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )

fi

return 0

}

_complete_d_option() {

date -v -3d +"%Y-%m-%d"

date -v -2d +"%Y-%m-%d"

date -v -1d +"%Y-%m-%d"

date +"%Y-%m-%d"

date -v +1d +"%Y-%m-%d"

date -v +2d +"%Y-%m-%d"

date -v +3d +"%Y-%m-%d"

}

complete -F _complete_func cli-test.sh

测试动态补全的效果

bash-3.2$ source bash_complete # 使自动补全脚本生效

bash-3.2$ ./cli-test.sh -u -d 2016-10-1 # 这是 2016-10-13 执行的结果,其他日子的结果会不一样

2016-10-10 2016-10-11 2016-10-12 2016-10-13 2016-10-14 2016-10-15 2016-10-16

上面就是动态补全,_complete_d_option 函数就是用来实现动态补全的。

zsh 自动补全

相比于bash,zsh 的补全机制更加强大,也更加直观。 同样,下面也通过例子来演示如何在 zsh 中实现上面 bash 中同样的补全功能。

参数自动补全

相比于 bash 的自动补全脚本,我觉得 zsh 的补全方式更加直观。

#compdef cli-test.sh

# filename: _cli-test.h

_cli_test() {

_arguments -C -s -S \

'-h::' \

'-u::' \

'-d::' \

'-p::'

}

_cli_test "$@"

zsh 中有个 fpath 的内置变量,将自动补全脚本放在 $fpath 中,或者在 $fpath 中创建指向自动补全的脚本的软连接都可以。 下面是我的环境中 fpath 的值

$ echo $fpath

/usr/local/share/zsh/site-functions /usr/share/zsh/site-functions /usr/share/zsh/5.0.8/functions

为了测试 zsh 下自动补全是否有效,我在 fpath 下给自己的自动补全脚本创建了软连接

$ cd /usr/local/share/zsh/site-functions

$ ln -s ~/projects/bash/autocomp/_cli-test.sh _cli-test.sh

测试结果

$ ./cli-test.sh -

-d -h -p -u

可以看出,zsh 的补全方法非常简单直观。稍微解释下上面的代码

_arguments

这个函数是 zsh 自带的,有点类似 bash 中的 compgen ,但是功能更加强大。

'-h::' \

这里 : 分割的3部分分别是 “待补全的参数:参数的说明:动态补全参数的内容“

自定义补全

根据上面的解释,要想动态补全 -d 参数非常简单,只要加个函数,并配置在 -d:: 之后即可

#compdef cli-test.sh

# filename: _cli-test.h

_cli_test() {

_arguments -C -s -S \

'-h::' \

'-u::' \

'-d:auto complete date:__complete_d_option' \

'-p::'

}

__complete_d_option() {

local expl

dates=( `generate_date` )

_wanted dates expl date compadd $* - $dates

}

generate_date() {

date -v -3d +"%Y-%m-%d"

date -v -2d +"%Y-%m-%d"

date -v -1d +"%Y-%m-%d"

date +"%Y-%m-%d"

date -v +1d +"%Y-%m-%d"

date -v +2d +"%Y-%m-%d"

date -v +3d +"%Y-%m-%d"

}

_cli_test "$@"

测试动态补全的效果

$ ./cli-test.sh -u -d 2016-10-

2016-10-14 2016-10-15 2016-10-16 2016-10-17 2016-10-18 2016-10-19 2016-10-20

总结

2中shell环境下的自动补全都介绍完了,它们自动补全的机制都不难,只是 zsh 毕竟是新一点的shell,补全方式更加简单易懂。 特别是对于存在子命令和复杂的参数补全,以及参数内容动态补全的情况下,zsh 的机制更加易于维护。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值