shell menu utils

This commit is contained in:
2018-12-22 22:00:21 +02:00
parent ee017c8c55
commit d1a90fd795
6 changed files with 254 additions and 15 deletions

1
bin/read-up Symbolic link
View File

@@ -0,0 +1 @@
../shell/read-up

View File

@@ -1 +0,0 @@
../web/scotty

1
bin/select-option Symbolic link
View File

@@ -0,0 +1 @@
../shell/select-option.sh

90
shell/read-up Executable file
View File

@@ -0,0 +1,90 @@
#!/usr/bin/env bash
_help() {
SELF=$( basename "$0" )
echo "Read arrows keys up/down
Usage: $SELF [-c Char]
-c Char Print Char character at the start of line
Returns
100 - number of rows above start point
0 if ctrl-c or ESC pressed
"
exit
}
CHAR=""
for (( i=1; i<=$#; i++ )); do
value=${!i}
j=$(( i + 1 ))
[[ "$value" = "-h" ]] && _help
[[ "$value" = "--help" ]] && _help
[[ "$value" = "-c" ]] && { CHAR="${!j}"; ((i++)); continue; }
done
printf -v EMPTYCHAR "%-${#CHAR}s" " "
ESC=$( printf "\033")
cursor_blink_on() { printf "$ESC[?25h"; }
cursor_blink_off() { printf "$ESC[?25l"; }
cursor_to() { printf "$ESC[$1;${2:-1}H"; }
get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; }
get_screen_rows() { tput lines; }
key_input() { read -s -n1 key1 2>/dev/null >&2
read -s -n2 -t 0.1 key2 2>/dev/null >&2
if [[ $key1 = "" ]]; then echo enter; return; fi
if [[ $key1$key2 = $ESC[A ]]; then echo up; return; fi
if [[ $key1$key2 = $ESC[B ]]; then echo down; return; fi
if [[ -z "$key2" ]]; then
if [[ $key1 = $'\e' ]]; then echo esc; return; fi
fi
}
reset_display() {
cursor_blink_on; stty echo;
}
print_char() { printf -- "$CHAR\r"; }
print_empty() { if [[ -n "$CHAR" ]]; then printf "$EMPTYCHAR\r"; fi; }
startrow=`get_cursor_row`
trap "cursor_blink_on; stty echo; cursor_to $startrow; exit 1" 2
#trap "cursor_blink_on; stty echo; printf '\n'; exit 1" 2
if [[ -n "$CHAR" ]]; then
cursor_blink_off
fi
selected=0
while true; do
cursor_to $(( $startrow - $selected))
print_char
# user key control
case `key_input` in
enter) break;;
esc) reset_display; exit 1;;
up)
cursor_to $(( $startrow - $selected))
print_empty
((selected++));
# limit going top
;;
down)
cursor_to $(( $startrow - $selected))
print_empty
((selected--));
# limit going down
;;
esac
lastrow=`get_cursor_row`
if [ $(( $startrow - $selected )) -lt 1 ]; then
((selected--))
fi
if [ $(( startrow - $selected )) -gt `get_screen_rows` ]; then
((selected++))
fi
done
cursor_blink_on
cursor_to $startrow
exit $(( 100 - $selected ))

148
shell/select-option.sh Executable file
View File

@@ -0,0 +1,148 @@
#!/usr/bin/env bash
# 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 ...)
function select_option {
local nformat
local optcount=$#
printf -v nformat "%%%dd. " ${#optcount}
local max_opt=0
for opt; do
if [[ "${#opt}" -gt $max_opt ]]; then
max_opt=${#opt}
fi
done
# 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"; }
if [[ $COLORS -eq 1 ]]; then
print_option() { printf " $ESC[33m $1 $ESC[0m "; }
print_selected() { printf " [$ESC[37;1m$1$ESC[0m] "; }
else
print_option() { printf " $1 "; }
print_selected() { printf " [$ESC[1m$1$ESC[0m] "; }
fi
get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; }
key_input() { read -s -n1 key1 2>/dev/null >&2
read -s -n2 -t 0.1 key2 2>/dev/null >&2
if [[ $key1$key2 = $ESC[A ]]; then echo up; return; fi
if [[ $key1$key2 = $ESC[B ]]; then echo down; return; fi
if [[ $key1 = $'\e' ]]; then echo esc; return; fi
if [[ $key1 = "" ]]; then echo enter; return; fi
}
reset_display() {
cursor_blink_on; stty echo; printf '\n';
}
# 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 1" 2
cursor_blink_off
local selected=0
while true; do
# print options by overwriting the last lines
local idx=0
local nidx
for opt; do
if [[ $SELECT_UNDERSCORES -eq 1 ]]; then
opt=${opt//_/ }
fi
if [[ $SELECT_NUMBERS -eq 1 ]]; then
printf -v nidx "$nformat" $(( idx + 1 ))
fi
printf -v padopt "%-${max_opt}s" "$opt"
cursor_to $(($startrow + $idx))
if [ $idx -eq $selected ]; then
print_selected "$nidx$padopt"
else
print_option "$nidx$padopt"
fi
((idx++))
done
# user key control
case `key_input` in
enter) break;;
esc) reset_display; exit 1;;
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
if [[ -n "$SELECT_TOFILE" ]]; then
local idx=0
for opt; do
if [ $idx -eq $selected ]; then
echo "$opt" > "$SELECT_TOFILE"
fi
((idx++))
done
fi
return $(( 10 + $selected ))
}
[[ $_ == $0 ]] && {
_help() {
SELF=$( basename "$0" )
echo "Select Option
Usage: $SELF [-n] [--nc] [-o File] [-_] list of options
-n Number list
--nc No colors
-o File Save the choice in a file
-_ Print spaces instead of underscores
Returns
(10 + index) of selection (first option = 10)
1 if ctrl-c or ESC pressed
Example:
$SELF -n one two three
EC=\$?
[[ \$EC -lt 10 ]] && { echo Exited..; } || { echo You selected \$(( \$EC - 9 )); }
"
exit
}
SELECT_COLORS=1
SELECT_NUMBERS=0
SELECT_UNDERSCORES=0
SELECT_TOFILE=""
for (( i=1; i<=$#; i++ )); do
value=${!i}
j=$(( i + 1 ))
[[ "$value" = "-h" ]] && _help
[[ "$value" = "--help" ]] && _help
[[ "$value" = "--nc" ]] && { SELECT_COLORS=0; continue; }
[[ "$value" = "-n" ]] && { SELECT_NUMBERS=1; continue; }
[[ "$value" = "-_" ]] && { SELECT_UNDERSCORES=1; continue; }
[[ "$value" = "-o" ]] && { SELECT_TOFILE="${!j}"; ((i++)); continue; }
opts+=( "$value" )
done
select_option "${opts[@]}"
exit $?
}