diff --git a/startup.sh b/startup.sh old mode 100644 new mode 100755 index 76bf882..5ea082d --- a/startup.sh +++ b/startup.sh @@ -17,6 +17,115 @@ 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 "$2 $1 "; } + print_selected() { printf "$2 $ESC[7m $1 $ESC[27m"; } + get_cursor_row() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${ROW#*[}; } + get_cursor_col() { IFS=';' read -sdR -p $'\E[6n' ROW COL; echo ${COL#*[}; } + 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 = "h" ]]; then echo left; fi; + if [[ $key = "l" ]]; then echo right; fi; + if [[ $key = "a" ]]; then echo all; fi; + if [[ $key = "n" ]]; then echo none; 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; + if [[ $key = [C || $key = l ]]; then echo right; fi; + if [[ $key = [D || $key = h ]]; then echo left; fi; + fi + } + print_options_multicol() { + # print options by overwriting the last lines + local curr_col=$1 + local curr_row=$2 + local curr_idx=0 + + local idx=0 + local row=0 + local col=0 + + curr_idx=$(( $curr_col + $curr_row * $colmax )) + + for option in "${options[@]}"; do + + row=$(( $idx/$colmax )) + col=$(( $idx - $row * $colmax )) + + cursor_to $(( $startrow + $row + 1)) $(( $offset * $col + 1)) + if [ $idx -eq $curr_idx ]; then + print_selected "$option" + else + print_option "$option" + fi + ((idx++)) + done + } + + # 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 return_value=$1 + local lastrow=`get_cursor_row` + local lastcol=`get_cursor_col` + local startrow=$(($lastrow - $#)) + local startcol=1 + local lines=$( tput lines ) + local cols=$( tput cols ) + local colmax=$2 + local offset=$(( $cols / $colmax )) + + local size=$4 + shift 4 + + # 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_row=0 + local active_col=0 + while true; do + print_options_multicol $active_col $active_row + # user key control + case `key_input` in + enter) break;; + up) ((active_row--)); + if [ $active_row -lt 0 ]; then active_row=0; fi;; + down) ((active_row++)); + if [ $active_row -ge $(( ${#options[@]} / $colmax )) ]; then active_row=$(( ${#options[@]} / $colmax )); fi;; + left) ((active_col=$active_col - 1)); + if [ $active_col -lt 0 ]; then active_col=0; fi;; + right) ((active_col=$active_col + 1)); + if [ $active_col -ge $colmax ]; then active_col=$(( $colmax - 1 )) ; fi;; + esac + done + + # cursor position back to normal + cursor_to $lastrow + printf "\n" + cursor_blink_on + + return $(( $active_col + $active_row * $colmax )) +} logo () { # This will be shown on every set as user is progressing echo -ne " @@ -36,17 +145,15 @@ 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 -case $fs in -1) set_option FS btrfs;; -2) set_option FS ext4;; -3) +options=("btrfs" "ext4" "luks" "exit") +select_option $? 1 "${options[@]}" + +case $? in +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 +170,54 @@ 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 $? 1 "${options[@]}" + +case ${options[$?]} 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 () { +echo -ne " +Please select key board layout from this list" # 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 +select_option $? 4 "${options[@]}" +keymap=${options[$?]} -done +echo -ne "Your 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 $? 1 "${options[@]}" + +case ${options[$?]} in y|Y|yes|Yes|YES) set_option MOUNT_OPTIONS "noatime,compress=zstd,ssd,commit=120";; n|N|no|NO|No) @@ -133,19 +240,12 @@ 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 $? 1 "${options[@]}" +disk=${options[$?]%|*} + +echo -e "\n${disk%|*} selected \n" set_option DISK ${disk%|*} - break -else - echo -e "\nInvalid selection, please try again. \n" -fi - -done drivessd }