Last active
November 17, 2022 15:56
-
-
Save webflo-dev/34ab3863c0293435260a0856e5bda53d to your computer and use it in GitHub Desktop.
multi select bash
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
function 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#*[}; } | |
local return_value=$1 | |
local -n options=$2 | |
local -n defaults=$3 | |
local selected=() | |
for ((i=0; i<${#options[@]}; i++)); do | |
if [[ ${defaults[i]} = "true" ]]; then | |
selected+=("true") | |
else | |
selected+=("false") | |
fi | |
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 | |
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 = "k" ]]; then echo up; fi; | |
if [[ $key = "j" ]]; then echo down; fi; | |
if [[ $key = $'\x1b' ]]; then | |
read -rsn2 key | |
if [[ $key = [A || $key = k ]]; then echo up; fi; | |
if [[ $key = [B || $key = j ]]; then echo down; fi; | |
fi | |
} | |
toggle_option() { | |
local option=$1 | |
if [[ ${selected[option]} == true ]]; then | |
selected[option]=false | |
else | |
selected[option]=true | |
fi | |
} | |
print_options() { | |
# print options by overwriting the last lines | |
local idx=0 | |
for option in "${options[@]}"; do | |
local prefix="[ ]" | |
if [[ ${selected[idx]} == true ]]; then | |
prefix="[\e[38;5;46m✔\e[0m]" | |
fi | |
cursor_to $(($startrow + $idx)) | |
if [ $idx -eq $1 ]; then | |
print_active "$option" "$prefix" | |
else | |
print_inactive "$option" "$prefix" | |
fi | |
((idx++)) | |
done | |
} | |
local active=0 | |
while true; do | |
print_options $active | |
# user key control | |
case `key_input` in | |
space) toggle_option $active;; | |
enter) print_options -1; 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 $return_value='("${selected[@]}")' | |
local values=() | |
for ((i=0; i<${#options[@]}; i++)); do | |
option=${options[$i]} | |
if [[ ${selected[$i]} == true ]]; then | |
values+=($option) | |
fi | |
done | |
eval $return_value='("${values[@]}")' | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
source=("one" "two" "three" "four") | |
default_selected=("two" "four") | |
multiselect selected_options source default_selected | |
for selected_option in "${selected_options[@]}"; do | |
echo "you selected: $selected_option" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment