2012-05-09 6 views
6

C'è un modo per specificare che un particolare comando ha cassa insensibilità, senza accendere caso insensibilità globalmente (almeno per quel guscio)?Ambito caso-insensibilità per il completamento bash su base comando-by-comando

Nel mio caso particolare, ho una piccola applicazione che mi dà accesso alla linea di comando per un database di indirizzi e-mail, in modo da digitare:

db get email john smith 

e torna indietro con l'indirizzo email di John Smith. Così sono riuscito a consentire il completamento in gran parte all'interno della app: impostazione

COMPREPLY=($(compgen -W "$(db --complete $COMP_CWORD "$COMP_WORDS[@]"}")" -- ${COMP_WORDS[COMP_CWORD]})) 

lavora per me permettere alla scheda completa-get e email. Tuttavia, se si digita j<tab>, rifiuta, perché nel database di posta elettronica, è correttamente in maiuscolo. Mi piacerebbe ottenere bash per completare questo comunque. (Se uso un capitale J, funziona.)

In mancanza di questo, posso avere cambiare la mia opzione --complete caso di risposta facendo corrispondere l'ingresso, suppongo, ma idealmente la riga di comando corrisponda al database se a tutto possibile

Si noti che ho questo lavoro all'interno della app quando si usa readline, è solo l'interfacciamento con bash che sembra essere un problema.

risposta

6

In effetti, sembra che non ci sia modo di fare in modo che il confronto senza distinzione tra maiuscole e minuscole non corrisponda alla distinzione tra maiuscole e minuscole (-W). Vedo le seguenti soluzioni alternative:

Soluzione semplice: Traduci sia la lista di parole che il token di input in lettere maiuscole. Nota: Questo è solo un'opzione se è accettabile per avere tutti i completamenti trasformano in tutto minuscolo.

complete_lower() { 

    local token=${COMP_WORDS[$COMP_CWORD]} 
    local words=$(db --complete $COMP_CWORD "${COMP_WORDS[@]}") 

    # Translate both the word list and the token to all-lowercase. 
    local wordsLower=$(printf %s "$words" | tr [:upper:] [:lower:]) 
    local tokenLower=$(printf %s "$token" | tr [:upper:] [:lower:]) 

    COMPREPLY=($(compgen -W "$wordsLower" -- "$tokenLower")) 
} 

Meglio, ma la soluzione più elaborato: roll your own, case-insensitive logica di corrispondenza:

complete_custommatch() { 

    local token=${COMP_WORDS[$COMP_CWORD]} 
    local words=$(db --complete $COMP_CWORD "${COMP_WORDS[@]}") 

    # Turn case-insensitive matching temporarily on, if necessary. 
    local nocasematchWasOff=0 
    shopt nocasematch >/dev/null || nocasematchWasOff=1 
    ((nocasematchWasOff)) && shopt -s nocasematch 

    # Loop over words in list and search for case-insensitive prefix match. 
    local w matches=() 
    for w in $words; do 
     if [[ "$w" == "$token"* ]]; then matches+=("$w"); fi 
    done 

    # Restore state of 'nocasematch' option, if necessary. 
    ((nocasematchWasOff)) && shopt -u nocasematch 

    COMPREPLY=("${matches[@]}") 
} 
+0

La soluzione di cui sopra non sembra essere del tutto corretto in quanto restituisce solo prima partita al posto di tutte le partite . rimuovere la "pausa" dovrebbe risolverlo. Un altro problema è che questo non funziona con garbo su versioni precedenti di bash che non hanno affatto l'opzione nocasematch. Non so quale sarebbe la soluzione migliore, ma ho usato il mio script locale SHOPT = $ (shopt -p) locale IGNORE_CASE = 0 [["$ {SHOPT # * shopt -u nocasematch} "==" $ SHOPT "]] || IGNORE_CASE = 1 – Neuron

+0

Grazie, @Neuron: ho aggiornato il codice per restituire tutte le corrispondenze. Per quanto riguarda l'opzione 'nocasematch' non disponibile (sai in quale versione è stata introdotta?): Si potrebbe usare il test e poi, in assenza dell'opzione, applicare' tr [: upper:] [: lower :] 'tecnica nel corpo del ciclo' for'. Un modo un po 'più conciso di eseguire il test di opzione della disponibilità è: 'haveNoCaseMatch locale = 0 \ n [[-z "$ (shopt -q nocasematch 2> & 1)"]] && haveNoCaseMatch = 1 ' – mklement0

+0

si dovrebbe scrivere che come COMPREPLY = ("$ {partite [@]}"), altrimenti si romperà le opzioni più parole (ad esempio, i nomi dei file) – Orwellophile