Erstellen Sie ein Bash-Vervollständigungsskript, um Pfade nach dem Gleichheitszeichen automatisch zu vervollständigen.

11

Ich möchte ein Bash-Vervollständigungsskript erstellen, das Argumente des Formulars --argund erkennt --some-arg=file.

Nachdem ich dieses Tutorial und einige Beispiele gelesen /usr/share/bash_completion/completions/habe, habe ich das folgende Skript geschrieben (um Zeit beim Eingeben einiger Flags mit Chromium zu sparen):

_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

Ich habe es in gespeichert ~/bash_completions/chromiumund einen Symlink mit erstellt sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium.
Dann habe ich es mit geladen . /usr/share/bash_completions/completions/chromium.

Jetzt habe ich zwei Probleme:

  • chromium --u<TAB>erweitert sich zu chromium --user-data-dir=<SPACE>(ich will den Raum nicht).
  • Pfade (Verzeichnisse und Dateien) werden nicht mehr ausgefüllt.

Wie kann ich diese Probleme lösen?

Rob W.
quelle
Ist ein Wechsel zu zsh eine Option?
Gilles 'SO - hör auf böse zu sein'

Antworten:

11

Ich habe die Lösung für beide Probleme gefunden!

  1. Verwenden Sie die nospaceOption , um kein Leerzeichen anzuhängen . Dies kann auf zwei Arten erfolgen:

    • Gib es weiter an complete:
      complete -o nospace -F _chromium chromium
    • Verwenden Sie das compoptintegrierte:
      compopt -o nospace(um die Option zu aktivieren)
      compopt +o nospace(um die Option zu deaktivieren)

    Ich fand es in der Bash-Dokumentation unter gnu.org, 8.7 Programmable Completion Builtins .

  2. Vervollständigung von Dateien.
    • Peterph schlug vor , die -fFlagge mit zu verwenden compgen. Ich folgte diesem Rat und setzte ihn um als COMPREPLY=( $(compgen -f "$cur") ). Dies funktionierte gut, bis ich versuchte, einen Pfad mit Leerzeichen zu vervollständigen.
      Beim Stapelüberlauf habe ich diese Antwort gefunden , die die manuelle Erstellung der Abschlussliste (ohne Verwendung compgen) empfiehlt . Dieser Ansatz hat gut funktioniert.
    • Verwenden Sie die filenamesOption, um Readline mitzuteilen, dass die Compspec Dateinamen generiert, damit Folgendes möglich ist:
      • Führen Sie eine beliebige dateinamenspezifische Verarbeitung durch (z. B. Hinzufügen eines Schrägstrichs zu Verzeichnisnamen, Zitieren von Sonderzeichen oder Unterdrücken von Leerzeichen).
      • Verwenden Sie verschiedene Farben, um den Dateityp anzugeben (wenn colored-statsaktiviert).

Mit Hilfe von Bashs String-Manipulation (zum Erweitern ~und Behandeln von Leerzeichen) habe ich ein Bash-Vervollständigungsskript erstellt, das alle in der Frage angegebenen Kriterien erfüllt.

_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.
quelle
Super Antwort, vielen Dank. Sie haben viel Zeit gespart. Ich habe -fswitch für die Vervollständigung des Dateipfads verwendet, aber es vervollständigt das /Zeichen nicht, wenn es sich um ein Verzeichnis handelt ... es ist jedoch eine kleine Sache.
Jiri Kremser
1

Um Dateinamen zu vervollständigen, versuchen Sie es -fmit compgen.

Ich fürchte, Sie werden die Leerzeichen nach den Optionen nicht mehr entfernen können, da die Fertigstellung so funktioniert - sobald eine eindeutige Übereinstimmung gefunden wurde, wird sie vollständig vervollständigt.

Peterph
quelle
Danke für den Vorschlag von -f. Ich habe es versucht, aber es behandelt Leerzeichen nicht richtig: Der Pfad /tmp/foo barführt zu zwei Abschlusseinträgen /tmp/foound bar. Über das Unerwünschte --arg=<SPACE>: Ich habe die Lösung dafür gefunden und sie in der Antwort unten veröffentlicht .
Rob W