Je voudrais créer une règle d'achèvement pour la liste des paramètres séparés par des virgules. Par exemple, j'ai une commande qui reçoit la liste des noms de serveurs:
myscript -s name1,name2,name3
En ce moment, j'ai réussi à écrire après l'achèvement:
_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
}
Mais il a au moins 2 problèmes:
- Les suggestions de valeur actuelle incluent toutes les valeurs précédentes dans leur préfixe.
- Il ne prend pas en compte les valeurs en double.
Quelles sont les meilleures pratiques pour de tels cas? Peut-être que bash-complétions a des fonctions groupées pour les listes csv?
bash
autocomplete
diffycat
la source
la source
IFS=, LIST=("$VARIABLE")
où $ VARIABLE contient vos valeurs séparées par des virgules.$VARIABLE
, sinon la rupture de mot ne se produit pas. il suffit d'utiliserIFS=, LIST=($VARIABLE)
.Réponses:
Il n'y a fondamentalement aucun moyen de résoudre les problèmes que vous décrivez, car bash utilise les valeurs
COMPREPLY
directement dans l'affichage, puis pour remplacer le texte de l'utilisateur - tandis que pour obtenir ce que vous voulez, vous devez d'abord générer les complétions possibles (juste le supplément noms de serveur, sans le préfixe) pour bash à afficher, puis lorsque bash est sur le point de remplacer le texte de l'utilisateur par la plus longue chaîne non conflictuelle, vous en aurez besoin pour appeler à nouveau votre script pour générer le texte avec le préfixe - et bash n'a aucune facilité pour cela.Le mieux que je pourrais trouver est de
COMPREPLY
générer le seul mot ayant le préfixe entier (COMPREPLY=( "${prefix},"$(compgen -W "${servers[@]}" -- ${realcur}) )
), de sorte que s'il n'y a qu'une seule complétion possible, il se termine automatiquement correctement, tandis que s'il y a plus d'une complétion possible , alors bash ne supprimera pas ce qui a été tapé jusqu'à présent (car le premier mot dansCOMPREPLY
a le préfixe entier et correspond donc au texte actuellement tapé et sera sélectionné par bash pour remplacer le texte de l'utilisateur) et affichera les options sans le préfixe - sauf pour ce seul mot qui contient déjà le préfixe, la sortie ressemblera à ceci:"apple" comme trié en dernier dans les options de complétion car il porte le préfixe qui commence par "b" - très déroutant. Je ne recommande donc pas de faire cela.
En ce qui concerne les doublons - afin de ne pas afficher les doublons, il vous suffit de pénétrer
$prefix
dans sa partie (facileIFS="," prefix_parts=($prefix)
:) puis de les parcourir et de ne laisser que$servers
les noms qui ne sont pas déjà répertoriés. Son fastidieux à taper, donc je ne le montrerai pas ici, mais relativement trivial donc je suis sûr que vous pouvez gérer :-).Pour résumer, je ne pense pas que vous devriez utiliser des valeurs séparées par des virgules pour les options d'entrée, du moins si vous vous attendez à ce que bash vous aide à terminer.
Vous pouvez prendre en charge un format d'options qui ressemble à ceci:
command -s <server> [<server> [..]]
puis pour terminer les entrées autres que celle immédiatement après l'-s
option, parcourez simplement le$COMP_WORDS
tableau$COMP_CWORD
jusqu'à ce que vous trouviez une option (chaîne qui correspond-*
) et si ses "-s" puis vous devez compléter le nom du serveur.la source