Skip to content

Commit 15bb724

Browse files
authored
fix: make the IncorrectConstruction errors on bad subcommand name more comprehensible. (#602)
1 parent ee2b725 commit 15bb724

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) {
@@ -963,7 +976,17 @@ class App {
963976
/// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag
964977
App *add_subcommand(std::string subcommand_name = "", std::string subcommand_description = "") {
965978
if(!subcommand_name.empty() && !detail::valid_name_string(subcommand_name)) {
966-
throw IncorrectConstruction("subcommand name is not valid");
979+
if(!detail::valid_first_char(subcommand_name[0])) {
980+
throw IncorrectConstruction(
981+
"Subcommand name starts with invalid character, allowed characters are [a-zA-z0-9]+'_','?','@' ");
982+
}
983+
for(auto c : subcommand_name) {
984+
if(!detail::valid_later_char(c)) {
985+
throw IncorrectConstruction(std::string("Subcommand name contains invalid character ('") + c +
986+
"'), allowed characters are "
987+
"[a-zA-z0-9]+'_','?','@','.','-' ");
988+
}
989+
}
967990
}
968991
CLI::App_p subcom = std::shared_ptr<App>(new App(std::move(subcommand_description), subcommand_name, this));
969992
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)