2222// c++
2323#include < iostream>
2424#include < cstring>
25+ #include < cctype>
2526
2627using namespace std ;
2728
@@ -45,15 +46,19 @@ GOptions::GOptions(int argc, char* argv[], const GOptions& user_defined_options)
4546 addGOptions (user_defined_options);
4647
4748 // switches for all everyone
48- defineSwitch (" gui" , " use Graphical User Interface " );
49- defineSwitch (" i" , " use interactive batch mode" );
49+ defineSwitch (" gui" , " run with the graphical user interface (Qt window) " );
50+ defineSwitch (" i" , " drop into the interactive Geant4 terminal session (non-GUI mode) " );
5051 defineOption (
51- GVariable (" conf_yaml" , " saved_configuration" , " the prefix for filename that store the used options" ),
52- " The default value appends \" _saved_configuration\" to the executable name." );
52+ GVariable (" conf_yaml" , " saved_configuration" , " infix for the YAML file that records the resolved options" ),
53+ " On exit the resolved configuration is written to <executable>.<conf_yaml>.yaml,\n "
54+ " so the default value produces, for example, gemc.saved_configuration.yaml.\n \n "
55+ " Example: -conf_yaml=run12 -> saves to gemc.run12.yaml\n \n " );
5356
5457 // add test timeout for the tests
55- defineOption (GVariable (" tt" , 500 , " tests timeout (ms)" ),
56- " Timeout in milliseconds for the code tests that have GUI. " );
58+ defineOption (GVariable (" tt" , 500 , " GUI test timeout (ms)" ),
59+ " Milliseconds a GUI-based test waits before it auto-closes, so the module\n "
60+ " example/test programs can run unattended in CI.\n \n "
61+ " Example: -tt=1000\n \n " );
5762
5863 // version is a special option, not settable by the user
5964 // it is set by the gversion.h file
@@ -72,16 +77,25 @@ GOptions::GOptions(int argc, char* argv[], const GOptions& user_defined_options)
7277 help += " - 0: (default) = shush\n " ;
7378 help += " - 1: log detailed information\n " ;
7479 help += " - 2: log extra detailed information\n \n " ;
75- help += " Example: -verbosity.gemc=1 \n \n " ;
76- help += " The YAML value can include multiple logger keys.\n \n " ;
80+ help += " Each key names a class or module; run 'help verbosity' to list the available keys.\n \n " ;
81+ help += " Example (one key): -verbosity.gemc=1\n " ;
82+ help += " Example (several keys): -verbosity=\" [{gemc: 1}, {<another_key>: 2}]\"\n \n " ;
83+ help += " Equivalent YAML:\n " ;
84+ help += " verbosity:\n " ;
85+ help += " - gemc: 1\n " ;
86+ help += " - <another_key>: 2\n \n " ;
7787 defineOption (" verbosity" , " Sets the log verbosity for various classes" , option_verbosity_names, help);
7888
7989 // debug option: boolean or integer, depending on consumer expectations
8090 help = " Debug information Types: \n \n " ;
8191 help += " - false: (default): do not print debug information\n " ;
8292 help += " - true: print debug information\n\n " ;
83- help += " Example: -debug=\" [{gemc: true}]\" \n \n " ;
84- help += " The YAML value can include multiple logger keys.\n \n " ;
93+ help += " Each key names a class or module; run 'help debug' to list the available keys.\n \n " ;
94+ help += " Example (on/off): -debug.gemc=true\n " ;
95+ help += " Example (several keys): -debug=\" [{gemc: true}, {<another_key>: 1}]\"\n \n " ;
96+ help += " Equivalent YAML:\n " ;
97+ help += " debug:\n " ;
98+ help += " - gemc: true\n \n " ;
8599 defineOption (" debug" , " Sets the debug level for various classes" , option_verbosity_names, help);
86100
87101 // Process help/version command-line arguments.
@@ -105,6 +119,12 @@ GOptions::GOptions(int argc, char* argv[], const GOptions& user_defined_options)
105119 else { printHelp (); }
106120 exit (EXIT_SUCCESS );
107121 }
122+ else if (strcmp (argv[i], " search" ) == 0 ) {
123+ // "gemc search <value>" lists options/switches whose name or description contains <value>.
124+ if (i + 1 < argc) { printSearch (argv[i + 1 ]); }
125+ else { printHelp (); }
126+ exit (EXIT_SUCCESS );
127+ }
108128 }
109129
110130 // finds and parse the yaml files
@@ -295,6 +315,42 @@ void GOptions::printOptionOrSwitchHelp(const std::string& tag) const {
295315 exit (EC__NOOPTIONFOUND );
296316}
297317
318+ // Private method: see header. Kept undocumented here to avoid duplicate param docs.
319+ void GOptions::printSearch (const std::string& tag) const {
320+ // Case-insensitive substring match against switch/option names and descriptions.
321+ auto to_lower = [](string s) {
322+ transform (s.begin (), s.end (), s.begin (), [](unsigned char c) { return std::tolower (c); });
323+ return s;
324+ };
325+ const string needle = to_lower (tag);
326+ auto matches = [&](const string& a, const string& b) {
327+ return to_lower (a).find (needle) != string::npos || to_lower (b).find (needle) != string::npos;
328+ };
329+
330+ long int fill_width = string (HELPFILLSPACE ).size () + 1 ;
331+ cout.fill (' .' );
332+ cout << KGRN << KBOLD << " Options and switches matching \" " << tag << " \" :" << RST << endl << endl;
333+
334+ bool found = false ;
335+ for (auto & s : switches) {
336+ if (matches (s.first , s.second .getDescription ())) {
337+ found = true ;
338+ cout << KGRN << " " << left;
339+ cout.width (fill_width);
340+ cout << " -" + s.first + RST + " " << " : " << s.second .getDescription () << endl;
341+ }
342+ }
343+ for (auto & option : goptions) {
344+ if (option.name != GVERSION_STRING && matches (option.name , option.description )) {
345+ found = true ;
346+ option.printHelp (false );
347+ }
348+ }
349+ if (!found) { cout << TPOINTITEM << " no match found." << endl; }
350+ cout << endl << " Use " << KGRN << " help <value>" << RST << " for the detailed help of a single option." << endl
351+ << endl;
352+ }
353+
298354// Private method: see header. Kept undocumented here to avoid duplicate param docs.
299355vector<string> GOptions::findYamls (int argc, char * argv[]) {
300356 vector<string> yaml_files;
@@ -523,7 +579,7 @@ void GOptions::printHelp() const {
523579 string (" help <value>" ) + RST ,
524580 string (" print detailed help for option <value> and exit" ),
525581 string (" search <value>" ) + RST ,
526- string (" list all options containing <value> in the description and exit\n " )
582+ string (" list all options/switches whose name or description contains <value> and exit\n " )
527583 };
528584 unsigned half_help = helps.size () / 2 ;
529585 for (unsigned i = 0 ; i < half_help; i++) {
0 commit comments