Actualmente estoy trabajando en un script de shell al que llamé makeyourself.sh
(vinculado a /usr/bin/mys
) que instala automáticamente un paquete Debian desde la fuente (a través de apt-get source -b $1
).
Entonces decidí agregar una función de autocompletar para el nombre del paquete que se proporciona como primer parámetro: sudo mys panth<tab><tab>
luego debería enumerar todos los paquetes que comienzan con panth
; mi intento fue el siguiente:
complete -C "apt-cache --no-generate pkgnames" mys
Pero no parece funcionar: cuando presiono la tecla tab como se mencionó anteriormente, cambia el parámetro a mys
, lo que me devuelve sudo mys mys
.
¿Qué estoy haciendo mal? ¿Tengo que especificar la ubicación en el comando donde complete
debo insertar la cadena que se completará, como {}
o $1
?
Utilizo ElementaryOS, una distribución de Linux basada en Ubuntu. El script es un script de shell estándar *.sh que utiliza el estándar#!/bin/bash
Respuesta1
Como sospecha, el comando recibe información sobre qué completar. Esto está documentado en el manual, pero no en eldocumentación del complete
edificio, necesitas leer elsección introductoria sobre finalización programable.
se invoca cualquier función o comando de shell especificado con las opciones
-F
y .-C
Cuando se invoca el comando o función, a las variablesCOMP_LINE
,COMP_POINT
,COMP_KEY
yCOMP_TYPE
se les asignan valores como se describe arriba (consulteVariables de bash). Si se invoca una función de shell, también se configuran las variablesCOMP_WORDS
y .COMP_CWORD
Cuando se invoca la función o el comando, el primer argumento es el nombre del comando cuyos argumentos se están completando, el segundo argumento es la palabra que se está completando y el tercer argumento es la palabra que precede a la palabra que se está completando en la línea de comando actual. No se realiza ningún filtrado de las terminaciones generadas con respecto a la palabra que se está completando; la función o comando tiene total libertad para generar las coincidencias.
Entonces el comando se llama con tres parámetros:
- El nombre del comando, para que pueda combinar terminaciones de comandos similares en un solo script.
- La palabra que se va a completar, para que pueda limitar la salida al prefijo que se filtrará de todos modos.
- La palabra anterior: útil, por ejemplo, para completar opciones.
Los mismos parámetros se pasan a las funciones de finalización ( complete -F somefunction
). Tenga en cuenta que ya sea que utilice una función o un comando, es su trabajo filtrar las coincidencias deseadas.
Con lo que intentaste, el comando que termina ejecutándose es apt-cache --no-generate pkgnames mys '' mys
. Esto imprime una lista de nombres de paquetes que comienzan con mys
( apt-cache pkgnames
solo mira el primer operando). El prefijo común más largo es mys
, por lo que bash comienza a completarse mys
y espera que selecciones la siguiente letra.
Dado que los argumentos se agregan al comando (no se pasan como parámetros posicionales; el argumento -C
se analiza como un comando de shell), no existe una manera fácil de analizarlos. La solución más sencilla es utilizar una función contenedora.
_mys () {
COMPREPLY=$(apt-cache --no-generate pkgnames "$2")
}
complete -F _mys mys