1 votes

Question sur les menus de sélection en bash

Avant que vous ne me disiez "il y a déjà des tonnes de guides sur ce sujet", sachez que j'ai effectivement réalisé un menu de sélection et qu'il fonctionne.

Cependant, il y a une chose qui me rend fou. La façon dont j'ai codé ce menu actuellement est ce qui se produit :

1) L'utilisateur choisit une option 2) Le menu se recharge 3) Une astérisque apparaît à côté de l'option pour indiquer qu'elle est sélectionnée.

Problème :

L'utilisateur doit sélectionner chaque option une par une, le menu se rechargeant après chaque sélection. Comme vous pouvez l'imaginer, cela est lent et rend la fenêtre du terminal désordonnée.

Ce que je veux :

L'utilisateur doit pouvoir taper 1-4 ou 1,4,7 pour sélectionner plusieurs options.

Ce que je ne veux pas :

Une queue de cheval ou un dialogue. En fait, j'en ai fait un aussi et il est impeccable. Cependant, je préférerais ne pas l'utiliser si je peux l'éviter ou l'utiliser comme solution de secours. Je pense que ce serait plus convivial (sans parler du fait que c'est plus facile pour les yeux) de ne pas en utiliser.

Code :

#                           #
### CSGO Plugin selection ###
#                           #

options=(
         "SurfTimer - 2.02 - Core of this server."
         "AutoFileLoader - Caches all material, model, and sound files for players to download."
         "Chat-Procesor - Chat Processing Plugin"
         "Dynamic - PreReq for many plugins to work properly."
         "FixAngles - Fixes 'wrong angle on material' error that gets spammed in console when using store items"
         "Mapchooser_Extended - Map Vote System. See maplist.cfg/mapcycle.cfg.")
....

menu() {
    echo "Avaliable options:"
    for i in ${!options[@]}; do
        printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
    done
    [[ "$msg" ]] && echo "$msg"; :
}

prompt="Check an option (again to uncheck, ENTER when done): "
while menu && read -rp "$prompt" num && [[ "$num" ]]; do
    [[ "$num" != *[![:digit:]]* ]] &&
    (( num > 0 && num <= ${#options[@]} )) ||
    { msg="Invalid option: $num"; continue; }
    ((num--)); msg="${options[num]} was ${choices[num]:+un}checked"
    [[ "${choices[num]}" ]] && choices[num]="" || choices[num]="+"
done

printf "You selected"; msg=" nothing"
for i in ${!options[@]}; do
    [[ "${choices[i]}" ]] && { printf " %s" "${options[i]}"; msg=""; }
done

2voto

dessert Points 36815

Je le ferais comme suit :

menu() {
    clear
    echo "Available options:"
    for i in ${!options[@]}; do
        printf "%3d%s) %s\n" $((i+1)) "${choices[i]:- }" "${options[i]}"
    done
}

prompt="Check an option (again to uncheck, ENTER when done): "
while menu && read -rp "$prompt" num && [[ "$num" ]]; do
    [[ "$num" =~ "-" ]] && num=$(seq $(sed -E 's/(\d*)-(\d*)/\1 \2/' <<<"$num"))
    for i in $num; do
      ((i--))
      [[ "${choices[i]}" ]] && choices[i]="" || choices[i]="*"
    done
done

Cela permet de vérifier si $num contient un trait d'union et construit la plage si nécessaire, puis boucle simplement sur le contenu du fichier $num afin que les utilisateurs puissent donner plusieurs options à la fois avec par exemple 1 2 4 ou 1-4 (mais pas une combinaison de ceux-ci !). Il faut également clear s le terminal à chaque fois avant l'impression du menu.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X