Czy utworzyć skrypt ukończenia bash, aby automatycznie uzupełniać ścieżki po znaku równości?

11

Chcę utworzyć skrypt zakończenia bash, który rozpoznaje argumenty formularza --argi --some-arg=file.

Po przeczytaniu tego samouczka i kilku przykładów /usr/share/bash_completion/completions/napisałem następujący skrypt (aby zaoszczędzić czas na wpisywaniu niektórych flag za pomocą 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

Zapisałem go ~/bash_completions/chromiumi utworzyłem dowiązanie symboliczne sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium.
Następnie załadowałem go za pomocą . /usr/share/bash_completions/completions/chromium.

Teraz mam dwa problemy:

  • chromium --u<TAB>rozwija się do chromium --user-data-dir=<SPACE>(nie chcę miejsca).
  • Ścieżki (katalogi i pliki) nie są już uzupełniane.

Jak mogę rozwiązać te problemy?

Rob W.
źródło
Czy przejście na Zsh jest opcją?
Gilles „SO- przestań być zły”

Odpowiedzi:

11

Znalazłem rozwiązanie obu problemów!

  1. Aby nie dodawać spacji, użyj nospaceopcji. Można to zrobić na dwa sposoby:

    • Przekaż to complete:
      complete -o nospace -F _chromium chromium
    • Użyj compoptwbudowanego:
      compopt -o nospace(aby włączyć opcję)
      compopt +o nospace(aby wyłączyć opcję)

    Znalazłem go w dokumentacji Bash na gnu.org, 8.7 Programowalne kompilacje uzupełniające .

  2. Uzupełnianie plików.
    • peterph zasugerował użycie -fflagi z compgen. Postępowałem zgodnie z tą radą i wdrożyłem ją jako COMPREPLY=( $(compgen -f "$cur") ). To działało dobrze, dopóki nie próbowałem uzupełnić ścieżki zawierającej spacje.
      W przypadku przepełnienia stosu znalazłem tę odpowiedź, która zaleca ręczne utworzenie listy ukończeń (bez użycia compgen). To podejście działało dobrze.
    • Użyj filenamesopcji, aby powiedzieć Readline, że compspec generuje nazwy plików, dzięki czemu może:
      • wykonać przetwarzanie specyficzne dla nazwy pliku (np. dodać ukośnik do nazw katalogów, cytować znaki specjalne lub ukryć końcowe spacje)
      • użyj różnych kolorów, aby wskazać typ pliku (z colored-statswłączonym)

Za pomocą manipulacji ciągiem Basha (w celu rozszerzenia ~i radzenia sobie ze spacjami) zbudowałem skrypty ukończenia basha, które spełniają wszystkie kryteria określone w pytaniu.

_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
Rob W.
źródło
Świetna odpowiedź, wielkie dzięki. Zaoszczędziłeś dużo czasu. Użyłem -fprzełącznika do uzupełnienia ścieżki do pliku, ale nie uzupełnia on /znaku, jeśli jest to katalog ... to jednak drobiazg.
Jiri Kremser
1

Aby uzupełnić nazwy plików, spróbuj przejść -fdo compgen.

Obawiam się, że nie będziesz w stanie pozbyć się spacji po opcjach, ponieważ tak działa uzupełnianie - gdy znajdzie unikalne dopasowanie, kompletuje je całkowicie.

Peter
źródło
Dzięki za sugestię -f. Próbowałem, ale nie obsługuje poprawnie spacji: Ścieżka /tmp/foo barpowoduje dwa wpisy zakończenia /tmp/fooi bar. O niechcianych --arg=<SPACE>: znalazłem rozwiązanie tego problemu i zamieściłem je w odpowiedzi poniżej .
Rob W