pargs.h)
gmx_install_headers(commandline ${COMMANDLINE_PUBLIC_HEADERS})
-# mdrun build does not include the selection machinery, which is used in the
-# tests
-if (BUILD_TESTING AND NOT GMX_BUILD_MDRUN_ONLY)
+if (BUILD_TESTING)
add_subdirectory(tests)
endif()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
#include <string>
+#include <boost/scoped_ptr.hpp>
+
#include "gromacs/commandline/cmdlinehelpcontext.h"
#include "gromacs/onlinehelp/helpformat.h"
#include "gromacs/onlinehelp/helpwritercontext.h"
#include "gromacs/options/options.h"
#include "gromacs/options/optionsvisitor.h"
#include "gromacs/options/timeunitmanager.h"
-#include "gromacs/selection/selectionfileoption.h"
-#include "gromacs/selection/selectionoption.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/file.h"
#include "gromacs/utility/stringutil.h"
namespace
{
+//! \addtogroup module_commandline
+//! \{
+
/********************************************************************
* OptionsFormatterInterface
*/
* Interface for output format specific formatting of options.
*
* \see OptionsFilter
- *
- * \ingroup module_commandline
*/
class OptionsFormatterInterface
{
//! Formats a single non-file, non-selection option.
virtual void formatOption(const HelpWriterContext &context,
const OptionInfo &option) = 0;
- //! Formats a single selection option.
- virtual void formatSelectionOption(const HelpWriterContext &context,
- const OptionInfo &option) = 0;
};
/********************************************************************
* An object implementing the OptionsFormatterInterface must be provided to the
* constructor, and does the actual formatting that is specific to the output
* format.
- *
- * \ingroup module_commandline
*/
class OptionsFilter : public OptionsVisitor
{
{
eSelectDescriptions,
eSelectFileOptions,
- eSelectSelectionOptions,
eSelectOtherOptions
};
OptionsFilter(const HelpWriterContext &context,
OptionsFormatterInterface *formatter)
: context_(context), formatter_(*formatter),
- filterType_(eSelectOtherOptions), bShowHidden_(false),
- bDidOutput_(false)
+ bShowHidden_(false), filterType_(eSelectOtherOptions),
+ title_(NULL), bDidOutput_(false)
{
}
}
//! Formats selected options using the formatter.
- void formatSelected(FilterType type, const Options &options);
+ void formatSelected(FilterType type, const Options &options,
+ const char *title);
virtual void visitSubSection(const Options §ion);
virtual void visitOption(const OptionInfo &option);
private:
+ void writeTitleIfSet()
+ {
+ if (title_ != NULL)
+ {
+ context_.writeTitle(title_);
+ }
+ }
+
const HelpWriterContext &context_;
OptionsFormatterInterface &formatter_;
- FilterType filterType_;
bool bShowHidden_;
+ FilterType filterType_;
+ const char *title_;
bool bDidOutput_;
+
+ GMX_DISALLOW_COPY_AND_ASSIGN(OptionsFilter);
};
-void OptionsFilter::formatSelected(FilterType type, const Options &options)
+void OptionsFilter::formatSelected(FilterType type, const Options &options,
+ const char *title)
{
filterType_ = type;
+ title_ = title;
bDidOutput_ = false;
visitSubSection(options);
if (bDidOutput_)
{
+ if (type != eSelectDescriptions)
+ {
+ context_.writeOptionListEnd();
+ }
context_.outputFile().writeLine();
}
}
{
if (filterType_ == eSelectDescriptions)
{
- if (bDidOutput_)
+ if (!section.description().empty())
{
- context_.outputFile().writeLine();
+ if (bDidOutput_)
+ {
+ context_.outputFile().writeLine();
+ }
+ else
+ {
+ writeTitleIfSet();
+ }
+ formatter_.formatDescription(context_, section);
+ bDidOutput_ = true;
}
- formatter_.formatDescription(context_, section);
- bDidOutput_ = true;
}
OptionsIterator iterator(section);
{
if (filterType_ == eSelectFileOptions)
{
+ if (!bDidOutput_)
+ {
+ writeTitleIfSet();
+ context_.writeOptionListStart();
+ }
formatter_.formatFileOption(context_,
*option.toType<FileNameOptionInfo>());
bDidOutput_ = true;
}
return;
}
- if (option.isType<SelectionFileOptionInfo>()
- || option.isType<SelectionOptionInfo>())
+ if (filterType_ == eSelectOtherOptions)
{
- if (filterType_ == eSelectSelectionOptions)
+ if (!bDidOutput_)
{
- formatter_.formatSelectionOption(context_, option);
- bDidOutput_ = true;
+ writeTitleIfSet();
+ context_.writeOptionListStart();
}
- return;
- }
- if (filterType_ == eSelectOtherOptions)
- {
formatter_.formatOption(context_, option);
bDidOutput_ = true;
return;
};
/********************************************************************
- * OptionsConsoleFormatter
+ * Helper functions
*/
-/*! \brief
- * Formatter implementation for console help.
- *
- * \ingroup module_commandline
- */
-class OptionsConsoleFormatter : public OptionsFormatterInterface
-{
- public:
- //! Creates a helper object for formatting options help for console.
- explicit OptionsConsoleFormatter(const CommonFormatterData &common);
-
- virtual void formatDescription(const HelpWriterContext &context,
- const Options §ion);
- virtual void formatFileOption(const HelpWriterContext &context,
- const FileNameOptionInfo &option);
- virtual void formatOption(const HelpWriterContext &context,
- const OptionInfo &option);
- virtual void formatSelectionOption(const HelpWriterContext &context,
- const OptionInfo &option);
-
- private:
- const CommonFormatterData &common_;
- TextTableFormatter fileOptionFormatter_;
- TextTableFormatter genericOptionFormatter_;
- TextTableFormatter selectionOptionFormatter_;
-};
-
-OptionsConsoleFormatter::OptionsConsoleFormatter(const CommonFormatterData &common)
- : common_(common)
+//! Formats the default option value as a string.
+std::string
+defaultOptionValue(const OptionInfo &option)
{
- fileOptionFormatter_.addColumn("Option", 6, false);
- fileOptionFormatter_.addColumn("Filename", 12, false);
- fileOptionFormatter_.addColumn("Type", 12, false);
- fileOptionFormatter_.addColumn("Description", 45, true);
-
- genericOptionFormatter_.addColumn("Option", 12, false);
- genericOptionFormatter_.addColumn("Type", 6, false);
- genericOptionFormatter_.addColumn("Value", 6, false);
- genericOptionFormatter_.addColumn("Description", 51, true);
-
- selectionOptionFormatter_.addColumn("Selection", 10, false);
- selectionOptionFormatter_.addColumn("Description", 67, true);
-}
-
-void OptionsConsoleFormatter::formatDescription(
- const HelpWriterContext &context, const Options §ion)
-{
- if (!section.description().empty())
+ if (option.valueCount() == 0
+ || (option.valueCount() == 1 && option.formatValue(0).empty()))
{
- File &file = context.outputFile();
- const std::string &title = section.title();
- if (!title.empty())
- {
- file.writeLine(title);
- file.writeLine();
- }
- context.writeTextBlock(section.description());
+ return option.formatDefaultValueIfSet();
}
-}
-
-void OptionsConsoleFormatter::formatFileOption(
- const HelpWriterContext &context, const FileNameOptionInfo &option)
-{
- int firstShortValue = 0; // The first value after which the type fits.
- int firstLongValue = -1; // First value that overlaps description column.
- int lastLongValue = -1; // Last value like the above.
-
- // Get the values to write and check where text overflows the columns.
- fileOptionFormatter_.clear();
- std::string name(formatString("-%s", option.name().c_str()));
- fileOptionFormatter_.addColumnLine(0, name);
- for (int i = 0; i < option.valueCount() || i == 0; ++i)
+ else
{
- std::string value;
- if (option.valueCount() == 0
- || (option.valueCount() == 1 && option.formatValue(0).empty()))
- {
- value = option.formatDefaultValueIfSet();
- }
- else
- {
- value = option.formatValue(i);
- }
- fileOptionFormatter_.addColumnLine(1, value);
- if (value.length() > 12U && i == firstShortValue)
- {
- firstShortValue = i + 1;
- }
- if (value.length() > 25U)
+ std::string result;
+ for (int i = 0; i < option.valueCount(); ++i)
{
- if (firstLongValue == -1)
+ if (i != 0)
{
- firstLongValue = i;
+ result.append(" ");
}
- lastLongValue = i;
+ result.append(option.formatValue(i));
}
+ return result;
}
+}
+
+//! Formats the flags for a file option as a string.
+std::string
+fileOptionFlagsAsString(const FileNameOptionInfo &option, bool bAbbrev)
+{
std::string type;
if (option.isInputOutputFile())
{
- type = "In/Out";
+ type = bAbbrev ? "In/Out" : "Input/Output";
}
else if (option.isInputFile())
{
}
if (!option.isRequired())
{
- type += ", Opt.";
+ type += bAbbrev ? ", Opt." : ", Optional";
}
if (option.isLibraryFile())
{
- type += ", Lib.";
+ type += bAbbrev ? ", Lib." : ", Library";
}
- bool bLongType = (type.length() > 12U);
- fileOptionFormatter_.addColumnLine(2, type);
- fileOptionFormatter_.addColumnHelpTextBlock(3, context, option.description());
+ // TODO: Add a tag for options that accept multiple files.
+ return type;
+}
- // Compute layout.
- if (name.length() > 6U || firstShortValue > 0)
- {
- fileOptionFormatter_.setColumnFirstLineOffset(1, 1);
- // Assume that the name is <20 chars, so that the type fits
- if (firstLongValue >= 0)
- {
- ++firstLongValue;
- ++lastLongValue;
- }
- }
- int firstDescriptionLine = 0;
- if (bLongType)
- {
- firstDescriptionLine = 1;
- }
- fileOptionFormatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
- if (firstLongValue >= 0
- && fileOptionFormatter_.lastColumnLine(3) >= firstLongValue)
+//! Formats the description for an option as a string.
+std::string
+descriptionWithOptionDetails(const CommonFormatterData &common,
+ const OptionInfo &option)
+{
+ std::string description(option.formatDescription());
+
+ const FloatOptionInfo *floatOption = option.toType<FloatOptionInfo>();
+ const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
+ if ((floatOption != NULL && floatOption->isTime())
+ || (doubleOption != NULL && doubleOption->isTime()))
{
- firstDescriptionLine = lastLongValue + 1;
- fileOptionFormatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
+ // TODO: It could be nicer to have this in basicoptions.cpp.
+ description = replaceAll(description, "%t", common.timeUnit);
}
- // Do the formatting.
- context.outputFile().writeString(fileOptionFormatter_.formatRow());
+ return description;
}
-void OptionsConsoleFormatter::formatOption(
- const HelpWriterContext &context, const OptionInfo &option)
+/********************************************************************
+ * OptionsExportFormatter
+ */
+
+/*! \brief
+ * Formatter implementation for help export.
+ */
+class OptionsExportFormatter : public OptionsFormatterInterface
{
- genericOptionFormatter_.clear();
- bool bIsBool = option.isType<BooleanOptionInfo>();
- std::string name(formatString("-%s%s", bIsBool ? "[no]" : "",
- option.name().c_str()));
- genericOptionFormatter_.addColumnLine(0, name);
- genericOptionFormatter_.addColumnLine(1, option.type());
- if (name.length() > 12U)
- {
- genericOptionFormatter_.setColumnFirstLineOffset(1, 1);
- }
+ public:
+ //! Creates a helper object for formatting options.
+ OptionsExportFormatter(const CommonFormatterData &common, bool bConsole);
+
+ virtual void formatDescription(const HelpWriterContext &context,
+ const Options §ion);
+ virtual void formatFileOption(const HelpWriterContext &context,
+ const FileNameOptionInfo &option);
+ virtual void formatOption(const HelpWriterContext &context,
+ const OptionInfo &option);
+
+ private:
+ const CommonFormatterData &common_;
+ boost::scoped_ptr<TextTableFormatter> consoleFormatter_;
- // TODO: Better handling of multiple long values
- std::string values;
- for (int i = 0; i < option.valueCount(); ++i)
+ GMX_DISALLOW_COPY_AND_ASSIGN(OptionsExportFormatter);
+};
+
+OptionsExportFormatter::OptionsExportFormatter(
+ const CommonFormatterData &common, bool bConsole)
+ : common_(common)
+{
+ if (bConsole)
{
- if (i != 0)
- {
- values.append(" ");
- }
- values.append(option.formatValue(i));
+ consoleFormatter_.reset(new TextTableFormatter());
+ consoleFormatter_->setFirstColumnIndent(1);
+ consoleFormatter_->setFoldLastColumnToNextLine(4);
+ consoleFormatter_->addColumn(NULL, 6, false);
+ consoleFormatter_->addColumn(NULL, 8, false);
+ consoleFormatter_->addColumn(NULL, 10, false);
+ consoleFormatter_->addColumn(NULL, 50, true);
}
- genericOptionFormatter_.addColumnLine(2, values);
+}
- std::string description(option.description());
- const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
- if (doubleOption != NULL && doubleOption->isTime())
+void OptionsExportFormatter::formatDescription(
+ const HelpWriterContext &context, const Options §ion)
+{
+ // TODO: Print title for the section?
+ context.writeTextBlock(section.description());
+}
+
+void OptionsExportFormatter::formatFileOption(
+ const HelpWriterContext &context, const FileNameOptionInfo &option)
+{
+ const bool bAbbrev = (context.outputFormat() == eHelpOutputFormat_Console);
+ std::string value("<" + option.type() + ">");
+ std::string defaultValue(defaultOptionValue(option));
+ std::string info = "(" + fileOptionFlagsAsString(option, bAbbrev) + ")";
+ if (!defaultValue.empty())
{
- description = replaceAll(description, "%t", common_.timeUnit);
+ info = "(" + defaultValue + ") " + info;
}
- const StringOptionInfo *stringOption = option.toType<StringOptionInfo>();
- if (stringOption != NULL && stringOption->isEnumerated())
+ std::string description(option.formatDescription());
+ if (context.outputFormat() == eHelpOutputFormat_Console)
{
- const std::vector<std::string> &allowedValues
- = stringOption->allowedValues();
- description.append(": ");
- for (size_t i = 0; i < allowedValues.size(); ++i)
- {
- if (i > 0)
- {
- description.append(i + 1 < allowedValues.size()
- ? ", " : ", or ");
- }
- description.append(allowedValues[i]);
- }
+ consoleFormatter_->clear();
+ consoleFormatter_->addColumnLine(0, "-" + option.name());
+ consoleFormatter_->addColumnLine(1, value);
+ consoleFormatter_->addColumnLine(2, info);
+ consoleFormatter_->addColumnHelpTextBlock(3, context, description);
+ context.outputFile().writeString(consoleFormatter_->formatRow());
}
- genericOptionFormatter_.addColumnHelpTextBlock(3, context, description);
- if (values.length() > 6U)
+ else
{
- genericOptionFormatter_.setColumnFirstLineOffset(3, 1);
+ value += " " + info;
+ context.writeOptionItem("-" + option.name(), value, description);
}
-
- context.outputFile().writeString(genericOptionFormatter_.formatRow());
}
-void OptionsConsoleFormatter::formatSelectionOption(
+void OptionsExportFormatter::formatOption(
const HelpWriterContext &context, const OptionInfo &option)
{
- File &file = context.outputFile();
-
- selectionOptionFormatter_.clear();
- std::string name(formatString("-%s", option.name().c_str()));
- selectionOptionFormatter_.addColumnLine(0, name);
- selectionOptionFormatter_.addColumnHelpTextBlock(1, context,
- option.description());
- file.writeString(selectionOptionFormatter_.formatRow());
-
- TextLineWrapper wrapper;
- wrapper.settings().setLineLength(77);
- wrapper.settings().setFirstLineIndent(4);
- wrapper.settings().setIndent(8);
- wrapper.settings().setContinuationChar('\\');
- // TODO: What to do with selection variables?
- // They are not printed as values for any option.
- for (int i = 0; i < option.valueCount(); ++i)
+ std::string name(option.name());
+ std::string value("<" + option.type() + ">");
+ std::string defaultValue(defaultOptionValue(option));
+ std::string description(descriptionWithOptionDetails(common_, option));
+ if (option.isType<BooleanOptionInfo>())
+ {
+ name = "[no]" + name;
+ // Old command-line parser doesn't accept any values for these.
+ // value = "[" + value + "]";
+ value.clear();
+ }
+ if (context.outputFormat() == eHelpOutputFormat_Console)
{
- std::string value(option.formatValue(i));
- file.writeLine(wrapper.wrapToString(value));
+ consoleFormatter_->clear();
+ consoleFormatter_->addColumnLine(0, "-" + name);
+ consoleFormatter_->addColumnLine(1, value);
+ if (!defaultValue.empty())
+ {
+ consoleFormatter_->addColumnLine(2, "(" + defaultValue + ")");
+ }
+ consoleFormatter_->addColumnHelpTextBlock(3, context, description);
+ context.outputFile().writeString(consoleFormatter_->formatRow());
+ }
+ else
+ {
+ if (!defaultValue.empty())
+ {
+ value += " (" + defaultValue + ")";
+ }
+ context.writeOptionItem("-" + name, value, description);
}
}
+//! \}
+
} // namespace
/********************************************************************
void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
{
- boost::scoped_ptr<OptionsFormatterInterface> formatter;
- const HelpWriterContext &writerContext = context.writerContext();
- CommonFormatterData common(impl_->timeUnit_.c_str());
- switch (writerContext.outputFormat())
+ const HelpWriterContext &writerContext = context.writerContext();
+ const bool bConsole
+ = (writerContext.outputFormat() == eHelpOutputFormat_Console);
+ CommonFormatterData common(impl_->timeUnit_.c_str());
+ OptionsExportFormatter formatter(common, bConsole);
+ OptionsFilter filter(writerContext, &formatter);
+ filter.setShowHidden(context.showHidden());
+
+ File &file = writerContext.outputFile();
+ if (!bConsole)
{
- case eHelpOutputFormat_Console:
- formatter.reset(new OptionsConsoleFormatter(common));
- break;
- default:
- // TODO: Implement once the situation with Redmine issue #969 is
- // more clear.
- GMX_THROW(NotImplementedError(
- "Command-line help is not implemented for this output format"));
+ // TODO: Write a proper synopsis, with all the options.
+ writerContext.writeTitle("Synopsis");
+ writerContext.writeTextBlock(context.moduleDisplayName());
+ file.writeLine("\n\n");
}
- OptionsFilter filter(writerContext, formatter.get());
- filter.setShowHidden(context.showHidden());
if (impl_->bShowDescriptions_)
{
- File &file = writerContext.outputFile();
- file.writeLine("DESCRIPTION");
- file.writeLine("-----------");
- file.writeLine();
filter.formatSelected(OptionsFilter::eSelectDescriptions,
- impl_->options_);
+ impl_->options_, "Description");
}
filter.formatSelected(OptionsFilter::eSelectFileOptions,
- impl_->options_);
+ impl_->options_, "File Options");
filter.formatSelected(OptionsFilter::eSelectOtherOptions,
- impl_->options_);
- filter.formatSelected(OptionsFilter::eSelectSelectionOptions,
- impl_->options_);
+ impl_->options_, "Options");
}
} // namespace gmx
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/filenameoption.h"
#include "gromacs/options/options.h"
-#include "gromacs/selection/selectioncollection.h"
-#include "gromacs/selection/selectionfileoption.h"
-#include "gromacs/selection/selectionoption.h"
-#include "gromacs/selection/selectionoptionmanager.h"
#include "gromacs/utility/file.h"
#include "testutils/stringtest.h"
.description("Output file description")
.filetype(eftPlot).outputFile());
- options.addOption(SelectionFileOption("sf"));
- options.addOption(SelectionOption("sel").description("Selection option"));
-
CommandLineHelpWriter writer(options);
bHidden_ = true;
checkHelp(&writer);
checkHelp(&writer);
}
-/*
+/* TODO: Add corresponding tests to either the selection module, or as part of
+ * trajectoryanalysis tests.
* Tests help printing with selection options with values.
*/
+#if 0
TEST_F(CommandLineHelpWriterTest, HandlesSelectionOptions)
{
using gmx::SelectionFileOption;
gmx::CommandLineHelpWriter writer(options);
checkHelp(&writer);
}
+#endif
/*
* Tests help printing for multiple sections.
<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
<ReferenceData>
<String Name="HelpText"><![CDATA[
-Option Filename Type Description
----------------------------------------------------------
--f Input File name option with a long value
- path/to/long/trajectory/name.xtc
--f2 Input File name option with a long value
- path/to/long/trajectory.xtc
--lib Input, Opt., Lib.
- path/to/long/trajectory/name.xtc
- File name option with a long value and type
--longfileopt Input, Opt. File name option with a long name
- deffile.dat
--longfileopt2 Input, Opt., Lib.
- path/to/long/file/name.dat
- File name option with multiple long fields
+FILE OPTIONS
+
+ -f <.xtc/.trr/...> (path/to/long/trajectory/name.xtc) (Input)
+ File name option with a long value: xtc trr cpt trj gro g96 pdb g87
+ -f2 <.xtc/.trr/...> (path/to/long/trajectory.xtc) (Input)
+ File name option with a long value: xtc trr cpt trj gro g96 pdb g87
+ -lib <.xtc/.trr/...> (path/to/long/trajectory/name.xtc) (Input, Opt., Lib.) File name option with a long value and type: xtc trr cpt trj gro g96 pdb g87
+ -longfileopt <.dat> (deffile.dat) (Input, Opt.)
+ File name option with a long name
+ -longfileopt2 <.dat> (path/to/long/file/name.dat) (Input, Opt., Lib.)
+ File name option with multiple long fields
]]></String>
</ReferenceData>
<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
<ReferenceData>
<String Name="HelpText"><![CDATA[
-Option Type Value Description
----------------------------------------------------
--[no]longboolean yes Boolean option with a long name
- bool
--dvec vector 1.135 2.32 3.2132
- Double vector option
--string string A very long string value that overflows even the description column Another very long string value that overflows even the description column
- String option with very long values (may be less
- relevant with selections having their own option
- type)
+OPTIONS
+
+ -[no]longboolean (yes) Boolean option with a long name
+ -dvec <vector> (1.135 2.32 3.2132) Double vector option
+ -string <string> (A very long string value that overflows even the description column Another very long string value that overflows even the description column)
+ String option with very long values (may be less relevant with selections
+ having their own option type)
]]></String>
</ReferenceData>
<ReferenceData>
<String Name="HelpText"><![CDATA[
DESCRIPTION
------------
-
-Main Title
Description for main section.
-Subsection 1 Title
-
Description for subsection 1.
-Subsection 2 Title
-
Description for subsection 2.
Description for subsection 3.
-Option Type Value Description
----------------------------------------------------
--sub1 int Option in subsection 1
--sub2 int Option in subsection 2
--main int Option in main section
+OPTIONS
+
+ -sub1 <int> Option in subsection 1
+ -sub2 <int> Option in subsection 2
+ -main <int> Option in main section
]]></String>
</ReferenceData>
<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
<ReferenceData>
<String Name="HelpText"><![CDATA[
-Option Filename Type Description
----------------------------------------------------------
--f traj.xtc Input Input file description
--lib libdata.dat Input, Opt., Lib.
- Library file description
--io inout.dat In/Out, Opt. Input/Output file description
--o Output, Opt. Output file description
+FILE OPTIONS
-Option Type Value Description
----------------------------------------------------
--[no]bool bool yes Boolean option
--[no]hidden bool yes Hidden option
--int int 2 Integer option
--ivec vector 1 2 3 Integer vector option
--double double 2.5 Double option
--dvec vector 1.1 2.3 3.2
- Double vector option
--time time 10 Time option (ps)
--string string test String option
--enum enum no Enum option: no, opt1, or opt2
+ -f <.xtc/.trr/...> (traj.xtc) (Input)
+ Input file description: xtc trr cpt trj gro g96 pdb g87
+ -lib <.dat> (libdata.dat) (Input, Opt., Lib.) Library file description
+ -io <.dat> (inout.dat) (In/Out, Opt.) Input/Output file description
+ -o <.xvg> (Output, Opt.) Output file description
-Selection Description
------------------------------------
--sf Provide selections from files
--sel Selection option
+OPTIONS
+
+ -[no]bool (yes) Boolean option
+ -[no]hidden (yes) Hidden option
+ -int <int> (2) Integer option
+ -ivec <vector> (1 2 3) Integer vector option
+ -double <real> (2.5) Double option
+ -dvec <vector> (1.1 2.3 3.2) Double vector option
+ -time <time> (10) Time option (ps)
+ -string <string> (test) String option
+ -enum <enum> (no) Enum option: no, opt1, opt2
]]></String>
</ReferenceData>
+++ /dev/null
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
- <String Name="HelpText"><![CDATA[
-Selection Description
------------------------------------
--sf Provide selections from files
--refsel Reference selection option
- resname SOL
--sel Selection option
- group "Protein" and surface
- group "Protein" and not surface
-
-]]></String>
-</ReferenceData>
class TextTableFormatter::Impl
{
public:
+ /*! \internal \brief
+ * Manages a single column for TextTableFormatter.
+ *
+ * \ingroup module_onlinehelp
+ */
struct ColumnData
{
+ //! Initializes a text table column with given values.
ColumnData(const char *title, int width, bool bWrap)
: title_(title != NULL ? title : ""),
- width_(width), bWrap_(bWrap), firstLine_(0)
+ width_(width), bWrap_(bWrap), firstLine_(0),
+ nextLineIndex_(0), nextLineOffset_(0)
{
GMX_ASSERT(width >= 0, "Negative width not possible");
GMX_ASSERT(title_.length() <= static_cast<size_t>(width),
* there is no text.
*/
int firstLine() const { return firstLine_; }
+
/*! \brief
- * Returns the index of the last line with text for the current row.
+ * Resets the formatting state.
*
- * If there is no text, returns -1.
+ * After this call, textForNextLine() and hasLinesRemaining() can
+ * be used to format the lines for the column.
*/
- int lastLine() const
+ void startFormatting()
{
- if (lines_.empty())
- {
- return -1;
- }
- return firstLine_ + static_cast<int>(lines_.size()) - 1;
+ nextLineIndex_ = (!lines_.empty() ? -firstLine_ : 0);
+ nextLineOffset_ = 0;
+ }
+ //! Whether there are lines remaining for textForNextLine().
+ bool hasLinesRemaining() const
+ {
+ return nextLineIndex_ < static_cast<int>(lines_.size());
}
/*! \brief
- * Returns the text for a line.
+ * Returns the text for the next line.
*
- * \param[in] line Zero-based line index.
- * \returns Text for line \p line, or empty string if \p line has
- * no text for this column.
+ * \param[in] columnWidth Width to wrap the text to.
+ * \returns Text for the next line, or empty string if there is
+ * no text for this column.
*/
- std::string textForLine(int line) const
+ std::string textForNextLine(int columnWidth)
{
- // The second conditional matches if there are no lines
- if (line < firstLine() || line > lastLine())
+ if (nextLineIndex_ < 0 || !hasLinesRemaining())
{
+ ++nextLineIndex_;
return std::string();
}
- return lines_[line - firstLine()];
+ if (bWrap_)
+ {
+ TextLineWrapperSettings settings;
+ settings.setLineLength(columnWidth);
+ TextLineWrapper wrapper(settings);
+ const std::string ¤tLine = lines_[nextLineIndex_];
+ const size_t prevOffset = nextLineOffset_;
+ const size_t nextOffset
+ = wrapper.findNextLine(currentLine, prevOffset);
+ if (nextOffset >= currentLine.size())
+ {
+ ++nextLineIndex_;
+ nextLineOffset_ = 0;
+ }
+ else
+ {
+ nextLineOffset_ = nextOffset;
+ }
+ return wrapper.formatLine(currentLine, prevOffset, nextOffset);
+ }
+ else
+ {
+ return lines_[nextLineIndex_++];
+ }
}
//! Statit data: title of the column.
int firstLine_;
//! Text lines for the current row.
std::vector<std::string> lines_;
+ //! Formatting state: index in `lines_` for the next line.
+ int nextLineIndex_;
+ //! Formatting state: offset within line `nextLineIndex_` for the next line.
+ size_t nextLineOffset_;
};
//! Container type for column data.
ColumnList columns_;
//! Indentation before the first column.
int firstColumnIndent_;
+ //! Indentation before the last column if folded.
+ int foldLastColumnToNextLineIndent_;
//! If true, no output has yet been produced.
bool bFirstRow_;
//! If true, a header will be printed before the first row.
};
TextTableFormatter::Impl::Impl()
- : firstColumnIndent_(0), bFirstRow_(true), bPrintHeader_(false)
+ : firstColumnIndent_(0), foldLastColumnToNextLineIndent_(-1),
+ bFirstRow_(true), bPrintHeader_(false)
{
}
impl_->firstColumnIndent_ = indent;
}
+void TextTableFormatter::setFoldLastColumnToNextLine(int indent)
+{
+ impl_->foldLastColumnToNextLineIndent_ = indent;
+}
+
bool TextTableFormatter::didOutput() const
{
return !impl_->bFirstRow_;
void TextTableFormatter::addColumnLine(int index, const std::string &text)
{
- Impl::ColumnData &column = impl_->columnData(index);
- TextLineWrapper wrapper;
- if (column.bWrap_)
- {
- wrapper.settings().setLineLength(column.width());
- }
+ Impl::ColumnData &column = impl_->columnData(index);
+ TextLineWrapper wrapper;
std::vector<std::string> lines(wrapper.wrapToVector(text));
column.lines_.insert(column.lines_.end(), lines.begin(), lines.end());
}
{
Impl::ColumnData &column = impl_->columnData(index);
TextLineWrapperSettings settings;
- if (column.bWrap_)
- {
- settings.setLineLength(column.width());
- }
+ // TODO: If in the future, there is actually a coupling between the markup
+ // and the wrapping, this must be postponed into formatRow(), where we do
+ // the actual line wrapping.
std::vector<std::string> lines(
context.substituteMarkupAndWrapToVector(settings, text));
column.lines_.insert(column.lines_.end(), lines.begin(), lines.end());
column.firstLine_ = firstLine;
}
-int TextTableFormatter::lastColumnLine(int index) const
-{
- return impl_->columnData(index).lastLine();
-}
-
std::string TextTableFormatter::formatRow()
{
- std::string result;
- Impl::ColumnList::const_iterator column;
+ std::string result;
+ Impl::ColumnList::iterator column;
// Print a header if this is the first line.
if (impl_->bPrintHeader_ && impl_->bFirstRow_)
{
result.append("\n");
}
- // Compute the last applicable line.
- int lastLine = -1;
+ // Format all the lines, one column at a time.
+ std::vector<std::string> lines;
+ std::vector<std::string> columnLines;
+ int currentWidth = 0;
+ bool bFoldLastColumn = false;
for (column = impl_->columns_.begin();
column != impl_->columns_.end();
++column)
{
- lastLine = std::max(lastLine, column->lastLine());
- }
-
- // Format the actual row data.
- for (int line = 0; line <= lastLine; ++line)
- {
- std::string lineResult;
- size_t currentWidth = 0;
- for (column = impl_->columns_.begin();
- column != impl_->columns_.end();
- ++column)
+ // Format the column into columnLines.
+ column->startFormatting();
+ columnLines.clear();
+ columnLines.reserve(lines.size());
+ for (size_t line = 0; column->hasLinesRemaining(); ++line)
{
- std::string value(column->textForLine(line));
- if (column != impl_->columns_.begin())
+ int columnWidth = column->width();
+ if (line < lines.size())
{
- ++currentWidth;
- if (!value.empty())
+ const int overflow = static_cast<int>(lines[line].length()) - currentWidth;
+ if (overflow > 0)
{
- lineResult.append(" ");
- if (lineResult.length() < currentWidth)
+ if (overflow > columnWidth)
{
- lineResult.resize(currentWidth, ' ');
+ columnLines.push_back(std::string());
+ continue;
}
+ columnWidth -= overflow;
}
}
- // TODO: Rewrap the text if wrapping is on and the previous columns
- // overflow.
- lineResult.append(value);
- currentWidth += column->width();
+ columnLines.push_back(column->textForNextLine(columnWidth));
}
+ if (column == impl_->columns_.end() - 1
+ && impl_->foldLastColumnToNextLineIndent_ >= 0
+ && columnLines.size() >= lines.size() + column->lines_.size())
+ {
+ bFoldLastColumn = true;
+ currentWidth += column->width();
+ break;
+ }
+ // Add columnLines into lines.
+ if (lines.size() < columnLines.size())
+ {
+ lines.resize(columnLines.size());
+ }
+ for (size_t line = 0; line < columnLines.size(); ++line)
+ {
+ if (column != impl_->columns_.begin() && !columnLines[line].empty())
+ {
+ lines[line].append(" ");
+ if (static_cast<int>(lines[line].length()) < currentWidth)
+ {
+ lines[line].resize(currentWidth, ' ');
+ }
+ }
+ lines[line].append(columnLines[line]);
+ }
+ currentWidth += column->width() + 1;
+ }
+
+ // Construct the result by concatenating all the lines.
+ std::vector<std::string>::const_iterator line;
+ for (line = lines.begin(); line != lines.end(); ++line)
+ {
result.append(impl_->firstColumnIndent_, ' ');
- result.append(lineResult);
+ result.append(*line);
result.append("\n");
}
+ if (bFoldLastColumn)
+ {
+ Impl::ColumnList::reference lastColumn = impl_->columns_.back();
+ const int totalIndent
+ = impl_->firstColumnIndent_ + impl_->foldLastColumnToNextLineIndent_;
+ lastColumn.startFormatting();
+ currentWidth -= impl_->foldLastColumnToNextLineIndent_;
+ while (lastColumn.hasLinesRemaining())
+ {
+ result.append(totalIndent, ' ');
+ result.append(lastColumn.textForNextLine(currentWidth));
+ result.append("\n");
+ }
+ }
+
impl_->bFirstRow_ = false;
clear();
return result;
* Does not throw.
*/
void setFirstColumnIndent(int indent);
+ /*! \brief
+ * Enables folding the last column to separate lines if it overflows.
+ *
+ * \param[in] indent Number of spaces to use for indenting the lines.
+ *
+ * If called with `indent >= 0`, the last column for each row is
+ * treated specially: if it contains more lines than the other columns,
+ * and if the text would fit more compactly as separate lines after the
+ * row, then the whole last column is written after the row with the
+ * given \p indent. The column text then spans the whole space
+ * reserved for the table, making long text fit into a smaller amount
+ * of vertical space.
+ * If not called, the last column is not treates specially.
+ *
+ * Does not throw.
+ */
+ void setFoldLastColumnToNextLine(int indent);
/*! \brief
* Whether formatRow() has been successfully called.
*/
std::string formatRow();
- /*! \brief
- * Returns the last line on which column \p index has text.
- *
- * \param[in] index Zero-based column index.
- * \returns Last line index (zero-based) on which \p index has text.
- *
- * The return value is the sum of the number of lines added with
- * addColumnLine() (taking into account possible wrapping) and the line
- * offset set with setColumnFirstLineOffset().
- *
- * Does not throw.
- */
- int lastColumnLine(int index) const;
-
private:
class Impl;
#include <boost/shared_ptr.hpp>
-#include "gromacs/onlinehelp/helpformat.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/file.h"
#include "gromacs/utility/gmxassert.h"
void HelpWriterContext::writeTitle(const std::string &title) const
{
- if (outputFormat() != eHelpOutputFormat_Console)
+ File &file = outputFile();
+ switch (outputFormat())
{
- // TODO: Implement once the situation with Redmine issue #969 is more
- // clear.
- GMX_THROW(NotImplementedError(
- "This output format is not implemented"));
+ case eHelpOutputFormat_Console:
+ file.writeLine(toUpperCase(title));
+ file.writeLine();
+ break;
+ case eHelpOutputFormat_Man:
+ file.writeLine(formatString(".SH %s", toUpperCase(title).c_str()));
+ break;
+ case eHelpOutputFormat_Html:
+ file.writeLine(formatString("<H3>%s</H3>", title.c_str()));
+ break;
+ default:
+ GMX_THROW(NotImplementedError(
+ "This output format is not implemented"));
}
- File &file = outputFile();
- file.writeLine(toUpperCase(title));
- file.writeLine();
}
void HelpWriterContext::writeTextBlock(const std::string &text) const
outputFile().writeLine(substituteMarkupAndWrapToString(settings, text));
}
+void HelpWriterContext::writeOptionListStart() const
+{
+ if (outputFormat() == eHelpOutputFormat_Html)
+ {
+ outputFile().writeLine("<dl>");
+ }
+}
+
+void HelpWriterContext::writeOptionItem(const std::string &name,
+ const std::string &args,
+ const std::string &description) const
+{
+ File &file = outputFile();
+ switch (outputFormat())
+ {
+ case eHelpOutputFormat_Console:
+ // TODO: Generalize this when there is need for it; the current,
+ // special implementation is in CommandLineHelpWriter.
+ GMX_THROW(NotImplementedError("Option item formatting for console output not implemented"));
+ break;
+ case eHelpOutputFormat_Man:
+ file.writeLine(formatString(".BI \"\\%s\" \" %s\"", name.c_str(), args.c_str()));
+ file.writeString(" ");
+ writeTextBlock(description);
+ file.writeLine();
+ break;
+ case eHelpOutputFormat_Html:
+ {
+ std::string substArgs =
+ substituteMarkupAndWrapToString(TextLineWrapperSettings(), args);
+ file.writeLine(formatString("<dt><b><tt>%s</tt></b> %s</dt>", name.c_str(),
+ substArgs.c_str()));
+ file.writeLine("<dd>");
+ writeTextBlock(description);
+ file.writeLine("</dd>");
+ break;
+ }
+ default:
+ GMX_THROW(NotImplementedError(
+ "This output format is not implemented"));
+ }
+}
+
+void HelpWriterContext::writeOptionListEnd() const
+{
+ if (outputFormat() == eHelpOutputFormat_Html)
+ {
+ outputFile().writeLine("</dl>");
+ }
+}
+
} // namespace gmx
* and writes the result directly to the output file.
*/
void writeTextBlock(const std::string &text) const;
+ /*! \brief
+ * Starts writing a list of options.
+ *
+ * Prints any necessary headers for a list of options formatted with
+ * writeOptionItem().
+ */
+ void writeOptionListStart() const;
+ /*! \brief
+ * Writes an entry for a single option into the output.
+ *
+ * \param[in] name Name of the option.
+ * \param[in] args Placeholder for values and other information about
+ * the option (placed after \p name).
+ * \param[in] description Full description of the option.
+ */
+ void writeOptionItem(const std::string &name, const std::string &args,
+ const std::string &description) const;
+ /*! \brief
+ * Finishes writing a list of options.
+ *
+ * Prints any necessary footers for a list of options formatted with
+ * writeOptionItem().
+ */
+ void writeOptionListEnd() const;
private:
class Impl;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013, 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.
checkText(formatter_.formatRow(), "FormattedRow3");
}
+TEST_F(TextTableFormatterTest, HandlesLastColumnFolding)
+{
+ setupStandardColumns();
+ formatter_.setFoldLastColumnToNextLine(4);
+ formatter_.clear();
+ formatter_.addColumnLine(0, "foo");
+ formatter_.addColumnLine(1, "bar");
+ formatter_.addColumnLine(2, "text");
+ formatter_.addColumnLine(3, g_wrapText);
+ checkText(formatter_.formatRow(), "FormattedTable");
+ formatter_.clear();
+ formatter_.addColumnLine(0, "foo");
+ formatter_.addColumnLine(1, "bar");
+ formatter_.addColumnLine(2, "text");
+ formatter_.addColumnLine(3, g_wrapText2);
+ checkText(formatter_.formatRow(), "FormattedRow2");
+ formatter_.clear();
+ formatter_.addColumnLine(0, "foo");
+ formatter_.addColumnLine(1, "bar");
+ formatter_.addColumnLine(2, "text");
+ formatter_.addColumnLine(3, "A quick brown fox jumps");
+ checkText(formatter_.formatRow(), "FormattedRow3");
+}
+
TEST_F(TextTableFormatterTest, HandlesEmptyColumns)
{
setupStandardColumns();
--- /dev/null
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+ <String Name="FormattedTable"><![CDATA[
+Col1 Col2 Col3Wrap Col4Wrap
+---------------------------------------
+foo bar text
+ A quick brown fox jumps over the
+ lazy dog
+]]></String>
+ <String Name="FormattedRow2"><![CDATA[
+foo bar text
+ A quick brown fox jumps
+ over the lazy dog
+]]></String>
+ <String Name="FormattedRow3"><![CDATA[
+foo bar text
+ A quick brown fox jumps
+]]></String>
+</ReferenceData>
<String Name="FormattedTable"><![CDATA[
Col1 Col2 Col3Wrap Col4Wrap
---------------------------------------
-foobar barfoo A quick brown A quick brown
- fox jumps over fox jumps
- the lazy dog over the lazy
- dog
+foobar barfoo A quick A quick brown
+ brown fox fox jumps
+ jumps over the over the lazy
+ lazy dog dog
]]></String>
<String Name="FormattedRow2"><![CDATA[
foobar A quick brown A quick brown
- barfoo fox jumps over fox jumps
- the lazy dog over the lazy
- dog
+ barfoo fox jumps fox jumps
+ over the lazy over the lazy
+ dog dog
]]></String>
<String Name="FormattedRow3"><![CDATA[
foobar A quick brown
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
return option().name();
}
-const std::string &OptionInfo::description() const
+std::string OptionInfo::type() const
{
- return option().description();
+ return option().typeString();
}
-const char *OptionInfo::type() const
+std::string OptionInfo::formatDescription() const
{
- return option().typeString();
+ std::string description(option().description());
+ std::string extraDescription(option().formatExtraDescription());
+ if (!extraDescription.empty())
+ {
+ description.append(extraDescription);
+ }
+ return description;
}
int OptionInfo::valueCount() const
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
bool isRequired() const;
//! Returns the name of the option.
const std::string &name() const;
- //! Returns the description of the option.
- const std::string &description() const;
//! Returns the type of the option as a string.
- const char *type() const;
+ std::string type() const;
+ //! Returns the description of the option.
+ std::string formatDescription() const;
//! Returns the number of values given for the option.
int valueCount() const;
//! Returns the i'th value of the option as a string.
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2014, 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.
bool isVector() const { return hasFlag(efOption_Vector); }
//! Returns the name of the option.
const std::string &name() const { return name_; }
- //! Returns the description of the option.
+ //! Returns the description of the option set by the calling code.
const std::string &description() const { return descr_; }
/*! \brief
virtual OptionInfo &optionInfo() = 0;
/*! \brief
* Returns a short string describing the type of the option.
+ */
+ virtual std::string typeString() const = 0;
+ /*! \brief
+ * Formats additional description for the option.
*
- * The caller is free to discard the returned string.
+ * If this method returns a non-empty string, it is appended to the
+ * plain description when printing help texts.
+ * The default implementation returns an empty string.
*/
- virtual const char *typeString() const = 0;
+ virtual std::string formatExtraDescription() const
+ { return std::string(); }
/*! \brief
* Returns the number of option values added so far.
*/
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
{
}
-const char *DoubleOptionStorage::typeString() const
+std::string DoubleOptionStorage::typeString() const
{
- return isVector() ? "vector" : (isTime() ? "time" : "double");
+ return isVector() ? "vector" : (isTime() ? "time" : "real");
}
std::string DoubleOptionStorage::formatSingleValue(const double &value) const
{
}
-const char *FloatOptionStorage::typeString() const
+std::string FloatOptionStorage::typeString() const
{
return isVector() ? "vector" : (isTime() ? "time" : "real");
}
}
}
+std::string StringOptionStorage::formatExtraDescription() const
+{
+ std::string result;
+ if (!allowed_.empty())
+ {
+ result.append(": ");
+ ValueList::const_iterator i;
+ for (i = allowed_.begin(); i != allowed_.end(); ++i)
+ {
+ if (i != allowed_.begin())
+ {
+ result.append(", ");
+ }
+ result.append(*i);
+ }
+ }
+ return result;
+}
+
std::string StringOptionStorage::formatSingleValue(const std::string &value) const
{
return value;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
}
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const { return "bool"; }
+ virtual std::string typeString() const { return "bool"; }
virtual std::string formatSingleValue(const bool &value) const;
private:
}
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const
+ virtual std::string typeString() const
{ return isVector() ? "vector" : "int"; }
virtual std::string formatSingleValue(const int &value) const;
}
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const
- { return "int"; }
+ virtual std::string typeString() const { return "int"; }
virtual std::string formatSingleValue(const gmx_int64_t &value) const;
private:
explicit DoubleOptionStorage(const DoubleOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const;
+ virtual std::string typeString() const;
virtual std::string formatSingleValue(const double &value) const;
//! \copydoc DoubleOptionInfo::isTime()
explicit FloatOptionStorage(const FloatOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const;
+ virtual std::string typeString() const;
virtual std::string formatSingleValue(const float &value) const;
//! \copydoc DoubleOptionStorage::isTime()
explicit StringOptionStorage(const StringOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const { return allowed_.empty() ? "string" : "enum"; }
+ virtual std::string typeString() const
+ { return allowed_.empty() ? "string" : "enum"; }
+ virtual std::string formatExtraDescription() const;
virtual std::string formatSingleValue(const std::string &value) const;
//! \copydoc StringOptionInfo::allowedValues()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, 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 FileTypeRegistry;
+//! \addtogroup module_options
+//! \{
+
+//! Shorthand for a list of file extensions.
+typedef std::vector<const char *> ExtensionList;
+
/********************************************************************
* FileTypeHandler
*/
/*! \internal \brief
* Handles a single file type known to FileNameOptionStorage.
- *
- * \ingroup module_options
*/
class FileTypeHandler
{
public:
+ //! Returns the list of extensions for this file type.
+ const ExtensionList &extensions() const { return extensions_; }
+
//! Returns whether \p filename has a valid extension for this type.
bool hasKnownExtension(const std::string &filename) const;
//! Adds a default extension for this type to \p filename.
private:
//! Possible extensions for this file type.
- std::vector<const char *> extensions_;
+ ExtensionList extensions_;
/*! \brief
* Needed for initialization; all initialization is handled by
/*! \internal \brief
* Singleton for managing static file type info for FileNameOptionStorage.
- *
- * \ingroup module_options
*/
class FileTypeRegistry
{
return typeHandler.addExtension(value);
}
+//! \}
+
} // namespace
/********************************************************************
}
}
+std::string FileNameOptionStorage::typeString() const
+{
+ const FileTypeRegistry ®istry = FileTypeRegistry::instance();
+ const FileTypeHandler &typeHandler = registry.handlerForType(filetype_);
+ const ExtensionList &extensions = typeHandler.extensions();
+ std::string result;
+ ExtensionList::const_iterator i;
+ int count = 0;
+ for (i = extensions.begin(); count < 2 && i != extensions.end(); ++i, ++count)
+ {
+ if (i != extensions.begin())
+ {
+ result.append("/");
+ }
+ result.append(*i);
+ }
+ if (i != extensions.end())
+ {
+ result.append("/...");
+ }
+ if (result.empty())
+ {
+ result = "file";
+ }
+ return result;
+}
+
+std::string FileNameOptionStorage::formatExtraDescription() const
+{
+ const FileTypeRegistry ®istry = FileTypeRegistry::instance();
+ const FileTypeHandler &typeHandler = registry.handlerForType(filetype_);
+ const ExtensionList &extensions = typeHandler.extensions();
+ std::string result;
+ if (extensions.size() > 2)
+ {
+ result.append(":");
+ ExtensionList::const_iterator i;
+ for (i = extensions.begin(); i != extensions.end(); ++i)
+ {
+ result.append(" ");
+ result.append((*i) + 1);
+ }
+ }
+ return result;
+}
+
std::string FileNameOptionStorage::formatSingleValue(const std::string &value) const
{
return value;
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014, 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.
explicit FileNameOptionStorage(const FileNameOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const { return "file"; }
+ virtual std::string typeString() const;
+ virtual std::string formatExtraDescription() const;
virtual std::string formatSingleValue(const std::string &value) const;
//! \copydoc FileNameOptionInfo::isInputFile()
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
// No implementation in this class for the pure virtual methods, but
// the declarations are still included for clarity.
- virtual const char *typeString() const = 0;
+ virtual std::string typeString() const = 0;
virtual int valueCount() const { return static_cast<int>(values_->size()); }
/*! \copydoc gmx::AbstractOptionStorage::formatValue()
*
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013,2014, 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.
virtual gmx::OptionInfo &optionInfo() { return info_; }
// These are not used.
- virtual const char *typeString() const { return "mock"; }
+ virtual std::string typeString() const { return "mock"; }
virtual std::string formatSingleValue(const std::string & /*value*/) const
{
return "";
/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2012, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014, 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.
SelectionFileOptionStorage(const SelectionFileOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const { return "file"; }
+ virtual std::string typeString() const { return "file"; }
virtual int valueCount() const { return 0; }
virtual std::string formatValue(int /*i*/) const { return ""; }
SelectionOptionStorage(const SelectionOption &settings);
virtual OptionInfo &optionInfo() { return info_; }
- virtual const char *typeString() const { return "sel"; }
+ virtual std::string typeString() const { return "selection"; }
virtual std::string formatSingleValue(const Selection &value) const;
//! \copydoc SelectionOptionInfo::setManager()
void TrajectoryAnalysisCommandLineRunner::Impl::RunnerCommandLineModule::writeHelp(
const CommandLineHelpContext &context) const
{
- // TODO: Implement #969.
- if (context.writerContext().outputFormat() != eHelpOutputFormat_Console)
- {
- return;
- }
TrajectoryAnalysisModulePointer module(factory_());
TrajectoryAnalysisCommandLineRunner runner(module.get());
runner.writeHelp(context);
"With [TT]-g2 t0[tt], [TT]-group2[tt] is not necessary, and angles",
"are calculated from the vectors as they are in the first frame.[PAR]",
"There are three options for output:",
- "[TT]-oav[tt] writes an xvgr file with the time and the average angle",
+ "[TT]-oav[tt] writes an xvg file with the time and the average angle",
"for each frame.",
"[TT]-oall[tt] writes all the individual angles.",
"[TT]-oh[tt] writes a histogram of the angles. The bin width can be",
TrajectoryAnalysisSettings *settings)
{
static const char *const desc[] = {
- "[THISMODULE] can calculate the free volume in a box as",
+ "[THISMODULE] calculates the free volume in a box as",
"a function of time. The free volume is",
"plotted as a fraction of the total volume.",
"The program tries to insert a probe with a given radius,",
.store(&impl_->ndxfile_)
.defaultBasename("index")
.description("Extra index groups"));
- options->addOption(SelectionFileOption("sf"));
// Add options for trajectory time control.
options->addOption(DoubleOption("b").store(&impl_->startTime_).timeValue()
options->addOption(BooleanOption("pbc").store(&settings.impl_->bPBC)
.description("Use periodic boundary conditions for distance calculation"));
}
+
+ options->addOption(SelectionFileOption("sf"));
}