gsu: Make man a generic gsu command.
[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 tilde_signs="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
139 local com num
140
141 echo "$gsu_self (_${gsu_banner_txt}_) manual"
142 echo "${equal_signs:0:${#gsu_self} + ${#gsu_banner_txt} + 16}"
143 echo
144
145 sed -e '1,/^#\{70,\}/d' -e '/^#\{70,\}/,$d' $0 -e 's/^# *//'
146 echo "----"
147 echo
148 echo "$gsu_self usage"
149 echo "${minus_signs:0:${#gsu_self} + 6}"
150 printf "\t"
151 gsu_usage 2>&1
152 echo "Each command has its own set of options as described below."
153 echo
154 echo "----"
155 echo
156 echo "Available commands:"
157
158 gsu_available_commands
159 for com in $result; do
160 num=${#com}
161 if test $num -lt 4; then
162 num=4
163 fi
164 echo "${minus_signs:0:$num}"
165 echo "$com"
166 echo "${minus_signs:0:$num}"
167 $0 help $com
168 echo
169 done
170 ret=$GSU_SUCCESS
171 }
172 export -f com_man
173
174 export gsu_help_txt="
175 Print online help.
176
177 Usage: help [command]
178
179 Without arguments, print the list of available commands. Otherwise,
180 print the help text for the given command."
181
182 com_help()
183 {
184 local a b
185 if test -z "$1"; then
186 gsu_banner_msg 2>&1
187 gsu_usage 2>&1
188 # sed is magic, baby
189 (printf "com_help()\n$gsu_help_txt" | head -n 4; echo "--"
190 printf "com_man()\n$gsu_man_txt" | head -n 4; echo "--"
191
192 grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0) \
193 | grep -v -- '--' \
194 | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
195 -e 'H;$!d;x;s/\n//g;b' \
196 -e :s \
197 -e 'x;s/\n//g;${p;x;}' \
198 | sed -e 's/^com_\([a-zA-Z_0-9]\+\)()#*/\1\t/' \
199 | sort \
200 | while read a b; do
201 printf "$a\t"
202 if test ${#a} -lt 8; then
203 printf "\t"
204 fi
205 echo "$b"
206 done
207 echo
208 echo "Try $gsu_self help <command> for info on <command>."
209 ret=$GSU_SUCCESS
210 return
211 fi
212 if test "$1" = "help"; then
213 echo "$gsu_help_txt"
214 ret=$GSU_SUCCESS
215 return
216 fi
217 if test "$1" = "man"; then
218 echo "$gsu_man_txt"
219 ret=$GSU_SUCCESS
220 return
221 fi
222 ret=$GSU_SUCCESS
223 if grep -q "^com_$1()" $0; then
224 sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
225 return
226 fi
227 gsu_print_available_commands
228 result="$1"
229 ret=-$E_GSU_BAD_COMMAND
230 }
231 export -f com_help
232
233 gsu()
234 {
235 local i
236
237 gsu_self="$(basename $0)"
238 gsu_init_errors
239 gsu_available_commands
240 gsu_cmds="$result"
241 if test $# -eq 0; then
242 gsu_usage
243 gsu_print_available_commands
244 exit 1
245 fi
246 arg="$1"
247 shift
248 for i in $gsu_cmds; do
249 if test "$arg" = "$i"; then
250 com_$arg "$@"
251 if test $ret -lt 0; then
252 gsu_err_msg
253 exit 1
254 fi
255 exit 0
256 fi
257 done
258 ret=-$E_GSU_BAD_COMMAND
259 result="$arg"
260 gsu_err_msg
261 gsu_print_available_commands
262 exit 1
263 }
264 # no need to export this