Створити скрипт завершення bash для автозаповнення шляхів після знака-рівності?


11

Я хочу створити скрипт завершення bash, який розпізнає аргументи форми --argі --some-arg=file.

Прочитавши цей підручник та кілька прикладів у /usr/share/bash_completion/completions/, я написав наступний сценарій (щоб заощадити час під час введення деяких прапорів за допомогою Chromium):

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=file
    if [[ ${cur} == "--"*"=" ]] ; then
        # Removed failures (is my logic OK?)
        return 0
    fi

    # Handle other options
    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _chromium chromium

Я зберег його ~/bash_completions/chromiumі створив симпосилання за допомогою sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium.
Потім я завантажив це за допомогою . /usr/share/bash_completions/completions/chromium.

Зараз у мене виникають дві проблеми:

  • chromium --u<TAB>розширюється до chromium --user-data-dir=<SPACE>(я не хочу місця).
  • Шляхи (каталоги та файли) вже не завершені.

Як я можу вирішити ці проблеми?


Чи є перехід на zsh варіант?
Жил "ТАК - перестань бути злим"

Відповіді:


11

Я знайшов рішення для обох проблем!

  1. Щоб не додавати пробіл, скористайтеся nospaceопцією. Це можна зробити двома способами:

    • Передайте його complete:
      complete -o nospace -F _chromium chromium
    • Використовуйте compoptвбудований:
      compopt -o nospace(щоб увімкнути опцію)
      compopt +o nospace(щоб вимкнути опцію)

    Я знайшов це в документації Bash на сайті gnu.org, 8.7 .

  2. Завершення файлів.
    • peterph запропонував використовувати -fпрапор с compgen. Я дотримувався цієї поради і реалізував її як COMPREPLY=( $(compgen -f "$cur") ). Це спрацювало чудово, поки я не спробував завершити шлях, що містить пробіли.
      На переповнення стека я знайшов цю відповідь, яка рекомендує створити список заповнення вручну (без використання compgen). Цей підхід спрацював чудово.
    • Скористайтеся filenamesопцією, щоб сказати Readline, що compspec генерує імена файлів, тому він може:
      • виконувати будь-яку обробку, пов’язану з іменем файлу (наприклад, додавання косої риски до імен каталогів, цитування спеціальних символів або придушення пробілів)
      • використовувати різні кольори для позначення типу файлу (з colored-statsувімкненим)

За допомогою маніпуляції з рядком Баша (для розширення ~та розгляду пробілів) я створив сценарії завершення баш, які відповідають усім критеріям, викладеним у питанні.

_chromium() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"

    # Some interesting options
    opts="
--disable-web-security
--easy-off-store-extension-install
--incognito
--load-extension=
--pack-extension=
--pack-extension-key=
--user-data-dir=
"
    # Handle --xxxxxx=
    if [[ ${prev} == "--"* && ${cur} == "=" ]] ; then
        compopt -o filenames
        COMPREPLY=(*)
        return 0
    fi
    # Handle --xxxxx=path
    if [[ ${prev} == '=' ]] ; then
        # Unescape space
        cur=${cur//\\ / }
        # Expand tilder to $HOME
        [[ ${cur} == "~/"* ]] && cur=${cur/\~/$HOME}
        # Show completion if path exist (and escape spaces)
        compopt -o filenames
        local files=("${cur}"*)
        [[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]// /\ }" )
        return 0
    fi

    # Handle other options
    COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
    if [[ ${#COMPREPLY[@]} == 1 && ${COMPREPLY[0]} != "--"*"=" ]] ; then
        # If there's only one option, without =, then allow a space
        compopt +o nospace
    fi
    return 0
}
complete -o nospace -F _chromium chromium

Дивовижна відповідь, велике спасибі Ви зекономили багато мого часу. Я використовував -fперемикач для завершення шляху до файлу, але він не заповнює /char, якщо це каталог ... але це невелика річ.
Іррі Кремсер

1

Щоб заповнити імена файлів, спробуйте перейти -fдо compgen.

Боюся, ви не зможете позбутися пробілів після варіантів, оскільки так працює завершення - коли він знайде унікальну відповідність, він завершить його повністю.


Дякуємо за пропозицію о -f. Я спробував це, але в ньому неправильно розглядаються пробіли: шлях /tmp/foo barпризводить до двох записів завершення /tmp/fooта bar. Про небажане --arg=<SPACE>: я знайшов рішення для цього і опублікував його у відповіді нижче .
Роб Ш
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.