Skip to content

Commit c72d2a0

Browse files
committed
Make the IncorrectConstruction errors on bad subcommand name more comprehensible.
1 parent e2e3cb2 commit c72d2a0

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

include/CLI/App.hpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,20 @@ class App {
368368
/// Set an alias for the app
369369
App *alias(std::string app_name) {
370370
if(!detail::valid_name_string(app_name)) {
371-
throw(IncorrectConstruction("alias is not a valid name string"));
371+
if(app_name.empty()) {
372+
throw IncorrectConstruction("Empty aliases are not allowed");
373+
}
374+
if(!detail::valid_first_char(app_name[0])) {
375+
throw IncorrectConstruction(
376+
"Alias starts with invalid character, allowed characters are [a-zA-z0-9]+'_','?','@' ");
377+
}
378+
for(auto c : app_name) {
379+
if(!detail::valid_later_char(c)) {
380+
throw IncorrectConstruction(std::string("Alias contains invalid character ('") + c +
381+
"'), allowed characters are "
382+
"[a-zA-z0-9]+'_','?','@','.','-' ");
383+
}
384+
}
372385
}
373386

374387
if(parent_ != nullptr) {
@@ -1013,7 +1026,17 @@ class App {
10131026
/// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
10141027
App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
10151028
if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
1016-
throw IncorrectConstruction("subcommand name is not valid");
1029+
if(!detail::valid_first_char(subcommand_name[0])) {
1030+
throw IncorrectConstruction(
1031+
"Subcommand name starts with invalid character, allowed characters are [a-zA-z0-9]+'_','?','@' ");
1032+
}
1033+
for(auto c : subcommand_name) {
1034+
if(!detail::valid_later_char(c)) {
1035+
throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
1036+
"'), allowed characters are "
1037+
"[a-zA-z0-9]+'_','?','@','.','-' ");
1038+
}
1039+
}
10171040
}
10181041
CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
10191042
return add_subcommand(std::move(subcom));

tests/SubcommandTest.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,18 @@ TEST_CASE_METHOD(TApp, "RequiredPosInSubcommand", "[subcom]") {
811811
CHECK_THROWS_AS(run(), CLI::RequiredError);
812812
}
813813

814+
TEST_CASE_METHOD(TApp, "invalidSubcommandName", "[subcom]") {
815+
816+
bool gotError{false};
817+
try {
818+
app.add_subcommand("foo/foo", "Foo a bar");
819+
} catch(const CLI::IncorrectConstruction &e) {
820+
gotError = true;
821+
CHECK_THAT(e.what(), Contains("/"));
822+
}
823+
CHECK(gotError);
824+
}
825+
814826
struct SubcommandProgram : public TApp {
815827

816828
CLI::App *start{nullptr};

0 commit comments

Comments
 (0)