36b177afc74c9cc74de5b1860becb738f9f67a60
[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         echo "$gsu_self: $txt" 1>&2
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 export gsu_help_txt="
99 Print online help.
100
101 Usage: help [command]
102
103 Without arguments, print the list of available commands. Otherwise,
104 print the help text for the given command."
105 com_help()
106 {
107         local a b
108         if test -z "$1"; then
109                 gsu_banner_msg
110                 gsu_usage
111                 # sed is magic, baby
112                 grep -A 2 "^com_\([a-zA-Z_0-9]\+\)()" $0 \
113                         | grep -v -- '--' \
114                         | sed -e '/^com_\([a-zA-Z_0-9]\+\)()/bs' \
115                                 -e 'H;$!d;x;s/\n//g;b' \
116                                 -e :s \
117                                 -e 'x;s/\n//g;${p;x;}' \
118                         | sed -e 's/^com_\([a-zA-Z_0-9]\+\)()#*/\1\t/' \
119                         | sort \
120                         | while read a b; do
121                                 echo -en "$a\t"
122                                 if test ${#a} -lt 8; then
123                                         echo -en "\t"
124                                 fi
125                                 echo "$b"
126                         done
127                 echo
128                 gsu_msg "Try $gsu_self help <command> for info on <command>."
129                 ret=$GSU_SUCCESS
130                 return
131         fi
132         if test "$1" = "help"; then
133                 gsu_short_msg "$gsu_help_txt"
134                 ret=$GSU_SUCCESS
135                 return
136         fi
137         ret=$GSU_SUCCESS
138         if grep -q "^com_$1()" $0; then
139                 sed -e "1,/com_$1()/d" -e '/^{/,$d' -e 's/^## *//' $0
140                 return
141         fi
142         gsu_print_available_commands
143         result="$1"
144         ret=-$E_GSU_BAD_COMMAND
145 }
146 export -f com_help
147
148 gsu_available_commands()
149 {
150         result="$( (echo help; grep "^com_[a-z_]\+()" $0) \
151                 | sed -e 's/^com_//' -e 's/()//' \
152                 | sort \
153                 | tr '\n' ' ')"
154         ret=$SUCCESS
155 }
156 export -f gsu_available_commands
157
158 gsu_print_available_commands()
159 {(
160         local i count
161         gsu_short_msg "Available commands:"
162         for i in $gsu_cmds; do
163                 printf "$i"
164                 count=$((count + 1))
165                 if test $((count % 4)) -eq 0; then
166                         echo
167                 else
168                         printf "\t"
169                         if test ${#i} -lt 8; then
170                                 printf "\t"
171                         fi
172                 fi
173         done
174         echo
175 ) 2>&1
176 }
177 export -f gsu_print_available_commands
178
179 gsu()
180 {
181         gsu_self="$(basename $0)"
182         gsu_init_errors
183         gsu_available_commands
184         gsu_cmds="$result"
185         if test $# -eq 0; then
186                 gsu_usage
187                 gsu_print_available_commands
188                 exit 1
189         fi
190         arg="$1"
191         shift
192         for i in $gsu_cmds; do
193                 if test "$arg" = "$i"; then
194                         com_$arg $*
195                         if test $ret -lt 0; then
196                                 gsu_err_msg
197                                 exit 1
198                         fi
199                         exit 0
200                 fi
201         done
202         ret=-$E_GSU_BAD_COMMAND
203         result="$arg"
204         gsu_err_msg
205         gsu_print_available_commands
206         exit 1
207 }
208 # no need to export this