如何用给定的参数设置bash完成GNU long选项? [英] How to bash complete a GNU long option with given set of arguments?

查看:135
本文介绍了如何用给定的参数设置bash完成GNU long选项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

GNU 建议使用 --name = value 语法,用于为长选项传递参数。

GNU advises to use --name=value syntax for passing argument for long option. It enables a long option to accept an argument that is itself optional.

假设您有完整的可能参数集,它使一个长选项可以接受本身是可选的参数。您如何为这样的选项编写bash完成代码?我希望完成操作在完成明确的参数时(而不是之前)增加空间。

Suppose you have a complete set of possible arguments. How do you write a bash completion code for such an option? I want the completion to add space when it completes an unambiguous argument, but not before.

推荐答案

这是我编写的模板代码用于完成虚拟命令 gnu-options 代码中给出的GNU选项。

Here is the template code I wrote for completing GNU options given in the code for imaginary command gnu-options.

不带参数的选项是在数组 opts 中定义。在关联数组 args 中定义了可能带有参数的选项。请注意,由于 with-args0 两者都出现,因此它是一个带有可选参数的选项。

Options that do not take arguments are defined in array opts. Options that do possibly take argument are defined in associative array args. Note that as with-args0 appears in both it is an option with optional argument.

脚本支持偶数大小写其中 $ COMP_WORDBREAKS 不包括'=',但是显示的补全时间更长。

The script supports even case where $COMP_WORDBREAKS does not include '=', but the shown completions are longer then.

# Hack for given strings $2,$3,... possibly being in $1 and $COMP_WORDBREAKS
# Only the part after each match is listed as a completion.
# Run 'shopt -s extdebug; declare -F __ltrim_colon_completions; shopt -u extdebug'
# to see location for the respective function for colon only.
__ltrim_completions ()
{
    local cur=$1; shift
    while [[ ${1+x} ]]; do
        if [[ "$cur" == *$1* && "$COMP_WORDBREAKS" == *$1* ]]; then
            local x_word=${cur%$1*}$1
            local i
            for i in ${!COMPREPLY[*]}; do
                COMPREPLY[$i]=${COMPREPLY[$i]#"$x_word"}
            done
        fi
        shift
    done
} 


_gnu_options()
{
    local IFS=$'\n' # needed for handling trailing space of some options and all arguments
    local cur prev words cword split # needed by _init_completion()
    local opts i prefix= wordlist
    local -A args=()
    # Do not treat = as word breaks even if they are in $COMP_WORDBREAKS:
    # Split option=value into option in $prev and value in $cur
    _init_completion -s || return

    # DEFINE OPTIONS THAT DO NOT TAKE AN ARGUMENT HERE:
    opts=(with-args0 option0 option1 par param)
    # DEFINE THE OPTIONS WITH ARGUMENTS HERE:
    args=([with-args0]= [with-args1]=$'arg10\narg11')
    args[with-args2]=\
'arg=20
arg=21
var=22
argx'
    args[with-args3]=

    for i in ${!args[*]}; do
        if [[ $prev = --$i ]]; then
            local j dobreak=
            [[ $split == false ]] && {
                # equal sign not used; check, if argument is optional.
                for j in ${opts[*]}; do [[ $i == $j ]] && { dobreak=t; break; } done
            }
            [[ $dobreak ]] && break
            [[ "$COMP_WORDBREAKS" != *=* && $split == true ]] && prefix="--$i="
            if [[ ${args[$i]} ]]; then
                COMPREPLY=( $( compgen -P "$prefix" -W "${args[$i]}" -- "$cur" ) )
                __ltrim_completions "$cur" =
            else
                case $i in
                    with-args0)
                        # expand file/directory name.
                        COMPREPLY=( $( compgen -P "$prefix" -A file -- "$cur" ) )
                        compopt -o filenames
                        ;;
                    *)
                        COMPREPLY=()
                        ;;
                esac
            fi
            return 0
        fi
    done

    wordlist=()
    for i in ${opts[*]}; do wordlist+=("--$i "); done
    for i in ${!args[*]}; do wordlist+=("--$i="); done
    COMPREPLY=( $( compgen -W "${wordlist[*]}" -- "$cur" ) )
    compopt -o nospace
} && complete -F _gnu_options gnu-options

这篇关于如何用给定的参数设置bash完成GNU long选项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆