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