diff --git a/lib/skel/.bashrc.d/functions b/lib/skel/.bashrc.d/functions index 96704a8..74ff439 100644 --- a/lib/skel/.bashrc.d/functions +++ b/lib/skel/.bashrc.d/functions @@ -102,11 +102,11 @@ fail(){ } pushd(){ - command pushd "$@" > /dev/null + command pushd "$@" > /dev/null } popd(){ - command popd "$@" > /dev/null + command popd "$@" > /dev/null } popdfail(){ @@ -128,3 +128,100 @@ ctrl_c(){ # ensure ctrl-c to cancel script ends the entire process and not just the current function trap ctrl_c INT + +# Renders a text based list of options that can be selected by the +# user using up, down and enter keys and returns the chosen option. +# +# Arguments : list of options, maximum of 256 +# "opt1" "opt2" ... +# Return value: selected index (0 for opt1, 1 for opt2 ...) +select_option(){ + + # little helpers for terminal print control and key input + ESC=$( printf "\033") + cursor_blink_on() { printf "$ESC[?25h"; } + cursor_blink_off() { printf "$ESC[?25l"; } + cursor_to() { printf "$ESC[$1;${2:-1}H"; } + print_option() { printf " $1 "; } + print_selected() { printf " $ESC[7m $1 $ESC[27m"; } + get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } + key_input() { read -s -n3 key 2>/dev/null >&2 + if [[ $key = $ESC[A ]]; then echo up; fi + if [[ $key = $ESC[B ]]; then echo down; fi + if [[ $key = "" ]]; then echo enter; fi; } + + # initially print empty new lines (scroll down if at bottom of screen) + for opt; do printf "\n"; done + + # determine current screen position for overwriting the options + local lastrow=`get_cursor_row` + local startrow=$(($lastrow - $#)) + + # ensure cursor and input echoing back on upon a ctrl+c during read -s + trap "cursor_blink_on; stty echo; printf '\n'; exit" 2 + cursor_blink_off + + local selected=0 + while true; do + # print options by overwriting the last lines + local idx=0 + for opt; do + cursor_to $(($startrow + $idx)) + if [ $idx -eq $selected ]; then + print_selected "$opt" + else + print_option "$opt" + fi + ((idx++)) + done + + # user key control + case `key_input` in + enter) break;; + up) ((selected--)); + if [ $selected -lt 0 ]; then selected=$(($# - 1)); fi;; + down) ((selected++)); + if [ $selected -ge $# ]; then selected=0; fi;; + esac + done + + # cursor position back to normal + cursor_to $lastrow + printf "\n" + cursor_blink_on + + return $selected +} + +# Example for above select_option +#echo "Select one option using up/down keys and enter to confirm:" +#echo + +#options=("one" "two" "three") + +#select_option "${options[@]}" +#choice=$? + +#echo "Choosen index = $choice" +#echo " value = ${options[$choice]}" + +select_opt(){ + select_option "$@" 1>&2 + local result=$? + echo $result + return $result +} + +# Examples for above select_opt +#case `select_opt "Yes" "No" "Cancel"` in +# 0) echo "selected Yes";; +# 1) echo "selected No";; +# 2) echo "selected Cancel";; +#esac + +#options=("Yes" "No" "${array[@]}") # join arrays to add some variable array +#case `select_opt "${options[@]}"` in +# 0) echo "selected Yes";; +# 1) echo "selected No";; +# *) echo "selected ${options[$?]}";; +#esac \ No newline at end of file