2012-05-09 9 views
6

¿Hay alguna manera de especificar que un comando en particular tenga insensibilidad de mayúsculas y minúsculas, sin activar la insensibilidad de mayúsculas (al menos para ese shell)?Configuración de la insensibilidad de mayúsculas y minúsculas para la finalización de bashs comando por comando

En mi caso particular, tengo una pequeña aplicación que me da acceso a la línea de comandos a una base de datos de direcciones de correo electrónico, así que escriba:

db get email john smith 

y vuelve atrás con dirección de correo electrónico de John Smith. Así que me las he arreglado para permitir la finalización en gran medida dentro de la aplicación: establecer

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

obras que me permita a tabuladores completa get y email. Sin embargo, si escribo j<tab>, se niega porque en la base de datos de correo electrónico está debidamente en mayúscula. Me gustaría obtener bash para completar esto de todos modos. (Si uso un capital J, funciona)

En su defecto, puedo tener mi opción --complete cambiar el caso de su respuesta haciendo coincidir la entrada, supongo, pero idealmente la línea de comando coincidiría con la base de datos si todo posible.

Tenga en cuenta que tengo esto funcionando dentro de la aplicación cuando uso readline, solo está interactuando con bash que parece ser un problema.

Respuesta

6

De hecho, parece que no hay forma de que compgen haga coincidir mayúsculas y minúsculas con la lista de palabras (-W). Veo las siguientes soluciones:

Solución simple: Traduzca primero la lista de palabras y el token de entrada a minúsculas en primer lugar. Nota: Esto es solo una opción si es aceptable tienen todas las terminaciones se convierten en minúsculas.

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")) 
} 

mejor, pero la solución más elaborada: Cómo crear sus propios, entre mayúsculas y minúsculas lógica de coincidencia:

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 solución anterior no parece ser del todo correcta, ya que devuelve sólo el primer partido en lugar de todos los partidos . eliminar el "descanso" debería resolver eso. Otro problema es que esto no funciona correctamente en versiones anteriores de bash que no tienen ninguna opción de casecasechch. No sé cuál sería la mejor solución para eso, pero utilicé en mi secuencia de comandos SHOPT local = $ (shopt -p) local IGNORE_CASE = 0 [["$ {SHOPT # * shopt -u nocasematch} "==" $ SHOPT "]] || IGNORE_CASE = 1 – Neuron

+0

Gracias, @Neuron: He actualizado el código para devolver todas las coincidencias. En cuanto a la opción 'nocasematch' que no está disponible (¿sabes en qué versión se introdujo?): Se podría usar tu prueba y luego, en ausencia de la opción, aplicar el' tr [: upper:] [: lower :] 'técnica en el cuerpo del bucle' for'. Una forma un poco más concisa de realizar la prueba de disponibilidad de opción es: 'local haveNoCaseMatch = 0 \ n [[-z" $ (shopt -q nocasematch 2> & 1) "]] && haveNoCaseMatch = 1 ' – mklement0

+0

Debe escribir eso como COMPREPLY = ("$ {matches [@]}") de lo contrario, romperá las opciones de varias palabras (p. ej., nombres de archivos) – Orwellophile

Cuestiones relacionadas