forked from michael.heier/citadel-core
07aa73b59e
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
124 lines
2.8 KiB
Bash
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)")'
|
|
}
|