Вопрос по выбору меню в bash
Прежде чем вы скажете мне, что "уже есть тонны руководств по этому вопросу", знайте, что у меня действительно есть меню выбора, и оно работает.
Однако есть одна вещь, которая сводит меня с ума. То, как у меня есть это меню в настоящее время, вот что происходит:
1) Пользователь выбирает опцию 2) Меню перезагружается 3) Опция имеет звездочку рядом с ней, чтобы показать, что она выбрана.
Проблема:
Пользователь должен выбирать каждый параметр по одному после перезагрузки меню после каждого выбора. Как вы можете себе представить, это медленно и портит окно терминала.
Что я хочу:
Пользователь должен иметь возможность ввести 1-4 или 1,4,7, чтобы выбрать несколько вариантов.
Что я не хочу:
Уиптейл или Диалог. Я действительно сделал один, и это безупречно. Однако я предпочел бы не использовать это, если я могу помочь или использовать это как запасной вариант. Я думаю, что было бы более удобным (не говоря уже о том, что проще), не использовать его.
Код:
# #
### 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
1 ответ
Я бы сделал это следующим образом:
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
Это тесты, если $num
содержит дефис и при необходимости строит диапазон, а затем просто перебирает содержимое $num
так что пользователи могут дать несколько вариантов одновременно, например, с 1 2 4
или же 1-4
(но не комбинация тех!). Это также clear
s терминал каждый раз перед печатью меню.