Voici un bout de code que j’ai créé ces derniers jours :
text_menu_description[1]="Rooter votre tablette"
text_menu_description[2]="Enlever le root de votre tablette"
text_menu_description[3]="Flasher une image officielle de votre tablette"
text_menu_description[4]="Flasher une Custom ROM dans votre tablette"
text_menu_description[5]="Sauvegarder votre tablette"
text_menu_description[6]="Redémarrer votre tablette"
text_menu_description[7]="Quitter le programme !"
text_menu_name[1]="ROOT"
text_menu_name[2]="UNROOT"
text_menu_name[3]="FLASH"
text_menu_name[4]="CUSTOM"
text_menu_name[5]="BACKUP"
text_menu_name[6]="REBOOT"
text_menu_name[7]="EXIT"
function display_menu() {
if [[ "${ZENITY}" -ne 0 ]]; then
while :
do
choice=$( echos_menu | zenity_list "${text_welcome}" "${title_welcome}" "${count['name']}")
case $choice in
"${text_menu_name[1]}") root_tablet ;;
"${text_menu_name[2]}") unroot_tablet ;;
"${text_menu_name[3]}") proceed_initial_rom ;;
"${text_menu_name[4]}") proceed_custom_rom ;;
"${text_menu_name[5]}") save_tablet ;;
"${text_menu_name[6]}") reboot_tablet ;;
"${text_menu_name[7]}") display_mssg "n" "${text_goodbye}" "${title_goodbye}"; exit 0 ;;
esac
done
elif [[ "${DIALOG}" -ne 0 ]]; then
while :
do
echos_menu
dialog_menu "${text_welcome}" "${title_welcome}" "${count['name']}"
rm "${FILE_TMP}.menu"
if [[ $? -eq 0 ]]; then
choice=$(<"${FILE_TMP}")
case $choice in
"${text_menu_name[1]}") root_tablet ;;
"${text_menu_name[2]}") unroot_tablet ;;
"${text_menu_name[3]}") proceed_initial_rom ;;
"${text_menu_name[4]}") proceed_custom_rom ;;
"${text_menu_name[5]}") save_tablet ;;
"${text_menu_name[6]}") reboot_tablet ;;
"${text_menu_name[7]}") display_mssg "n" "${text_goodbye}" "${title_goodbye}"; exit 0 ;;
esac
fi
done
else
while :
do
echo "${title_welcome}"
PS3="${text_welcome}"
select choice in "${text_menu_description[@]}"
do
case $REPLY in
1) root_tablet ;;
2) unroot_tablet ;;
3) flash_initial_rom ;;
4) flash_custom_rom ;;
5) save_tablet ;;
6) reboot_tablet ;;
7|q|Q) display_mssg "n" "${text_goodbye}" "${title_goodbye}"; exit 0 ;;
esac
done
done
fi
if [[ $? -eq 1 ]]; then display_mssg "n" "${text_goodbye}" "${title_goodbye}"; fi
}
function echos_menu() {
i=1
if [[ $DIALOG -eq 1 ]]; then
while [ $i -le ${#text_menu_name[@]} ]; do
echo "${text_menu_name[$i]}|${text_menu_description[$i]}" >> "${FILE_TMP}.menu"
let "i = $i + 1";
done
while IFS="|" read col1 col2 || [ -n "$col1" ]; do
menu+=("$col1" "$col2")
done < "${FILE_TMP}.menu"
else
while [ $i -le ${#text_menu_name[@]} ]; do
echo "${text_menu_name[$i]}";
echo "${text_menu_description[$i]}";
let "i = $i + 1";
done
fi
unset i;
}
function zenity_list() {
height=$(bc <<< "$3 * 45 + 5")
zenity --column="${text_column_name}" --column="${text_column_description}" \
--list --height="${height}" --width=500 \
--text "$1" --title "$2"
}
La question que je me pose est la suivante : est-il possible d’écrire différemment ma function display_menu pour que là où il y a les ‘case’, ce soit géré dynamiquement … par gestion d’une boucle, par exemple - quite à renommer les fonctions appelées selon la valeur contenue dans le tableau ‘text_menu_name’
Avant même de penser aux boucles, il faudrait factoriser tes 3 cas : d’abord récupérer le choix de l’utilisateur en fonction des méthodes disponibles, le normaliser éventuellement (3ème cas où on n’obtient pas un texte [mono]ROOT/UNROOT…[/mono] mais un nombre correspondant à la position dans le tableau – ne pas oublier de traiter le cas [mono]Q[/mono]), et enfin seulement traiter le choix normalisé.
Grosso modo l’algo pourrait ressembler à :
while true; do
CHOIX_TEXTE="" # s'assurer que le choix est invalide
if [ ZENITY ]; then
CHOIX_TEXTE="$(récupérer le choix via Zenity)"
elif [ DIALOG ]; then
CHOIX_TEXTE="$(récupérer le choix via Dialog)"
else
CHOIX_NUM="$(récupérer le choix via Select)"
CHOIX_TEXTE="$(récupérer le texte correspondant à CHOIX_NUM)"
fi
case $CHOIX_TEXTE in
...
esac
done
Une fois que tu auras ça, tu n’auras plus qu’à transformer ton [mono]case[/mono] en [mono]for[/mono] (ta question initiale) à l’aide d’un algo du genre :
for INDEX in {1..${text_menu_name[#]}}; do
if [ "$CHOIX_TEXTE" = "${text_menu_name[$INDEX]}" ]; then
"${text_menu_command[$INDEX]}" # pas besoin d'expliquer je pense, le nom de variable est clair ;)
break
fi
done
Voilà, c’est l’idée générale.
Je te remercie …
Comme quoi, cela fait du bien de faire regarder par d’autres yeux … @force d’être dedans, je n’avais même plus remarqué que je pouvais circoncire mon code …
Bref, voilà la touche actuelle :
function display_menu() {
while true; do
if [[ "${ZENITY}" -ne 0 ]]; then
choice=$( echos_menu | zenity_list "${text_welcome}" "${title_welcome}" "${count['name']}")
elif [[ "${DIALOG}" -ne 0 ]]; then
echos_menu
dialog_menu "${text_welcome}" "${title_welcome}" "${count['name']}"
[[ $? -eq 0 ]] && choice=$(<"${FILE_TMP}")
rm "${FILE_TMP}.menu"
else
echo "${title_welcome}"
PS3="${text_welcome} ${text_quit} "
select menu in "${text_menu_description[@]}"
do
if [[ "$REPLY" == "q" || "$REPLY" == "Q" ]]; then
choice="${text_menu_name[${#text_menu_name[*]}]}"
break
else
choice="${text_menu_name[$REPLY]}"
break
fi
done
unset menu
fi
if [[ "$choice" ]]; then
for (( x=1 ; x <= ${#text_menu_name[@]} ; x++ )); do
if [[ "$choice" == "${text_menu_name[$x]}" ]]; then
"${text_menu_name[$x]}"
break
fi
done
unset x
fi
done
[[ $? -eq 1 ]] && EXIT
}
Comme tu le vois, la seule partie que je ne suis pas arrivé à mettre en place - si je puis m’exprimer ainsi - est ta boucle for :
Cela ne voulait pas fonctionner - donc en comprenant le principe, je l’ai transcris ainsi :
[quote=« PengouinPdt »]Comme tu le vois, la seule partie que je ne suis pas arrivé à mettre en place - si je puis m’exprimer ainsi - est ta boucle for :
for INDEX in {1..${text_menu_name[#]}}; do
Cela ne voulait pas fonctionner[/quote]
Ça m’étonne pas plus que ça : j’ai du mal à mémoriser les recoins de la syntaxe shell/bash, et j’avais pas le temps d’aller fouiner dans la doc. D’où le fait que je t’aie filé des algos plutôt que du code qui marche.
Effectivement ta manière de faire la boucle est bien plus claire (sans compter qu’elle marche, elle ).
Détail : dans le 3ème cas ([mono]select[/mono]) tu n’as pas besoin des deux [mono]break[/mono] à l’intérieur du [mono]if/else[/mono]. Un seul [mono]break[/mono] après le [mono]fi[/mono] suffit.
Et je maintiens qu’il y a besoin du [mono]choice=« »[/mono] au minimum pour le deuxième cas ([mono]dialog[/mono]) car dans cette branche il est possible que [mono]choice[/mono] ne soit jamais modifié, et donc garde la valeur qu’il avait lors de la précédente itération du [mono]while[/mono].
Mais perso j’effacerais cette variable au début du [mono]while[/mono] plutôt qu’au début du deuxième cas, ça évitera de l’oublier si jamais un jour tu rajoutes une autre méthode de choix des options qui pose le même problème.
Il est tard, je suis probablement très fatigué, mais c’est quoi la différence entre ça :
if [[ "$choice" ]]; then
for (( x=1 ; x <= ${#text_menu_name[@]} ; x++ )); do
if [[ "$choice" == "${text_menu_name[$x]}" ]]; then
"${text_menu_name[$x]}"
break
fi
done
unset x
fi
et
if [[ "$choice" ]]; then
"$choice"
fi
Pour la boucle [mono]foreach[/mono] (mêm si je répugne à l’utiliser avec un break au milieu), la bonne façon de l’écrire c’est :
for name(in "${text_menu_name[@]}" ; do
if [[ "$choice" == "${name}" ]]; then
"${name}"
break
fi
done
J’ai pas lu tout le code, mais cette boucle me paraît louche, cette condition aussi et l’instruction au milieu aussi.
quote="syam"
Et je maintiens qu’il y a besoin du [mono]choice=""[/mono] au minimum pour le deuxième cas ([mono]dialog[/mono]) car dans cette branche il est possible que [mono]choice[/mono] ne soit jamais modifié, et donc garde la valeur qu’il avait lors de la précédente itération du [mono]while[/mono].
Mais perso j’effacerais cette variable au début du [mono]while[/mono] plutôt qu’au début du deuxième cas, ça évitera de l’oublier si jamais un jour tu rajoutes une autre méthode de choix des options qui pose le même problème.[/quote]
@syam: Là, sincèrement, je ne te comprends pas.
Dans ma condition [mono]Dialog[/mono], j’ai bien ma variable choice …
Et, pourquoi pas tu de son effacement ?
@MisterFreez: Ahhh, c’est la réflexion que je me suis faite hier soir …
Pourquoi faire la dernière instruction de boucle for … alors que, justement, la variable choice détient la bonne valeur …
Donc :
[quote=“PengouinPdt”]@syam: Là, sincèrement, je ne te comprends pas.
Dans ma condition [mono]Dialog[/mono], j’ai bien ma variable choice …
C’est justement cette ligne qui pose problème.
[mono]choice[/mono] n’est modifié que si [mono][[ $? -eq 0 ]][/mono]. Donc si cette condition est fausse, [mono]choice[/mono] conserve sa valeur actuelle c’est à dire celle qui lui a été assignée lors de la précédente itération du [mono]while[/mono].