MarlinMT  0.1.0
CmdLineParser.cc
Go to the documentation of this file.
1 
2 // -- marlinmt headers
5 #include <marlinmt/Exceptions.h>
6 #include <marlinmt/Logging.h>
7 #include <marlinmt/Utils.h>
8 
9 // -- TCLAP headers
10 #include <tclap/CmdLine.h>
11 #include <tclap/ValueArg.h>
12 
13 namespace marlinmt {
14 
15  class Output : public TCLAP::StdOutput {
16  public:
17  void failure(TCLAP::CmdLineInterface& c, TCLAP::ArgException& e) override {
18  std::string progName = c.getProgramName();
19  std::cerr << "PARSE ERROR: " << e.argId() << std::endl
20  << " " << e.error() << std::endl << std::endl;
21  if ( c.hasHelpAndVersion() ) {
22  std::cerr << "Brief USAGE: " << std::endl;
23  _shortUsage( c, std::cerr );
24  std::cerr << std::endl << "For complete USAGE and HELP type: "
25  << std::endl << " " << progName << " "
26  << TCLAP::Arg::nameStartString() << "help"
27  << std::endl << std::endl;
28  }
29  else {
30  usage(c) ;
31  }
32  MARLINMT_RETHROW( e, "Command line parsing failed" ) ;
33  }
34 
35  void usage(TCLAP::CmdLineInterface& c) override {
36  version(c);
37  std::cout << std::endl << "USAGE: " << std::endl << std::endl;
38  _shortUsage( c, std::cout );
39  std::cout << std::endl << std::endl << "Where: " << std::endl << std::endl;
40  _longUsage( c, std::cout );
41  std::cout << std::endl;
42  std::cout << "Dynamic command line options:" << std::endl;
43  std::cout << std::endl ;
44  std::cout << " --{section}.parameter=value" << std::endl ;
45  std::cout << " --constant.name=value" << std::endl ;
46  std::cout << " --{processor}.parameter=value" << std::endl ;
47  std::cout << std::endl ;
48  spacePrint( std::cout, "with {section} = datasource, logging, scheduler, geometry, bookstore, global", 75, 5, 17 );
49  spacePrint( std::cout, "with {processor} the name of a processor configuration section", 75, 5, 0 );
50  std::cout << std::endl ;
51  std::stringstream ss ;
52  ss << "Dynamic command line options may be specified in order to overwrite individual "
53  "configuration parameters, e.g:" ;
54  spacePrint( std::cout, ss.str(), 75, 5, 0 );
55  ss.str("");
56  std::cout << std::endl;
57  spacePrint( std::cout, c.getProgramName() + " -c config.xml \\", 75, 5, 0 );
58  spacePrint( std::cout, "--logging.Verbosity=ERROR \\", 75, 8, 0 );
59  spacePrint( std::cout, "--constant.Calibration=0.0087 \\", 75, 8, 0 );
60  spacePrint( std::cout, "--MyProcessor.EnergyCut=0.42", 75, 8, 0 );
61  std::cout << std::endl;
62  }
63 
64  void version(TCLAP::CmdLineInterface& c) override {
65  std::string progName = c.getProgramName();
66  std::string xversion = c.getVersion();
67  std::cout << std::endl << progName << " version: "
68  << xversion << std::endl << std::endl;
69  }
70  };
71 
72  //--------------------------------------------------------------------------
73  //--------------------------------------------------------------------------
74 
75  void CmdLineParser::setOptionalArgs( bool opt ) {
76  _optionalArgs = opt ;
77  }
78 
79  //--------------------------------------------------------------------------
80 
81  std::vector<std::string> CmdLineParser::getStandardOptions() const {
82  return { "-c", "--config",
83  "-x", "--example",
84  "-j", "--nthreads",
85  "--help", "--version" };
86  }
87 
88  //--------------------------------------------------------------------------
89 
91  ParseResult parseResult {} ;
92  parseResult._arguments.reserve(argc) ;
93  // Create command line object
94  TCLAP::CmdLine cmdLine( "MarlinMT", ' ', MARLINMT_RELEASE , true ) ;
95  Output output ;
96  cmdLine.setOutput( &output ) ;
97  // Config argument
98  TCLAP::ValueArg<std::string> configArg( "c", "config", "The input configuration settings (plugin:descriptor)", (!_optionalArgs), "", "string" ) ;
99  // Dump example config argument
100  TCLAP::ValueArg<std::string> exampleArg( "x", "example", "Dump an example configuration (plugin:descriptor)", false, "", "string" ) ;
101  cmdLine.xorAdd( configArg, exampleArg ) ;
102  // number of cores
103  TCLAP::ValueArg<std::string> nthreadsArg( "j", "nthreads", "The number of worker threads (only in multi-threaded mode). 'auto' will use all available cores", false, "1", "unsigned int / string" ) ;
104  cmdLine.add( nthreadsArg ) ;
105  // parse additional args
106  std::vector<std::string> parserArgs{} ;
107  parserArgs.reserve(argc) ;
108  parserArgs.push_back( argv[0] ) ; // for the program name
109  for(int i=1 ; i<argc ; i++) {
110  parseResult._arguments.push_back( argv[i] ) ;
111  }
112  auto &args = cmdLine.getArgList() ;
113  // analyze the arguments.
114  for( auto &arg : parseResult._arguments ) {
115  if( arg.substr( 0, 2 ) == "--" ) {
116  auto argName = arg.substr( 2 ) ;
117  auto iter = std::find_if( args.begin(), args.end(), [&](auto val){
118  return (val->getName() == argName) ;
119  }) ;
120  // Not an additional arg. Add it for later parsing
121  if( args.end() != iter ) {
122  parserArgs.push_back( arg ) ;
123  continue ;
124  }
125  // Parse the additional argument
126  auto tokens = details::split_string<std::string>( argName, "=" ) ;
127  if( 2 != tokens.size() ) {
128  MARLINMT_THROW( "Additional argument '" + arg + "' with wrong syntax. Expected '--name=value' format" ) ;
129  }
130  auto res = parseResult._additionalArgs.insert( { tokens[0], tokens[1] } ) ;
131  if( not res.second ) {
132  MARLINMT_THROW( "Additional argument '" + arg + "' set twice on command line" ) ;
133  }
134  }
135  else {
136  parserArgs.push_back( arg ) ;
137  }
138  }
139  // parse the command line
140  cmdLine.parse( parserArgs ) ;
141  // extract command line values
142  parseResult._programName = cmdLine.getProgramName() ;
143  if( configArg.isSet() ) {
144  parseResult._config = configArg.getValue() ;
145  parseResult._dumpExample = false ;
146  }
147  else if( exampleArg.isSet() ) {
148  parseResult._config = exampleArg.getValue() ;
149  parseResult._dumpExample = true ;
150  }
151  parseResult._nthreads = details::nthreads( nthreadsArg.getValue() ) ;
152  return parseResult ;
153  }
154 
155 }
156 
std::vector< std::string > _arguments
All command line arguments except the program name (argv[0])
Definition: CmdLineParser.h:23
unsigned int nthreads(const std::string &str)
Definition: Utils.h:580
#define MARLINMT_RETHROW(orig, message)
Definition: Exceptions.h:10
ParseResult parse(int argc, char **argv)
Parse the command line.
#define MARLINMT_THROW(message)
Definition: Exceptions.h:8
void setOptionalArgs(bool opt=true)
Set all cmd line arguments to optional during parsing.
void version(TCLAP::CmdLineInterface &c) override
void failure(TCLAP::CmdLineInterface &c, TCLAP::ArgException &e) override
std::vector< std::string > getStandardOptions() const
Get all possible command options (short and long options)
ParseResult struct. The result of the command line parsing.
Definition: CmdLineParser.h:19
void usage(TCLAP::CmdLineInterface &c) override
#define MARLINMT_RELEASE