3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements gmx::CommandLineHelpWriter.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_commandline
38 #include "cmdlinehelpwriter.h"
42 #include "gromacs/onlinehelp/helpformat.h"
43 #include "gromacs/onlinehelp/helpwritercontext.h"
44 #include "gromacs/options/basicoptioninfo.h"
45 #include "gromacs/options/filenameoptioninfo.h"
46 #include "gromacs/options/options.h"
47 #include "gromacs/options/optionsvisitor.h"
48 #include "gromacs/options/timeunitmanager.h"
49 #include "gromacs/selection/selectionfileoptioninfo.h"
50 #include "gromacs/selection/selectionoptioninfo.h"
51 #include "gromacs/utility/exceptions.h"
52 #include "gromacs/utility/file.h"
53 #include "gromacs/utility/stringutil.h"
61 /********************************************************************
66 * Helper object for writing section descriptions to help.
68 * \ingroup module_commandline
70 class DescriptionWriter : public OptionsVisitor
73 //! Creates a helper object for writing section descriptions.
74 explicit DescriptionWriter(const HelpWriterContext &context)
79 virtual void visitSubSection(const Options §ion);
80 virtual void visitOption(const OptionInfo & /*option*/) { }
83 const HelpWriterContext &context_;
86 void DescriptionWriter::visitSubSection(const Options §ion)
88 if (!section.description().empty())
90 File &file = context_.outputFile();
91 const std::string &title = section.title();
94 file.writeLine(title);
97 context_.writeTextBlock(section.description());
100 OptionsIterator(section).acceptSubSections(this);
104 /********************************************************************
105 * FileParameterWriter
109 * Helper object for writing help for file parameters.
111 * \ingroup module_commandline
113 class FileParameterWriter : public OptionsTypeVisitor<FileNameOptionInfo>
116 //! Creates a helper object for writing file parameters.
117 explicit FileParameterWriter(const HelpWriterContext &context);
119 //! Returns true if anything was written out.
120 bool didOutput() const { return formatter_.didOutput(); }
122 virtual void visitSubSection(const Options §ion);
123 virtual void visitOptionType(const FileNameOptionInfo &option);
126 const HelpWriterContext &context_;
127 TextTableFormatter formatter_;
130 FileParameterWriter::FileParameterWriter(const HelpWriterContext &context)
133 formatter_.addColumn("Option", 6, false);
134 formatter_.addColumn("Filename", 12, false);
135 formatter_.addColumn("Type", 12, false);
136 formatter_.addColumn("Description", 45, true);
139 void FileParameterWriter::visitSubSection(const Options §ion)
141 OptionsIterator iterator(section);
142 iterator.acceptSubSections(this);
143 iterator.acceptOptions(this);
146 void FileParameterWriter::visitOptionType(const FileNameOptionInfo &option)
148 int firstShortValue = 0; // The first value after which the type fits.
149 int firstLongValue = -1; // First value that overlaps description column.
150 int lastLongValue = -1; // Last value like the above.
152 // Get the values to write and check where text overflows the columns.
154 std::string name(formatString("-%s", option.name().c_str()));
155 formatter_.addColumnLine(0, name);
156 for (int i = 0; i < option.valueCount() || i == 0; ++i)
159 if (option.valueCount() == 0
160 || (option.valueCount() == 1 && option.formatValue(0).empty()))
162 value = option.formatDefaultValueIfSet();
166 value = option.formatValue(i);
168 formatter_.addColumnLine(1, value);
169 if (value.length() > 12U && i == firstShortValue)
171 firstShortValue = i + 1;
173 if (value.length() > 25U)
175 if (firstLongValue == -1)
183 if (option.isInputOutputFile())
187 else if (option.isInputFile())
191 else if (option.isOutputFile())
195 if (!option.isRequired())
199 if (option.isLibraryFile())
203 bool bLongType = (type.length() > 12U);
204 formatter_.addColumnLine(2, type);
205 formatter_.addColumnLine(3, context_.substituteMarkup(option.description()));
208 if (name.length() > 6U || firstShortValue > 0)
210 formatter_.setColumnFirstLineOffset(1, 1);
211 // Assume that the name is <20 chars, so that the type fits
212 if (firstLongValue >= 0)
218 int firstDescriptionLine = 0;
221 firstDescriptionLine = 1;
223 formatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
224 if (firstLongValue >= 0 && formatter_.lastColumnLine(3) >= firstLongValue)
226 firstDescriptionLine = lastLongValue + 1;
227 formatter_.setColumnFirstLineOffset(3, firstDescriptionLine);
230 // Do the formatting.
231 context_.outputFile().writeString(formatter_.formatRow());
235 /********************************************************************
240 * Helper object for writing help for non-file parameters.
242 * \ingroup module_commandline
244 class ParameterWriter : public OptionsVisitor
247 //! Creates a helper object for writing non-file parameters.
248 ParameterWriter(const HelpWriterContext &context,
249 const char *timeUnit);
251 //! Sets the writer to show hidden options.
252 void setShowHidden(bool bSet) { bShowHidden_ = bSet; }
253 //! Returns true if anything was written out.
254 bool didOutput() const { return formatter_.didOutput(); }
256 virtual void visitSubSection(const Options §ion);
257 virtual void visitOption(const OptionInfo &option);
260 const HelpWriterContext &context_;
261 TextTableFormatter formatter_;
262 const char *timeUnit_;
266 ParameterWriter::ParameterWriter(const HelpWriterContext &context,
267 const char *timeUnit)
268 : context_(context), timeUnit_(timeUnit), bShowHidden_(false)
270 formatter_.addColumn("Option", 12, false);
271 formatter_.addColumn("Type", 6, false);
272 formatter_.addColumn("Value", 6, false);
273 formatter_.addColumn("Description", 51, true);
276 void ParameterWriter::visitSubSection(const Options §ion)
278 OptionsIterator iterator(section);
279 iterator.acceptSubSections(this);
280 iterator.acceptOptions(this);
283 void ParameterWriter::visitOption(const OptionInfo &option)
285 if (option.isType<FileNameOptionInfo>()
286 || option.isType<SelectionFileOptionInfo>()
287 || option.isType<SelectionOptionInfo>()
288 || (!bShowHidden_ && option.isHidden()))
294 bool bIsBool = option.isType<BooleanOptionInfo>();
295 std::string name(formatString("-%s%s", bIsBool ? "[no]" : "",
296 option.name().c_str()));
297 formatter_.addColumnLine(0, name);
298 formatter_.addColumnLine(1, option.type());
299 if (name.length() > 12U)
301 formatter_.setColumnFirstLineOffset(1, 1);
303 // TODO: Better handling of multiple long values
305 for (int i = 0; i < option.valueCount(); ++i)
311 values.append(option.formatValue(i));
313 formatter_.addColumnLine(2, values);
314 std::string description(context_.substituteMarkup(option.description()));
315 const DoubleOptionInfo *doubleOption = option.toType<DoubleOptionInfo>();
316 if (doubleOption != NULL && doubleOption->isTime())
318 description = replaceAll(description, "%t", timeUnit_);
320 formatter_.addColumnLine(3, description);
321 if (values.length() > 6U)
323 formatter_.setColumnFirstLineOffset(3, 1);
326 context_.outputFile().writeString(formatter_.formatRow());
330 /********************************************************************
331 * SelectionParameterWriter
335 * Helper object for writing help for selection parameters.
337 * \ingroup module_commandline
339 class SelectionParameterWriter : public OptionsVisitor
342 //! Creates a helper object for writing selection parameters.
343 explicit SelectionParameterWriter(const HelpWriterContext &context);
345 //! Returns true if anything was written out.
346 bool didOutput() const { return formatter_.didOutput(); }
348 virtual void visitSubSection(const Options §ion);
349 virtual void visitOption(const OptionInfo &option);
352 const HelpWriterContext &context_;
353 TextTableFormatter formatter_;
356 SelectionParameterWriter::SelectionParameterWriter(const HelpWriterContext &context)
359 formatter_.addColumn("Selection", 10, false);
360 formatter_.addColumn("Description", 67, true);
363 void SelectionParameterWriter::visitSubSection(const Options §ion)
365 OptionsIterator iterator(section);
366 iterator.acceptSubSections(this);
367 iterator.acceptOptions(this);
370 void SelectionParameterWriter::visitOption(const OptionInfo &option)
372 if (!option.isType<SelectionFileOptionInfo>()
373 && !option.isType<SelectionOptionInfo>())
378 File &file = context_.outputFile();
381 std::string name(formatString("-%s", option.name().c_str()));
382 formatter_.addColumnLine(0, name);
383 formatter_.addColumnLine(1, context_.substituteMarkup(option.description()));
384 file.writeString(formatter_.formatRow());
386 // TODO: What to do with selection variables?
387 // They are not printed as values for any option.
388 for (int i = 0; i < option.valueCount(); ++i)
390 std::string value(option.formatValue(i));
392 file.writeLine(formatString(" %s", value.c_str()));
398 /********************************************************************
399 * CommandLineHelpWriter::Impl
403 * Private implementation class for CommandLineHelpWriter.
405 * \ingroup module_commandline
407 class CommandLineHelpWriter::Impl
410 //! Sets the Options object to use for generating help.
411 explicit Impl(const Options &options);
413 //! Options object to use for generating help.
414 const Options &options_;
415 //! Time unit to show in descriptions.
416 std::string timeUnit_;
417 //! Whether to write descriptions to output.
418 bool bShowDescriptions_;
419 //! Whether to write hidden options to output.
423 CommandLineHelpWriter::Impl::Impl(const Options &options)
424 : options_(options), timeUnit_(TimeUnitManager().timeUnitAsString()),
425 bShowDescriptions_(false), bShowHidden_(false)
429 /********************************************************************
430 * CommandLineHelpWriter
433 CommandLineHelpWriter::CommandLineHelpWriter(const Options &options)
434 : impl_(new Impl(options))
438 CommandLineHelpWriter::~CommandLineHelpWriter()
442 CommandLineHelpWriter &CommandLineHelpWriter::setShowHidden(bool bSet)
444 impl_->bShowHidden_ = bSet;
448 CommandLineHelpWriter &CommandLineHelpWriter::setShowDescriptions(bool bSet)
450 impl_->bShowDescriptions_ = bSet;
454 CommandLineHelpWriter &CommandLineHelpWriter::setTimeUnitString(const char *timeUnit)
456 impl_->timeUnit_ = timeUnit;
460 void CommandLineHelpWriter::writeHelp(const HelpWriterContext &context)
462 if (context.outputFormat() != eHelpOutputFormat_Console)
464 // TODO: Implement once the situation with Redmine issue #969 is more
466 GMX_THROW(NotImplementedError(
467 "Command-line help is not implemented for this output format"));
469 File &file = context.outputFile();
470 if (impl_->bShowDescriptions_)
472 file.writeLine("DESCRIPTION");
473 file.writeLine("-----------");
475 DescriptionWriter(context).visitSubSection(impl_->options_);
478 FileParameterWriter writer(context);
479 writer.visitSubSection(impl_->options_);
480 if (writer.didOutput())
486 ParameterWriter writer(context, impl_->timeUnit_.c_str());
487 writer.setShowHidden(impl_->bShowHidden_);
488 writer.visitSubSection(impl_->options_);
489 if (writer.didOutput())
495 SelectionParameterWriter writer(context);
496 writer.visitSubSection(impl_->options_);
497 if (writer.didOutput())