Commit 9b5867869d841cb4626691546ff7f9d0ce1817a8

Authored by Henry Fredrick Schreiner
Committed by Henry Schreiner
1 parent 675f1e7f

Refactoring default for options

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);