Article 5CA7R Large multi-select list bash script.

Large multi-select list bash script.

by
replica9000
from LinuxQuestions.org on (#5CA7R)
I found a multi-select bash script from here: https://gist.github.com/sergiofbsilv...008dc367946953

It works well except for 2 things:
- If the list is longer than the viewable terminal lines, the output becomes garbled. My list may contain a couple thousand items.
- The list will be imported as a variable, and I can't seem to use a variable with OPTIONS_VALUES and OPTIONS_LABELS.

I might be able to solve the second issue, but it doesn't matter if I can't solve the first issue. Any help appreciated.

Code:#/bin/bash
# from SO: https://stackoverflow.com/a/54261882/317605 (by https://stackoverflow.com/users/8207842/dols3m)
function prompt_for_multiselect {

# 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_inactive() { printf "$2 $1 "; }
print_active() { printf "$2 $ESC[7m $1 $ESC[27m"; }
get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; }
key_input() {
local key
IFS= read -rsn1 key 2>/dev/null >&2
if [[ $key = "" ]]; then echo enter; fi;
if [[ $key = $'\x20' ]]; then echo space; fi;
if [[ $key = $'\x1b' ]]; then
read -rsn2 key
if [[ $key = [A ]]; then echo up; fi;
if [[ $key = [B ]]; then echo down; fi;
fi
}
toggle_option() {
local arr_name=$1
eval "local arr=(\"\${${arr_name}[@]}\")"
local option=$2
if [[ ${arr[option]} == true ]]; then
arr[option]=
else
arr[option]=true
fi
eval $arr_name='("${arr[@]}")'
}

local retval=$1
local options
local defaults

IFS=';' read -r -a options <<< "$2"
if [[ -z $3 ]]; then
defaults=()
else
IFS=';' read -r -a defaults <<< "$3"
fi
local selected=()

for ((i=0; i<${#options[@]}; i++)); do
selected+=("${defaults[i]:-false}")
printf "\n"
done

# determine current screen position for overwriting the options
local lastrow=`get_cursor_row`
local startrow=$(($lastrow - ${#options[@]}))

# 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 active=0
while true; do
# print options by overwriting the last lines
local idx=0
for option in "${options[@]}"; do
local prefix="[ ]"
if [[ ${selected[idx]} == true ]]; then
prefix="[x]"
fi

cursor_to $(($startrow + $idx))
if [ $idx -eq $active ]; then
print_active "$option" "$prefix"
else
print_inactive "$option" "$prefix"
fi
((idx++))
done

# user key control
case `key_input` in
space) toggle_option selected $active;;
enter) break;;
up) ((active--));
if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi;;
down) ((active++));
if [ $active -ge ${#options[@]} ]; then active=0; fi;;
esac
done

# cursor position back to normal
cursor_to $lastrow
printf "\n"
cursor_blink_on

eval $retval='("${selected[@]}")'
}

# Usage Example

OPTIONS_VALUES=("APPL" "MSFT" "GOOG")
OPTIONS_LABELS=("Apple" "Microsoft" "Google")

for i in "${!OPTIONS_VALUES[@]}"; do
OPTIONS_STRING+="${OPTIONS_VALUES[$i]} (${OPTIONS_LABELS[$i]});"
done

prompt_for_multiselect SELECTED "$OPTIONS_STRING"

for i in "${!SELECTED[@]}"; do
if [ "${SELECTED[$i]}" == "true" ]; then
CHECKED+=("${OPTIONS_VALUES[$i]}")
fi
done
echo "${CHECKED[@]}"latest?d=yIl2AUoC8zA latest?i=FpRtOv_quV0:mk-jm2XWhdo:F7zBnMy latest?i=FpRtOv_quV0:mk-jm2XWhdo:V_sGLiP latest?d=qj6IDK7rITs latest?i=FpRtOv_quV0:mk-jm2XWhdo:gIN9vFwFpRtOv_quV0
External Content
Source RSS or Atom Feed
Feed Location https://feeds.feedburner.com/linuxquestions/latest
Feed Title LinuxQuestions.org
Feed Link https://www.linuxquestions.org/questions/
Reply 0 comments