#!/bin/bash if [[ $(type -t gsu_is_a_number) != "function" ]]; then GSU_DIR=${GSU_DIR:=$HOME/.gsu} . $GSU_DIR/common || exit 1 fi export GSU_NODE_NAME_PATTERN='[a-zA-Z_]' _get_geometry() { local x y result="$(stty size)" if (($? != 0)); then gsu_msg "fatal: could not get terminal geometry" exit 1 fi x="${result#* }" y="${result%% *}" (($x > 190)) && x=190 result="$y $x" } gsu_infobox() { _get_geometry dialog --infobox "$1" $result } gsu_checklist_all_on() { local header="$1" local items="$2" local i state opts num=0 _get_geometry ops="$result 16" for i in $items; do let num++ opts+=" $i $num on" done result=$(dialog --checklist "$header" $opts 3>&1 1>&2 2>&3 3>&-) ret="$?" } gsu_radiolist() { local header="$1" local selected_item="$2" local items="$3" local i state ops num=0 _get_geometry ops="$result 16" for i in $items; do let num++ if [[ "$i" == "$selected_item" ]]; then state="on" else state="off" fi ops+=" $i $num $state" done result=$(dialog --radiolist "$header" $ops 3>&1 1>&2 2>&3 3>&-) ret="$?" } gsu_inputbox() { local g text="$1" init="$2" _get_geometry g="$result" result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)" ret="$?" } gsu_textbox() { local file="$1" _get_geometry dialog --textbox "$file" $result } # dialog segfaults if message is too long. Hence we always use a temporary file gsu_msgbox() { local tmp="$(mktemp gsu_msgbox.XXXXXXXXXX)" if (($? != 0)); then dialog --msgbox "mktemp error" 0 0 return fi echo "$1" > "$tmp" gsu_textbox "$tmp" rm -f "$tmp" } gsu_cmd_output_box() { local tmp="$(mktemp)" if (($? != 0)); then dialog --msgbox "mktemp error" 0 0 return fi $@ > "$tmp" 2>&1 echo "exit code: $?" >> "$tmp" gsu_textbox "$tmp" rm -f "$tmp" } gsu_yesno() { local text="$1" _get_geometry dialog --yesno "$text" $result ret=$? if (($ret == 0)); then result="yes" elif (($ret == 1)); then result="no" else result= fi } gsu_menu() { local header="${1:-root}" local items="$2" local i state opts num=0 _get_geometry opts="$result 16" for i in $items; do let num++ opts+=" $i $num" done result="$(dialog --menu "$gsu_banner_txt ($header)" $opts 3>&1 1>&2 2>&3 3>&-)" ret="$?" } _get_level() { local tmp="${1%%$GSU_NODE_NAME_PATTERN*}" result="${#tmp}" } _get_subtree() { local tree="$1" root="${2%/}" local TAB=' ' first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")" [[ -z "$first" ]] && return line_num="${first%%:*}" _get_level "${first#*:}" level="$result" #echo "line: $line_num, root: $root, indent level: $level" result="$(sed -e "1,${line_num}d;" <<< "$tree" \ | sed -e "/^$TAB\{1,$level\}$GSU_NODE_NAME_PATTERN/,\$d" \ | sed -e "/^$TAB\{$(($level + 2))\}/d")" ret="$level" } _get_root_nodes() { local tree="$1" TAB=' ' result="$(grep "^${TAB}${GSU_NODE_NAME_PATTERN}" <<< "$tree")" } _browse() { local header="$1" old_header local tree="$2" subtree="$3" while :; do gsu_menu "$header" "$subtree" (($ret != 0)) && return [[ -z "$result" ]] && return if [[ "${result%/}" != "$result" ]]; then old_header="$header" header="$result" _get_subtree "$tree" "$header" _browse "$header" "$tree" "$result" header="$old_header" continue fi eval ${gsu_name}_$result done } gsu_gui() { local tree="$1" subtree _gsu_setup type -t dialog &> /dev/null if (($? != 0)); then gsu_msg "dialog executable not found" exit 1 fi _get_root_nodes "$tree" subtree="$result" _browse "main menu" "$tree" "$subtree" }