Creare uno script di completamento bash per completare automaticamente i percorsi dopo il segno di uguale?


11

Voglio creare uno script di completamento bash che riconosca gli argomenti del modulo --arge --some-arg=file.

Dopo aver letto questo tutorial e alcuni esempi in /usr/share/bash_completion/completions/, ho scritto il seguente script (per risparmiare tempo nel digitare alcune bandiere con 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

L'ho salvato in ~/bash_completions/chromiume ho creato un collegamento simbolico usando sudo ln -s ~/bash_completions/chromium /usr/share/bash_completion/completions/chromium.
Quindi l'ho caricato usando . /usr/share/bash_completions/completions/chromium.

Ora sto riscontrando due problemi:

  • chromium --u<TAB>si espande in chromium --user-data-dir=<SPACE>(non voglio lo spazio).
  • I percorsi (directory e file) non vengono più completati.

Come posso risolvere questi problemi?


Il passaggio a zsh è un'opzione?
Gilles 'SO- smetti di essere malvagio' il

Risposte:


11

Ho trovato la soluzione ad entrambi i problemi!

  1. Per non aggiungere uno spazio, utilizzare l' nospaceopzione. Questo può essere fatto in due modi:

    • Passalo al complete:
      complete -o nospace -F _chromium chromium
    • Usa il compoptbuilt-in:
      compopt -o nospace(per abilitare l'opzione)
      compopt +o nospace(per disabilitare l'opzione)

    L'ho trovato nella documentazione di Bash su gnu.org, 8.7 Programmi di completamento programmabili .

  2. Completamento dei file.
    • peterph ha suggerito di usare la -fbandiera con compgen. Ho seguito quel consiglio e l'ho implementato come COMPREPLY=( $(compgen -f "$cur") ). Funzionava bene, fino a quando ho provato a completare un percorso contenente spazi.
      Su Stack Overflow, ho trovato questa risposta che raccomanda la creazione manuale dell'elenco di completamento (senza utilizzo compgen). Questo approccio ha funzionato bene.
    • Utilizzare l' filenamesopzione per dire a Readline che compspec genera nomi di file, in modo che possa:
      • eseguire qualsiasi elaborazione specifica del nome file (come l'aggiunta di una barra ai nomi di directory, la citazione di caratteri speciali o la soppressione di spazi finali)
      • usa colori diversi per indicare il tipo di file (con colored-statsabilitato)

Con l'aiuto della manipolazione di stringhe di Bash (per espandere ~e gestire gli spazi), ho costruito degli script di completamento bash che soddisfano tutti i criteri indicati nella domanda.

_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

Risposta fantastica, grazie mille. Mi hai risparmiato molto tempo. Ho usato -fswitch per il completamento del percorso del file, ma non completa il /carattere se si tratta di una directory ... è una piccola cosa però.
Jiri Kremser,

1

Per completare i nomi dei file, prova a passare -fa compgen.

Temo che non sarai in grado di liberarti degli spazi dopo le opzioni, poiché è così che funziona il completamento: una volta trovata una corrispondenza unica, la completa completamente.


Grazie per il suggerimento di -f. L'ho provato, ma non si occupa correttamente degli spazi: il percorso /tmp/foo barrisulta in due voci di completamento /tmp/fooe bar. A proposito di indesiderati --arg=<SPACE>: ho trovato la soluzione e l'ho pubblicata nella risposta di seguito .
Rob W,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.