Skip to content

Commit 8a33945

Browse files
committed
[MISC] Allow recursive subcommands
1 parent e7920c3 commit 8a33945

File tree

1 file changed

+34
-11
lines changed

1 file changed

+34
-11
lines changed

include/sharg/parser.hpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,21 +185,11 @@ class parser
185185
update_notifications version_updates = update_notifications::on,
186186
std::vector<std::string> subcommands = {}) :
187187
version_check_dev_decision{version_updates},
188-
subcommands{std::move(subcommands)},
189188
original_arguments{arguments}
190189
{
191-
for (auto & sub : this->subcommands)
192-
{
193-
if (!std::regex_match(sub, app_name_regex))
194-
{
195-
throw design_error{"The subcommand name must only contain alpha-numeric characters or '_' and '-' "
196-
"(regex: \"^[a-zA-Z0-9_-]+$\")."};
197-
}
198-
}
199-
200190
info.app_name = app_name;
201191

202-
init();
192+
add_subcommands(std::move(subcommands));
203193
}
204194

205195
//!\overload
@@ -674,10 +664,43 @@ class parser
674664
*/
675665
parser_meta_data info;
676666

667+
/*!\brief Adds subcommands to the parser.
668+
* \param[in] subcommands A list of subcommands.
669+
* \throws sharg::design_error if the subcommand name contains illegal characters.
670+
*/
671+
void add_subcommands(std::vector<std::string> const & subcommands)
672+
{
673+
for (auto const & sub : subcommands)
674+
{
675+
if (!std::regex_match(sub, app_name_regex))
676+
{
677+
std::string const error_message =
678+
detail::to_string(std::quoted(info.app_name),
679+
" contains an invalid subcommand name: ",
680+
std::quoted(sub),
681+
". The subcommand name must only contain alpha-numeric characters ",
682+
"or '_' and '-' (regex: \"^[a-zA-Z0-9_-]+$\").");
683+
throw design_error{error_message};
684+
};
685+
}
686+
687+
auto & parser_subcommands = this->subcommands;
688+
parser_subcommands.insert(parser_subcommands.end(), subcommands.cbegin(), subcommands.cend());
689+
690+
std::ranges::sort(parser_subcommands);
691+
auto const [first, last] = std::ranges::unique(parser_subcommands);
692+
parser_subcommands.erase(first, last);
693+
694+
init();
695+
}
696+
677697
private:
678698
//!\brief Keeps track of whether the parse function has been called already.
679699
bool parse_was_called{false};
680700

701+
//!\brief Keeps track of whether the init function has been called already.
702+
bool init_was_called{false};
703+
681704
//!\brief Keeps track of whether the user has added a positional list option to check if this was the very last.
682705
bool has_positional_list_option{false};
683706

0 commit comments

Comments
 (0)