2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013,2014, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements gmx::CommandLineHelpWriter.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_commandline
42 #include "cmdlinehelpwriter.h"
46 #include <boost/scoped_ptr.hpp>
48 #include "gromacs/commandline/cmdlinehelpcontext.h"
49 #include "gromacs/commandline/shellcompletions.h"
50 #include "gromacs/onlinehelp/helpformat.h"
51 #include "gromacs/onlinehelp/helpwritercontext.h"
52 #include "gromacs/options/basicoptions.h"
53 #include "gromacs/options/filenameoption.h"
54 #include "gromacs/options/options.h"
55 #include "gromacs/options/optionsvisitor.h"
56 #include "gromacs/options/timeunitmanager.h"
57 #include "gromacs/utility/exceptions.h"
58 #include "gromacs/utility/file.h"
59 #include "gromacs/utility/stringutil.h"
67 //! \addtogroup module_commandline
70 /********************************************************************
71 * DescriptionsFormatter
74 class DescriptionsFormatter : public OptionsVisitor
78 * Creates a new description formatter.
80 * \param[in] context Help context to use to write the help.
82 explicit DescriptionsFormatter(const HelpWriterContext &context)
83 : context_(context), title_(NULL), bDidOutput_(false)
87 //! Formats all section descriptions from a given options.
88 void format(const Options &options, const char *title)
92 visitSubSection(options);
95 context_.outputFile().writeLine();
99 //! Formats the description for a single subsection and handles recursion.
100 virtual void visitSubSection(const Options §ion);
101 // This method is not used and never called.
102 virtual void visitOption(const OptionInfo & /*option*/) {}
105 const HelpWriterContext &context_;
109 GMX_DISALLOW_COPY_AND_ASSIGN(DescriptionsFormatter);
112 void DescriptionsFormatter::visitSubSection(const Options §ion)
114 if (!section.description().empty())
118 context_.outputFile().writeLine();
120 else if (title_ != NULL)
122 context_.writeTitle(title_);
124 // TODO: Print title for the section?
125 context_.writeTextBlock(section.description());
129 OptionsIterator iterator(section);
130 iterator.acceptSubSections(this);
133 /********************************************************************
134 * OptionsFormatterInterface
138 * Interface for output format specific formatting of options.
142 class OptionsFormatterInterface
145 virtual ~OptionsFormatterInterface() {}
147 //! Formats a single option option.
148 virtual void formatOption(const OptionInfo &option) = 0;
151 /********************************************************************
156 * Output format independent processing of options.
158 * Together with code in CommandLineHelpWriter::writeHelp(), this class
159 * implements the common logic for writing out the help.
160 * An object implementing the OptionsFormatterInterface must be provided to the
161 * constructor, and does the actual formatting that is specific to the output
164 class OptionsFilter : public OptionsVisitor
167 //! Specifies the type of output that formatSelected() produces.
175 * Creates a new filtering object.
180 : formatter_(NULL), filterType_(eSelectOtherOptions),
185 //! Sets whether hidden options will be shown.
186 void setShowHidden(bool bShowHidden)
188 bShowHidden_ = bShowHidden;
191 //! Formats selected options using the formatter.
192 void formatSelected(FilterType type,
193 OptionsFormatterInterface *formatter,
194 const Options &options);
196 virtual void visitSubSection(const Options §ion);
197 virtual void visitOption(const OptionInfo &option);
200 OptionsFormatterInterface *formatter_;
201 FilterType filterType_;
204 GMX_DISALLOW_COPY_AND_ASSIGN(OptionsFilter);
207 void OptionsFilter::formatSelected(FilterType type,
208 OptionsFormatterInterface *formatter,
209 const Options &options)
211 formatter_ = formatter;
213 visitSubSection(options);
216 void OptionsFilter::visitSubSection(const Options §ion)
218 OptionsIterator iterator(section);
219 iterator.acceptSubSections(this);
220 iterator.acceptOptions(this);
223 void OptionsFilter::visitOption(const OptionInfo &option)
225 if (!bShowHidden_ && option.isHidden())
229 if (option.isType<FileNameOptionInfo>())
231 if (filterType_ == eSelectFileOptions)
233 formatter_->formatOption(option);
237 if (filterType_ == eSelectOtherOptions)
239 formatter_->formatOption(option);
244 /********************************************************************
245 * CommonFormatterData
248 class CommonFormatterData
251 explicit CommonFormatterData(const char *timeUnit)
256 const char *timeUnit;
259 /********************************************************************
263 //! Formats option name and value.
264 void formatOptionNameAndValue(const OptionInfo &option, std::string *name,
267 *name = option.name();
268 *value = "<" + option.type() + ">";
269 if (option.isType<FileNameOptionInfo>())
271 // TODO: Make these work also for other option types.
272 if (option.maxValueCount() != 1)
276 if (option.minValueCount() == 0)
278 *value = "[" + *value + "]";
281 if (option.isType<BooleanOptionInfo>())
283 *name = "[no]" + *name;
284 // Old command-line parser doesn't accept any values for these.
285 // value = "[" + value + "]";
290 //! Formats the default option value as a string.
292 defaultOptionValue(const OptionInfo &option)
294 if (option.valueCount() == 0
295 || (option.valueCount() == 1 && option.formatValue(0).empty()))
297 return option.formatDefaultValueIfSet();
302 for (int i = 0; i < option.valueCount(); ++i)
308 result.append(option.formatValue(i));
314 //! Formats the flags for a file option as a string.
316 fileOptionFlagsAsString(const FileNameOptionInfo &option, bool bAbbrev)
319 if (option.isInputOutputFile())
321 type = bAbbrev ? "In/Out" : "Input/Output";
323 else if (option.isInputFile())
327 else if (option.isOutputFile())
331 if (!option.isRequired())
333 type += bAbbrev ? ", Opt." : ", Optional";
335 if (option.isLibraryFile())
337 type += bAbbrev ? ", Lib." : ", Library";
342 //! Formats the description for an option as a string.
344 descriptionWithOptionDetails(const CommonFormatterData &common,
345 const OptionInfo &option)
347 std::string description(option.formatDescription());
349 const FloatOptionInfo *floatOption = option.toType<FloatOptionInfo>();
350 const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
351 if ((floatOption != NULL && floatOption->isTime())
352 || (doubleOption != NULL && doubleOption->isTime()))
354 // TODO: It could be nicer to have this in basicoptions.cpp.
355 description = replaceAll(description, "%t", common.timeUnit);
361 /********************************************************************
362 * OptionsListFormatter
366 * Formatter implementation for help export.
368 class OptionsListFormatter : public OptionsFormatterInterface
371 //! Creates a helper object for formatting options.
372 OptionsListFormatter(const HelpWriterContext &context,
373 const CommonFormatterData &common,
376 //! Initiates a new section in the options list.
377 void startSection(const char *title)
382 //! Finishes a section in the options list.
387 context_.writeOptionListEnd();
388 context_.outputFile().writeLine();
392 virtual void formatOption(const OptionInfo &option);
395 void writeSectionStartIfNecessary()
401 context_.writeTitle(title_);
403 context_.writeOptionListStart();
408 const HelpWriterContext &context_;
409 const CommonFormatterData &common_;
410 boost::scoped_ptr<TextTableFormatter> consoleFormatter_;
414 GMX_DISALLOW_COPY_AND_ASSIGN(OptionsListFormatter);
417 OptionsListFormatter::OptionsListFormatter(
418 const HelpWriterContext &context,
419 const CommonFormatterData &common,
421 : context_(context), common_(common), title_(NULL), bDidOutput_(false)
425 consoleFormatter_.reset(new TextTableFormatter());
426 consoleFormatter_->setFirstColumnIndent(1);
427 consoleFormatter_->setFoldLastColumnToNextLine(4);
428 consoleFormatter_->addColumn(NULL, 6, false);
429 consoleFormatter_->addColumn(NULL, 8, false);
430 consoleFormatter_->addColumn(NULL, 10, false);
431 consoleFormatter_->addColumn(NULL, 50, true);
435 void OptionsListFormatter::formatOption(const OptionInfo &option)
437 writeSectionStartIfNecessary();
438 std::string name, value;
439 formatOptionNameAndValue(option, &name, &value);
440 std::string defaultValue(defaultOptionValue(option));
442 if (!defaultValue.empty())
444 info = "(" + defaultValue + ")";
446 const FileNameOptionInfo *fileOption = option.toType<FileNameOptionInfo>();
447 if (fileOption != NULL)
449 const bool bAbbrev = (context_.outputFormat() == eHelpOutputFormat_Console);
455 info.append(fileOptionFlagsAsString(*fileOption, bAbbrev));
458 std::string description(descriptionWithOptionDetails(common_, option));
459 if (context_.outputFormat() == eHelpOutputFormat_Console)
461 consoleFormatter_->clear();
462 consoleFormatter_->addColumnLine(0, "-" + name);
463 consoleFormatter_->addColumnLine(1, value);
466 consoleFormatter_->addColumnLine(2, info);
468 consoleFormatter_->addColumnHelpTextBlock(3, context_, description);
469 context_.outputFile().writeString(consoleFormatter_->formatRow());
478 context_.writeOptionItem("-" + name, value, description);
486 /********************************************************************
487 * CommandLineHelpWriter::Impl
491 * Private implementation class for CommandLineHelpWriter.
493 * \ingroup module_commandline
495 class CommandLineHelpWriter::Impl
498 //! Sets the Options object to use for generating help.
499 explicit Impl(const Options &options);
501 //! Options object to use for generating help.
502 const Options &options_;
503 //! Time unit to show in descriptions.
504 std::string timeUnit_;
505 //! Whether to write descriptions to output.
506 bool bShowDescriptions_;
509 CommandLineHelpWriter::Impl::Impl(const Options &options)
510 : options_(options), timeUnit_(TimeUnitManager().timeUnitAsString()),
511 bShowDescriptions_(false)
515 /********************************************************************
516 * CommandLineHelpWriter
519 CommandLineHelpWriter::CommandLineHelpWriter(const Options &options)
520 : impl_(new Impl(options))
524 CommandLineHelpWriter::~CommandLineHelpWriter()
528 CommandLineHelpWriter &CommandLineHelpWriter::setShowDescriptions(bool bSet)
530 impl_->bShowDescriptions_ = bSet;
534 CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
536 impl_->timeUnit_ = timeUnit;
540 void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
542 if (context.isCompletionExport())
544 context.shellCompletionWriter().writeModuleCompletions(
545 context.moduleDisplayName(), impl_->options_);
548 const HelpWriterContext &writerContext = context.writerContext();
550 = (writerContext.outputFormat() == eHelpOutputFormat_Console);
551 OptionsFilter filter;
552 filter.setShowHidden(context.showHidden());
554 File &file = writerContext.outputFile();
557 // TODO: Write a proper synopsis, with all the options.
558 writerContext.writeTitle("Synopsis");
559 writerContext.writeTextBlock(context.moduleDisplayName());
560 file.writeLine("\n\n");
563 if (impl_->bShowDescriptions_)
565 DescriptionsFormatter descriptionFormatter(writerContext);
566 descriptionFormatter.format(impl_->options_, "Description");
568 CommonFormatterData common(impl_->timeUnit_.c_str());
569 OptionsListFormatter formatter(writerContext, common, bConsole);
570 formatter.startSection("File Options");
571 filter.formatSelected(OptionsFilter::eSelectFileOptions,
572 &formatter, impl_->options_);
573 formatter.finishSection();
574 formatter.startSection("Options");
575 filter.formatSelected(OptionsFilter::eSelectOtherOptions,
576 &formatter, impl_->options_);
577 formatter.finishSection();