2

我正在尝试构建一个 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
4

2 回答 2

3

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

由于“=”包含在“--compose_filter”中$COMP_WORDBREAKS${prev}没有“=”。

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

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

您可以使用echo重定向到另一个终端的语句来帮助您的函数进行调试。例如:

echo "cur: $cur, prev: $prev" > /dev/pts/2
于 2011-02-18T14:44:13.090 回答
0

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

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 在这个例子中是一个数组,它只包含一个参数。放入使用'='的每个参数

于 2012-01-20T22:54:17.020 回答