/*
+ * This file is part of the GROMACS molecular simulation package.
*
- * This source code is part of
+ * 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.
*
- * G R O M A C S
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
*
- * GROningen MAchine for Chemical Simulations
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
*
* To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
+ * the research papers on the package. Check out http://www.gromacs.org.
*/
/*! \internal \file
* \brief
* Implements gmx::CommandLineHelpWriter.
*
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
* \ingroup module_commandline
*/
+#include "gmxpre.h"
+
#include "cmdlinehelpwriter.h"
+#include <cstring>
+
+#include <algorithm>
#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/basicoptions.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/arrayref.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/file.h"
#include "gromacs/utility/stringutil.h"
+#include "shellcompletions.h"
+
namespace gmx
{
namespace
{
+//! \addtogroup module_commandline
+//! \{
+
+/********************************************************************
+ * DescriptionsFormatter
+ */
+
+class DescriptionsFormatter : public OptionsVisitor
+{
+ public:
+ /*! \brief
+ * Creates a new description formatter.
+ *
+ * \param[in] context Help context to use to write the help.
+ */
+ explicit DescriptionsFormatter(const HelpWriterContext &context)
+ : context_(context), title_(NULL), bDidOutput_(false)
+ {
+ }
+
+ //! Formats all section descriptions from a given options.
+ void format(const Options &options, const char *title)
+ {
+ title_ = title;
+ bDidOutput_ = false;
+ visitSubSection(options);
+ if (bDidOutput_)
+ {
+ context_.outputFile().writeLine();
+ }
+ }
+
+ //! Formats the description for a single subsection and handles recursion.
+ virtual void visitSubSection(const Options §ion);
+ // This method is not used and never called.
+ virtual void visitOption(const OptionInfo & /*option*/) {}
+
+ private:
+ const HelpWriterContext &context_;
+ const char *title_;
+ bool bDidOutput_;
+
+ GMX_DISALLOW_COPY_AND_ASSIGN(DescriptionsFormatter);
+};
+
+void DescriptionsFormatter::visitSubSection(const Options §ion)
+{
+ if (!section.description().empty())
+ {
+ if (bDidOutput_)
+ {
+ context_.outputFile().writeLine();
+ }
+ else if (title_ != NULL)
+ {
+ context_.writeTitle(title_);
+ }
+ // TODO: Print title for the section?
+ context_.writeTextBlock(section.description());
+ bDidOutput_ = true;
+ }
+
+ OptionsIterator iterator(section);
+ iterator.acceptSubSections(this);
+}
+
/********************************************************************
* OptionsFormatterInterface
*/
-/*! \internal \brief
+/*! \brief
* Interface for output format specific formatting of options.
*
* \see OptionsFilter
- *
- * \ingroup module_commandline
*/
class OptionsFormatterInterface
{
public:
virtual ~OptionsFormatterInterface() {}
- //! Formats the description text block for a section.
- virtual void formatDescription(const HelpWriterContext &context,
- const Options §ion) = 0;
- //! Formats a single file option.
- virtual void formatFileOption(const HelpWriterContext &context,
- const FileNameOptionInfo &option) = 0;
- //! 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;
+ //! Formats a single option option.
+ virtual void formatOption(const OptionInfo &option) = 0;
};
/********************************************************************
* OptionsFilter
*/
-/*! \internal \brief
+/*! \brief
* Output format independent processing of options.
*
* Together with code in CommandLineHelpWriter::writeHelp(), this class
* 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
{
//! Specifies the type of output that formatSelected() produces.
enum FilterType
{
- eSelectDescriptions,
eSelectFileOptions,
- eSelectSelectionOptions,
eSelectOtherOptions
};
/*! \brief
* Creates a new filtering object.
*
- * \param[in] context Help context to use to write the help.
- * \param[in] formatter Output format specific formatter.
- *
* Does not throw.
*/
- OptionsFilter(const HelpWriterContext &context,
- OptionsFormatterInterface *formatter)
- : context_(context), formatter_(*formatter),
- filterType_(eSelectOtherOptions), bShowHidden_(false),
- bDidOutput_(false)
+ OptionsFilter()
+ : formatter_(NULL), filterType_(eSelectOtherOptions),
+ bShowHidden_(false)
{
}
}
//! Formats selected options using the formatter.
- void formatSelected(FilterType type, const Options &options);
+ void formatSelected(FilterType type,
+ OptionsFormatterInterface *formatter,
+ const Options &options);
virtual void visitSubSection(const Options §ion);
virtual void visitOption(const OptionInfo &option);
private:
- const HelpWriterContext &context_;
- OptionsFormatterInterface &formatter_;
+ OptionsFormatterInterface *formatter_;
FilterType filterType_;
bool bShowHidden_;
- bool bDidOutput_;
+
+ GMX_DISALLOW_COPY_AND_ASSIGN(OptionsFilter);
};
-void OptionsFilter::formatSelected(FilterType type, const Options &options)
+void OptionsFilter::formatSelected(FilterType type,
+ OptionsFormatterInterface *formatter,
+ const Options &options)
{
+ formatter_ = formatter;
filterType_ = type;
- bDidOutput_ = false;
visitSubSection(options);
- if (bDidOutput_)
- {
- context_.outputFile().writeLine();
- }
}
void OptionsFilter::visitSubSection(const Options §ion)
{
- if (filterType_ == eSelectDescriptions)
- {
- if (bDidOutput_)
- {
- context_.outputFile().writeLine();
- }
- formatter_.formatDescription(context_, section);
- bDidOutput_ = true;
- }
-
OptionsIterator iterator(section);
iterator.acceptSubSections(this);
iterator.acceptOptions(this);
{
if (filterType_ == eSelectFileOptions)
{
- formatter_.formatFileOption(context_,
- *option.toType<FileNameOptionInfo>());
- bDidOutput_ = true;
- }
- return;
- }
- if (option.isType<SelectionFileOptionInfo>()
- || option.isType<SelectionOptionInfo>())
- {
- if (filterType_ == eSelectSelectionOptions)
- {
- formatter_.formatSelectionOption(context_, option);
- bDidOutput_ = true;
+ formatter_->formatOption(option);
}
return;
}
if (filterType_ == eSelectOtherOptions)
{
- formatter_.formatOption(context_, option);
- bDidOutput_ = true;
+ formatter_->formatOption(option);
return;
}
}
};
/********************************************************************
- * OptionsConsoleFormatter
+ * Helper functions
*/
-/*! \internal \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 option name and value.
+void formatOptionNameAndValue(const OptionInfo &option, std::string *name,
+ std::string *value)
{
- 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())
+ *name = option.name();
+ *value = "<" + option.type() + ">";
+ if (option.isType<FileNameOptionInfo>())
{
- File &file = context.outputFile();
- const std::string &title = section.title();
- if (!title.empty())
+ // TODO: Make these work also for other option types.
+ if (option.maxValueCount() != 1)
{
- file.writeLine(title);
- file.writeLine();
+ *value += " [...]";
}
- context.writeTextBlock(section.description());
+ if (option.minValueCount() == 0)
+ {
+ *value = "[" + *value + "]";
+ }
+ }
+ if (option.isType<BooleanOptionInfo>())
+ {
+ *name = "[no]" + *name;
+ // Old command-line parser doesn't accept any values for these.
+ // value = "[" + value + "]";
+ value->clear();
}
}
-void OptionsConsoleFormatter::formatFileOption(
- const HelpWriterContext &context, const FileNameOptionInfo &option)
+//! Formats the default option value as a string.
+std::string
+defaultOptionValue(const OptionInfo &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)
+ if (option.valueCount() == 0
+ || (option.valueCount() == 1 && option.formatValue(0).empty()))
{
- 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)
+ return option.formatDefaultValueIfSet();
+ }
+ else
+ {
+ 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_.addColumnLine(3, context.substituteMarkup(option.description()));
+ return type;
+}
- // Compute layout.
- if (name.length() > 6U || firstShortValue > 0)
+//! 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()))
{
- fileOptionFormatter_.setColumnFirstLineOffset(1, 1);
- // Assume that the name is <20 chars, so that the type fits
- if (firstLongValue >= 0)
+ // TODO: It could be nicer to have this in basicoptions.cpp.
+ description = replaceAll(description, "%t", common.timeUnit);
+ }
+
+ return description;
+}
+
+/********************************************************************
+ * OptionsSynopsisFormatter
+ */
+
+/*! \brief
+ * Formatter implementation for synopsis.
+ */
+class SynopsisFormatter : public OptionsFormatterInterface
+{
+ public:
+ //! Creates a helper object for formatting the synopsis.
+ explicit SynopsisFormatter(const HelpWriterContext &context)
+ : context_(context), lineLength_(0), indent_(0), currentLength_(0)
{
- ++firstLongValue;
- ++lastLongValue;
}
- }
- int firstDescriptionLine = 0;
- if (bLongType)
+
+ //! Starts formatting the synopsis.
+ void start(const char *name);
+ //! Finishes formatting the synopsis.
+ void finish();
+
+ virtual void formatOption(const OptionInfo &option);
+
+ private:
+ const HelpWriterContext &context_;
+ int lineLength_;
+ int indent_;
+ int currentLength_;
+
+ GMX_DISALLOW_COPY_AND_ASSIGN(SynopsisFormatter);
+};
+
+void SynopsisFormatter::start(const char *name)
+{
+ currentLength_ = std::strlen(name) + 1;
+ indent_ = std::min(currentLength_, 13);
+ File &file = context_.outputFile();
+ switch (context_.outputFormat())
{
- firstDescriptionLine = 1;
+ case eHelpOutputFormat_Console:
+ lineLength_ = 78;
+ file.writeString(name);
+ break;
+ case eHelpOutputFormat_Man:
+ lineLength_ = 70;
+ file.writeString(name);
+ break;
+ case eHelpOutputFormat_Html:
+ lineLength_ = 78;
+ file.writeLine("<pre>");
+ file.writeString(name);
+ break;
+ default:
+ GMX_THROW(NotImplementedError("Synopsis formatting not implemented for this output format"));
}
- fileOptionFormatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
- if (firstLongValue >= 0
- && fileOptionFormatter_.lastColumnLine(3) >= firstLongValue)
+}
+
+void SynopsisFormatter::finish()
+{
+ File &file = context_.outputFile();
+ file.writeLine();
+ if (context_.outputFormat() == eHelpOutputFormat_Html)
{
- firstDescriptionLine = lastLongValue + 1;
- fileOptionFormatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
+ file.writeLine("</pre>");
}
-
- // Do the formatting.
- context.outputFile().writeString(fileOptionFormatter_.formatRow());
+ file.writeLine();
}
-void OptionsConsoleFormatter::formatOption(
- const HelpWriterContext &context, const OptionInfo &option)
+void SynopsisFormatter::formatOption(const OptionInfo &option)
{
- 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)
+ std::string name, value;
+ formatOptionNameAndValue(option, &name, &value);
+ std::string fullOptionText(" [-" + name);
+ if (!value.empty())
{
- genericOptionFormatter_.setColumnFirstLineOffset(1, 1);
+ fullOptionText.append(" ");
+ fullOptionText.append(value);
}
- // TODO: Better handling of multiple long values
- std::string values;
- for (int i = 0; i < option.valueCount(); ++i)
+ fullOptionText.append("]");
+ const int totalLength = fullOptionText.size();
+
+ if (context_.outputFormat() == eHelpOutputFormat_Html)
{
- if (i != 0)
- {
- values.append(" ");
- }
- values.append(option.formatValue(i));
+ value = replaceAll(value, "<", "<");
+ value = replaceAll(value, ">", ">");
}
- genericOptionFormatter_.addColumnLine(2, values);
- std::string description(context.substituteMarkup(option.description()));
- const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
- if (doubleOption != NULL && doubleOption->isTime())
+
+ File &file = context_.outputFile();
+ currentLength_ += totalLength;
+ if (currentLength_ >= lineLength_)
{
- description = replaceAll(description, "%t", common_.timeUnit);
+ file.writeString(formatString("\n%*c", indent_ - 1, ' '));
+ currentLength_ = indent_ - 1 + totalLength;
}
- genericOptionFormatter_.addColumnLine(3, description);
- if (values.length() > 6U)
+ file.writeString(fullOptionText);
+}
+
+/********************************************************************
+ * OptionsListFormatter
+ */
+
+/*! \brief
+ * Formatter implementation for help export.
+ */
+class OptionsListFormatter : public OptionsFormatterInterface
+{
+ public:
+ //! Creates a helper object for formatting options.
+ OptionsListFormatter(const HelpWriterContext &context,
+ const CommonFormatterData &common,
+ const char *title);
+
+ //! Initiates a new section in the options list.
+ void startSection(const char *header)
+ {
+ header_ = header;
+ bDidOutput_ = false;
+ }
+ //! Finishes a section in the options list.
+ void finishSection()
+ {
+ if (bDidOutput_)
+ {
+ context_.writeOptionListEnd();
+ context_.outputFile().writeLine();
+ }
+ }
+
+ virtual void formatOption(const OptionInfo &option);
+
+ private:
+ void writeSectionStartIfNecessary()
+ {
+ if (title_ != NULL)
+ {
+ context_.writeTitle(title_);
+ title_ = NULL;
+ }
+ if (!bDidOutput_)
+ {
+ if (header_ != NULL)
+ {
+ context_.writeTextBlock(header_);
+ }
+ context_.writeOptionListStart();
+ }
+ bDidOutput_ = true;
+ }
+
+ const HelpWriterContext &context_;
+ const CommonFormatterData &common_;
+ boost::scoped_ptr<TextTableFormatter> consoleFormatter_;
+ const char *title_;
+ const char *header_;
+ bool bDidOutput_;
+
+ GMX_DISALLOW_COPY_AND_ASSIGN(OptionsListFormatter);
+};
+
+OptionsListFormatter::OptionsListFormatter(
+ const HelpWriterContext &context,
+ const CommonFormatterData &common,
+ const char *title)
+ : context_(context), common_(common),
+ title_(title), header_(NULL), bDidOutput_(false)
+{
+ if (context.outputFormat() == eHelpOutputFormat_Console)
{
- genericOptionFormatter_.setColumnFirstLineOffset(3, 1);
+ 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);
}
-
- context.outputFile().writeString(genericOptionFormatter_.formatRow());
}
-void OptionsConsoleFormatter::formatSelectionOption(
- const HelpWriterContext &context, const OptionInfo &option)
+void OptionsListFormatter::formatOption(const OptionInfo &option)
{
- File &file = context.outputFile();
-
- selectionOptionFormatter_.clear();
- std::string name(formatString("-%s", option.name().c_str()));
- selectionOptionFormatter_.addColumnLine(0, name);
- selectionOptionFormatter_.addColumnLine(1, context.substituteMarkup(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)
+ writeSectionStartIfNecessary();
+ std::string name, value;
+ formatOptionNameAndValue(option, &name, &value);
+ std::string defaultValue(defaultOptionValue(option));
+ std::string info;
+ if (!defaultValue.empty())
{
- std::string value(option.formatValue(i));
- file.writeLine(wrapper.wrapToString(value));
+ info = "(" + defaultValue + ")";
+ }
+ const FileNameOptionInfo *fileOption = option.toType<FileNameOptionInfo>();
+ if (fileOption != NULL)
+ {
+ const bool bAbbrev = (context_.outputFormat() == eHelpOutputFormat_Console);
+ if (!info.empty())
+ {
+ info.append(" ");
+ }
+ info.append("(");
+ info.append(fileOptionFlagsAsString(*fileOption, bAbbrev));
+ info.append(")");
+ }
+ std::string description(descriptionWithOptionDetails(common_, option));
+ if (context_.outputFormat() == eHelpOutputFormat_Console)
+ {
+ consoleFormatter_->clear();
+ consoleFormatter_->addColumnLine(0, "-" + name);
+ consoleFormatter_->addColumnLine(1, value);
+ if (!info.empty())
+ {
+ consoleFormatter_->addColumnLine(2, info);
+ }
+ consoleFormatter_->addColumnHelpTextBlock(3, context_, description);
+ context_.outputFile().writeString(consoleFormatter_->formatRow());
+ }
+ else
+ {
+ if (!info.empty())
+ {
+ value.append(" ");
+ value.append(info);
+ }
+ context_.writeOptionItem("-" + name, value, description);
}
}
+//! \}
+
} // namespace
/********************************************************************
//! Sets the Options object to use for generating help.
explicit Impl(const Options &options);
+ //! Format the list of known issues.
+ void formatBugs(const HelpWriterContext &context);
+
//! Options object to use for generating help.
- const Options &options_;
+ const Options &options_;
+ //! List of bugs/knows issues.
+ ConstArrayRef<const char *> bugs_;
//! Time unit to show in descriptions.
- std::string timeUnit_;
+ std::string timeUnit_;
//! Whether to write descriptions to output.
- bool bShowDescriptions_;
- //! Whether to write hidden options to output.
- bool bShowHidden_;
+ bool bShowDescriptions_;
};
CommandLineHelpWriter::Impl::Impl(const Options &options)
: options_(options), timeUnit_(TimeUnitManager().timeUnitAsString()),
- bShowDescriptions_(false), bShowHidden_(false)
+ bShowDescriptions_(false)
+{
+}
+
+void CommandLineHelpWriter::Impl::formatBugs(const HelpWriterContext &context)
{
+ if (bugs_.empty())
+ {
+ return;
+ }
+ context.writeTitle("Known Issues");
+ if (context.outputFormat() != eHelpOutputFormat_Console)
+ {
+ context.writeTextBlock("[UL]");
+ }
+ ConstArrayRef<const char *>::const_iterator i;
+ for (i = bugs_.begin(); i != bugs_.end(); ++i)
+ {
+ const char *const bug = *i;
+ // TODO: The context should be able to do this also for console output, but
+ // that requires a lot more elaborate parser for the markup.
+ if (context.outputFormat() == eHelpOutputFormat_Console)
+ {
+ TextLineWrapperSettings settings;
+ settings.setIndent(2);
+ settings.setFirstLineIndent(0);
+ settings.setLineLength(78);
+ context.outputFile().writeLine(
+ context.substituteMarkupAndWrapToString(
+ settings, formatString("* %s", bug)));
+ }
+ else
+ {
+ context.writeTextBlock(formatString("[LI]%s", bug));
+ }
+ }
+ if (context.outputFormat() != eHelpOutputFormat_Console)
+ {
+ context.writeTextBlock("[ul]");
+ }
}
+
/********************************************************************
* CommandLineHelpWriter
*/
{
}
-CommandLineHelpWriter &CommandLineHelpWriter::setShowHidden(bool bSet)
+CommandLineHelpWriter &
+CommandLineHelpWriter::setShowDescriptions(bool bSet)
{
- impl_->bShowHidden_ = bSet;
+ impl_->bShowDescriptions_ = bSet;
return *this;
}
-CommandLineHelpWriter &CommandLineHelpWriter::setShowDescriptions(bool bSet)
+CommandLineHelpWriter &
+CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
{
- impl_->bShowDescriptions_ = bSet;
+ impl_->timeUnit_ = timeUnit;
return *this;
}
-CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
+CommandLineHelpWriter &
+CommandLineHelpWriter::setKnownIssues(const ConstArrayRef<const char *> &bugs)
{
- impl_->timeUnit_ = timeUnit;
+ impl_->bugs_ = bugs;
return *this;
}
-void CommandLineHelpWriter::writeHelp(const HelpWriterContext &context)
+void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
{
- boost::scoped_ptr<OptionsFormatterInterface> formatter;
- CommonFormatterData common(impl_->timeUnit_.c_str());
- switch (context.outputFormat())
+ if (context.isCompletionExport())
{
- 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"));
+ context.shellCompletionWriter().writeModuleCompletions(
+ context.moduleDisplayName(), impl_->options_);
+ return;
+ }
+ const HelpWriterContext &writerContext = context.writerContext();
+ OptionsFilter filter;
+ filter.setShowHidden(context.showHidden());
+
+ {
+ writerContext.writeTitle("Synopsis");
+ SynopsisFormatter synopsisFormatter(writerContext);
+ synopsisFormatter.start(context.moduleDisplayName());
+ filter.formatSelected(OptionsFilter::eSelectFileOptions,
+ &synopsisFormatter, impl_->options_);
+ filter.formatSelected(OptionsFilter::eSelectOtherOptions,
+ &synopsisFormatter, impl_->options_);
+ synopsisFormatter.finish();
}
- OptionsFilter filter(context, formatter.get());
- filter.setShowHidden(impl_->bShowHidden_);
if (impl_->bShowDescriptions_)
{
- File &file = context.outputFile();
- file.writeLine("DESCRIPTION");
- file.writeLine("-----------");
- file.writeLine();
- filter.formatSelected(OptionsFilter::eSelectDescriptions,
- impl_->options_);
+ DescriptionsFormatter descriptionFormatter(writerContext);
+ descriptionFormatter.format(impl_->options_, "Description");
}
+ CommonFormatterData common(impl_->timeUnit_.c_str());
+ OptionsListFormatter formatter(writerContext, common, "Options");
+ formatter.startSection("Options to specify input and output files:[PAR]");
filter.formatSelected(OptionsFilter::eSelectFileOptions,
- impl_->options_);
+ &formatter, impl_->options_);
+ formatter.finishSection();
+ formatter.startSection("Other options:[PAR]");
filter.formatSelected(OptionsFilter::eSelectOtherOptions,
- impl_->options_);
- filter.formatSelected(OptionsFilter::eSelectSelectionOptions,
- impl_->options_);
+ &formatter, impl_->options_);
+ formatter.finishSection();
+
+ impl_->formatBugs(writerContext);
}
} // namespace gmx