@@ -32,7 +32,7 @@ namespace cpputil {
3232class CommandLineConfig {
3333 public:
3434 /* * Strict parse with help, config, and debug support */
35- static void strict_with_convenience (int argc, char ** argv) {
35+ static void strict_with_convenience (int argc, char ** argv, bool sort_args = false , bool show_defaults_in_Help = true ) {
3636 Heading::create (" Help and argument utilities:" );
3737 auto & help = FlagArg::create (" h" )
3838 .alternate (" help" )
@@ -41,23 +41,23 @@ class CommandLineConfig {
4141 .description (" Print program arguments and quit" );
4242 auto & read_config = ValueArg<std::string>::create (" config" )
4343 .usage (" <path/to/file.conf>" )
44- .default_val (" " )
4544 .description (" Read program args from a configuration file" );
4645 auto & write_config = ValueArg<std::string>::create (" example_config" )
4746 .usage (" <path/to/file.conf>" )
48- .default_val (" " )
4947 .description (" Print an example configuration file" );
5048
51- Args::sort_args ([](Arg * a1, Arg * a2) {
52- return *(a1->alias_begin ()) < *(a2->alias_begin ());
53- });
49+ if (sort_args) {
50+ Args::sort_args ([](Arg * a1, Arg * a2) {
51+ return *(a1->alias_begin ()) < *(a2->alias_begin ());
52+ });
53+ }
5454 Args::read (argc, argv);
5555
5656 if (help) {
5757 std::cout << std::endl;
5858 std::cout << " Usage: " << argv[0 ] << " [options]" << std::endl;
5959 std::cout << std::endl;
60- write_help (std::cout);
60+ write_help (std::cout, show_defaults_in_Help );
6161 exit (0 );
6262 }
6363
@@ -96,6 +96,23 @@ class CommandLineConfig {
9696 exit (1 );
9797 }
9898 write_config_file (ofs, argv[0 ]);
99+ exit (0 );
100+ }
101+
102+ auto missing_arg = false ;
103+ for (auto it = Args::arg_begin (); it != Args::arg_end (); ++it) {
104+ auto arg = *it;
105+ assert (!(arg->is_required () && arg->has_default ()) && " Arguments cannot be both required and have a default." );
106+ if (arg->is_required () && !arg->has_been_provided ()) {
107+ if (!missing_arg) {
108+ std::cerr << " Errors:" << std::endl;
109+ }
110+ missing_arg = true ;
111+ std::cerr << " Argument '" << *arg->alias_begin () << " ' is required!" << std::endl;
112+ }
113+ }
114+ if (missing_arg) {
115+ exit (1 );
99116 }
100117 }
101118
@@ -173,24 +190,55 @@ class CommandLineConfig {
173190 }
174191
175192 /* * Prints arg aliases, usages, and descriptions */
176- static void write_help (std::ostream& os) {
193+ static void write_help (std::ostream& os, bool show_defaults_in_Help ) {
177194 ofilterstream<Indent> ofs (os);
178195 ofs.filter ().indent ();
179196
197+ auto show_defaults = show_defaults_in_Help;
198+
180199 for (auto g = Args::group_begin (); g != Args::group_end (); ++g) {
181200 ofs << g->heading () << std::endl;
182201 ofs << std::endl;
183202 for (auto a = g->arg_begin (); a != g->arg_end (); ++a) {
203+ std::string default_val;
204+ bool short_default = false ;
205+ bool default_has_newline = false ;
206+
184207 write_arg (ofs, *a);
185- ofs << std::endl;
186208
209+ if (show_defaults && (*a)->has_default ()) {
210+ std::ostringstream ss;
211+ (*a)->debug (ss);
212+ default_val = ss.str ();
213+ if (default_val.find (" \n " ) != std::string::npos) {
214+ default_has_newline = true ;
215+ } else if (default_val.length () < 20 ) {
216+ short_default = true ;
217+ ofs << " (default: " << default_val << " )" ;
218+ }
219+ }
220+
221+ ofs << std::endl;
187222 ofs.filter ().indent (2 );
188223
189224 ofilterstream<Wrap> wrap (ofs);
190225 wrap.filter ().limit (60 );
191226 (*a)->description (wrap);
192227 wrap << std::endl;
193228
229+ // try to print the default value
230+ if (show_defaults && !short_default && (*a)->has_default ()) {
231+ if (!default_has_newline && default_val.length () < 150 ) {
232+ // only show default argument if the default does not take more than one line
233+ wrap << " Default: " << default_val << std::endl;
234+ } else {
235+ wrap << " Default: use --debug_args to see this default" << std::endl;
236+ }
237+ }
238+ if ((*a)->is_required ()) {
239+ wrap << " Required argument" << std::endl;
240+ }
241+
194242 ofs.filter ().unindent (2 );
195243 }
196244 ofs << std::endl;
0 commit comments