From b24bd7859411dba56cf74806cc056ae62f6cc81a Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Sun, 16 Jan 2022 15:14:12 -0600 Subject: [PATCH] Interactive select list --- startup.sh | 142 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 40 deletions(-) diff --git a/startup.sh b/startup.sh index 76bf882..e74f9fd 100644 --- a/startup.sh +++ b/startup.sh @@ -17,6 +17,69 @@ set_option() { fi echo "${1}=${2}" >>$CONFIG_FILE # add option } +# 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 ...) +select_option() { + + # 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_option() { printf " $1 "; } + print_selected() { printf " $ESC[7m $1 $ESC[27m"; } + get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } + key_input() { read -s -n3 key 2>/dev/null >&2 + if [[ $key = $ESC[A ]]; then echo up; fi + if [[ $key = $ESC[B ]]; then echo down; fi + if [[ $key = "" ]]; then echo enter; fi; } + + # 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" 2 + cursor_blink_off + + local selected=0 + while true; do + # print options by overwriting the last lines + local idx=0 + for opt; do + cursor_to $(($startrow + $idx)) + if [ $idx -eq $selected ]; then + print_selected "$opt" + else + print_option "$opt" + fi + ((idx++)) + done + + # user key control + case `key_input` in + enter) break;; + 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 + + return $selected +} logo () { # This will be shown on every set as user is progressing echo -ne " @@ -36,17 +99,16 @@ filesystem () { # This function will handle file systems. At this movement we are handling only # btrfs and ext4. Others will be added in future. echo -ne " - Please Select your file system for both boot and root - 1) btrfs - 2) ext4 - 3) luks with btrfs - 0) exit +Please Select your file system for both boot and root " -read fs +options=("btrfs" "ext4" "luks" "exit") +select_option "${options[@]}" +fs=$? + case $fs in -1) set_option FS btrfs;; -2) set_option FS ext4;; -3) +0) set_option FS btrfs;; +1) set_option FS ext4;; +2) while true; do echo -ne "Please enter your luks password: \n" read -s luks_password # read password without echo @@ -63,54 +125,60 @@ while true; do fi done ;; -0) exit ;; +3) exit ;; *) echo "Wrong option please select again"; filesystem;; esac } timezone () { # Added this from arch wiki https://wiki.archlinux.org/title/System_time time_zone="$(curl --fail https://ipapi.co/timezone)" -echo -ne "System detected your timezone to be '$time_zone' \n" -echo -ne "Is this correct? yes/no:" -read answer -case $answer in +echo -ne " +System detected your timezone to be '$time_zone' \n" +echo -ne "Is this correct? +" +options=("Yes" "No") +select_option "${options[@]}" +choice=$? + +case ${options[$choice]} in y|Y|yes|Yes|YES) + echo "${time_zone} set as timezone" set_option TIMEZONE $time_zone;; n|N|no|NO|No) echo "Please enter your desired timezone e.g. Europe/London :" read new_timezone + echo "${new_timezone} set as timezone" set_option TIMEZONE $new_timezone;; *) echo "Wrong option. Try again";timezone;; esac } keymap () { -# These are default key maps as presented in official arch repo archinstall -options=(by ca cf cz de dk es et fa fi fr gr hu il it lt lv mk nl no pl ro ru sg ua uk us) PS3=" + Please select key board layout from this list " -select keymap in "${options[@]}" -do -# check if selection is part of list, silence error output and use else block for output -if echo -e '%s\n' "${options[@]}" | grep -Fqw $keymap 2> /dev/null; then - echo -e "\nYour key boards layout: ${keymap} \n" - set_option KEYMAP $keymap - break -else - echo -e "\nInvalid selection, please try again. \n" -fi +# These are default key maps as presented in official arch repo archinstall +options=(by ca cf cz de dk es et fa fi fr gr hu il it lt lv mk nl no pl ro ru sg ua uk us) -done +select_option "${options[@]}" +choice=$? +keymap=${options[$choice]} + +echo -ne "\nYour key boards layout: ${keymap} \n" +set_option KEYMAP $keymap } drivessd () { echo -ne " Is this an ssd? yes/no: " -read ssd_drive -case $ssd_drive in +options=("Yes" "No") +select_option "${options[@]}" +choice=$? + +case ${options[$choice]} in y|Y|yes|Yes|YES) set_option MOUNT_OPTIONS "noatime,compress=zstd,ssd,commit=120";; n|N|no|NO|No) @@ -133,19 +201,13 @@ echo -ne " PS3=' Select the disk to install on: ' options=($(lsblk -n --output TYPE,KNAME,SIZE | awk '$1=="disk"{print "/dev/"$2"|"$3}')) -select disk in "${options[@]}" -do -# check if selection is part of list, silence error output and use else block for output -if echo -e '%s\n' "${options[@]}" | grep -Fqw ${disk} 2> /dev/null; then - echo -e "\n${disk%|*} selected \n" +select_option "${options[@]}" +choice=$? +disk=${options[$choice]%|*} + +echo -e "\n${disk%|*} selected \n" set_option DISK ${disk%|*} - break -else - echo -e "\nInvalid selection, please try again. \n" -fi - -done drivessd }