support automatique options verbosity et interaction

This commit is contained in:
Jephté Clain 2025-03-03 08:09:58 +04:00
parent 882549375c
commit ead5b5adcf
2 changed files with 111 additions and 37 deletions

View File

@ -124,8 +124,8 @@ optdesc
commence par ++, c'est une option avancée qui n'est pas affichée par défaut."
function parse_args() {
eval "$NULIB__DISABLE_SET_X"
[ -n "$NULIB_ARGS_ONERROR_RETURN" ] && set_die_return
local __r=
local __DIE='[ -n "$NULIB_ARGS_ONERROR_RETURN" ] && return 1 || die'
if ! is_array args; then
eerror "Invalid args definition: args must be defined"
@ -145,17 +145,33 @@ function parse_args() {
__r=1
else
__DEFS=("$@")
__parse_args || __r=1
__nulib_args_parse_args || __r=1
fi
eval "$NULIB__ENABLE_SET_X"
if [ -n "$__r" ]; then
eval "$__DIE"
die || return
fi
}
function __parse_args() {
function __nulib_args_add_sopt() {
local noauto="$1"; shift
local def
for def in "$@"; do
array_contains "$noauto" "$def" || __sopts="$__sopts$def"
done
}
function __nulib_args_add_lopt() {
local noauto="$1"; shift
local def
for def in "$@"; do
array_contains "$noauto" "$def" || __lopts="$__lopts${__lopts:+,}$def"
done
}
function __nulib_args_parse_args() {
## tout d'abord, construire la liste des options
local __AUTOH=1 __AUTOHELP=1 # faut-il gérer automatiquement l'affichage de l'aide?
local __AUTOD=1 __AUTODEBUG=1 # faut-il rajouter les options -D et --debug
local -a __NOAUTOL __NOAUTOLOGTO # faut-il rajouter les options pour gérer la journalisation?
local -a __NOAUTOV __NOAUTOVERBOSITY # options de verbosité qui ont été définies par l'utilisateur
local -a __NOAUTOI __NOAUTOINTERACTION # options d'interaction qui ont été définies par l'utilisateur
local __ADVHELP # y a-t-il des options avancées?
local __popt __sopts __lopts
local -a __defs
@ -165,10 +181,10 @@ function __parse_args() {
+) __popt="$1"; shift; continue;;
-) __popt="$1"; shift; continue;;
-*) IFS=, read -a __defs <<<"$1"; shift;;
*) eerror "Invalid arg definition: expected option, got '$1'"; eval "$__DIE";;
*) die "Invalid arg definition: expected option, got '$1'" || return;;
esac
# est-ce que l'option prend un argument?
local __def __witharg __valdesc
local __def __longdef __witharg __valdesc
__witharg=
for __def in "${__defs[@]}"; do
if [ "${__def%::*}" != "$__def" ]; then
@ -180,23 +196,36 @@ function __parse_args() {
# définitions __sopts et __lopts
for __def in "${__defs[@]}"; do
__def="${__def%%:*}"
__longdef=
if [[ "$__def" == --* ]]; then
# --longopt
__def="${__def#--}"
__lopts="$__lopts${__lopts:+,}$__def$__witharg"
__longdef=1
elif [[ "$__def" == -* ]] && [ ${#__def} -eq 2 ]; then
# -o
__def="${__def#-}"
__sopts="$__sopts$__def$__witharg"
[ "$__def" == h ] && __AUTOH=
[ "$__def" == D ] && __AUTOD=
case "$__def" in
h) __AUTOH=;;
L) __NOAUTOL+=("-$__def");;
Q|q|v|D) __NOAUTOV+=("-$__def");;
b|y|i) __NOAUTOI+=("-$__def");;
esac
else
# -longopt ou longopt
__def="${__def#-}"
__lopts="$__lopts${__lopts:+,}$__def$__witharg"
__longdef=1
fi
if [ -n "$__longdef" ]; then
case "$__def" in
help|help++) __AUTOHELP=;;
log-to) __NOAUTOLOGTO+=("--$__def");;
very-quiet|quiet|verbose|debug) __NOAUTOVERBOSITY+=("--$__def");;
batch|automatic|interactive) __NOAUTOINTERACTION+=("--$__def");;
esac
fi
[ "$__def" == help -o "$__def" == help++ ] && __AUTOHELP=
[ "$__def" == debug ] && __AUTODEBUG=
done
# sauter l'action
shift
@ -209,8 +238,12 @@ function __parse_args() {
[ -n "$__AUTOH" ] && __sopts="${__sopts}h"
[ -n "$__AUTOHELP" ] && __lopts="$__lopts${__lopts:+,}help,help++"
[ -n "$__AUTOD" ] && __sopts="${__sopts}D"
[ -n "$__AUTODEBUG" ] && __lopts="$__lopts${__lopts:+,}debug"
__nulib_args_add_sopt __NOAUTOL L
__nulib_args_add_lopt __NOAUTOLOGTO log-to
__nulib_args_add_sopt __NOAUTOV Q q v D
__nulib_args_add_lopt __NOAUTOVERBOSITY very-quiet quiet verbose debug
__nulib_args_add_sopt __NOAUTOI b y i
__nulib_args_add_lopt __NOAUTOINTERACTION batch automatic interactive
__sopts="$__popt$__sopts"
local -a __getopt_args
@ -222,7 +255,7 @@ function __parse_args() {
else
# relancer pour avoir le message d'erreur
LANG=C getopt "${__getopt_args[@]}" 2>&1 1>/dev/null
eval "$__DIE"
die || return
fi
## puis traiter les options
@ -373,7 +406,7 @@ $prefix$usage"
fi
[[ "$1" == -* ]] || break
option_="$1"; shift
__parse_opt "$option_"
__nulib_args_parse_opt "$option_"
if [ -n "$__witharg" ]; then
# l'option prend un argument
value_="$1"; shift
@ -387,7 +420,7 @@ $prefix$usage"
unset -f inc@ res@ add@ set@ showhelp@
args=("$@")
}
function __parse_opt() {
function __nulib_args_parse_opt() {
# $1 est l'option spécifiée
local option_="$1"
set -- "${__DEFS[@]}"
@ -460,27 +493,62 @@ function __parse_opt() {
[ -n "$__found" ] && return 0
done
if [ -n "$__AUTOH" -a "$option_" == -h ]; then
__action="showhelp@"
case "$option_" in
-h)
if [ -n "$__AUTOH" ]; then
__action='showhelp@'
return 0
fi
;;
--help)
if [ -n "$__AUTOHELP" ]; then
if [ "$option_" == --help ]; then
__action="showhelp@"
return 0
elif [ "$option_" == --help++ ]; then
__action="showhelp@ ++"
__action='showhelp@'
return 0
fi
fi
if [ -n "$__AUTOD" -a "$option_" == -D ]; then
__action=set_debug
;;
--help++)
if [ -n "$__AUTOHELP" ]; then
__action='showhelp@ ++'
return 0
fi
if [ -n "$__AUTODEBUG" -a "$option_" == --debug ]; then
__action=set_debug
;;
-L)
if ! array_contains __NOAUTOL "$option_"; then
__action='elogto $value_'
return 0
fi
;;
--log-to)
if ! array_contains __NOAUTOL "$option_"; then
__action='elogto $value_'
return 0
fi
;;
-Q|-q|-v|-D)
if ! array_contains __NOAUTOV "$option_"; then
__action='set_verbosity $option_'
return 0
fi
;;
--very-quiet|--quiet|--verbose|--debug)
if ! array_contains __NOAUTOVERBOSITY "$option_"; then
__action='set_verbosity $option_'
return 0
fi
;;
-b|-y|-i)
if ! array_contains __NOAUTOI "$option_"; then
__action='set_interaction $option_'
return 0
fi
;;
--batch|--automatic|--interactive)
if ! array_contains __NOAUTOINTERACTION "$option_"; then
__action='set_interaction $option_'
return 0
fi
;;
esac
# ici, l'option n'a pas été trouvée, on ne devrait pas arriver ici
eerror "Unexpected option '$option_'"; eval "$__DIE"
die "Unexpected option '$option_'" || return
}

View File

@ -108,11 +108,17 @@ function set_interaction() {
# set_interaction en fonction des arguments de la ligne de commande. A utiliser
# de cette manière:
# parse_opts ... "${PRETTYOPTS[@]}" @ args -- ...
PRETTYOPTS=(
# NB: ce n'est pas nécessaire, sauf si on veut afficher ces options dans l'aide
LOGTOOPTS=(
-L:,--log-to:LOGFILE '$elogto $value_' "++enregistrer les messages dans le fichier spécifié"
)
VERBOSITYOPTS=(
-Q,--very-quiet,-q,--quiet,-v,--verbose,-D,--debug '$set_verbosity $option_' "++spécifier le niveau de verbiage"
)
INTERACTIONOPTS=(
-b,--batch,-y,--automatic,-i,--interactive '$set_interaction $option_' "++spécifier le niveau d'interaction"
)
PRETTYOPTS=("${LOGTOOPTS[@]}" "${VERBOSITYOPTS[@]}" "${INTERACTIONOPTS[@]}")
function show_error() { [ "$__verbosity" -ge 1 ]; }
function show_warn() { [ "$__verbosity" -ge 2 ]; }