Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions include/CLI/App.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,10 @@ class App {
/// Check to see if a subcommand is part of this command (text version)
CLI11_NODISCARD App *get_subcommand(std::string subcom) const;

/// Get a subcommand by name (noexcept non-const version)
/// returns null if subcommand doesn't exist
CLI11_NODISCARD App *get_subcommand_no_throw(std::string subcom) const noexcept;

/// Get a pointer to subcommand by index
CLI11_NODISCARD App *get_subcommand(int index = 0) const;

Expand Down Expand Up @@ -907,8 +911,9 @@ class App {
}

/// Check with name instead of pointer to see if subcommand was selected
CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const {
return get_subcommand(subcommand_name)->parsed_ > 0;
CLI11_NODISCARD bool got_subcommand(std::string subcommand_name) const noexcept {
App *sub = get_subcommand_no_throw(subcommand_name);
return (sub != nullptr) ? (sub->parsed_ > 0) : false;
}

/// Sets excluded options for the subcommand
Expand Down Expand Up @@ -1038,7 +1043,7 @@ class App {
std::vector<Option *> get_options(const std::function<bool(Option *)> filter = {});

/// Get an option by name (noexcept non-const version)
Option *get_option_no_throw(std::string option_name) noexcept;
CLI11_NODISCARD Option *get_option_no_throw(std::string option_name) noexcept;

/// Get an option by name (noexcept const version)
CLI11_NODISCARD const Option *get_option_no_throw(std::string option_name) const noexcept;
Expand Down
14 changes: 7 additions & 7 deletions include/CLI/impl/App_inl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand(std::string subcom) const
return subc;
}

CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand_no_throw(std::string subcom) const noexcept {
return _find_subcommand(subcom, false, false);
}

CLI11_NODISCARD CLI11_INLINE App *App::get_subcommand(int index) const {
if(index >= 0) {
auto uindex = static_cast<unsigned>(index);
Expand Down Expand Up @@ -796,7 +800,7 @@ CLI11_INLINE std::vector<Option *> App::get_options(const std::function<bool(Opt
return options;
}

CLI11_INLINE Option *App::get_option_no_throw(std::string option_name) noexcept {
CLI11_NODISCARD CLI11_INLINE Option *App::get_option_no_throw(std::string option_name) noexcept {
for(Option_p &opt : options_) {
if(opt->check_name(option_name)) {
return opt.get();
Expand Down Expand Up @@ -1441,12 +1445,8 @@ CLI11_INLINE void App::_parse_config(const std::vector<ConfigItem> &args) {
CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t level) {

if(level < item.parents.size()) {
try {
auto *subcom = get_subcommand(item.parents.at(level));
return subcom->_parse_single_config(item, level + 1);
} catch(const OptionNotFound &) {
return false;
}
auto *subcom = get_subcommand_no_throw(item.parents.at(level));
return (subcom != nullptr) ? subcom->_parse_single_config(item, level + 1) : false;
}
// check for section open
if(item.name == "++") {
Expand Down
6 changes: 4 additions & 2 deletions tests/SubcommandTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ TEST_CASE_METHOD(TApp, "BasicSubcommands", "[subcom]") {

CHECK(app.get_subcommand(sub1) == sub1);
CHECK(app.get_subcommand("sub1") == sub1);
CHECK(app.get_subcommand_no_throw("sub1") == sub1);
CHECK_THROWS_AS(app.get_subcommand("sub3"), CLI::OptionNotFound);

CHECK_NOTHROW(app.get_subcommand_no_throw("sub3"));
CHECK(app.get_subcommand_no_throw("sub3") == nullptr);
run();
CHECK(app.get_subcommands().empty());

Expand Down Expand Up @@ -90,7 +92,7 @@ TEST_CASE_METHOD(TApp, "MultiSubFallthrough", "[subcom]") {
CHECK(!sub2->parsed());
CHECK(0u == sub2->count());

CHECK_THROWS_AS(app.got_subcommand("sub3"), CLI::OptionNotFound);
CHECK(!app.got_subcommand("sub3"));
}

TEST_CASE_METHOD(TApp, "CrazyNameSubcommand", "[subcom]") {
Expand Down