mirror of https://github.com/dyne/zuper.git
sub/command optarg parser refurbished from Tomb
This commit is contained in:
parent
f0417a1c03
commit
a9b9d76b0d
150
zuper
150
zuper
|
|
@ -704,6 +704,7 @@ EOF
|
|||
func "$_num key/values stored in $_path"
|
||||
}
|
||||
|
||||
|
||||
# }}} Key/Value filesave
|
||||
|
||||
# {{{ Get/Set REST API
|
||||
|
|
@ -845,6 +846,155 @@ EOF
|
|||
|
||||
# }}} Get/Set REST API
|
||||
|
||||
# {{{ Parse commandline options
|
||||
|
||||
# for example usage, see Tomb http://tomb.dyne.org
|
||||
vars+=(subcommand)
|
||||
arrs+=(option_main option_params)
|
||||
maps+=(option option_subcommands)
|
||||
|
||||
# Hi, dear developer! Are you trying to add a new subcommand, or
|
||||
# to add some options? Well, keep in mind that option names are
|
||||
# global: they cannot bear a different meaning or behaviour across
|
||||
# subcommands. The only exception is "-o" which means: "options
|
||||
# passed to the local subcommand", and thus can bear a different
|
||||
# meaning for different subcommands.
|
||||
#
|
||||
# For example, "-s" means "size" and accepts one argument. If you
|
||||
# are tempted to add an alternate option "-s" (e.g., to mean
|
||||
# "silent", and that doesn't accept any argument) DON'T DO IT!
|
||||
#
|
||||
# There are two reasons for that:
|
||||
# I. Usability; users expect that "-s" is "size"
|
||||
# II. Option parsing WILL EXPLODE if you do this kind of bad
|
||||
# things (it will complain: "option defined more than once")
|
||||
#
|
||||
# If you want to use the same option in multiple commands then you
|
||||
# can only use the non-abbreviated long-option version like:
|
||||
# -force and NOT -f
|
||||
|
||||
option.is_set() {
|
||||
|
||||
# Check whether a commandline option is set.
|
||||
#
|
||||
# Synopsis: option_is_set -flag [out]
|
||||
#
|
||||
# First argument is the commandline flag (e.g., "-s").
|
||||
# If the second argument is present and set to 'out', print out the
|
||||
# result: either 'set' or 'unset' (useful for if conditions).
|
||||
#
|
||||
# Return 0 if is set, 1 otherwise
|
||||
local -i r # the return code (0 = set, 1 = unset)
|
||||
|
||||
[[ -n ${(k)option[$1]} ]];
|
||||
r=$?
|
||||
|
||||
[[ $2 == "out" ]] && {
|
||||
[[ $r == 0 ]] && { print 'set' } || { print 'unset' }
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
# Print the option value matching the given flag
|
||||
# Unique argument is the commandline flag (e.g., "-s").
|
||||
option.value() {
|
||||
print -n - "${option[$1]}"
|
||||
}
|
||||
option.parse() {
|
||||
|
||||
### Detect subcommand
|
||||
local -aU every_opts #every_opts behave like a set; that is, an array with unique elements
|
||||
for optspec in ${option_subcommands}${option_main}; do
|
||||
for opt in ${=optspec}; do
|
||||
every_opts+=${opt}
|
||||
done
|
||||
done
|
||||
local -a oldstar
|
||||
oldstar=("${(@)argv}")
|
||||
#### detect early: useful for --option-parsing
|
||||
zparseopts -M -D -Adiscardme ${every_opts}
|
||||
if [[ -n ${(k)discardme[--option-parsing]} ]]; then
|
||||
print $1
|
||||
if [[ -n "$1" ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
unset discardme
|
||||
if ! zparseopts -M -E -D -Adiscardme ${every_opts}; then
|
||||
_failure "Error parsing."
|
||||
return 127
|
||||
fi
|
||||
unset discardme
|
||||
subcommand=${1}
|
||||
if [[ -z $subcommand ]]; then
|
||||
subcommand="__default"
|
||||
fi
|
||||
|
||||
if [[ -z ${(k)option_subcommands[$subcommand]} ]]; then
|
||||
_warning "There's no such command \"::1 subcommand::\"." $subcommand
|
||||
exitv=127 _failure "Please try -h for help."
|
||||
fi
|
||||
argv=("${(@)oldstar}")
|
||||
unset oldstar
|
||||
|
||||
### Parsing global + command-specific options
|
||||
# zsh magic: ${=string} will split to multiple arguments when spaces occur
|
||||
set -A cmd_opts ${option_main} ${=option_subcommands[$subcommand]}
|
||||
# if there is no option, we don't need parsing
|
||||
if [[ -n $cmd_opts ]]; then
|
||||
zparseopts -M -E -D -Aoption ${cmd_opts}
|
||||
if [[ $? != 0 ]]; then
|
||||
_warning "Some error occurred during option processing."
|
||||
exitv=127 _failure "See \"sdk help\" for more info."
|
||||
fi
|
||||
fi
|
||||
#build option_params (array of arguments) and check if there are unrecognized options
|
||||
ok=0
|
||||
option_params=()
|
||||
for arg in $*; do
|
||||
if [[ $arg == '--' || $arg == '-' ]]; then
|
||||
ok=1
|
||||
continue #it shouldn't be appended to option_params
|
||||
elif [[ $arg[1] == '-' ]]; then
|
||||
if [[ $ok == 0 ]]; then
|
||||
exitv=127 _failure "Unrecognized option ::1 arg:: for subcommand ::2 subcommand::" $arg $subcommand
|
||||
fi
|
||||
fi
|
||||
option_params+=$arg
|
||||
done
|
||||
# First parameter actually is the subcommand: delete it and shift
|
||||
[[ $subcommand != '__default' ]] && { option_params[1]=(); shift }
|
||||
|
||||
### End parsing command-specific options
|
||||
|
||||
[[ "$option_params" == "" ]] && {
|
||||
func "sdk command: ::1 subcommand::" $subcommand
|
||||
} || {
|
||||
func "sdk command: ::1 subcommand:: ::2 param::" $subcommand $option_params
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Later: process subcommand
|
||||
# case "$subcommand" in
|
||||
# help)
|
||||
# print "TODO: help"
|
||||
# ;;
|
||||
# __default)
|
||||
# zdump
|
||||
# ;;
|
||||
|
||||
# # Reject unknown command and suggest help
|
||||
# *)
|
||||
# _warning "Command \"::1 subcommand::\" not recognized." $subcommand
|
||||
# _message "Try -h for help."
|
||||
# return 1
|
||||
# ;;
|
||||
# esac
|
||||
|
||||
# }}}
|
||||
|
||||
# {{{ Helpers
|
||||
|
||||
function helper.isfound isfound() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue