feat: subcommand arg support

This commit is contained in:
2026-06-02 22:28:48 +02:00
parent 0bd35bd8b1
commit f2b0bc66f1
2 changed files with 43 additions and 6 deletions
+30 -4
View File
@@ -1,4 +1,4 @@
std::mod::init clap 0.1.1 std::mod::init clap 0.2.0
## ##
# must be called after declaring a `clap__flags` as associative arrays, where: # must be called after declaring a `clap__flags` as associative arrays, where:
@@ -8,12 +8,27 @@ std::mod::init clap 0.1.1
# If the flag expects a value it must have assigned "value", if its a flat flag # If the flag expects a value it must have assigned "value", if its a flat flag
# "bool", otherwise UB. # "bool", otherwise UB.
# #
# Returns the data in -A clap__options (with values or `1` for boolean flags) # Returns the data in -A clap__options (with values or `1` for boolean flags),
# and -a clap_arguments # -a clap_arguments and -a clap__subcommand_arguments
#
# # Subcommands
#
# Subcommands whould be done by nested parsing, there's no "one pass" parsing.
# An implementation should be obvious by the following.
#
# If CLAP__PARSE_IS_SUBCOMMAND=1, `clap_arguments` will only have the first
# subcommand it finds and `clap__subcommand_arguments` will contain the rest of
# the arguments and flags, for nested parsing. Subcommand might be empty in the
# case no arguments were provided or a `--` was given.
#
# If unset or equal to 0, `clap_arguments` will have proper parsed arguments
# (not flags) and `clap__subcommand_arguments` will be empty.
## ##
clap::parse() { clap::parse() {
declare -gA clap__options=() declare -gA clap__options=()
declare -ga clap__arguments=() declare -ga clap__arguments=()
declare -ga clap__subcommand_arguments=()
local is_subcommand=${CLAP__PARSE_IS_SUBCOMMAND:-0}
local flag_i local flag_i
local short_flag local short_flag
@@ -24,6 +39,11 @@ clap::parse() {
shift shift
if [[ "$flag_i" == "--" ]]; then if [[ "$flag_i" == "--" ]]; then
if [ "$is_subcommand" -eq 1 ]; then
clap__subcommand_arguments=("$@")
return
fi
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
clap__arguments+=("$1") clap__arguments+=("$1")
shift shift
@@ -73,11 +93,17 @@ clap::parse() {
[ -n "$flag_i" ] [ -n "$flag_i" ]
do true; done do true; done
else else
if [ "$is_subcommand" -eq 1 ]; then
clap__arguments=("$flag_i")
clap__subcommand_arguments=("$@")
return
fi
clap__arguments+=("$flag_i") clap__arguments+=("$flag_i")
fi fi
done done
export clap__options clap__arguments export clap__options clap__arguments clap__subcommand_arguments
} }
clap::flag::is-short() { clap::flag::is-short() {
+13 -2
View File
@@ -38,7 +38,7 @@ std::assert-eq "should have parsed 1 arg" 1 "${#clap__arguments[@]}"
clap::parse -- -- clap::parse -- --
std::assert-eq "should have parsed 0 flags" 0 "${#clap__options[@]}" std::assert-eq "should have parsed 0 flags" 0 "${#clap__options[@]}"
std::assert-eq "should have parsed 1 arg" 1 "${#clap__arguments[@]}" std::assert-eq "should have parsed 1 arg" 1 "${#clap__arguments[@]}"
std::assert "1st arg should be '--'" "${clap__arguments[0]}" "==" "--" std::assert "1st arg should be '--'" "${clap__arguments[0]}" == "--"
# shellcheck disable=2251 # shellcheck disable=2251
! clap::parse --long-flagarg &>/dev/null ! clap::parse --long-flagarg &>/dev/null
@@ -47,12 +47,23 @@ std::assert "1st arg should be '--'" "${clap__arguments[0]}" "==" "--"
clap::parse --long-flag arg clap::parse --long-flag arg
std::assert-eq "should have parsed 0 args" 0 "${#clap__arguments[@]}" std::assert-eq "should have parsed 0 args" 0 "${#clap__arguments[@]}"
std::assert "'--long-flag' should be set" "${clap__options[$__long_flag]}" "==" arg std::assert "'--long-flag' should be set" "${clap__options[$__long_flag]}" == arg
clap::parse --long-bool-flag arg clap::parse --long-bool-flag arg
std::assert-eq "should have parsed 1 args" 1 "${#clap__arguments[@]}" std::assert-eq "should have parsed 1 args" 1 "${#clap__arguments[@]}"
std::assert-eq "'--long-bool-flag' should be set" 1 "${clap__options[$__long_bool_flag]}" std::assert-eq "'--long-bool-flag' should be set" 1 "${clap__options[$__long_bool_flag]}"
# --- Subcommands
CLAP__PARSE_IS_SUBCOMMAND=1 clap::parse --long-flag arg subcommand --subc-arg
std::assert-eq "should have parsed 1 subcommand" 1 "${#clap__arguments[@]}"
std::assert "subcommand should be 'subcommand'" subcommand == "${clap__arguments[0]}"
std::assert "'--long-flag' should be 'arg'" arg == "${clap__options[$__long_flag]}"
std::assert-eq "should have 1 subcommand argument" 1 "${#clap__subcommand_arguments[@]}"
std::assert "subcommand argument should be '--subc-arg'" "--subc-arg" == "${clap__subcommand_arguments[0]}"
# --- Help Menus
declare -a clap__help_commands=() declare -a clap__help_commands=()
declare -a clap__help_options=() declare -a clap__help_options=()