source: src/UIElements/CommandLineUI/CommandLineParser.cpp@ 751d7f1

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 751d7f1 was 3139b2, checked in by Frederik Heber <heber@…>, 13 years ago

Renamed ActionTrait and ActionTraits.

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