Skip to content

Instantly share code, notes, and snippets.

@DanielFGray
Last active May 2, 2023 08:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DanielFGray/ab9801481f92e19b6e87321ede56c91e to your computer and use it in GitHub Desktop.
Save DanielFGray/ab9801481f92e19b6e87321ede56c91e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
cleanup() {
tput cnorm > /dev/tty
stty "$_stty" <> /dev/tty
}
_stty=$(stty -g < /dev/tty)
trap cleanup exit SIGTERM SIGQUIT
menu() {
local tput current hl items i keys
declare -A tput=(
[cuu1]=$(tput cuu1) # up one line
[cud1]=$(tput cud1) # down one line
[sgr0]=$(tput sgr0) # reset color
[setaf_1]=$(tput setaf 1) # red
[setaf_2]=$(tput setaf 2) # green
[civis]=$(tput civis) # hide cursor
# [cnorm]=$(tput cnorm) # show cursor
[ed]=$(tput ed) # erase down
)
printf '%s' "${tput[civis]}" > /dev/tty
current=0
hl=(' ' "> ${tput[setaf_2]}")
mapfile -t items
while :; do
[[ $1 == '-p' && -n "$2" ]] && printf '%s\n' "$2" > /dev/tty
for (( i = 0; i < ${#items[@]}; i++ )) do
printf '%s\n' "${hl[i==current]}${items[i]}${tput[sgr0]}" > /dev/tty
done
read -rsn1 keys < /dev/tty
case "$keys" in
j|J) (( current < ${#items[@]}-1 )) && (( current ++ )) ;;
k|K) (( current > 0 )) && (( current -- )) ;;
esac
[[ $1 == '-p' && -n "$2" ]] && printf '%s' "${tput[cuu1]}" > /dev/tty
for (( i = 0; i < ${#items[@]}; i++ )) do
printf '%s%s' "${tput[cuu1]}" "${tput[ed]}" > /dev/tty
done
if [[ -z "$keys" ]]; then
printf '%s%s' "${items[current]}" "${tput[ed]}"
break
fi
done
cleanup
}
options=$(printf 'foo\nbar\nbaz\nquux\n')
choice1=$(menu -p 'choose a word:' <<< "$options")
choice2=$(printf '%d\n' {1..5} | menu -p 'choose a number:' )
[[ -n "$choice1" ]] &&
printf 'you chose the word: %s\n' "$choice1"
[[ -n "$choice2" ]] &&
printf 'you chose the number: %s\n' "$choice2"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment