37092a3985ee835768dbfc5ec7d4fd2fcd68f572
[gsu.git] / funcs / gsu
1 # gsu -- the global subcommand utility
2 # (C) 2006-2007 Andre Noll
3
4 gsu_init_errors()
5 {
6 gsu_errors="
7 GSU_SUCCESS success
8 E_GSU_BAD_COMMAND invalid command
9 E_GSU_NOT_A_NUMBER not a number
10 $gsu_errors
11 "
12 local a b i=0
13 while read a b; do
14 if test -z "$a"; then
15 continue
16 fi
17 #echo "a:$a, b: $b"
18 gsu_error_txt[i]="$b"
19 eval $a=$i
20 i=$(($i + 1))
21 done << EOF
22 $gsu_errors
23 EOF
24 }
25 export -f gsu_init_errors
26
27 # check if $1 is a number
28 gsu_is_a_number()
29 {
30 result="$1"
31 if test "$1" -eq "$1" &> /dev/null; then
32 ret=$GSU_SUCCESS
33 else
34 ret=-$E_GSU_NOT_A_NUMBER
35 fi
36 }
37 export -f gsu_is_a_number
38
39 gsu_short_msg()
40 {
41 echo "$1" 1>&2
42 }
43 export -f gsu_short_msg
44
45 gsu_msg()
46 {
47 gsu_short_msg "$gsu_self: $1"
48 }
49 export -f gsu_msg
50
51 gsu_date_msg()
52 {
53 gsu_short_msg "$gsu_self $(date): $1"
54 }
55 export -f gsu_date_msg
56
57 gsu_banner_msg()
58 {
59 local txt="*** $gsu_self --"
60 if test -z "$gsu_banner_txt"; then
61 txt="$txt set \$gsu_banner_txt to customize this message"
62 else
63 txt="$txt $gsu_banner_txt"
64 fi
65 gsu_short_msg "$txt ***"
66 }
67 export -f gsu_banner_msg
68
69 gsu_err_msg()
70 {
71 local txt="$result" err
72
73 gsu_is_a_number "$ret"
74 if test $ret -lt 0; then
75 gsu_msg "unknown error ($ret:$txt)"
76 exit 1
77 fi
78 if test $result -ge 0; then
79 gsu_msg "unknown error ($result:$txt)"
80 exit 1
81 fi
82 err=$((0 - $result))
83 if test -n "$txt"; then
84 txt="$txt: ${gsu_error_txt[$err]}"
85 else
86 txt="${gsu_error_txt[$err]}"
87 fi
88 gsu_msg "$txt"
89 }
90 export -f gsu_err_msg
91
92 gsu_usage()
93 {
94 gsu_short_msg "Usage: $gsu_self command [options]"
95 }
96 export -f gsu_usage
97
98 gsu_available_commands()
99 {
100 result="$( (printf "help\nman\n"; grep "^com_[a-z_]\+()" $0) \
101 | sed -e 's/^com_//' -e 's/()//' \
102 | sort \
103 | tr '\n' ' ')"
104 ret=$GSU_SUCCESS
105 }
106 export -f gsu_available_commands
107
108 gsu_print_available_commands()
109 {(
110 local i count
111 gsu_short_msg "Available commands:"
112 for i in $gsu_cmds; do
113 printf "$i"
114 count=$(($count + 1))
115 if test $(($count % 4)) -eq 0; then
116 echo
117 else
118 printf "\t"
119 if test ${#i} -lt 8; then
120 printf "\t"
121 fi
122 fi
123 done
124 echo
125 ) 2>&1
126 }
127 export -f gsu_print_available_commands
128
129 export gsu_man_txt="
130 Print the manual.
131
132 Usage: man"
133
134 com_man()
135 {
136 local equal_signs="=================================================="
137 local minus_signs="--------------------------------------------------"
138 local com num
139
140 echo "$gsu_self (_${gsu_banner_txt}_) manual"
141 echo "${equal_signs:0:${#gsu_self} + ${#gsu_banner_txt} + 16}"
142 echo
143
144 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
145 echo "----"
146 echo
147 echo "$gsu_self usage"
148 echo "${minus_signs:0:${#gsu_self} + 6}"
149 printf "\t"
150 gsu_usage 2>&1
151 echo "Each command has its own set of options as described below."
152 echo
153 echo "----"
154 echo
155 echo "Available commands:"
156
157 gsu_available_commands
158 for com in $result; do
159 num=${#com}
160 if test $num -lt 4; then
161 num=4
162 fi
163 echo "${minus_signs:0:$num}"
164 echo "$com"
165 echo "${minus_signs:0:$num}"
166 $0 help $com
167 echo
168 done
169 ret=$GSU_SUCCESS
170 }
171 export -f com_man
172
173 export gsu_help_txt="
174 Print online help.
175
176 Usage: help [command]
177
178 Without arguments, print the list of available commands. Otherwise,
179 print the help text for the given command."
180
181 com_help()
182 {
183 local a b
184 if test -z "$1"; then
185 gsu_banner_msg 2>&1
186 gsu_usage 2>&1
187 # sed is magic, baby
188 (printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
189 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
190
191 grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0) \
192 | grep -v -- '--' \
193 | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
194 -e 'H;$!d;x;s/\n//g;b' \
195 -e :s \
196 -e 'x;s/\n//g;${p;x;}' \
197 | sed -e 's/^com_\([a-zA-Z_0-9]\+\)()#*/\1\t/' \
198 | sort \
199 | while read a b; do
200 printf "$a\t"
201 if test ${#a} -lt 8; then
202 printf "\t"
203 fi
204 echo "$b"
205 done
206 echo
207 echo "Try $gsu_self help <command> for info on <command>."
208 ret=$GSU_SUCCESS
209 return
210 fi
211 if test "$1" = "help"; then
212 echo "$gsu_help_txt"
213 ret=$GSU_SUCCESS
214 return
215 fi
216 if test "$1" = "man"; then
217 echo "$gsu_man_txt"
218 ret=$GSU_SUCCESS
219 return
220 fi
221 ret=$GSU_SUCCESS
222 if grep -q "^com_$1()" $0; then
223 sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
224 return
225 fi
226 gsu_print_available_commands
227 result="$1"
228 ret=-$E_GSU_BAD_COMMAND
229 }
230 export -f com_help
231
232 gsu()
233 {
234 local i
235
236 gsu_self="$(basename $0)"
237 gsu_init_errors
238 gsu_available_commands
239 gsu_cmds="$result"
240 if test $# -eq 0; then
241 gsu_usage
242 gsu_print_available_commands
243 exit 1
244 fi
245 arg="$1"
246 shift
247 for i in $gsu_cmds; do
248 if test "$arg" = "$i"; then
249 com_$arg "$@"
250 if test $ret -lt 0; then
251 gsu_err_msg
252 exit 1
253 fi
254 exit 0
255 fi
256 done
257 ret=-$E_GSU_BAD_COMMAND
258 result="$arg"
259 gsu_err_msg
260 gsu_print_available_commands
261 exit 1
262 }
263 # no need to export this