Me gustaría crear una regla de finalización para la lista de parámetros separados por comas. Por ejemplo, tengo un comando que recibe la lista de nombres de servidores:
myscript -s name1,name2,name3
En este momento he logrado escribir después de completar:
_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
}
Pero tiene al menos 2 problemas:
- Las sugerencias para el valor actual incluyen todos los valores anteriores en su prefijo.
- No considera valores duplicados.
¿Cuáles son las mejores prácticas para tales casos? ¿Quizás bash-completions tiene algunas funciones incluidas para las listas csv?
bash
autocomplete
diffycat
fuente
fuente
IFS=, LIST=("$VARIABLE")
donde $ VARIABLE contiene sus valores separados por comas.$VARIABLE
, de lo contrario no se romperán las palabras. solo usaIFS=, LIST=($VARIABLE)
.Respuestas:
Básicamente, no hay forma de solucionar los problemas que describe, porque bash usa los valores
COMPREPLY
directamente en la pantalla y luego reemplaza el texto del usuario, mientras que para obtener lo que desea, primero debe generar las posibles terminaciones (solo las nombres de servidor, sin el prefijo) para que se muestre bash, luego cuando bash está a punto de reemplazar el texto del usuario con la cadena no conflictiva más larga, necesitará que vuelva a llamar a su script para generar el texto con el prefijo - y bash no tiene facilidades para eso.Lo mejor que se me ocurre es que
COMPREPLY
se genere solo la primera palabra con el prefijo completo (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), de modo que si solo hay una posible finalización, se complete automáticamente correctamente, mientras que si hay más de una posible finalización , bash no eliminará lo que se escribió hasta el momento (porque la primera palabraCOMPREPLY
tiene el prefijo completo y, por lo tanto, coincide con el texto actualmente escrito y será seleccionado por bash para reemplazar el texto del usuario) y mostrará las opciones sin el prefijo, excepto para esa palabra que ya contiene el prefijo, por lo que la salida se verá así:"apple" como se ordenó en último lugar en las opciones de finalización porque lleva el prefijo que comienza con "b", muy confuso. Así que no recomiendo hacer eso.
Con respecto a los duplicados: para no mostrar duplicados, solo necesita dividir
$prefix
su parte (fácilIFS="," prefix_parts=($prefix)
:) y luego iterar sobre ellos y solo dejar en$servers
los nombres que aún no están listados. Es tedioso escribir, así que no lo mostraré aquí, pero es relativamente trivial, así que estoy seguro de que puedes administrar :-).Para resumir, no creo que deba usar valores separados por comas para las opciones de entrada, al menos si espera que bash lo ayude a completarlo.
Puede admitir un formato de opciones como este:
command -s <server> [<server> [..]]
y luego, para completar entradas que no sean la inmediatamente posterior a la-s
opción, simplemente escanee a través de la$COMP_WORDS
matriz$COMP_CWORD
hasta encontrar una opción (cadena que coincida-*
) y si es "-s", entonces debe completar el nombre del servidor.fuente