Completamento bash per valori separati da virgola


16

Vorrei creare una regola di completamento per l'elenco dei parametri separati da virgola. Ad esempio, ho un comando che riceve un elenco di nomi di server:

myscript -s name1,name2,name3

In questo momento sono riuscito a scrivere il seguente completamento:

_myscript () {
  local cur prev opts

  _get_comp_words_by_ref cur prev

  opts='-s'

  servers='name1 name2 name3'

  if [[ ${cur} == -* ]] ; then
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
  else
    case "${prev}" in
      -s)
        if [[ "$cur" == *,* ]]; then
          local realcur prefix
          realcur=${cur##*,}
          prefix=${cur%,*}
          COMPREPLY=( $(compgen -W "${servers}" -P "${prefix}," -- ${realcur}) )
        else
          COMPREPLY=( $(compgen -W "${servers}" -- ${cur}) )
        fi
        ;;
      *)
        # do nothing
        ;;
    esac
  fi
}

Ma ha almeno 2 problemi:

  1. I suggerimenti per il valore corrente includono tutti i valori precedenti nel loro prefisso.
  2. Non considera valori duplicati.

Quali sono le migliori pratiche per tali casi? Forse bash-completions ha alcune funzioni in bundle per csv-lists?


3
Ciò che potrebbe aiutare è che puoi dividere i valori separati da virgola in un elenco iterabile come questo: IFS=, LIST=("$VARIABLE")dove $ VARIABLE contiene i tuoi valori separati da virgola.
Michael Ehrenreich,

2
Bella idea @MichaelEhrenreich, ma non devi citare il $VARIABLE, altrimenti la rottura delle parole non accade. basta usare IFS=, LIST=($VARIABLE).
Guss,

Risposte:


6

Non c'è praticamente alcun modo per risolvere i problemi che descrivi, perché bash utilizza i valori COMPREPLYdirettamente nel display e quindi per sostituire il testo dell'utente - mentre per ottenere ciò che desideri, devi prima generare i possibili completamenti (solo i nomi dei server, senza prefisso) per bash da visualizzare, quindi quando bash sta per sostituire il testo dell'utente con la stringa più lunga non in conflitto, sarebbe necessario che richiami nuovamente lo script per generare il testo con il prefisso - e bash non ha possibilità per quello.

Il meglio che potrei trovare è quello di COMPREPLYessere generato con solo la prima parola che ha l'intero prefisso ( COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )), in modo che se c'è un solo possibile completamento, questo si completa automaticamente, mentre se c'è più di un possibile completamento , quindi bash non rimuoverà ciò che è stato digitato finora (perché la prima parola in COMPREPLYha l'intero prefisso e quindi corrisponde al testo attualmente digitato e sarà selezionata da bash per sostituire il testo dell'utente) e visualizzerà le opzioni senza il prefisso - tranne per quella parola che contiene già il prefisso, quindi l'output sarà simile al seguente:

$ command -s banana,a
ananas     apricot    banana,apple

"apple" come ultimo ordinato nelle opzioni di completamento perché porta il prefisso che inizia con "b" - molto confuso. Quindi non consiglio di farlo.

Per quanto riguarda i duplicati - per non mostrare i duplicati, devi solo entrare $prefixnella sua parte (facile IFS="," prefix_parts=($prefix):) e quindi scorrere su di essi e lasciare solo nei $serversnomi che non sono già elencati. È noioso da scrivere, quindi non lo mostrerò qui, ma relativamente banale, quindi sono sicuro che puoi farcela :-).

Per riassumere, non penso che dovresti usare valori separati da virgola per le opzioni di input, almeno se ti aspetti che bash ti aiuti con il completamento.

Puoi supportare un formato di opzioni come questo: command -s <server> [<server> [..]]e quindi per il completamento di voci diverse da quella immediatamente successiva -sall'opzione, esegui nuovamente la scansione $COMP_WORDSdell'array $COMP_CWORDfino a quando non trovi un'opzione (stringa che corrisponde -*) e se i suoi "-s" allora devi completare il nome del server.

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.