ghp 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1012 +0,0 @@
1
- # $Id$
2
- # vim:et:ft=sh:sts=2:sw=2
3
- #
4
- # Copyright 2008 Kate Ward. All Rights Reserved.
5
- # Released under the LGPL (GNU Lesser General Public License)
6
- #
7
- # shFlags -- Advanced command-line flag library for Unix shell scripts.
8
- # http://code.google.com/p/shflags/
9
- #
10
- # Author: kate.ward@forestent.com (Kate Ward)
11
- #
12
- # This module implements something like the google-gflags library available
13
- # from http://code.google.com/p/google-gflags/.
14
- #
15
- # FLAG TYPES: This is a list of the DEFINE_*'s that you can do. All flags take
16
- # a name, default value, help-string, and optional 'short' name (one-letter
17
- # name). Some flags have other arguments, which are described with the flag.
18
- #
19
- # DEFINE_string: takes any input, and intreprets it as a string.
20
- #
21
- # DEFINE_boolean: typically does not take any argument: say --myflag to set
22
- # FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
23
- # Alternately, you can say
24
- # --myflag=true or --myflag=t or --myflag=0 or
25
- # --myflag=false or --myflag=f or --myflag=1
26
- # Passing an option has the same affect as passing the option once.
27
- #
28
- # DEFINE_float: takes an input and intreprets it as a floating point number. As
29
- # shell does not support floats per-se, the input is merely validated as
30
- # being a valid floating point value.
31
- #
32
- # DEFINE_integer: takes an input and intreprets it as an integer.
33
- #
34
- # SPECIAL FLAGS: There are a few flags that have special meaning:
35
- # --help (or -?) prints a list of all the flags in a human-readable fashion
36
- # --flagfile=foo read flags from foo. (not implemented yet)
37
- # -- as in getopt(), terminates flag-processing
38
- #
39
- # EXAMPLE USAGE:
40
- #
41
- # -- begin hello.sh --
42
- # #! /bin/sh
43
- # . ./shflags
44
- # DEFINE_string name 'world' "somebody's name" n
45
- # FLAGS "$@" || exit $?
46
- # eval set -- "${FLAGS_ARGV}"
47
- # echo "Hello, ${FLAGS_name}."
48
- # -- end hello.sh --
49
- #
50
- # $ ./hello.sh -n Kate
51
- # Hello, Kate.
52
- #
53
- # NOTE: Not all systems include a getopt version that supports long flags. On
54
- # these systems, only short flags are recognized.
55
-
56
- #==============================================================================
57
- # shFlags
58
- #
59
- # Shared attributes:
60
- # flags_error: last error message
61
- # flags_return: last return value
62
- #
63
- # __flags_longNames: list of long names for all flags
64
- # __flags_shortNames: list of short names for all flags
65
- # __flags_boolNames: list of boolean flag names
66
- #
67
- # __flags_opts: options parsed by getopt
68
- #
69
- # Per-flag attributes:
70
- # FLAGS_<flag_name>: contains value of flag named 'flag_name'
71
- # __flags_<flag_name>_default: the default flag value
72
- # __flags_<flag_name>_help: the flag help string
73
- # __flags_<flag_name>_short: the flag short name
74
- # __flags_<flag_name>_type: the flag type
75
- #
76
- # Notes:
77
- # - lists of strings are space separated, and a null value is the '~' char.
78
-
79
- # return if FLAGS already loaded
80
- [ -n "${FLAGS_VERSION:-}" ] && return 0
81
- FLAGS_VERSION='1.0.3'
82
-
83
- # return values
84
- FLAGS_TRUE=0
85
- FLAGS_FALSE=1
86
- FLAGS_ERROR=2
87
-
88
- # reserved flag names
89
- FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
90
-
91
- _flags_debug() { echo "flags:DEBUG $@" >&2; }
92
- _flags_warn() { echo "flags:WARN $@" >&2; }
93
- _flags_error() { echo "flags:ERROR $@" >&2; }
94
- _flags_fatal() { echo "flags:FATAL $@" >&2; }
95
-
96
- # specific shell checks
97
- if [ -n "${ZSH_VERSION:-}" ]; then
98
- setopt |grep "^shwordsplit$" >/dev/null
99
- if [ $? -ne ${FLAGS_TRUE} ]; then
100
- _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
101
- exit ${FLAGS_ERROR}
102
- fi
103
- if [ -z "${FLAGS_PARENT:-}" ]; then
104
- _flags_fatal "zsh does not pass \$0 through properly. please declare' \
105
- \"FLAGS_PARENT=\$0\" before calling shFlags"
106
- exit ${FLAGS_ERROR}
107
- fi
108
- fi
109
-
110
- #
111
- # constants
112
- #
113
-
114
- # getopt version
115
- __FLAGS_GETOPT_VERS_STD=0
116
- __FLAGS_GETOPT_VERS_ENH=1
117
- __FLAGS_GETOPT_VERS_BSD=2
118
-
119
- getopt >/dev/null 2>&1
120
- case $? in
121
- 0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;; # bsd getopt
122
- 2)
123
- # TODO(kward): look into '-T' option to test the internal getopt() version
124
- if [ "`getopt --version`" = '-- ' ]; then
125
- __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
126
- else
127
- __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
128
- fi
129
- ;;
130
- *)
131
- _flags_fatal 'unable to determine getopt version'
132
- exit ${FLAGS_ERROR}
133
- ;;
134
- esac
135
-
136
- # getopt optstring lengths
137
- __FLAGS_OPTSTR_SHORT=0
138
- __FLAGS_OPTSTR_LONG=1
139
-
140
- __FLAGS_NULL='~'
141
-
142
- # flag info strings
143
- __FLAGS_INFO_DEFAULT='default'
144
- __FLAGS_INFO_HELP='help'
145
- __FLAGS_INFO_SHORT='short'
146
- __FLAGS_INFO_TYPE='type'
147
-
148
- # flag lengths
149
- __FLAGS_LEN_SHORT=0
150
- __FLAGS_LEN_LONG=1
151
-
152
- # flag types
153
- __FLAGS_TYPE_NONE=0
154
- __FLAGS_TYPE_BOOLEAN=1
155
- __FLAGS_TYPE_FLOAT=2
156
- __FLAGS_TYPE_INTEGER=3
157
- __FLAGS_TYPE_STRING=4
158
-
159
- # set the constants readonly
160
- __flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
161
- for __flags_const in ${__flags_constants}; do
162
- # skip certain flags
163
- case ${__flags_const} in
164
- FLAGS_HELP) continue ;;
165
- FLAGS_PARENT) continue ;;
166
- esac
167
- # set flag readonly
168
- if [ -z "${ZSH_VERSION:-}" ]; then
169
- readonly ${__flags_const}
170
- else # handle zsh
171
- case ${ZSH_VERSION} in
172
- [123].*) readonly ${__flags_const} ;;
173
- *) readonly -g ${__flags_const} ;; # declare readonly constants globally
174
- esac
175
- fi
176
- done
177
- unset __flags_const __flags_constants
178
-
179
- #
180
- # internal variables
181
- #
182
-
183
- __flags_boolNames=' ' # space separated list of boolean flag names
184
- __flags_longNames=' ' # space separated list of long flag names
185
- __flags_shortNames=' ' # space separated list of short flag names
186
-
187
- __flags_columns='' # screen width in columns
188
- __flags_opts='' # temporary storage for parsed getopt flags
189
-
190
- #------------------------------------------------------------------------------
191
- # private functions
192
- #
193
-
194
- # Define a flag.
195
- #
196
- # Calling this function will define the following info variables for the
197
- # specified flag:
198
- # FLAGS_flagname - the name for this flag (based upon the long flag name)
199
- # __flags_<flag_name>_default - the default value
200
- # __flags_flagname_help - the help string
201
- # __flags_flagname_short - the single letter alias
202
- # __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
203
- #
204
- # Args:
205
- # _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
206
- # _flags__name: string: long flag name
207
- # _flags__default: default flag value
208
- # _flags__help: string: help string
209
- # _flags__short: string: (optional) short flag name
210
- # Returns:
211
- # integer: success of operation, or error
212
- _flags_define()
213
- {
214
- if [ $# -lt 4 ]; then
215
- flags_error='DEFINE error: too few arguments'
216
- flags_return=${FLAGS_ERROR}
217
- _flags_error "${flags_error}"
218
- return ${flags_return}
219
- fi
220
-
221
- _flags_type_=$1
222
- _flags_name_=$2
223
- _flags_default_=$3
224
- _flags_help_=$4
225
- _flags_short_=${5:-${__FLAGS_NULL}}
226
-
227
- _flags_return_=${FLAGS_TRUE}
228
-
229
- # TODO(kward): check for validity of the flag name (e.g. dashes)
230
-
231
- # check whether the flag name is reserved
232
- echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
233
- if [ $? -eq 0 ]; then
234
- flags_error="flag name (${_flags_name_}) is reserved"
235
- _flags_return_=${FLAGS_ERROR}
236
- fi
237
-
238
- # require short option for getopt that don't support long options
239
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
240
- -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
241
- -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
242
- then
243
- flags_error="short flag required for (${_flags_name_}) on this platform"
244
- _flags_return_=${FLAGS_ERROR}
245
- fi
246
-
247
- # check for existing long name definition
248
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
249
- if _flags_itemInList "${_flags_name_}" \
250
- ${__flags_longNames} ${__flags_boolNames}
251
- then
252
- flags_error="flag name ([no]${_flags_name_}) already defined"
253
- _flags_warn "${flags_error}"
254
- _flags_return_=${FLAGS_FALSE}
255
- fi
256
- fi
257
-
258
- # check for existing short name definition
259
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
260
- -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
261
- then
262
- if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
263
- flags_error="flag short name (${_flags_short_}) already defined"
264
- _flags_warn "${flags_error}"
265
- _flags_return_=${FLAGS_FALSE}
266
- fi
267
- fi
268
-
269
- # handle default value. note, on several occasions the 'if' portion of an
270
- # if/then/else contains just a ':' which does nothing. a binary reversal via
271
- # '!' is not done because it does not work on all shells.
272
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
273
- case ${_flags_type_} in
274
- ${__FLAGS_TYPE_BOOLEAN})
275
- if _flags_validateBoolean "${_flags_default_}"; then
276
- case ${_flags_default_} in
277
- true|t|0) _flags_default_=${FLAGS_TRUE} ;;
278
- false|f|1) _flags_default_=${FLAGS_FALSE} ;;
279
- esac
280
- else
281
- flags_error="invalid default flag value '${_flags_default_}'"
282
- _flags_return_=${FLAGS_ERROR}
283
- fi
284
- ;;
285
-
286
- ${__FLAGS_TYPE_FLOAT})
287
- if _flags_validateFloat "${_flags_default_}"; then
288
- :
289
- else
290
- flags_error="invalid default flag value '${_flags_default_}'"
291
- _flags_return_=${FLAGS_ERROR}
292
- fi
293
- ;;
294
-
295
- ${__FLAGS_TYPE_INTEGER})
296
- if _flags_validateInteger "${_flags_default_}"; then
297
- :
298
- else
299
- flags_error="invalid default flag value '${_flags_default_}'"
300
- _flags_return_=${FLAGS_ERROR}
301
- fi
302
- ;;
303
-
304
- ${__FLAGS_TYPE_STRING}) ;; # everything in shell is a valid string
305
-
306
- *)
307
- flags_error="unrecognized flag type '${_flags_type_}'"
308
- _flags_return_=${FLAGS_ERROR}
309
- ;;
310
- esac
311
- fi
312
-
313
- if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
314
- # store flag information
315
- eval "FLAGS_${_flags_name_}='${_flags_default_}'"
316
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
317
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
318
- \"${_flags_default_}\""
319
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
320
- eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
321
-
322
- # append flag name(s) to list of names
323
- __flags_longNames="${__flags_longNames}${_flags_name_} "
324
- __flags_shortNames="${__flags_shortNames}${_flags_short_} "
325
- [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
326
- __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
327
- fi
328
-
329
- flags_return=${_flags_return_}
330
- unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
331
- _flags_type_
332
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
333
- return ${flags_return}
334
- }
335
-
336
- # Return valid getopt options using currently defined list of long options.
337
- #
338
- # This function builds a proper getopt option string for short (and long)
339
- # options, using the current list of long options for reference.
340
- #
341
- # Args:
342
- # _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
343
- # Output:
344
- # string: generated option string for getopt
345
- # Returns:
346
- # boolean: success of operation (always returns True)
347
- _flags_genOptStr()
348
- {
349
- _flags_optStrType_=$1
350
-
351
- _flags_opts_=''
352
-
353
- for _flags_flag_ in ${__flags_longNames}; do
354
- _flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
355
- case ${_flags_optStrType_} in
356
- ${__FLAGS_OPTSTR_SHORT})
357
- _flags_shortName_=`_flags_getFlagInfo \
358
- ${_flags_flag_} ${__FLAGS_INFO_SHORT}`
359
- if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
360
- _flags_opts_="${_flags_opts_}${_flags_shortName_}"
361
- # getopt needs a trailing ':' to indicate a required argument
362
- [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
363
- _flags_opts_="${_flags_opts_}:"
364
- fi
365
- ;;
366
-
367
- ${__FLAGS_OPTSTR_LONG})
368
- _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
369
- # getopt needs a trailing ':' to indicate a required argument
370
- [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
371
- _flags_opts_="${_flags_opts_}:"
372
- ;;
373
- esac
374
- done
375
-
376
- echo "${_flags_opts_}"
377
- unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
378
- _flags_type_
379
- return ${FLAGS_TRUE}
380
- }
381
-
382
- # Returns flag details based on a flag name and flag info.
383
- #
384
- # Args:
385
- # string: long flag name
386
- # string: flag info (see the _flags_define function for valid info types)
387
- # Output:
388
- # string: value of dereferenced flag variable
389
- # Returns:
390
- # integer: one of FLAGS_{TRUE|FALSE|ERROR}
391
- _flags_getFlagInfo()
392
- {
393
- _flags_name_=$1
394
- _flags_info_=$2
395
-
396
- _flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
397
- _flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
398
- eval "${_flags_strToEval_}"
399
- if [ -n "${_flags_value_}" ]; then
400
- flags_return=${FLAGS_TRUE}
401
- else
402
- # see if the _flags_name_ variable is a string as strings can be empty...
403
- # note: the DRY principle would say to have this function call itself for
404
- # the next three lines, but doing so results in an infinite loop as an
405
- # invalid _flags_name_ will also not have the associated _type variable.
406
- # Because it doesn't (it will evaluate to an empty string) the logic will
407
- # try to find the _type variable of the _type variable, and so on. Not so
408
- # good ;-)
409
- _flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
410
- _flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
411
- eval "${_flags_strToEval_}"
412
- if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
413
- flags_return=${FLAGS_TRUE}
414
- else
415
- flags_return=${FLAGS_ERROR}
416
- flags_error="invalid flag name (${_flags_nameVar_})"
417
- fi
418
- fi
419
-
420
- echo "${_flags_value_}"
421
- unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
422
- _flags_nameVar_ _flags_typeVar_
423
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
424
- return ${flags_return}
425
- }
426
-
427
- # check for presense of item in a list. passed a string (e.g. 'abc'), this
428
- # function will determine if the string is present in the list of strings (e.g.
429
- # ' foo bar abc ').
430
- #
431
- # Args:
432
- # _flags__str: string: string to search for in a list of strings
433
- # unnamed: list: list of strings
434
- # Returns:
435
- # boolean: true if item is in the list
436
- _flags_itemInList()
437
- {
438
- _flags_str_=$1
439
- shift
440
-
441
- echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
442
- if [ $? -eq 0 ]; then
443
- flags_return=${FLAGS_TRUE}
444
- else
445
- flags_return=${FLAGS_FALSE}
446
- fi
447
-
448
- unset _flags_str_
449
- return ${flags_return}
450
- }
451
-
452
- # Returns the width of the current screen.
453
- #
454
- # Output:
455
- # integer: width in columns of the current screen.
456
- _flags_columns()
457
- {
458
- if [ -z "${__flags_columns}" ]; then
459
- # determine the value and store it
460
- if eval stty size >/dev/null 2>&1; then
461
- # stty size worked :-)
462
- set -- `stty size`
463
- __flags_columns=$2
464
- elif eval tput cols >/dev/null 2>&1; then
465
- set -- `tput cols`
466
- __flags_columns=$1
467
- else
468
- __flags_columns=80 # default terminal width
469
- fi
470
- fi
471
- echo ${__flags_columns}
472
- }
473
-
474
- # Validate a boolean.
475
- #
476
- # Args:
477
- # _flags__bool: boolean: value to validate
478
- # Returns:
479
- # bool: true if the value is a valid boolean
480
- _flags_validateBoolean()
481
- {
482
- _flags_bool_=$1
483
-
484
- flags_return=${FLAGS_TRUE}
485
- case "${_flags_bool_}" in
486
- true|t|0) ;;
487
- false|f|1) ;;
488
- *) flags_return=${FLAGS_FALSE} ;;
489
- esac
490
-
491
- unset _flags_bool_
492
- return ${flags_return}
493
- }
494
-
495
- # Validate a float.
496
- #
497
- # Args:
498
- # _flags__float: float: value to validate
499
- # Returns:
500
- # bool: true if the value is a valid float
501
- _flags_validateFloat()
502
- {
503
- _flags_float_=$1
504
-
505
- if _flags_validateInteger ${_flags_float_}; then
506
- flags_return=${FLAGS_TRUE}
507
- else
508
- flags_return=${FLAGS_TRUE}
509
- case ${_flags_float_} in
510
- -*) # negative floats
511
- _flags_test_=`expr "${_flags_float_}" : '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
512
- ;;
513
- *) # positive floats
514
- _flags_test_=`expr "${_flags_float_}" : '\([0-9][0-9]*\.[0-9][0-9]*\)'`
515
- ;;
516
- esac
517
- [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
518
- fi
519
-
520
- unset _flags_float_ _flags_test_
521
- return ${flags_return}
522
- }
523
-
524
- # Validate an integer.
525
- #
526
- # Args:
527
- # _flags__integer: interger: value to validate
528
- # Returns:
529
- # bool: true if the value is a valid integer
530
- _flags_validateInteger()
531
- {
532
- _flags_int_=$1
533
-
534
- flags_return=${FLAGS_TRUE}
535
- case ${_flags_int_} in
536
- -*) # negative ints
537
- _flags_test_=`expr "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
538
- ;;
539
- *) # positive ints
540
- _flags_test_=`expr "${_flags_int_}" : '\([0-9][0-9]*\)'`
541
- ;;
542
- esac
543
- [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
544
-
545
- unset _flags_int_ _flags_test_
546
- return ${flags_return}
547
- }
548
-
549
- # Parse command-line options using the standard getopt.
550
- #
551
- # Note: the flag options are passed around in the global __flags_opts so that
552
- # the formatting is not lost due to shell parsing and such.
553
- #
554
- # Args:
555
- # @: varies: command-line options to parse
556
- # Returns:
557
- # integer: a FLAGS success condition
558
- _flags_getoptStandard()
559
- {
560
- flags_return=${FLAGS_TRUE}
561
- _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
562
-
563
- # check for spaces in passed options
564
- for _flags_opt_ in "$@"; do
565
- # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
566
- _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
567
- if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
568
- flags_error='the available getopt does not support spaces in options'
569
- flags_return=${FLAGS_ERROR}
570
- break
571
- fi
572
- done
573
-
574
- if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
575
- __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
576
- _flags_rtrn_=$?
577
- if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
578
- _flags_warn "${__flags_opts}"
579
- flags_error='unable to parse provided options with getopt.'
580
- flags_return=${FLAGS_ERROR}
581
- fi
582
- fi
583
-
584
- unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
585
- return ${flags_return}
586
- }
587
-
588
- # Parse command-line options using the enhanced getopt.
589
- #
590
- # Note: the flag options are passed around in the global __flags_opts so that
591
- # the formatting is not lost due to shell parsing and such.
592
- #
593
- # Args:
594
- # @: varies: command-line options to parse
595
- # Returns:
596
- # integer: a FLAGS success condition
597
- _flags_getoptEnhanced()
598
- {
599
- flags_return=${FLAGS_TRUE}
600
- _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
601
- _flags_boolOpts_=`echo "${__flags_boolNames}" \
602
- |sed 's/^ *//;s/ *$//;s/ /,/g'`
603
- _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
604
-
605
- __flags_opts=`getopt \
606
- -o ${_flags_shortOpts_} \
607
- -l "${_flags_longOpts_},${_flags_boolOpts_}" \
608
- -- "$@" 2>&1`
609
- _flags_rtrn_=$?
610
- if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
611
- _flags_warn "${__flags_opts}"
612
- flags_error='unable to parse provided options with getopt.'
613
- flags_return=${FLAGS_ERROR}
614
- fi
615
-
616
- unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
617
- return ${flags_return}
618
- }
619
-
620
- # Dynamically parse a getopt result and set appropriate variables.
621
- #
622
- # This function does the actual conversion of getopt output and runs it through
623
- # the standard case structure for parsing. The case structure is actually quite
624
- # dynamic to support any number of flags.
625
- #
626
- # Args:
627
- # argc: int: original command-line argument count
628
- # @: varies: output from getopt parsing
629
- # Returns:
630
- # integer: a FLAGS success condition
631
- _flags_parseGetopt()
632
- {
633
- _flags_argc_=$1
634
- shift
635
-
636
- flags_return=${FLAGS_TRUE}
637
-
638
- if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
639
- set -- $@
640
- else
641
- # note the quotes around the `$@' -- they are essential!
642
- eval set -- "$@"
643
- fi
644
-
645
- # provide user with number of arguments to shift by later
646
- # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
647
- # properly give user access to non-flag arguments mixed in between flag
648
- # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
649
- # for backwards compatibility reasons.
650
- FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
651
-
652
- # handle options. note options with values must do an additional shift
653
- while true; do
654
- _flags_opt_=$1
655
- _flags_arg_=${2:-}
656
- _flags_type_=${__FLAGS_TYPE_NONE}
657
- _flags_name_=''
658
-
659
- # determine long flag name
660
- case "${_flags_opt_}" in
661
- --) shift; break ;; # discontinue option parsing
662
-
663
- --*) # long option
664
- _flags_opt_=`expr "${_flags_opt_}" : '--\(.*\)'`
665
- _flags_len_=${__FLAGS_LEN_LONG}
666
- if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
667
- _flags_name_=${_flags_opt_}
668
- else
669
- # check for negated long boolean version
670
- if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
671
- _flags_name_=`expr "${_flags_opt_}" : 'no\(.*\)'`
672
- _flags_type_=${__FLAGS_TYPE_BOOLEAN}
673
- _flags_arg_=${__FLAGS_NULL}
674
- fi
675
- fi
676
- ;;
677
-
678
- -*) # short option
679
- _flags_opt_=`expr "${_flags_opt_}" : '-\(.*\)'`
680
- _flags_len_=${__FLAGS_LEN_SHORT}
681
- if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
682
- # yes. match short name to long name. note purposeful off-by-one
683
- # (too high) with awk calculations.
684
- _flags_pos_=`echo "${__flags_shortNames}" \
685
- |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
686
- e=${_flags_opt_}`
687
- _flags_name_=`echo "${__flags_longNames}" \
688
- |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
689
- fi
690
- ;;
691
- esac
692
-
693
- # die if the flag was unrecognized
694
- if [ -z "${_flags_name_}" ]; then
695
- flags_error="unrecognized option (${_flags_opt_})"
696
- flags_return=${FLAGS_ERROR}
697
- break
698
- fi
699
-
700
- # set new flag value
701
- [ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
702
- _flags_type_=`_flags_getFlagInfo \
703
- "${_flags_name_}" ${__FLAGS_INFO_TYPE}`
704
- case ${_flags_type_} in
705
- ${__FLAGS_TYPE_BOOLEAN})
706
- if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
707
- if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
708
- eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
709
- else
710
- eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
711
- fi
712
- else
713
- _flags_strToEval_="_flags_val_=\
714
- \${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
715
- eval "${_flags_strToEval_}"
716
- if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
717
- eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
718
- else
719
- eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
720
- fi
721
- fi
722
- ;;
723
-
724
- ${__FLAGS_TYPE_FLOAT})
725
- if _flags_validateFloat "${_flags_arg_}"; then
726
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
727
- else
728
- flags_error="invalid float value (${_flags_arg_})"
729
- flags_return=${FLAGS_ERROR}
730
- break
731
- fi
732
- ;;
733
-
734
- ${__FLAGS_TYPE_INTEGER})
735
- if _flags_validateInteger "${_flags_arg_}"; then
736
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
737
- else
738
- flags_error="invalid integer value (${_flags_arg_})"
739
- flags_return=${FLAGS_ERROR}
740
- break
741
- fi
742
- ;;
743
-
744
- ${__FLAGS_TYPE_STRING})
745
- eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
746
- ;;
747
- esac
748
-
749
- # handle special case help flag
750
- if [ "${_flags_name_}" = 'help' ]; then
751
- if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
752
- flags_error='help requested'
753
- flags_return=${FLAGS_FALSE}
754
- break
755
- fi
756
- fi
757
-
758
- # shift the option and non-boolean arguements out.
759
- shift
760
- [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} ] && shift
761
- done
762
-
763
- # give user back non-flag arguments
764
- FLAGS_ARGV=''
765
- while [ $# -gt 0 ]; do
766
- FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
767
- shift
768
- done
769
-
770
- unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
771
- _flags_strToEval_ _flags_type_ _flags_val_
772
- return ${flags_return}
773
- }
774
-
775
- #------------------------------------------------------------------------------
776
- # public functions
777
- #
778
-
779
- # A basic boolean flag. Boolean flags do not take any arguments, and their
780
- # value is either 1 (false) or 0 (true). For long flags, the false value is
781
- # specified on the command line by prepending the word 'no'. With short flags,
782
- # the presense of the flag toggles the current value between true and false.
783
- # Specifying a short boolean flag twice on the command results in returning the
784
- # value back to the default value.
785
- #
786
- # A default value is required for boolean flags.
787
- #
788
- # For example, lets say a Boolean flag was created whose long name was 'update'
789
- # and whose short name was 'x', and the default value was 'false'. This flag
790
- # could be explicitly set to 'true' with '--update' or by '-x', and it could be
791
- # explicitly set to 'false' with '--noupdate'.
792
- DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@" || return "$?"; }
793
-
794
- # Other basic flags.
795
- DEFINE_float() { _flags_define ${__FLAGS_TYPE_FLOAT} "$@" || return "$?"; }
796
- DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@" || return "$?"; }
797
- DEFINE_string() { _flags_define ${__FLAGS_TYPE_STRING} "$@" || return "$?"; }
798
-
799
- # Parse the flags.
800
- #
801
- # Args:
802
- # unnamed: list: command-line flags to parse
803
- # Returns:
804
- # integer: success of operation, or error
805
- FLAGS()
806
- {
807
- # define a standard 'help' flag if one isn't already defined
808
- [ -z "${__flags_help_type:-}" ] && \
809
- DEFINE_boolean 'help' false 'show this help' 'h'
810
-
811
- # parse options
812
- if [ $# -gt 0 ]; then
813
- if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
814
- _flags_getoptStandard "$@"
815
- else
816
- _flags_getoptEnhanced "$@"
817
- fi
818
- flags_return=$?
819
- else
820
- # nothing passed; won't bother running getopt
821
- __flags_opts='--'
822
- flags_return=${FLAGS_TRUE}
823
- fi
824
-
825
- if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
826
- _flags_parseGetopt $# "${__flags_opts}"
827
- flags_return=$?
828
- fi
829
-
830
- [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
831
- return ${flags_return}
832
- }
833
-
834
- # This is a helper function for determining the `getopt` version for platforms
835
- # where the detection isn't working. It simply outputs debug information that
836
- # can be included in a bug report.
837
- #
838
- # Args:
839
- # none
840
- # Output:
841
- # debug info that can be included in a bug report
842
- # Returns:
843
- # nothing
844
- flags_getoptInfo()
845
- {
846
- # platform info
847
- _flags_debug "uname -a: `uname -a`"
848
- _flags_debug "PATH: ${PATH}"
849
-
850
- # shell info
851
- if [ -n "${BASH_VERSION:-}" ]; then
852
- _flags_debug 'shell: bash'
853
- _flags_debug "BASH_VERSION: ${BASH_VERSION}"
854
- elif [ -n "${ZSH_VERSION:-}" ]; then
855
- _flags_debug 'shell: zsh'
856
- _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
857
- fi
858
-
859
- # getopt info
860
- getopt >/dev/null
861
- _flags_getoptReturn=$?
862
- _flags_debug "getopt return: ${_flags_getoptReturn}"
863
- _flags_debug "getopt --version: `getopt --version 2>&1`"
864
-
865
- unset _flags_getoptReturn
866
- }
867
-
868
- # Returns whether the detected getopt version is the enhanced version.
869
- #
870
- # Args:
871
- # none
872
- # Output:
873
- # none
874
- # Returns:
875
- # bool: true if getopt is the enhanced version
876
- flags_getoptIsEnh()
877
- {
878
- test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
879
- }
880
-
881
- # Returns whether the detected getopt version is the standard version.
882
- #
883
- # Args:
884
- # none
885
- # Returns:
886
- # bool: true if getopt is the standard version
887
- flags_getoptIsStd()
888
- {
889
- test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
890
- }
891
-
892
- # This is effectively a 'usage()' function. It prints usage information and
893
- # exits the program with ${FLAGS_FALSE} if it is ever found in the command line
894
- # arguments. Note this function can be overridden so other apps can define
895
- # their own --help flag, replacing this one, if they want.
896
- #
897
- # Args:
898
- # none
899
- # Returns:
900
- # integer: success of operation (always returns true)
901
- flags_help()
902
- {
903
- if [ -n "${FLAGS_HELP:-}" ]; then
904
- echo "${FLAGS_HELP}" >&2
905
- else
906
- echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
907
- fi
908
- if [ -n "${__flags_longNames}" ]; then
909
- echo 'flags:' >&2
910
- for flags_name_ in ${__flags_longNames}; do
911
- flags_flagStr_=''
912
- flags_boolStr_=''
913
-
914
- flags_default_=`_flags_getFlagInfo \
915
- "${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
916
- flags_help_=`_flags_getFlagInfo \
917
- "${flags_name_}" ${__FLAGS_INFO_HELP}`
918
- flags_short_=`_flags_getFlagInfo \
919
- "${flags_name_}" ${__FLAGS_INFO_SHORT}`
920
- flags_type_=`_flags_getFlagInfo \
921
- "${flags_name_}" ${__FLAGS_INFO_TYPE}`
922
-
923
- [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
924
- && flags_flagStr_="-${flags_short_}"
925
-
926
- if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
927
- [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
928
- && flags_flagStr_="${flags_flagStr_},"
929
- [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
930
- && flags_boolStr_='[no]'
931
- flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
932
- fi
933
-
934
- case ${flags_type_} in
935
- ${__FLAGS_TYPE_BOOLEAN})
936
- if [ ${flags_default_} -eq ${FLAGS_TRUE} ]; then
937
- flags_defaultStr_='true'
938
- else
939
- flags_defaultStr_='false'
940
- fi
941
- ;;
942
- ${__FLAGS_TYPE_FLOAT}|${__FLAGS_TYPE_INTEGER})
943
- flags_defaultStr_=${flags_default_} ;;
944
- ${__FLAGS_TYPE_STRING}) flags_defaultStr_="'${flags_default_}'" ;;
945
- esac
946
- flags_defaultStr_="(default: ${flags_defaultStr_})"
947
-
948
- flags_helpStr_=" ${flags_flagStr_} ${flags_help_} ${flags_defaultStr_}"
949
- flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
950
- flags_columns_=`_flags_columns`
951
- if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
952
- echo "${flags_helpStr_}" >&2
953
- else
954
- echo " ${flags_flagStr_} ${flags_help_}" >&2
955
- # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
956
- # because it doesn't like empty strings when used in this manner.
957
- flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
958
- |awk '{printf "%"length($0)-2"s", ""}'`"
959
- flags_helpStr_=" ${flags_emptyStr_} ${flags_defaultStr_}"
960
- flags_helpStrLen_=`expr "${flags_helpStr_}" : '.*'`
961
- if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
962
- -o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
963
- # indented to match help string
964
- echo "${flags_helpStr_}" >&2
965
- else
966
- # indented four from left to allow for longer defaults as long flag
967
- # names might be used too, making things too long
968
- echo " ${flags_defaultStr_}" >&2
969
- fi
970
- fi
971
- done
972
- fi
973
-
974
- unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
975
- flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
976
- flags_columns_ flags_short_ flags_type_
977
- return ${FLAGS_TRUE}
978
- }
979
-
980
- # Reset shflags back to an uninitialized state.
981
- #
982
- # Args:
983
- # none
984
- # Returns:
985
- # nothing
986
- flags_reset()
987
- {
988
- for flags_name_ in ${__flags_longNames}; do
989
- flags_strToEval_="unset FLAGS_${flags_name_}"
990
- for flags_type_ in \
991
- ${__FLAGS_INFO_DEFAULT} \
992
- ${__FLAGS_INFO_HELP} \
993
- ${__FLAGS_INFO_SHORT} \
994
- ${__FLAGS_INFO_TYPE}
995
- do
996
- flags_strToEval_=\
997
- "${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
998
- done
999
- eval ${flags_strToEval_}
1000
- done
1001
-
1002
- # reset internal variables
1003
- __flags_boolNames=' '
1004
- __flags_longNames=' '
1005
- __flags_shortNames=' '
1006
-
1007
- unset flags_name_ flags_type_ flags_strToEval_
1008
- }
1009
-
1010
- # parse stops on first non-option arg
1011
- FLAGS_SUB="$FLAGS_FALSE"
1012
-