source: src/UIElements/CommandLineUI/CommandLineParser.cpp@ 61749d1

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 61749d1 was ec098d, checked in by Frederik Heber <heber@…>, 14 years ago

Made info of CommandLineParser::AddOptionToParser() prettier.

  • Property mode set to 100644
File size: 18.8 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2010 University of Bonn. All rights reserved.
5 * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
6 */
7
8/*
9 * CommandLineParser.cpp
10 *
11 * Created on: May 8, 2010
12 * Author: heber
13 */
14
15// include config.h
16#ifdef HAVE_CONFIG_H
17#include <config.h>
18#endif
19
20#include "CodePatterns/MemDebug.hpp"
21
22#include <boost/filesystem.hpp>
23#include <boost/program_options.hpp>
24#include <fstream>
25#include <iostream>
26#include <map>
27
28#include "Actions/Action.hpp"
29#include "Actions/ActionRegistry.hpp"
30#include "Actions/ActionTraits.hpp"
31#include "Actions/OptionRegistry.hpp"
32#include "Actions/OptionTrait.hpp"
33#include "Actions/Values.hpp"
34#include "CodePatterns/Log.hpp"
35#include "CodePatterns/Verbose.hpp"
36#include "CommandLineParser.hpp"
37#include "CommandLineParser_validate.hpp"
38
39#include "CodePatterns/Singleton_impl.hpp"
40
41class element;
42
43/** Constructor of class CommandLineParser.
44 *
45 */
46CommandLineParser::CommandLineParser() :
47 analysis("Analysis options"),
48 atom("Atom options"),
49 command("Command options"),
50 fragmentation("Fragmentation options"),
51 graph("Graph options"),
52 molecule("Molecule options"),
53 options("Secondary options"),
54 parser("Parser options"),
55 selection("Selection options"),
56 tesselation("Tesselation options"),
57 world("World options")
58{
59 // put all options lists into a lookup
60 CmdParserLookup["analysis"] = &analysis;
61 CmdParserLookup["atom"] = &atom;
62 CmdParserLookup["command"] = &command;
63 CmdParserLookup["edit"] = &edit;
64 CmdParserLookup["fragmentation"] = &fragmentation;
65 CmdParserLookup["graph"] = &graph;
66 CmdParserLookup["options"] = &options;
67 CmdParserLookup["molecule"] = &molecule;
68 CmdParserLookup["parser"] = &parser;
69 CmdParserLookup["selection"] = &selection;
70 CmdParserLookup["tesselation"] = &tesselation;
71 CmdParserLookup["world"] = &world;
72}
73
74/** Destructor of class CommandLineParser.
75 *
76 */
77CommandLineParser::~CommandLineParser()
78{}
79
80/** Initializes command arguments to accept.
81 * Goes through ActionRegistry and puts all actions therein into the map.
82 */
83void CommandLineParser::InitializeCommandArguments()
84{
85 ActionRegistry &AR = ActionRegistry::getInstance();
86 bool ActionAlreadyAdded_flag = false;
87 for (ActionRegistry::const_iterator actioniter = AR.getBeginIter(); actioniter != AR.getEndIter(); ++actioniter) {
88 ActionAlreadyAdded_flag = false;
89 Action* const currentAction = actioniter->second;
90 //std::cout << "Current Action to initialize is: " << actioniter->first << std::endl;
91
92 for (ActionTraits::options_const_iterator optioniter = currentAction->Traits.getBeginIter();
93 optioniter != currentAction->Traits.getEndIter();
94 ++optioniter) {
95 if (optioniter->first == actioniter->first)
96 ActionAlreadyAdded_flag = true;
97 ASSERT( OptionRegistry::getInstance().isOptionPresentByName(optioniter->first),
98 "CommandLineParser::Init() - Option not present in OptionRegistry." );
99 const OptionTrait* const currentOption = OptionRegistry::getInstance().getOptionByName(optioniter->first);
100 // add the option
101// std::cout << "Registering Option "
102// << currentOption->getName()
103// << " with type '" << currentOption->getTypeName() << "' "
104// << " with description '" << currentOption->getDescription() << "' ";
105// if (currentOption->hasShortForm())
106// std::cout << ", with short form " << currentOption->getShortForm();
107// else
108// std::cout << ", with no short form ";
109// if (currentOption->hasDefaultValue())
110// std::cout << ", with default value " << currentOption->getDefaultValue();
111// else
112// std::cout << ", with no default value ";
113// std::cout << std::endl;
114
115 AddOptionToParser(currentOption, (CmdParserLookup["options"]));
116 }
117
118 if (!ActionAlreadyAdded_flag) {
119 // add the action
120// std::cout << "Registering Action "
121// << currentAction->Traits.getName()
122// << " in menu " << currentAction->Traits.getMenuName()
123// << " with type '" << currentAction->Traits.getTypeName() << "' "
124// << " with description '" << currentAction->Traits.getDescription() << "' ";
125// if (currentAction->Traits.hasShortForm())
126// std::cout << ", with short form " << currentAction->Traits.getShortForm();
127// else
128// std::cout << ", with no short form ";
129// if (currentAction->Traits.hasDefaultValue())
130// std::cout << ", with default value " << currentAction->Traits.getDefaultValue();
131// else
132// std::cout << ", with no default value ";
133// std::cout << std::endl;
134
135 ASSERT(CmdParserLookup.find(currentAction->Traits.getMenuName()) != CmdParserLookup.end(),
136 "CommandLineParser: boost::program_options::options_description for this Action not present.");
137 AddOptionToParser(dynamic_cast<const OptionTrait * const>(&(currentAction->Traits)),(CmdParserLookup[currentAction->Traits.getMenuName()]));
138 }
139 }
140 // note: positioning is not important on the command line
141}
142
143/** Adds an Action or Option to the CommandLineParser.
144 * Note that Action is derived from Option(Trait)
145 *
146 * This ugly switch function is necessary because of the compile-time problem:
147 * po::value<T> has to be instantiated at compile-time however we do know the type not until run-time.
148 * Not even a templated function like po::value<T> getProgramOptionValuefromType() does help, specialized
149 * to each available type, as the signatures of all the functions differ. Hence, they cannot not put into
150 * one type_info -> po::value<T> map ...
151 *
152 * \param *currentOption pointer to Action/Option to add
153 * \param *OptionList program_options list to add to
154 */
155void CommandLineParser::AddOptionToParser(const OptionTrait * const currentOption, po::options_description* OptionList)
156{
157 // check whether dynamic_cast in Init() suceeded
158 ASSERT(currentOption != NULL, "CommandLineParser::AddOptionToParser() - currentOption is NULL!");
159 // add other options
160// std::cout << "Adding Action " << currentOption->getName() << " with type "
161// << currentOption->getType()->name() << ", " << (currentOption->hasDefaultValue() ? "with" : "without")
162// << " default value, and KeyandShortform " << currentOption->getKeyAndShortForm()
163// << " to CommandLineParser." << std::endl;
164 switch(TypeToEnums.getEnumforType(currentOption->getType())) {
165 default:
166 case TypeEnumContainer::NoneType:
167 OptionList->add_options()
168 (currentOption->getKeyAndShortForm().c_str(), currentOption->getDescription().c_str())
169 ;
170 break;
171 case TypeEnumContainer::BooleanType:
172 OptionList->add_options()
173 (currentOption->getKeyAndShortForm().c_str(),
174 currentOption->hasDefaultValue() ?
175 po::value < bool >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
176 po::value < bool >(),
177 currentOption->getDescription().c_str())
178 ;
179 break;
180 case TypeEnumContainer::BoxType:
181 OptionList->add_options()
182 (currentOption->getKeyAndShortForm().c_str(),
183// currentOption->hasDefaultValue() ?
184// po::value < BoxValue >()->default_value(boost::lexical_cast<BoxValue>(currentOption->getDefaultValue().c_str())) :
185 po::value < BoxValue >(),
186 currentOption->getDescription().c_str())
187 ;
188 break;
189 case TypeEnumContainer::FileType:
190 OptionList->add_options()
191 (currentOption->getKeyAndShortForm().c_str(),
192// currentOption->hasDefaultValue() ?
193// po::value < boost::filesystem::path >()->default_value(boost::lexical_cast<boost::filesystem::path>(currentOption->getDefaultValue().c_str())) :
194 po::value < boost::filesystem::path >(),
195 currentOption->getDescription().c_str())
196 ;
197 break;
198 case TypeEnumContainer::ListOfFilesType:
199 OptionList->add_options()
200 (currentOption->getKeyAndShortForm().c_str(),
201// currentOption->hasDefaultValue() ?
202// po::value < std::vector<boost::filesystem::path> >()->default_value(boost::lexical_cast< std::vector<boost::filesystem::path> >(currentOption->getDefaultValue().c_str())) :
203 po::value < std::vector<boost::filesystem::path> >()->multitoken(),
204 currentOption->getDescription().c_str())
205 ;
206 break;
207 case TypeEnumContainer::IntegerType:
208 OptionList->add_options()
209 (currentOption->getKeyAndShortForm().c_str(),
210 currentOption->hasDefaultValue() ?
211 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
212 po::value < int >(),
213 currentOption->getDescription().c_str())
214 ;
215 break;
216 case TypeEnumContainer::ListOfIntegersType:
217 OptionList->add_options()
218 (currentOption->getKeyAndShortForm().c_str(),
219// currentOption->hasDefaultValue() ?
220// po::value < std::vector<int> >()->default_value(boost::lexical_cast< std::vector<int> >(currentOption->getDefaultValue().c_str())) :
221 po::value < std::vector<int> >()->multitoken(),
222 currentOption->getDescription().c_str())
223 ;
224 break;
225 case TypeEnumContainer::DoubleType:
226 OptionList->add_options()
227 (currentOption->getKeyAndShortForm().c_str(),
228 currentOption->hasDefaultValue() ?
229 po::value < double >()->default_value(boost::lexical_cast<double>(currentOption->getDefaultValue().c_str())) :
230 po::value < double >(),
231 currentOption->getDescription().c_str())
232 ;
233 break;
234 case TypeEnumContainer::ListOfDoublesType:
235 OptionList->add_options()
236 (currentOption->getKeyAndShortForm().c_str(),
237// currentOption->hasDefaultValue() ?
238// po::value < std::vector<double> >()->default_value(boost::lexical_cast< std::vector<double> >(currentOption->getDefaultValue().c_str())) :
239 po::value < std::vector<double> >()->multitoken(),
240 currentOption->getDescription().c_str())
241 ;
242 break;
243 case TypeEnumContainer::StringType:
244 OptionList->add_options()
245 (currentOption->getKeyAndShortForm().c_str(),
246 currentOption->hasDefaultValue() ?
247 po::value < std::string >()->default_value(currentOption->getDefaultValue()) :
248 po::value < std::string >(),
249 currentOption->getDescription().c_str())
250 ;
251 break;
252 case TypeEnumContainer::ListOfStringsType:
253 OptionList->add_options()
254 (currentOption->getKeyAndShortForm().c_str(),
255// currentOption->hasDefaultValue() ?
256// po::value < std::vector<std::string> >()->default_value(boost::lexical_cast< std::vector<std::string> >(currentOption->getDefaultValue().c_str())) :
257 po::value < std::vector<std::string> >()->multitoken(),
258 currentOption->getDescription().c_str())
259 ;
260 break;
261 case TypeEnumContainer::VectorType:
262 OptionList->add_options()
263 (currentOption->getKeyAndShortForm().c_str(),
264// currentOption->hasDefaultValue() ?
265// po::value < VectorValue >()->default_value(boost::lexical_cast<VectorValue>(currentOption->getDefaultValue().c_str())) :
266 po::value < VectorValue >(),
267 currentOption->getDescription().c_str())
268 ;
269 break;
270 case TypeEnumContainer::ListOfVectorsType:
271 OptionList->add_options()
272 (currentOption->getKeyAndShortForm().c_str(),
273// currentOption->hasDefaultValue() ?
274// po::value < std::vector<VectorValue> >()->default_value(boost::lexical_cast< std::vector<VectorValue> >(currentOption->getDefaultValue().c_str())) :
275 po::value < std::vector<VectorValue> >()->multitoken(),
276 currentOption->getDescription().c_str())
277 ;
278 break;
279 case TypeEnumContainer::MoleculeType:
280 OptionList->add_options()
281 (currentOption->getKeyAndShortForm().c_str(),
282// currentOption->hasDefaultValue() ?
283// po::value < const molecule * >()->default_value(boost::lexical_cast<const molecule *>(currentOption->getDefaultValue().c_str())) :
284 po::value < int >(),
285 currentOption->getDescription().c_str())
286 ;
287 break;
288 case TypeEnumContainer::ListOfMoleculesType:
289 OptionList->add_options()
290 (currentOption->getKeyAndShortForm().c_str(),
291// currentOption->hasDefaultValue() ?
292// po::value < std::vector<const molecule *> >()->default_value(boost::lexical_cast< std::vector<const molecule *> >(currentOption->getDefaultValue().c_str())) :
293 po::value < std::vector<int> >()->multitoken(),
294 currentOption->getDescription().c_str())
295 ;
296 break;
297 case TypeEnumContainer::AtomType:
298 OptionList->add_options()
299 (currentOption->getKeyAndShortForm().c_str(),
300 currentOption->hasDefaultValue() ?
301 po::value < int >()->default_value(boost::lexical_cast<int>(currentOption->getDefaultValue().c_str())) :
302 po::value < int >(),
303 currentOption->getDescription().c_str())
304 ;
305 break;
306 case TypeEnumContainer::ListOfAtomsType:
307 OptionList->add_options()
308 (currentOption->getKeyAndShortForm().c_str(),
309// currentOption->hasDefaultValue() ?
310// po::value < std::vector<const atom *> >()->default_value(boost::lexical_cast< std::vector<const atom *> >(currentOption->getDefaultValue().c_str())) :
311 po::value < std::vector<int> >()->multitoken(),
312 currentOption->getDescription().c_str())
313 ;
314 break;
315 case TypeEnumContainer::ElementType:
316 OptionList->add_options()
317 (currentOption->getKeyAndShortForm().c_str(),
318// currentOption->hasDefaultValue() ?
319// po::value < const element * >()->default_value(boost::lexical_cast<const element *>(currentOption->getDefaultValue().c_str())) :
320 po::value < int >(),
321 currentOption->getDescription().c_str())
322 ;
323 break;
324 case TypeEnumContainer::ListOfElementsType:
325 OptionList->add_options()
326 (currentOption->getKeyAndShortForm().c_str(),
327// currentOption->hasDefaultValue() ?
328// po::value < std::vector<const element *> >()->default_value(boost::lexical_cast< std::vector<const element *> >(currentOption->getDefaultValue().c_str())) :
329 po::value < std::vector<int> >()->multitoken(),
330 currentOption->getDescription().c_str())
331 ;
332 break;
333 case TypeEnumContainer::RandomNumberDistribution_ParametersType:
334 OptionList->add_options()
335 (currentOption->getKeyAndShortForm().c_str(),
336 currentOption->hasDefaultValue() ?
337 po::value < std::string >()->default_value(boost::lexical_cast< std::string >(currentOption->getDefaultValue().c_str())) :
338 po::value < std::string >(),
339 currentOption->getDescription().c_str())
340 ;
341 break;
342 }
343}
344
345/** States whether there are command line arguments.
346 * \return true - there are none, false - there is at least one command line argument
347 */
348bool CommandLineParser::isEmpty()
349{
350 return vm.empty();
351}
352
353/** Sets the options.
354 * \param _argc arg count from main()
355 * \param **_argv argument array from main()
356 */
357void CommandLineParser::setOptions(int _argc, char **_argv)
358{
359 argc = _argc;
360 argv = _argv;
361 config_file_options.add(options);
362 // append all option_descriptions to both cmdline_options and visible
363 for (CmdParserLookupMap::iterator iter = CmdParserLookup.begin();
364 iter != CmdParserLookup.end();
365 ++iter) {
366 cmdline_options.add(*(iter->second));
367 visible.add(*(iter->second));
368 }
369}
370
371/** Parses the command line arguments.
372 * Calls program_options::store() and program_options::notify()
373 */
374void CommandLineParser::Parse()
375{
376 po::store(po::command_line_parser(argc,argv).options(cmdline_options).run(), vm);
377 std::ifstream input;
378 input.open("example.cfg");
379 if (!input.fail())
380 po::store(po::parse_config_file(input, config_file_options), vm);
381 input.close();
382 po::notify(vm);
383}
384
385/** Scan the argument list for -a or --arguments and store their order for later use.
386 */
387void CommandLineParser::scanforSequenceOfArguments()
388{
389 std::map <std::string, std::string> ShortFormToActionMap = getShortFormToActionMap();
390 DoLog(0) && (Log() << Verbose(0) << "Scanning command line arguments and recognizing Actions." << std::endl);
391 // go through all arguments
392 for (int i=1;i<argc;i++) {
393 DoLog(2) && (Log() << Verbose(2) << "Checking on " << argv[i] << std::endl);
394 // check whether they
395 if (argv[i][0] == '-') { // .. begin with -
396 DoLog(2) && (Log() << Verbose(2) << "Possible argument: " << argv[i] << endl);
397 if (argv[i][1] == '-') { // .. or --
398 DoLog(1) && (Log() << Verbose(1) << "Putting " << argv[i] << " into the sequence." << endl);
399 SequenceOfActions.push_back(&(argv[i][2]));
400 // .. and check that next letter is not numeric, if so insert
401 } else if (((argv[i][1] < '0') || (argv[i][1] > '9')) && ((argv[i][1] != '.'))) {
402 std::map <std::string, std::string>::iterator iter = ShortFormToActionMap.find(&(argv[i][1]));
403 if (iter != ShortFormToActionMap.end()) {
404 DoLog(1) && (Log() << Verbose(1) << "Putting " << iter->second << " for " << iter->first << " into the sequence." << endl);
405 SequenceOfActions.push_back(iter->second);
406 }
407 }
408 }
409 }
410}
411
412/** Makes the Parser parse the command line options with current known options.
413 * \param _argc arg count from main()
414 * \param **_argv argument array from main()
415 */
416void CommandLineParser::Run(int _argc, char **_argv)
417{
418 setOptions(_argc,_argv);
419 Parse();
420 scanforSequenceOfArguments();
421}
422
423/** Go through all Actions and create a map from short form to their token.
424 * \return map from Action's ShortForm to token.
425 */
426std::map <std::string, std::string> CommandLineParser::getShortFormToActionMap() const
427{
428 std::map <std::string, std::string> result;
429
430 ActionRegistry &AR = ActionRegistry::getInstance();
431 for (ActionRegistry::const_iterator iter = AR.getBeginIter(); iter != AR.getEndIter(); ++iter)
432 if ((iter->second)->Traits.hasShortForm()) {
433 ASSERT(result.find((iter->second)->Traits.getShortForm()) == result.end(),
434 "Short form "+toString((iter->second)->Traits.getShortForm())+
435 " for action "+toString(iter->first)+" already present from "+
436 std::string(result[(iter->second)->Traits.getShortForm()])+"!");
437 result[(iter->second)->Traits.getShortForm()] = (iter->second)->getName();
438 }
439
440 return result;
441}
442
443CONSTRUCT_SINGLETON(CommandLineParser)
Note: See TracBrowser for help on using the repository browser.