zoukankan      html  css  js  c++  java
  • Bash的自动补全

    内置补全命令

    Bash内置两个补全命令,分别是compgen和complete。compgen命令根据不同的参数,生成匹配单词的候选补全列表,例子如下:

    monster@monster-Z:~$ compgen -W 'ha hia hoo world' h
    ha
    hia
    hoo
    

    compgen的常用选项是-W,通过-W参数指定空格分隔的单词列表。h即为我们在命令行当前输入的单词,执行完之后会输出候选的匹配列表。

    complete命令的参数类似于compgen,但是它的作用是说明命令如何进行补全,例如同样使用-W参数指定候选单词列表:

    monster@monster-Z:~$ complete -W 'word1 word2 word3 hello' foo
    monster@monster-Z:~$ foo word
    word1  word2  word3  

    当输入"foo w"再按<tab>的时候,会自动补全为"foo word",再此基础上再按<tab>时,会输出最后一行的"word1 word2 word3"

    我们还可以通过-F参数指定一个补全函数:

    monster@monster-Z:~$ complete -F _foo foo

    现在键入foo命令之后,会调用_foo函数来生成补全的列表,完成补全的功能,而这是补全脚本实现的关键所在。

    补全相关的内置变量

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

    COMP_WORDS: 类型为数组,存放当前命令行中输入的所有单词

    COMP_CWORD: 类型为整数,当前光标下输入的单词位于COMP_WORDS数组中的索引

    COMPREPLY: 类型为数组,候选的补全结果

    COMP_WORDBREAKS: 类型为字符串,表示单词之间的分隔符

    COMP_LINE: 类型为字符串,表示当前命令行输入

    例如我们定义如下一个补全函数_foo: (注:declare -p var的意思是显示变量var的值)

    monster@monster-Z:~$ function _foo()
    > {
    > echo -e "
    "
    > declare -p COMP_WORDS
    > declare -p COMP_CWORD
    > declare -p COMP_LINE
    > declare -p COMP_WORDBREAKS
    > }
    monster@monster-Z:~$ complete -F _foo foo
    

      

    假设我们再在命令行下输入以下内容,再按Tab键补全:

    monster@monster-Z:~$ foo b
    
    declare -a COMP_WORDS='([0]="foo" [1]="b")'
    declare -- COMP_CWORD="1"
    declare -- COMP_LINE="foo b"
    declare -- COMP_WORDBREAKS=" 	
    "'><=;|&(:"
    

    需要注意的是,补全功能是Bash自带的,并非一定需要Bash-completion包

    编写脚本

    补全脚本分成两部分:编写一个补全函数和使用complete命令应用补全函数。

    一般补全函数都会定义以下两个变量:

    local cur prev
    

    其中cur表示当前光标下的单词,而prev则对应上一个单词:

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

    初始化相应的变量之后,我们需要定义补全行为,即输入什么的情况下补全什么内容,例如当输入-开头的选项时,我们将所有的选项作为候选的补全结果:

    local opts="-h --help -f --file -o --output"
    
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
    

    不过在给COMPREPLY赋值之前,最好将它重置清空,避免被其他补全函数干扰

    完整的补全函数如下所示:

    function _foo() {
            local cur prev opts
    
            COMPREPLY=()
    
            cur="${COMP_WORDS[COMP_CWORD]}"
            prev="${COMP_WORDS[COMP_CWORD-1]}"
            opts="-h --help -f --file -o --output"
    
            if [[ ${cur} == -* ]] ; then
                    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
                    return 0
            fi
    }
    

    现在在命令行下就可以对foo命令进行参数补全了:

    monster@monster-Z:~$ complete -F _foo foo
    monster@monster-Z:~$ foo -
    -f        --file    -h        --help    -o        --output  
    

    利用号prev变量可以让补全结果更完整,例如当输入--file之后,我们希望补全特殊的文件(假设以.sh结尾的文件)

    case "${prev}" in
        -f|--file)
            COMPREPLY=( $(compgen -o filenames -W "`ls *.sh`" -- ${cur}) )
            ;;
    esac
    

    现在再执行foo命令,--file参数的值也可以补全了:

    monster@monster-Z:~/TEST/sh$ foo --file 
    array.sh                      test1.sh
    hello.sh                      test.sh
    pipe.sh                       while.sh

    在补全函数中加入如下命令:

    _get_comp_words_by_ref -n : cur prev words cword
    

    变量cur中包含了命令行当前所在的单词,prev为前一个单词, words为完整的命令行单词数组,cword为单词数组的当前下标

    参考连接:

    1、http://kodango.com/bash-competion-programming

    2、https://debian-administration.org/article/317/An_introduction_to_bash_completion_part_2

  • 相关阅读:
    Dungeon Master (广搜)
    棋盘游戏,dfs搜索
    水管工游戏——dfs
    URL的井号
    模态与非模态对话框
    网站建设之空连接标准
    CSS浮动(float,clear)通俗讲解
    CSS从大图中抠取小图完整教程(background-position应用)
    URI(标识某一互联网资源的字符串)
    CDN
  • 原文地址:https://www.cnblogs.com/YaoDD/p/6117826.html
Copyright © 2011-2022 走看看