Завершение Bash со знаком равенства и перечисляемыми значениями флагов - PullRequest
1 голос
/ 18 февраля 2011

Я пытаюсь создать подпрограмму завершения bash, которая будет предлагать флаги командной строки и подходящие значения флагов.Например, в приведенной ниже команде fstcompose я бы хотел, чтобы подпрограмма соревнования сначала предложила флаг compose_filter = , а затем предложила возможные значения из [alt_sequence, auto, match, sequence].

fstcompose --compose_filter=

Для любых флагов, у которых нет набора связанных значений, я хочу, чтобы соревнование вернулось к стандартному режиму предложения путей или файлов.

Единственная проблема, с которой я столкнулсяface - это знак равенства =, рассматриваемый как отдельный токен и устанавливаемый как 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

Ответы [ 2 ]

2 голосов
/ 18 февраля 2011

Ваш первый 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
0 голосов
/ 21 января 2012

это поможет некоторым людям, я думаю. Приведенный ниже код должен работать (писал на лету)

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 это массив в этом примере, он содержит только один параметр. Поместите в каждый параметр, который использует '='

...