citadel-core/cli/utils/multiselect.sh
Philipp Walter b2faa3c287
Merge Stable into Beta (#65)
* Citadel 0.0.6 (#59)

Co-authored-by: nolim1t - f6287b82CC84bcbd <nolim1t@users.noreply.github.com>

* feat: add Citadel CLI (#33)

add commands for:
- Show status for all services
- Run a command inside a (app) container
- Switch branch / update channel
- Switch Bitcoin/Electrum/Lightning implementation
- app commands
- debug command
- Fix update / backup / starting stuck
- Edit node configs (Bitcoin Core, LND)
- Edit app configs (Nextcloud etc.)
- Memory usage / System info
- Start
- Stop
- Restart
- Reboot
- Shutdown
- List all installed apps & services
- Logs
- Version
- Help

Co-authored-by: Aaron Dewes <aaron.dewes@protonmail.com>
Co-authored-by: nolim1t - f6287b82CC84bcbd <nolim1t@users.noreply.github.com>
2022-07-15 18:34:49 +02:00

124 lines
2.8 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
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=$((idx + 1))
done
}
get_result() {
local result=()
for ((i = 0; i < ${#options[@]}; i++)); do
if ${selected[i]}; then
result+=(${options[i]})
fi
done
echo "${result[@]}"
}
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=$((active - 1))
if [ $active -lt 0 ]; then active=$((${#options[@]} - 1)); fi
;;
down)
active=$((active + 1))
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='("$(get_result)")'
}