We have a simple menu with prompt of menu numbers to user.
It is still under construction.
Is there a way to "count" the menu choices so the prompt maximum count can be changed dynamically?
See attached TODO note in code
read_options(){
local choice
# the max choice is static
#TODO add max choice as variable
read -p "Enter choice [ 1 - 3] " choice
case $choice in
1) one ;;
2) two ;;
3) three ;;
4) select_command_DEBUG "pass command to function" "lsusb" ;; #pass$
5) select_command_DEBUG " menu 5 pass list_wlan_interfaces() to func$
" list_wlan_interfaces " ;;
6) pause ;; # back to GUI exit 0;;
*) echo -e "${RED}Error...${STD}" && sleep 2
esac
}
#!/usr/bin/bash
files='*sh';
actions='cat edit quit'
PS3="Pick one of the above [${actions}]: "
TMOUT=10
select i in ${actions}
do
case $i in
cat) eval cat "${files}" ;;
edit) eval ${EDITOR-vi} "${files}" ;;
quit) break ;;
"") print -u2 you must select one of the above [${actions}] ;;
esac
done
Sure, but it just replaces the "menu" static text structure with static array.
Since "case" gets executed in one pass I would have to make two passes. Make first one to search for invalid option and somehow count the number of steps taken until the "not found option" error is executed.
Hm.. I don't quite understand the comments and the count ing part in particular.
You must have the list of available menu choices stored somewhere: hardwired, read from file etc... I've just provided a sample using select with the hardwired menu choices in the form of an array - this is just a sample showing the select capability WITH the dynamic prompt choices.
What are you trying to do with count ing?
I'm confused as what you're after. You'll have to explain it again...
select uses two variables: the one you pass it; and REPLY. Consider this :
$ PS3='enter choice '
$ select choice in bish bash bosh
> do
> printf "choice is %s; REPLY is %s\n" "$choice" "$REPLY"
> done
1) bish
2) bash
3) bosh
enter choice 1
choice is bish; REPLY is 1
enter choice 2
choice is bash; REPLY is 2
enter choice 3
choice is bosh; REPLY is 3
enter choice 4
choice is ; REPLY is 4
enter choice fred
choice is ; REPLY is fred
enter choice
choice contains the keyword that you want as a menu item; REPLY contains what was actually entered.
Bash has hash arrays, so you could do something like:
declare -A mymenu
...
mymenu["some_key"]="some value"
...
select mychoice in "${!mymenu[@]}"
do
if [[ -z "$mychoice" ]]
then
echo "bad choice %s - try again\n" "$REPLY"
continue
fi
# use $mychoice or ${mymenu[$mychoice]} here
done
EDIT
Okay, after re-reading your original post I realise I was misinterpretting what you meant by a dynamic menu.
read_options(){
local choice
local -a choices one two three debug pause
local PS3
printf -vPS3 "Enter choice [1 - %d] " ${#choices}
# the max choice is static
#TODO add max choice as variable
# read -p "Enter choice [ 1 - 3] " choice
select choice "${choices[@]}"
do
#case $choice in
case $REPLY in
1) one ;;
2) two ;;
3) three ;;
4) select_command_DEBUG "pass command to function" "lsusb" ;; #pass$
5) select_command_DEBUG " menu 5 pass list_wlan_interfaces() to func$
" list_wlan_interfaces " ;;
6) pause ;; # back to GUI exit 0;;
*) echo -e "${RED}Error...${STD}" && sleep 2
esac
done
}
Your "dynamic" menu isn't very flexible as you have problems when you want to add something in the middle.
Consider
select choice in fred ginger mary
do case choice in
fred) do_fred ;;
ginger) do_ginger ;;
mary) do_mary ;;
esac
done
select choice in fred mike ginger mary
do case choice in
fred) do_fred ;;
ginger) do_ginger ;;
mary) do_mary ;;
mike) do_mike ;;
esac
done
I didn't have to put the case item "mike" in the same position in the case statement; I can also move the other options around and leave the case statement as-is. No, you don't have the number of items readily available (unless you use the array above, which could make the select statement more readable) but the choice variable will be empty if the user enters the wrong thing.
In my opinion that makes select more flexible than your menu.