gsu: Document gsu().
[gsu.git] / misc / gsu / gui
1 #!/bin/bash
2
3 if [[ $(type -t gsu_is_a_number) != "function" ]]; then
4         GSU_DIR=${GSU_DIR:=${HOME:-}/.gsu}
5         . $GSU_DIR/common || exit 1
6 fi
7
8 export GSU_NODE_NAME_PATTERN='[a-zA-Z_]'
9
10 _get_geometry()
11 {
12         local x y
13         result="$(stty size)"
14         if (($? != 0)); then
15                 gsu_msg "fatal: could not get terminal geometry"
16                 exit 1
17         fi
18         x="${result#* }"
19         y="${result%% *}"
20         (($x > 190)) && x=190
21         result="$y $x"
22 }
23
24 gsu_infobox()
25 {
26         _get_geometry
27         dialog --infobox "$1" $result
28 }
29
30 gsu_checklist_all_on()
31 {
32         local header="$1"
33         local items="$2"
34         local i state opts num=0
35
36         _get_geometry
37         ops="$result 16"
38         for i in $items; do
39                 let num++
40                 opts+=" $i $num on"
41         done
42         result=$(dialog --checklist "$header" $opts 3>&1 1>&2 2>&3 3>&-)
43         ret="$?"
44 }
45
46 gsu_radiolist()
47 {
48         local header="$1"
49         local selected_item="$2"
50         local items="$3"
51         local i state ops num=0
52
53         _get_geometry
54         ops="$result 16"
55         for i in $items; do
56                 let num++
57                 if [[ "$i" == "$selected_item" ]]; then
58                         state="on"
59                 else
60                         state="off"
61                 fi
62                 ops+=" $i $num $state"
63         done
64         result=$(dialog --radiolist "$header" $ops 3>&1 1>&2 2>&3 3>&-)
65         ret="$?"
66 }
67
68 gsu_inputbox()
69 {
70         local g text="$1" init="$2"
71
72         _get_geometry
73         g="$result"
74         result="$(dialog --inputbox "$text" $g "$init" 3>&1 1>&2 2>&3 3>&-)"
75         ret="$?"
76 }
77
78 gsu_textbox()
79 {
80         local file="$1"
81
82         _get_geometry
83         dialog --textbox "$file" $result
84 }
85
86 # dialog segfaults if message is too long. Hence we always use a temporary file
87 gsu_msgbox()
88 {
89         local tmp="$(mktemp gsu_msgbox.XXXXXXXXXX)"
90
91         if (($? != 0)); then
92                 dialog --msgbox "mktemp error" 0 0
93                 return
94         fi
95         echo "$1" > "$tmp"
96         gsu_textbox "$tmp"
97         rm -f "$tmp"
98 }
99
100 gsu_cmd_output_box()
101 {
102         local tmp="$(mktemp)"
103
104         if (($? != 0)); then
105                 dialog --msgbox "mktemp error" 0 0
106                 return
107         fi
108         $@ > "$tmp" 2>&1
109         echo "exit code: $?" >> "$tmp"
110         gsu_textbox "$tmp"
111         rm -f "$tmp"
112 }
113
114 gsu_yesno()
115 {
116         local text="$1"
117
118         _get_geometry
119         dialog --yesno "$text" $result
120         ret=$?
121         if (($ret == 0)); then
122                 result="yes"
123         elif (($ret == 1)); then
124                 result="no"
125         else
126                 result=
127         fi
128 }
129
130 gsu_menu()
131 {
132         local header="${1:-root}"
133         local items="$2"
134         local i state opts num=0
135
136         _get_geometry
137         opts="$result 16"
138         for i in $items; do
139                 let num++
140                 opts+=" $i $num"
141         done
142         result="$(dialog --menu "$gsu_banner_txt ($header)" $opts 3>&1 1>&2 2>&3 3>&-)"
143         ret="$?"
144 }
145
146 _get_level()
147 {
148         local tmp="${1%%$GSU_NODE_NAME_PATTERN*}"
149         result="${#tmp}"
150 }
151
152 _get_subtree()
153 {
154         local tree="$1" root="${2%/}"
155         local TAB='     '
156
157         first="$(grep -n "$TAB\{1,\}$root/" <<< "$tree")"
158         [[ -z "$first" ]] && return
159
160         line_num="${first%%:*}"
161         _get_level "${first#*:}"
162         level="$result"
163
164         #echo "line: $line_num, root: $root, indent level: $level"
165         result="$(sed -e "1,${line_num}d;" <<< "$tree" \
166                 | sed -e "/^$TAB\{1,$level\}$GSU_NODE_NAME_PATTERN/,\$d" \
167                 | sed -e "/^$TAB\{$(($level + 2))\}/d")"
168         ret="$level"
169 }
170
171 _get_root_nodes()
172 {
173         local tree="$1" TAB='   '
174
175         result="$(grep "^${TAB}${GSU_NODE_NAME_PATTERN}" <<< "$tree")"
176 }
177
178 _browse()
179 {
180         local header="$1" old_header
181         local tree="$2" subtree="$3"
182
183         while :; do
184                 gsu_menu "$header" "$subtree"
185                 (($ret != 0)) && return
186                 [[ -z "$result" ]] && return
187                 if [[ "${result%/}" != "$result" ]]; then
188                         old_header="$header"
189                         header="$result"
190                         _get_subtree "$tree" "$header"
191                         _browse "$header" "$tree" "$result"
192                         header="$old_header"
193                         continue
194                 fi
195                 eval ${gsu_name}_$result
196         done
197 }
198
199 gsu_gui()
200 {
201         local tree="$1" subtree
202
203         _gsu_setup
204         type -t dialog &> /dev/null
205         if (($? != 0)); then
206                 gsu_msg "dialog executable not found"
207                 exit 1
208         fi
209         _get_root_nodes "$tree"
210         subtree="$result"
211         _browse "main menu" "$tree" "$subtree"
212 }