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 * OptionsFormatterInterface
75 * Interface for output format specific formatting of options.
79 class OptionsFormatterInterface
82 virtual ~OptionsFormatterInterface() {}
84 //! Formats the description text block for a section.
85 virtual void formatDescription(const HelpWriterContext &context,
86 const Options §ion) = 0;
87 //! Formats a single file option.
88 virtual void formatFileOption(const HelpWriterContext &context,
89 const FileNameOptionInfo &option) = 0;
90 //! Formats a single non-file, non-selection option.
91 virtual void formatOption(const HelpWriterContext &context,
92 const OptionInfo &option) = 0;
95 /********************************************************************
100 * Output format independent processing of options.
102 * Together with code in CommandLineHelpWriter::writeHelp(), this class
103 * implements the common logic for writing out the help.
104 * An object implementing the OptionsFormatterInterface must be provided to the
105 * constructor, and does the actual formatting that is specific to the output
108 class OptionsFilter : public OptionsVisitor
111 //! Specifies the type of output that formatSelected() produces.
120 * Creates a new filtering object.
122 * \param[in] context Help context to use to write the help.
123 * \param[in] formatter Output format specific formatter.
127 OptionsFilter(const HelpWriterContext &context,
128 OptionsFormatterInterface *formatter)
129 : context_(context), formatter_(*formatter),
130 bShowHidden_(false), filterType_(eSelectOtherOptions),
131 title_(NULL), bDidOutput_(false)
135 //! Sets whether hidden options will be shown.
136 void setShowHidden(bool bShowHidden)
138 bShowHidden_ = bShowHidden;
141 //! Formats selected options using the formatter.
142 void formatSelected(FilterType type, const Options &options,
145 virtual void visitSubSection(const Options §ion);
146 virtual void visitOption(const OptionInfo &option);
149 void writeTitleIfSet()
153 context_.writeTitle(title_);
157 const HelpWriterContext &context_;
158 OptionsFormatterInterface &formatter_;
160 FilterType filterType_;
164 GMX_DISALLOW_COPY_AND_ASSIGN(OptionsFilter);
167 void OptionsFilter::formatSelected(FilterType type, const Options &options,
173 visitSubSection(options);
176 if (type != eSelectDescriptions)
178 context_.writeOptionListEnd();
180 context_.outputFile().writeLine();
184 void OptionsFilter::visitSubSection(const Options §ion)
186 if (filterType_ == eSelectDescriptions)
188 if (!section.description().empty())
192 context_.outputFile().writeLine();
198 formatter_.formatDescription(context_, section);
203 OptionsIterator iterator(section);
204 iterator.acceptSubSections(this);
205 iterator.acceptOptions(this);
208 void OptionsFilter::visitOption(const OptionInfo &option)
210 if (!bShowHidden_ && option.isHidden())
214 if (option.isType<FileNameOptionInfo>())
216 if (filterType_ == eSelectFileOptions)
221 context_.writeOptionListStart();
223 formatter_.formatFileOption(context_,
224 *option.toType<FileNameOptionInfo>());
229 if (filterType_ == eSelectOtherOptions)
234 context_.writeOptionListStart();
236 formatter_.formatOption(context_, option);
242 /********************************************************************
243 * CommonFormatterData
246 class CommonFormatterData
249 explicit CommonFormatterData(const char *timeUnit)
254 const char *timeUnit;
257 /********************************************************************
261 //! Formats the default option value as a string.
263 defaultOptionValue(const OptionInfo &option)
265 if (option.valueCount() == 0
266 || (option.valueCount() == 1 && option.formatValue(0).empty()))
268 return option.formatDefaultValueIfSet();
273 for (int i = 0; i < option.valueCount(); ++i)
279 result.append(option.formatValue(i));
285 //! Formats the flags for a file option as a string.
287 fileOptionFlagsAsString(const FileNameOptionInfo &option, bool bAbbrev)
290 if (option.isInputOutputFile())
292 type = bAbbrev ? "In/Out" : "Input/Output";
294 else if (option.isInputFile())
298 else if (option.isOutputFile())
302 if (!option.isRequired())
304 type += bAbbrev ? ", Opt." : ", Optional";
306 if (option.isLibraryFile())
308 type += bAbbrev ? ", Lib." : ", Library";
313 //! Formats the description for an option as a string.
315 descriptionWithOptionDetails(const CommonFormatterData &common,
316 const OptionInfo &option)
318 std::string description(option.formatDescription());
320 const FloatOptionInfo *floatOption = option.toType<FloatOptionInfo>();
321 const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
322 if ((floatOption != NULL && floatOption->isTime())
323 || (doubleOption != NULL && doubleOption->isTime()))
325 // TODO: It could be nicer to have this in basicoptions.cpp.
326 description = replaceAll(description, "%t", common.timeUnit);
332 /********************************************************************
333 * OptionsExportFormatter
337 * Formatter implementation for help export.
339 class OptionsExportFormatter : public OptionsFormatterInterface
342 //! Creates a helper object for formatting options.
343 OptionsExportFormatter(const CommonFormatterData &common, bool bConsole);
345 virtual void formatDescription(const HelpWriterContext &context,
346 const Options §ion);
347 virtual void formatFileOption(const HelpWriterContext &context,
348 const FileNameOptionInfo &option);
349 virtual void formatOption(const HelpWriterContext &context,
350 const OptionInfo &option);
353 const CommonFormatterData &common_;
354 boost::scoped_ptr<TextTableFormatter> consoleFormatter_;
356 GMX_DISALLOW_COPY_AND_ASSIGN(OptionsExportFormatter);
359 OptionsExportFormatter::OptionsExportFormatter(
360 const CommonFormatterData &common, bool bConsole)
365 consoleFormatter_.reset(new TextTableFormatter());
366 consoleFormatter_->setFirstColumnIndent(1);
367 consoleFormatter_->setFoldLastColumnToNextLine(4);
368 consoleFormatter_->addColumn(NULL, 6, false);
369 consoleFormatter_->addColumn(NULL, 8, false);
370 consoleFormatter_->addColumn(NULL, 10, false);
371 consoleFormatter_->addColumn(NULL, 50, true);
375 void OptionsExportFormatter::formatDescription(
376 const HelpWriterContext &context, const Options §ion)
378 // TODO: Print title for the section?
379 context.writeTextBlock(section.description());
382 void OptionsExportFormatter::formatFileOption(
383 const HelpWriterContext &context, const FileNameOptionInfo &option)
385 const bool bAbbrev = (context.outputFormat() == eHelpOutputFormat_Console);
386 std::string value("<" + option.type() + ">");
387 if (option.maxValueCount() != 1)
391 if (option.minValueCount() == 0)
393 value = "[" + value + "]";
395 std::string defaultValue(defaultOptionValue(option));
396 std::string info = "(" + fileOptionFlagsAsString(option, bAbbrev) + ")";
397 if (!defaultValue.empty())
399 info = "(" + defaultValue + ") " + info;
401 std::string description(option.formatDescription());
402 if (context.outputFormat() == eHelpOutputFormat_Console)
404 consoleFormatter_->clear();
405 consoleFormatter_->addColumnLine(0, "-" + option.name());
406 consoleFormatter_->addColumnLine(1, value);
407 consoleFormatter_->addColumnLine(2, info);
408 consoleFormatter_->addColumnHelpTextBlock(3, context, description);
409 context.outputFile().writeString(consoleFormatter_->formatRow());
414 context.writeOptionItem("-" + option.name(), value, description);
418 void OptionsExportFormatter::formatOption(
419 const HelpWriterContext &context, const OptionInfo &option)
421 std::string name(option.name());
422 std::string value("<" + option.type() + ">");
423 std::string defaultValue(defaultOptionValue(option));
424 std::string description(descriptionWithOptionDetails(common_, option));
425 if (option.isType<BooleanOptionInfo>())
427 name = "[no]" + name;
428 // Old command-line parser doesn't accept any values for these.
429 // value = "[" + value + "]";
432 if (context.outputFormat() == eHelpOutputFormat_Console)
434 consoleFormatter_->clear();
435 consoleFormatter_->addColumnLine(0, "-" + name);
436 consoleFormatter_->addColumnLine(1, value);
437 if (!defaultValue.empty())
439 consoleFormatter_->addColumnLine(2, "(" + defaultValue + ")");
441 consoleFormatter_->addColumnHelpTextBlock(3, context, description);
442 context.outputFile().writeString(consoleFormatter_->formatRow());
446 if (!defaultValue.empty())
448 value += " (" + defaultValue + ")";
450 context.writeOptionItem("-" + name, value, description);
458 /********************************************************************
459 * CommandLineHelpWriter::Impl
463 * Private implementation class for CommandLineHelpWriter.
465 * \ingroup module_commandline
467 class CommandLineHelpWriter::Impl
470 //! Sets the Options object to use for generating help.
471 explicit Impl(const Options &options);
473 //! Options object to use for generating help.
474 const Options &options_;
475 //! Time unit to show in descriptions.
476 std::string timeUnit_;
477 //! Whether to write descriptions to output.
478 bool bShowDescriptions_;
481 CommandLineHelpWriter::Impl::Impl(const Options &options)
482 : options_(options), timeUnit_(TimeUnitManager().timeUnitAsString()),
483 bShowDescriptions_(false)
487 /********************************************************************
488 * CommandLineHelpWriter
491 CommandLineHelpWriter::CommandLineHelpWriter(const Options &options)
492 : impl_(new Impl(options))
496 CommandLineHelpWriter::~CommandLineHelpWriter()
500 CommandLineHelpWriter &CommandLineHelpWriter::setShowDescriptions(bool bSet)
502 impl_->bShowDescriptions_ = bSet;
506 CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
508 impl_->timeUnit_ = timeUnit;
512 void CommandLineHelpWriter::writeHelp(const CommandLineHelpContext &context)
514 if (context.isCompletionExport())
516 context.shellCompletionWriter().writeModuleCompletions(
517 context.moduleDisplayName(), impl_->options_);
520 const HelpWriterContext &writerContext = context.writerContext();
522 = (writerContext.outputFormat() == eHelpOutputFormat_Console);
523 CommonFormatterData common(impl_->timeUnit_.c_str());
524 OptionsExportFormatter formatter(common, bConsole);
525 OptionsFilter filter(writerContext, &formatter);
526 filter.setShowHidden(context.showHidden());
528 File &file = writerContext.outputFile();
531 // TODO: Write a proper synopsis, with all the options.
532 writerContext.writeTitle("Synopsis");
533 writerContext.writeTextBlock(context.moduleDisplayName());
534 file.writeLine("\n\n");
537 if (impl_->bShowDescriptions_)
539 filter.formatSelected(OptionsFilter::eSelectDescriptions,
540 impl_->options_, "Description");
542 filter.formatSelected(OptionsFilter::eSelectFileOptions,
543 impl_->options_, "File Options");
544 filter.formatSelected(OptionsFilter::eSelectOtherOptions,
545 impl_->options_, "Options");