Commit 9b5867869d841cb4626691546ff7f9d0ce1817a8
Committed by
Henry Schreiner
1 parent
675f1e7f
Refactoring default for options
Showing
3 changed files
with
40 additions
and
23 deletions
examples/subcom_in_files/subcommand_a.cpp
| @@ -11,7 +11,7 @@ | @@ -11,7 +11,7 @@ | ||
| 11 | void setup_subcommand_a(CLI::App &app) { | 11 | void setup_subcommand_a(CLI::App &app) { |
| 12 | // Create the option and subcommand objects. | 12 | // Create the option and subcommand objects. |
| 13 | auto opt = std::make_shared<SubcommandAOptions>(); | 13 | auto opt = std::make_shared<SubcommandAOptions>(); |
| 14 | - auto sub = app.add_subcommand("subcommand_a", "performs subcommand a", true); | 14 | + auto sub = app.add_subcommand("subcommand_a", "performs subcommand a"); |
| 15 | 15 | ||
| 16 | // Add options to sub, binding them to opt. | 16 | // Add options to sub, binding them to opt. |
| 17 | sub->add_option("-f,--file", opt->file, "File name")->required(); | 17 | sub->add_option("-f,--file", opt->file, "File name")->required(); |
include/CLI/App.hpp
| @@ -63,13 +63,13 @@ class App { | @@ -63,13 +63,13 @@ class App { | ||
| 63 | /// Description of the current program/subcommand | 63 | /// Description of the current program/subcommand |
| 64 | std::string description_; | 64 | std::string description_; |
| 65 | 65 | ||
| 66 | - /// Footer to put after all options in the help output | 66 | + /// Footer to put after all options in the help output INHERITABLE |
| 67 | std::string footer_; | 67 | std::string footer_; |
| 68 | 68 | ||
| 69 | - /// If true, allow extra arguments (ie, don't throw an error). | 69 | + /// If true, allow extra arguments (ie, don't throw an error). INHERITABLE |
| 70 | bool allow_extras_{false}; | 70 | bool allow_extras_{false}; |
| 71 | 71 | ||
| 72 | - /// If true, return immediately on an unrecognised option (implies allow_extras) | 72 | + /// If true, return immediately on an unrecognised option (implies allow_extras) INHERITABLE |
| 73 | bool prefix_command_{false}; | 73 | bool prefix_command_{false}; |
| 74 | 74 | ||
| 75 | /// This is a function that runs when complete. Great for subcommands. Can throw. | 75 | /// This is a function that runs when complete. Great for subcommands. Can throw. |
| @@ -78,11 +78,14 @@ class App { | @@ -78,11 +78,14 @@ class App { | ||
| 78 | ///@} | 78 | ///@} |
| 79 | /// @name Options | 79 | /// @name Options |
| 80 | ///@{ | 80 | ///@{ |
| 81 | + | ||
| 82 | + /// The default values for options, customizable and changeable INHERITABLE | ||
| 83 | + OptionDefaults option_defaults_; | ||
| 81 | 84 | ||
| 82 | /// The list of options, stored locally | 85 | /// The list of options, stored locally |
| 83 | std::vector<Option_p> options_; | 86 | std::vector<Option_p> options_; |
| 84 | 87 | ||
| 85 | - /// A pointer to the help flag if there is one | 88 | + /// A pointer to the help flag if there is one INHERITABLE |
| 86 | Option *help_ptr_{nullptr}; | 89 | Option *help_ptr_{nullptr}; |
| 87 | 90 | ||
| 88 | ///@} | 91 | ///@} |
| @@ -106,10 +109,10 @@ class App { | @@ -106,10 +109,10 @@ class App { | ||
| 106 | /// Storage for subcommand list | 109 | /// Storage for subcommand list |
| 107 | std::vector<App_p> subcommands_; | 110 | std::vector<App_p> subcommands_; |
| 108 | 111 | ||
| 109 | - /// If true, the program name is not case sensitive | 112 | + /// If true, the program name is not case sensitive INHERITABLE |
| 110 | bool ignore_case_{false}; | 113 | bool ignore_case_{false}; |
| 111 | 114 | ||
| 112 | - /// Allow subcommand fallthrough, so that parent commands can collect commands after subcommand. | 115 | + /// Allow subcommand fallthrough, so that parent commands can collect commands after subcommand. INHERITABLE |
| 113 | bool fallthrough_{false}; | 116 | bool fallthrough_{false}; |
| 114 | 117 | ||
| 115 | /// A pointer to the parent if this is a subcommand | 118 | /// A pointer to the parent if this is a subcommand |
| @@ -121,7 +124,7 @@ class App { | @@ -121,7 +124,7 @@ class App { | ||
| 121 | /// -1 for 1 or more, 0 for not required, # for exact number required | 124 | /// -1 for 1 or more, 0 for not required, # for exact number required |
| 122 | int require_subcommand_ = 0; | 125 | int require_subcommand_ = 0; |
| 123 | 126 | ||
| 124 | - /// The group membership | 127 | + /// The group membership INHERITABLE |
| 125 | std::string group_{"Subcommands"}; | 128 | std::string group_{"Subcommands"}; |
| 126 | 129 | ||
| 127 | ///@} | 130 | ///@} |
| @@ -140,10 +143,22 @@ class App { | @@ -140,10 +143,22 @@ class App { | ||
| 140 | ///@} | 143 | ///@} |
| 141 | 144 | ||
| 142 | /// Special private constructor for subcommand | 145 | /// Special private constructor for subcommand |
| 143 | - App(std::string description_, bool help, detail::enabler) : description_(std::move(description_)) { | ||
| 144 | - | ||
| 145 | - if(help) | ||
| 146 | - set_help_flag("-h,--help", "Print this help message and exit"); | 146 | + App(std::string description_, App* parent) : description_(std::move(description_)), parent_(parent) { |
| 147 | + // Inherit if not from a nullptr | ||
| 148 | + if(parent_ != nullptr) { | ||
| 149 | + if(parent_->help_ptr_ != nullptr) | ||
| 150 | + set_help_flag(parent_->help_ptr_->get_name(), parent_->help_ptr_->get_description()); | ||
| 151 | + | ||
| 152 | + /// OptionDefaults | ||
| 153 | + option_defaults_ = parent_->option_defaults_; | ||
| 154 | + | ||
| 155 | + // INHERITABLE | ||
| 156 | + allow_extras_ = parent_->allow_extras_; | ||
| 157 | + prefix_command_ = parent_->prefix_command_; | ||
| 158 | + ignore_case_ = parent_->ignore_case_; | ||
| 159 | + fallthrough_ = parent_->fallthrough_; | ||
| 160 | + group_ = parent_->group_; | ||
| 161 | + } | ||
| 147 | } | 162 | } |
| 148 | 163 | ||
| 149 | public: | 164 | public: |
| @@ -151,7 +166,9 @@ class App { | @@ -151,7 +166,9 @@ class App { | ||
| 151 | ///@{ | 166 | ///@{ |
| 152 | 167 | ||
| 153 | /// Create a new program. Pass in the same arguments as main(), along with a help string. | 168 | /// Create a new program. Pass in the same arguments as main(), along with a help string. |
| 154 | - App(std::string description_ = "", bool help = true) : App(description_, help, detail::dummy) {} | 169 | + App(std::string description_ = "") : App(description_, nullptr) { |
| 170 | + set_help_flag("-h,--help", "Print this help message and exit"); | ||
| 171 | + } | ||
| 155 | 172 | ||
| 156 | /// Set footer. | 173 | /// Set footer. |
| 157 | App *set_footer(std::string footer) { | 174 | App *set_footer(std::string footer) { |
| @@ -223,6 +240,9 @@ class App { | @@ -223,6 +240,9 @@ class App { | ||
| 223 | 240 | ||
| 224 | /// Get the group of this subcommand | 241 | /// Get the group of this subcommand |
| 225 | const std::string &get_group() const { return group_; } | 242 | const std::string &get_group() const { return group_; } |
| 243 | + | ||
| 244 | + /// Get the OptionDefault object, to set option defaults | ||
| 245 | + OptionDefaults* option_defaults() {return &option_defaults_;} | ||
| 226 | 246 | ||
| 227 | ///@} | 247 | ///@} |
| 228 | /// @name Adding options | 248 | /// @name Adding options |
| @@ -251,6 +271,7 @@ class App { | @@ -251,6 +271,7 @@ class App { | ||
| 251 | options_.emplace_back(); | 271 | options_.emplace_back(); |
| 252 | Option_p &option = options_.back(); | 272 | Option_p &option = options_.back(); |
| 253 | option.reset(new Option(name, description, callback, defaulted, this)); | 273 | option.reset(new Option(name, description, callback, defaulted, this)); |
| 274 | + option->copy_from(option_defaults_); | ||
| 254 | return option.get(); | 275 | return option.get(); |
| 255 | } else | 276 | } else |
| 256 | throw OptionAlreadyAdded(myopt.get_name()); | 277 | throw OptionAlreadyAdded(myopt.get_name()); |
| @@ -615,15 +636,10 @@ class App { | @@ -615,15 +636,10 @@ class App { | ||
| 615 | /// @name Subcommmands | 636 | /// @name Subcommmands |
| 616 | ///@{ | 637 | ///@{ |
| 617 | 638 | ||
| 618 | - /// Add a subcommand. Like the constructor, you can override the help message addition by setting help=false | ||
| 619 | - App *add_subcommand(std::string name, std::string description = "", bool help = true) { | ||
| 620 | - subcommands_.emplace_back(new App(description, help, detail::dummy)); | 639 | + /// Add a subcommand. Inherits INHERITABLE and OptionDefaults, and help flag |
| 640 | + App *add_subcommand(std::string name, std::string description = "") { | ||
| 641 | + subcommands_.emplace_back(new App(description, this)); | ||
| 621 | subcommands_.back()->name_ = name; | 642 | subcommands_.back()->name_ = name; |
| 622 | - subcommands_.back()->allow_extras_ = allow_extras_; | ||
| 623 | - subcommands_.back()->prefix_command_ = prefix_command_; | ||
| 624 | - subcommands_.back()->parent_ = this; | ||
| 625 | - subcommands_.back()->ignore_case_ = ignore_case_; | ||
| 626 | - subcommands_.back()->fallthrough_ = fallthrough_; | ||
| 627 | for(const auto &subc : subcommands_) | 643 | for(const auto &subc : subcommands_) |
| 628 | if(subc.get() != subcommands_.back().get()) | 644 | if(subc.get() != subcommands_.back().get()) |
| 629 | if(subc->check_name(subcommands_.back()->name_) || subcommands_.back()->check_name(subc->name_)) | 645 | if(subc->check_name(subcommands_.back()->name_) || subcommands_.back()->check_name(subc->name_)) |
tests/HelpTest.cpp
| @@ -314,7 +314,8 @@ TEST(THelp, RemoveHelp) { | @@ -314,7 +314,8 @@ TEST(THelp, RemoveHelp) { | ||
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | TEST(THelp, NoHelp) { | 316 | TEST(THelp, NoHelp) { |
| 317 | - CLI::App app{"My prog", false}; | 317 | + CLI::App app{"My prog"}; |
| 318 | + app.set_help_flag(); | ||
| 318 | 319 | ||
| 319 | std::string help = app.help(); | 320 | std::string help = app.help(); |
| 320 | 321 | ||
| @@ -332,7 +333,7 @@ TEST(THelp, NoHelp) { | @@ -332,7 +333,7 @@ TEST(THelp, NoHelp) { | ||
| 332 | } | 333 | } |
| 333 | 334 | ||
| 334 | TEST(THelp, CustomHelp) { | 335 | TEST(THelp, CustomHelp) { |
| 335 | - CLI::App app{"My prog", false}; | 336 | + CLI::App app{"My prog"}; |
| 336 | 337 | ||
| 337 | CLI::Option *help_option = app.set_help_flag("--yelp", "display help and exit"); | 338 | CLI::Option *help_option = app.set_help_flag("--yelp", "display help and exit"); |
| 338 | EXPECT_EQ(app.get_help_ptr(), help_option); | 339 | EXPECT_EQ(app.get_help_ptr(), help_option); |