Скрипт вложенного bash для автозаполнения - PullRequest
1 голос
/ 18 февраля 2012

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

Вот команды и подкоманды, которые я 'Я хотел бы выполнить автозаполнение

  • Основная команда foo, для подкоманд version, process и help необходимо выполнить автозаполнение.Дальнейшее автозаполнение зависит от подкоманды.

    • Если пользователь вводит - после основной команды, автозаполнение выполняет завершение для этих слов: --activate или --deactivate

    • Если пользователь вводит --deactivate, он должен выполнить автозаполнение вывода команды bash (скажем, ls).

  • version: автозаполнение не выполнено
  • process: по умолчанию для автозаполнения указывается список каталогов (включая текущий и родительский)

    • Если пользователь вводит -, автозаполнение выполняет завершение для этих слов: --color, --verbose и затем останавливается
  • Если пользователь вводит help, автозаполнение относится к другим подкомандам (process или version).

Вот моя текущая реализация сценария автозаполнения (который плохо работает):

_foo() {
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    words=("${COMP_WORDS[@]}")
    cword=$COMP_WORD
    opts="process version help"

    case "$prev" in
    -*)
        local subopts="--activate --deactivate"
            COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
            case "$cur" in
                --deactivate)
                    COMPREPLY=( $(ls) )
                ;;
            esac
         ;;
    version)
        COMPREPLY=()
        ;;
    process)
        case "$cur" in
            -*)
                local subopts="--color --verbose"
                COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
                ;;
            *)
                COMPREPLY=( $(compgen -A directory))
                ;;
        esac
        ;;
    help)
        COMPREPLY=( $(compgen -W "process version" -- ${cur}) )
        ;;
   esac
   } 
 complete -F _foo foo

Вы, вероятно, видите, что Bash также не является моей главной сильной стороной.Я думал о написании отдельных функций bash для каждой подкоманды, но сейчас я не знаю, как это сделать.Если у вас есть предложения о том, как это реализовать, я был бы очень признателен.

Спасибо!

1 Ответ

3 голосов
/ 21 февраля 2012

В случае возможных подкоманд на первом уровне это немного неясно для меня.Можно ли ввести foo --activate или foo - --activate?Последний выглядит как-то странно, но больше подходит под ваш код.Первое звучит более разумно, но подразумевает, что --activate и т. Д. Как глобальный параметр, который должен обрабатываться на том же уровне, что и ваши подкоманды.Я еще ничего не вошел.Попробуйте следующий код:

_foo() {
    local cur prev opts

    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    words=("${COMP_WORDS[@]}")
    cword=$COMP_CWORD
    opts="process version help"

    case "$prev" in
    -*)
        local subopts="--activate --deactivate"
        COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
        case "$cur" in
            --deactivate)
                COMPREPLY=( $(ls) )
            ;;
        esac
        return 0
         ;;
    version)
        COMPREPLY=()
        return 0
        ;;
    process)
        case "$cur" in
            -*)
                local subopts="--color --verbose"
                COMPREPLY=( $(compgen -W "${subopts}" -- ${cur}) )
                ;;
            *)
                COMPREPLY=( $(compgen -A directory))
                ;;
        esac
        return 0
        ;;
    help)
        COMPREPLY=( $(compgen -W "process version" -- ${cur}) )
        return 0
        ;;
   esac
   COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
   return 0
} 
complete -F _foo foo

, который в основном совпадает с вашим, но: Внизу установите COMPREPLY на ваши подкоманды первого уровня, чтобы они были выполнены.В случае ввода подкоманды вы должны вернуть (0), чтобы не достигнуть окончательного утверждения.

Приведенный пример будет работать с foo - --activate, что может не соответствовать вашему желанию.Поэтому, если вы хотите ввести foo --activate, измените соответствующие строки на

    case "$prev" in
    --activate)
        COMPREPLY=()
        return 0
        ;;
    --deactivate)
        COMPREPLY=( $(compgen -W "$(ls)" -- ${cur}) )
        return 0
        ;;
    version)
    ...
...