【问题标题】:Bash completions with equals sign and enumerable flag values带有等号和可枚举标志值的 Bash 补全
【发布时间】:2011-06-29 18:41:51
【问题描述】:

我正在尝试构建一个 bash 完成例程,它会建议命令行标志和合适的标志值。例如,在下面的 fstcompose 命令中,我希望比赛例程首先建议 compose_filter= 标志,然后从 [alt_sequence, auto, match, sequence] 建议可能的值.

fstcompose --compose_filter=

对于没有一组关联值的任何标志,我希望比赛退回到建议路径或文件的默认模式。

我面临的一个问题是将 = 等号视为单独的标记,并设置为 prev COMP_WORD。是否有一种技术可以在前一个 = 字符之前(包括前一个 = 字符)检测整个标志?或者有没有更好的方法来实现这种带有可枚举值的标志完成?下面是我正在使用的完成例程的示例。

_fstcompose()
{
  local cur prev opts filters pprev
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  prev="${COMP_WORDS[COMP_CWORD-1]}"
  opts="--compose_filter= --connect"
  filters="alt_sequence auto match sequence"

  if [[ ${cur} == -* ]] ; then
  COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
  return 0
  fi

  if [[ ${prev} == "--compose_filter=" ]] ; then
  COMPREPLY=($(compgen -W "${filters}" -- ${cur}))
  return 0
  fi
  _filedir
}
complete -o nospace -F _fstcompose fstcompose

【问题讨论】:

  • 我提出了一个类似的问题和答案here。我无法将此标记为重复。
  • 最小答案here

标签: bash shell bash-completion


【解决方案1】:

您的第一个 return 0 会阻止对第二个 if 进行评估。尝试使用从最具体到最不具体的case 语句,或者至少以这种方式排列你的if 语句。

由于$COMP_WORDBREAKS 中包含“=”,因此${prev} 是没有“=”的“--compose_filter”。

如果您从$COMP_WORDBREAKS 中删除“=”,则--compose_filter 仍然是${cur},而不是${prev}。这样做而不保留和恢复其值将破坏其他完成。

我不确定还有什么其他问题。

您可以在函数中添加echo 语句,这些语句被重定向到另一个终端以帮助调试。例如:

echo "cur: $cur, prev: $prev" > /dev/pts/2

【讨论】:

    【解决方案2】:

    我认为这会帮助一些人。 下面的代码应该可以工作(即时编写)

    have fstcompose &&{
        function elementExists(){
            local i isRunning result
            i=0
            isRunning=1
            result=0
            #~ for i in ${opts_with_equal[@]}; do
            while [ "$isRunning" -eq 1 ]; do
                if [ "$i" -ge "${#opts_with_equal[@]}" ]; then
                    isRunning=0
                elif [ "${opts_with_equal[$i]}" == "$1" ]; then
                    result=1
                    isRunning=0
                fi
                ((i++))
            done
            echo $result
        }
        function _fstcompose(){
            local prev cur opts opts_with_equal isEqualOptions
            COMPREPLY=()
            _get_comp_words_by_ref -n : cur prev
            opts="--compose_filter --connect"
            opts_with_equal=(--compose_filter)
    
            case ${cur} in
                '--compose_filter'*)
                    prev="${cur%%=*}="
                    cur=${cur#*=}
                    COMPREPLY=( ${prev}$(compgen -W "alt_sequence auto match sequence" -- "${cur}") )
                    return 0
                    ;;
            esac
    
            if [[ "${cur}" != -* ]]; then
                _filedir
            else
                isEqualOptions=$(elementExists "${cur}")
                if [ "${isEqualOptions:-0}" -eq 1 ]; then
                    COMPREPLY=( $(compgen -W "${opts}" -S '=' -- "${cur}") )
                else
                    COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                fi
            fi
    
        }
        complete -o nospace -F _fstcompose fstcompose
    }
    # Local variables:
    # mode: shell-script
    # sh-basic-offset: 4
    # sh-indent-comment: t
    # indent-tabs-mode: nil
    # End:
    # ex: ts=4 sw=4 et filetype=sh
    

    注意:opts_with_equal 在这个例子中是一个数组,它只包含一个参数。放入每个使用'='的参数

    【讨论】:

    • 开头的have是什么?我的系统中没有这样的命令或功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多