完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
概述 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 echo " -d } 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 -d 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 - 自定义补全 上面的补全是补全固定的参数,简单,但是用处也不大,用户记不住的其实就是那些会变的参数内容。 下面尝试动态补全 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-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 的机制更加易于维护。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4866 浏览 0 评论
87350 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4670 浏览 2 评论
3562 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2449 浏览 0 评论
1945浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1315浏览 1评论
1219浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1288浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1206浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 15:37 , Processed in 1.068456 second(s), Total 73, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号