/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
: assigner_(options), bSkipUnknown_(false)
{
assigner_.setAcceptBooleanNoPrefix(true);
- assigner_.setNoStrictSectioning(true);
}
const char *CommandLineParser::Impl::toOptionName(const char *arg) const
}
#endif
+/*
+ * Tests help output with option groups.
+ */
+TEST_F(CommandLineHelpWriterTest, HandlesOptionGroups)
+{
+ using gmx::IntegerOption;
+
+ gmx::Options options(NULL, NULL);
+ gmx::IOptionsContainer &group1 = options.addGroup();
+ gmx::IOptionsContainer &group2 = options.addGroup();
+ group2.addOption(IntegerOption("sub2").description("Option in group 2"));
+ group1.addOption(IntegerOption("sub11").description("Option in group 1"));
+ options.addOption(IntegerOption("main").description("Option in root group"));
+ group1.addOption(IntegerOption("sub12").description("Option in group 1"));
+
+ gmx::CommandLineHelpWriter writer(options);
+ checkHelp(&writer);
+}
+
/*
* Tests help output using a help text.
*/
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="HelpText"><![CDATA[
+SYNOPSIS
+
+gmx [-main <int>] [-sub11 <int>] [-sub12 <int>] [-sub2 <int>]
+
+OPTIONS
+
+Other options:
+
+ -main <int>
+ Option in root group
+ -sub11 <int>
+ Option in group 1
+ -sub12 <int>
+ Option in group 1
+ -sub2 <int>
+ Option in group 2
+
+]]></String>
+</ReferenceData>
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
class AbstractOptionStorage;
template <typename T> class OptionStorageTemplate;
class OptionManagerContainer;
-class Options;
+
+namespace internal
+{
+class OptionsImpl;
+}
/*! \brief
* Abstract base class for specifying option properties.
* without otherwise unnecessary accessors.
*/
friend class AbstractOptionStorage;
- /*! \brief
- * Needed to be able to call createStorage().
- */
- friend class Options;
+ //! Needed to be able to call createStorage().
+ friend class internal::OptionsImpl;
};
/*! \brief
#ifndef GMX_OPTIONS_OPTIONS_IMPL_H
#define GMX_OPTIONS_OPTIONS_IMPL_H
+#include <list>
+#include <map>
#include <string>
#include <vector>
class AbstractOptionStorage;
+namespace internal
+{
+
/*! \internal
* \brief
* Private implementation class for Options.
*
* \ingroup module_options
*/
-class Options::Impl
+class OptionsImpl
{
public:
+ /*! \internal \brief
+ * Describes a group of options (see Options::addGroup()).
+ *
+ * \ingroup module_options
+ */
+ class Group : public IOptionsContainer
+ {
+ public:
+ //! Convenience typedef for list of options.
+ typedef std::vector<AbstractOptionStorage *> OptionList;
+ //! Convenience typedef for list of subgroups.
+ typedef std::list<Group> SubgroupList;
+
+ //! Creates a group within the given Options.
+ explicit Group(OptionsImpl *parent) : parent_(parent) {}
+
+ //! Adds an option subgroup.
+ IOptionsContainer &addGroup();
+ // From IOptionsContainer
+ virtual OptionInfo *addOption(const AbstractOption &settings);
+
+ //! Containing options object.
+ OptionsImpl *parent_;
+ /*! \brief
+ * List of options, in insertion order.
+ *
+ * Pointers in this container point to the objects managed by
+ * Impl::optionsMap_.
+ */
+ OptionList options_;
+ //! List of groups, in insertion order.
+ SubgroupList subgroups_;
+ };
+
//! Smart pointer for managing an AbstractOptionStorage object.
typedef gmx_unique_ptr<AbstractOptionStorage>::type
AbstractOptionStoragePointer;
//! Convenience type for list of sections.
typedef std::vector<Options *> SubSectionList;
- //! Convenience type for list of options.
- typedef std::vector<AbstractOptionStoragePointer> OptionList;
+ //! Convenience typedef for a map that contains all the options.
+ typedef std::map<std::string, AbstractOptionStoragePointer> OptionMap;
//! Sets the name and title.
- Impl(const char *name, const char *title);
- ~Impl();
+ OptionsImpl(const char *name, const char *title);
/*! \brief
* Finds a subsection by name.
* This is non-empty only for the top-level Options object.
*/
OptionManagerContainer managers_;
+ /*! \brief
+ * Group that contains all options (and subgroups).
+ *
+ * This is used to store the insertion order of options.
+ */
+ Group rootGroup_;
+ //! Map from option names to options; owns the option storage objects.
+ OptionMap optionMap_;
/*! \brief
* List of subsections, in insertion order.
*
* management is performed elsewhere.
*/
SubSectionList subSections_;
- /*! \brief
- * List of options, in insertion order.
- *
- * All objects in this container are owned by this object, and are
- * freed in the destructor.
- */
- OptionList options_;
//! Options object that contains this object as a subsection, or NULL.
Options *parent_;
};
+} // namespace internal
+
} // namespace gmx
#endif
#include "options.h"
+#include <utility>
+
#include "gromacs/options/abstractoption.h"
#include "gromacs/options/abstractoptionstorage.h"
#include "gromacs/utility/arrayref.h"
}
/********************************************************************
- * Options::Impl
+ * OptionsImpl
*/
-Options::Impl::Impl(const char *name, const char * /*title*/)
- : name_(name != NULL ? name : ""),
- parent_(NULL)
+namespace internal
{
-}
-Options::Impl::~Impl()
+OptionsImpl::OptionsImpl(const char *name, const char * /*title*/)
+ : name_(name != NULL ? name : ""), rootGroup_(this),
+ parent_(NULL)
{
}
-Options *Options::Impl::findSubSection(const char *name) const
+Options *OptionsImpl::findSubSection(const char *name) const
{
SubSectionList::const_iterator i;
for (i = subSections_.begin(); i != subSections_.end(); ++i)
return NULL;
}
-AbstractOptionStorage *Options::Impl::findOption(const char *name) const
+AbstractOptionStorage *OptionsImpl::findOption(const char *name) const
{
- OptionList::const_iterator i;
- for (i = options_.begin(); i != options_.end(); ++i)
+ OptionMap::const_iterator i = optionMap_.find(name);
+ if (i == optionMap_.end())
{
- if ((*i)->name() == name)
- {
- return i->get();
- }
+ return NULL;
}
- return NULL;
+ return i->second.get();
}
-void Options::Impl::startSource()
+void OptionsImpl::startSource()
{
- OptionList::const_iterator i;
- for (i = options_.begin(); i != options_.end(); ++i)
+ OptionMap::const_iterator i;
+ for (i = optionMap_.begin(); i != optionMap_.end(); ++i)
{
- AbstractOptionStorage &option = **i;
+ AbstractOptionStorage &option = *i->second;
option.startSource();
}
SubSectionList::const_iterator j;
}
}
+/********************************************************************
+ * OptionsImpl::Group
+ */
+
+IOptionsContainer &OptionsImpl::Group::addGroup()
+{
+ subgroups_.push_back(Group(parent_));
+ return subgroups_.back();
+}
+
+OptionInfo *OptionsImpl::Group::addOption(const AbstractOption &settings)
+{
+ OptionsImpl *root = parent_;
+ while (root->parent_ != NULL)
+ {
+ root = root->parent_->impl_.get();
+ }
+ AbstractOptionStoragePointer option(settings.createStorage(root->managers_));
+ options_.reserve(options_.size() + 1);
+ std::pair<OptionMap::iterator, bool> insertionResult =
+ parent_->optionMap_.insert(std::make_pair(option->name(),
+ move(option)));
+ if (!insertionResult.second)
+ {
+ GMX_THROW(APIError("Duplicate option: " + option->name()));
+ }
+ AbstractOptionStorage &insertedOption = *insertionResult.first->second;
+ options_.push_back(&insertedOption);
+ return &insertedOption.optionInfo();
+}
+
+} // namespace internal
+
+using internal::OptionsImpl;
+
/********************************************************************
* Options
*/
Options::Options(const char *name, const char *title)
- : impl_(new Impl(name, title))
+ : impl_(new OptionsImpl(name, title))
{
}
GMX_RELEASE_ASSERT(impl_->parent_ == NULL,
"Can only add a manager in a top-level Options object");
// This ensures that all options see the same set of managers.
- GMX_RELEASE_ASSERT(impl_->options_.empty(),
+ GMX_RELEASE_ASSERT(impl_->optionMap_.empty(),
"Can only add a manager before options");
// This check could be relaxed if we instead checked that the subsections
// do not have options.
{
// This is required, because managers are used from the root Options
// object, so they are only seen after the subsection has been added.
- GMX_RELEASE_ASSERT(section->impl_->options_.empty(),
+ GMX_RELEASE_ASSERT(section->impl_->optionMap_.empty(),
"Can only add a subsection before it has any options");
GMX_RELEASE_ASSERT(section->impl_->managers_.empty(),
"Can only have managers in a top-level Options object");
section->impl_->parent_ = this;
}
+IOptionsContainer &Options::addGroup()
+{
+ return impl_->rootGroup_.addGroup();
+}
+
OptionInfo *Options::addOption(const AbstractOption &settings)
{
- Options::Impl *root = impl_.get();
- while (root->parent_ != NULL)
- {
- root = root->parent_->impl_.get();
- }
- Impl::AbstractOptionStoragePointer option(settings.createStorage(root->managers_));
- if (impl_->findOption(option->name().c_str()) != NULL)
- {
- GMX_THROW(APIError("Duplicate option: " + option->name()));
- }
- impl_->options_.push_back(move(option));
- return &impl_->options_.back()->optionInfo();
+ return impl_->rootGroup_.addOption(settings);
}
bool Options::isSet(const char *name) const
void Options::finish()
{
// TODO: Consider how to customize these error messages based on context.
- ExceptionInitializer errors("Invalid input values");
- Impl::OptionList::const_iterator i;
- for (i = impl_->options_.begin(); i != impl_->options_.end(); ++i)
+ ExceptionInitializer errors("Invalid input values");
+ OptionsImpl::OptionMap::const_iterator i;
+ for (i = impl_->optionMap_.begin(); i != impl_->optionMap_.end(); ++i)
{
- AbstractOptionStorage &option = **i;
+ AbstractOptionStorage &option = *i->second;
try
{
option.finish();
errors.addCurrentExceptionAsNested();
}
}
- Impl::SubSectionList::const_iterator j;
+ OptionsImpl::SubSectionList::const_iterator j;
for (j = impl_->subSections_.begin(); j != impl_->subSections_.end(); ++j)
{
Options §ion = **j;
class OptionsAssigner;
class OptionsIterator;
+namespace internal
+{
+class OptionsImpl;
+}
+
/*! \brief
* Base class for option managers.
*
*/
void addSubSection(Options *section);
+ /*! \brief
+ * Creates a subgroup of options within the current options.
+ *
+ * To add options to the group, use the returned interface.
+ *
+ * Currently, this is only used to influence the order of options:
+ * all options in a group appear before options in a group added after
+ * it, no matter in which order the options are added to the groups.
+ * In the future, the groups could also be used to influence the help
+ * output.
+ */
+ IOptionsContainer &addGroup();
+
// From IOptionsContainer
virtual OptionInfo *addOption(const AbstractOption &settings);
using IOptionsContainer::addOption;
void finish();
private:
- class Impl;
-
- PrivateImplPointer<Impl> impl_;
+ PrivateImplPointer<internal::OptionsImpl> impl_;
+ //! Needed for the implementation to access subsections.
+ friend class internal::OptionsImpl;
//! Needed to be able to extend the interface of this object.
friend class OptionsAssigner;
//! Needed to be able to extend the interface of this object.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
Options &options_;
//! Recognize boolean option "name" also as "noname".
bool bAcceptBooleanNoPrefix_;
- //! Look for options in all sections, not just the current one.
- bool bNoStrictSectioning_;
/*! \brief
* List of (sub)sections being assigned to.
*
OptionsAssigner::Impl::Impl(Options *options)
: options_(*options), bAcceptBooleanNoPrefix_(false),
- bNoStrictSectioning_(false), currentOption_(NULL),
- currentValueCount_(0), reverseBoolean_(false)
+ currentOption_(NULL), currentValueCount_(0), reverseBoolean_(false)
{
sectionStack_.push_back(&options_);
}
{
GMX_RELEASE_ASSERT(currentOption_ == NULL,
"Cannot search for another option while processing one");
- AbstractOptionStorage *option = NULL;
- Options *section = NULL;
- Options *root = ¤tSection();
- Options *oldRoot = NULL;
- int upcount = 0;
- std::deque<Options *> searchList;
- searchList.push_back(root);
- while (option == NULL && !searchList.empty())
+ const Options §ion = currentSection();
+ AbstractOptionStorage *option = section.impl_->findOption(name);
+ if (option == NULL && bAcceptBooleanNoPrefix_)
{
- section = searchList.front();
- option = section->impl_->findOption(name);
- if (option == NULL && bAcceptBooleanNoPrefix_)
+ if (name[0] == 'n' && name[1] == 'o')
{
- if (name[0] == 'n' && name[1] == 'o')
+ option = section.impl_->findOption(name + 2);
+ if (option != NULL && option->isBoolean())
{
- option = section->impl_->findOption(name + 2);
- if (option != NULL && option->isBoolean())
- {
- reverseBoolean_ = true;
- }
- else
- {
- option = NULL;
- }
+ reverseBoolean_ = true;
}
- }
- searchList.pop_front();
- if (bNoStrictSectioning_)
- {
- Options::Impl::SubSectionList::const_iterator i;
- for (i = section->impl_->subSections_.begin();
- i != section->impl_->subSections_.end(); ++i)
+ else
{
- if (*i != oldRoot)
- {
- searchList.push_back(*i);
- }
- }
- if (searchList.empty() && root != &options_)
- {
- root = root->impl_->parent_;
- ++upcount;
- searchList.push_back(root);
+ option = NULL;
}
}
}
- if (bNoStrictSectioning_ && option != NULL)
- {
- while (upcount > 0)
- {
- sectionStack_.pop_back();
- --upcount;
- }
- std::vector<Options *> sections;
- while (section != ¤tSection())
- {
- sections.push_back(section);
- section = section->impl_->parent_;
- }
- while (!sections.empty())
- {
- sectionStack_.push_back(sections.back());
- sections.pop_back();
- }
- }
return option;
}
impl_->bAcceptBooleanNoPrefix_ = bEnabled;
}
-void OptionsAssigner::setNoStrictSectioning(bool bEnabled)
-{
- impl_->bNoStrictSectioning_ = bEnabled;
-}
-
void OptionsAssigner::start()
{
impl_->options_.impl_->startSource();
void OptionsAssigner::finish()
{
GMX_RELEASE_ASSERT(impl_->currentOption_ == NULL, "finishOption() not called");
- if (impl_->bNoStrictSectioning_)
- {
- while (impl_->inSubSection())
- {
- finishSubSection();
- }
- }
GMX_RELEASE_ASSERT(!impl_->inSubSection(), "finishSubSection() not called");
}
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
* Does not throw.
*/
void setAcceptBooleanNoPrefix(bool bEnabled);
- /*! \brief
- * Sets the assigner to find options in non-active sections.
- *
- * By default, options are only looked for in the currently active
- * subsection. With this option set, if no matching option is found in
- * the current section, a breadth-first search is performed, first on
- * all subsections of the current section, and then going up one level
- * at a time. The first matching option is used, and the current
- * section is changed to the section that contains the matching option.
- *
- * Can be set or cleared at any time, and will have effect on all
- * subsequent calls of startOption().
- *
- * Does not throw.
- */
- void setNoStrictSectioning(bool bEnabled);
/*! \brief
* Starts assigning values.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2012,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2012,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
namespace gmx
{
+using internal::OptionsImpl;
+
+namespace
+{
+
+//! Helper function to call visitOptions() and handle correct indirection.
+void visitOption(OptionsVisitor *visitor, OptionInfo &optionInfo)
+{
+ visitor->visitOption(optionInfo);
+}
+//! Helper function to call visitOptions() and handle correct indirection.
+void visitOption(OptionsModifyingVisitor *visitor, OptionInfo &optionInfo)
+{
+ visitor->visitOption(&optionInfo);
+}
+
+//! Helper function to recursively visit all options in a group.
+template <class VisitorType>
+void acceptOptionsGroup(const OptionsImpl::Group &group, VisitorType *visitor)
+{
+ OptionsImpl::Group::OptionList::const_iterator option;
+ for (option = group.options_.begin(); option != group.options_.end(); ++option)
+ {
+ visitOption(visitor, (*option)->optionInfo());
+ }
+ OptionsImpl::Group::SubgroupList::const_iterator subgroup;
+ for (subgroup = group.subgroups_.begin(); subgroup != group.subgroups_.end(); ++subgroup)
+ {
+ acceptOptionsGroup(*subgroup, visitor);
+ }
+}
+
+} // namespace
+
/********************************************************************
* OptionsIterator
*/
void OptionsIterator::acceptSubSections(OptionsVisitor *visitor) const
{
- const Options::Impl::SubSectionList &subSectionList =
+ const OptionsImpl::SubSectionList &subSectionList =
options_.impl_->subSections_;
- Options::Impl::SubSectionList::const_iterator i;
+ OptionsImpl::SubSectionList::const_iterator i;
for (i = subSectionList.begin(); i != subSectionList.end(); ++i)
{
visitor->visitSubSection(*(*i));
void OptionsIterator::acceptOptions(OptionsVisitor *visitor) const
{
- const Options::Impl::OptionList &optionList =
- options_.impl_->options_;
- Options::Impl::OptionList::const_iterator i;
- for (i = optionList.begin(); i != optionList.end(); ++i)
- {
- // This is not strictly const-correct, since optionInfo() is
- // not const (while the input options is), but this makes things much
- // simpler.
- visitor->visitOption((*i)->optionInfo());
- }
+ acceptOptionsGroup(options_.impl_->rootGroup_, visitor);
}
/********************************************************************
void OptionsModifyingIterator::acceptSubSections(OptionsModifyingVisitor *visitor) const
{
- const Options::Impl::SubSectionList &subSectionList =
+ const OptionsImpl::SubSectionList &subSectionList =
options_.impl_->subSections_;
- Options::Impl::SubSectionList::const_iterator i;
+ OptionsImpl::SubSectionList::const_iterator i;
for (i = subSectionList.begin(); i != subSectionList.end(); ++i)
{
visitor->visitSubSection(*i);
void OptionsModifyingIterator::acceptOptions(OptionsModifyingVisitor *visitor) const
{
- const Options::Impl::OptionList &optionList =
- options_.impl_->options_;
- Options::Impl::OptionList::const_iterator i;
- for (i = optionList.begin(); i != optionList.end(); ++i)
- {
- visitor->visitOption(&(*i)->optionInfo());
- }
+ acceptOptionsGroup(options_.impl_->rootGroup_, visitor);
}
} // namespace gmx
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
* Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
* and including many others, as listed in the AUTHORS file in the
* top-level source directory and at http://www.gromacs.org.
EXPECT_EQ(0, value1);
}
-TEST(OptionsAssignerTest, HandlesSubSections)
+TEST(OptionsAssignerTest, HandlesGroups)
{
- gmx::Options options(NULL, NULL);
- gmx::Options sub1("section1", NULL);
- gmx::Options sub2("section2", NULL);
- int value = 3;
- int value1 = 1;
- int value2 = 2;
+ gmx::Options options(NULL, NULL);
+ gmx::IOptionsContainer &group1 = options.addGroup();
+ gmx::IOptionsContainer &group2 = options.addGroup();
+ int value = 3;
+ int value1 = 1;
+ int value2 = 2;
using gmx::IntegerOption;
- ASSERT_NO_THROW(options.addSubSection(&sub1));
- ASSERT_NO_THROW(options.addSubSection(&sub2));
ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
- ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&value1)));
- ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&value2)));
+ ASSERT_NO_THROW(group1.addOption(IntegerOption("q").store(&value1)));
+ ASSERT_NO_THROW(group2.addOption(IntegerOption("r").store(&value2)));
gmx::OptionsAssigner assigner(&options);
EXPECT_NO_THROW(assigner.start());
- ASSERT_NO_THROW(assigner.startSubSection("section1"));
ASSERT_NO_THROW(assigner.startOption("p"));
EXPECT_NO_THROW(assigner.appendValue("5"));
EXPECT_NO_THROW(assigner.finishOption());
- EXPECT_NO_THROW(assigner.finishSubSection());
- ASSERT_NO_THROW(assigner.startOption("p"));
+ ASSERT_NO_THROW(assigner.startOption("q"));
EXPECT_NO_THROW(assigner.appendValue("4"));
EXPECT_NO_THROW(assigner.finishOption());
- ASSERT_NO_THROW(assigner.startSubSection("section2"));
- ASSERT_NO_THROW(assigner.startOption("p"));
+ ASSERT_NO_THROW(assigner.startOption("r"));
EXPECT_NO_THROW(assigner.appendValue("6"));
EXPECT_NO_THROW(assigner.finishOption());
- EXPECT_NO_THROW(assigner.finishSubSection());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(4, value);
- EXPECT_EQ(5, value1);
+ EXPECT_EQ(5, value);
+ EXPECT_EQ(4, value1);
EXPECT_EQ(6, value2);
}
-TEST(OptionsAssignerTest, HandlesNoStrictSubSections)
+TEST(OptionsAssignerTest, HandlesSubSections)
{
gmx::Options options(NULL, NULL);
gmx::Options sub1("section1", NULL);
gmx::Options sub2("section2", NULL);
- int pvalue = 3;
- int pvalue1 = 1;
- int qvalue = 4;
- int pvalue2 = 2;
- int rvalue = 5;
+ int value = 3;
+ int value1 = 1;
+ int value2 = 2;
using gmx::IntegerOption;
ASSERT_NO_THROW(options.addSubSection(&sub1));
ASSERT_NO_THROW(options.addSubSection(&sub2));
- ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&pvalue)));
- ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&pvalue1)));
- ASSERT_NO_THROW(sub1.addOption(IntegerOption("q").store(&qvalue)));
- ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&pvalue2)));
- ASSERT_NO_THROW(sub2.addOption(IntegerOption("r").store(&rvalue)));
+ ASSERT_NO_THROW(options.addOption(IntegerOption("p").store(&value)));
+ ASSERT_NO_THROW(sub1.addOption(IntegerOption("p").store(&value1)));
+ ASSERT_NO_THROW(sub2.addOption(IntegerOption("p").store(&value2)));
gmx::OptionsAssigner assigner(&options);
- assigner.setNoStrictSectioning(true);
EXPECT_NO_THROW(assigner.start());
- ASSERT_NO_THROW(assigner.startOption("q"));
- EXPECT_NO_THROW(assigner.appendValue("6"));
- EXPECT_NO_THROW(assigner.finishOption());
+ ASSERT_NO_THROW(assigner.startSubSection("section1"));
ASSERT_NO_THROW(assigner.startOption("p"));
- EXPECT_NO_THROW(assigner.appendValue("7"));
- EXPECT_NO_THROW(assigner.finishOption());
- ASSERT_NO_THROW(assigner.startOption("r"));
- EXPECT_NO_THROW(assigner.appendValue("8"));
+ EXPECT_NO_THROW(assigner.appendValue("5"));
EXPECT_NO_THROW(assigner.finishOption());
+ EXPECT_NO_THROW(assigner.finishSubSection());
ASSERT_NO_THROW(assigner.startOption("p"));
- EXPECT_NO_THROW(assigner.appendValue("9"));
+ EXPECT_NO_THROW(assigner.appendValue("4"));
EXPECT_NO_THROW(assigner.finishOption());
- EXPECT_NO_THROW(assigner.finishSubSection());
+ ASSERT_NO_THROW(assigner.startSubSection("section2"));
ASSERT_NO_THROW(assigner.startOption("p"));
- EXPECT_NO_THROW(assigner.appendValue("10"));
+ EXPECT_NO_THROW(assigner.appendValue("6"));
EXPECT_NO_THROW(assigner.finishOption());
+ EXPECT_NO_THROW(assigner.finishSubSection());
EXPECT_NO_THROW(assigner.finish());
EXPECT_NO_THROW(options.finish());
- EXPECT_EQ(6, qvalue);
- EXPECT_EQ(7, pvalue1);
- EXPECT_EQ(8, rvalue);
- EXPECT_EQ(9, pvalue2);
- EXPECT_EQ(10, pvalue);
+ EXPECT_EQ(4, value);
+ EXPECT_EQ(5, value1);
+ EXPECT_EQ(6, value2);
}
TEST(OptionsAssignerTest, HandlesMultipleSources)
FileNameOptionManager fileoptManager;
SelectionOptionManager seloptManager(selections);
Options options(NULL, NULL);
- Options moduleOptions(module_->name(), module_->description());
- Options commonOptions("common", "Common analysis control");
- Options selectionOptions("selection", "Common selection control");
options.addManager(&fileoptManager);
options.addManager(&seloptManager);
- options.addSubSection(&commonOptions);
- options.addSubSection(&selectionOptions);
- options.addSubSection(&moduleOptions);
+ IOptionsContainer &commonOptions = options.addGroup();
+ IOptionsContainer &moduleOptions = options.addGroup();
module_->initOptions(&moduleOptions, settings);
common->initOptions(&commonOptions);
- selections->initOptions(&selectionOptions);
+ selections->initOptions(&commonOptions);
{
CommandLineParser parser(&options);
options.finish();
}
- common->optionsFinished(&commonOptions);
- module_->optionsFinished(&moduleOptions, settings);
+ common->optionsFinished(&options);
+ module_->optionsFinished(&options, settings);
common->initIndexGroups(selections, bUseDefaultGroups_);
SelectionOptionManager seloptManager(&selections);
Options options(NULL, NULL);
- Options moduleOptions(impl_->module_->name(), impl_->module_->description());
- Options commonOptions("common", "Common analysis control");
- Options selectionOptions("selection", "Common selection control");
options.addManager(&seloptManager);
- options.addSubSection(&commonOptions);
- options.addSubSection(&selectionOptions);
- options.addSubSection(&moduleOptions);
+ IOptionsContainer &commonOptions = options.addGroup();
+ IOptionsContainer &moduleOptions = options.addGroup();
impl_->module_->initOptions(&moduleOptions, &settings);
common.initOptions(&commonOptions);
- selections.initOptions(&selectionOptions);
+ selections.initOptions(&commonOptions);
CommandLineHelpWriter(options)
.setHelpText(settings.helpText())