Add gsu_gui.
authorAndre Noll <maan@systemlinux.org>
Fri, 23 Sep 2011 12:04:23 +0000 (14:04 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Fri, 29 Aug 2014 19:39:58 +0000 (21:39 +0200)
The dialog-based shell library for earth-shaking graphical user
interfaces that don't suck.

Its main entry function gsu_gui() allows to pass a tree to control
the menus.

misc/gsu/gui [new file with mode: 0644]

diff --git a/misc/gsu/gui b/misc/gsu/gui
new file mode 100644 (file)
index 0000000..30c95a4
--- /dev/null
@@ -0,0 +1,207 @@
+#!/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 "$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 "$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
+       _get_root_nodes "$tree"
+       subtree="$result"
+       _browse "$gsu_name main menu" "$tree" "$subtree"
+}