2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013,2014,2015, 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::CommandLineHelpModule.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_commandline
44 #include "cmdlinehelpmodule.h"
49 #include <boost/scoped_ptr.hpp>
51 #include "gromacs/commandline/cmdlinehelpcontext.h"
52 #include "gromacs/commandline/cmdlinehelpwriter.h"
53 #include "gromacs/commandline/cmdlineparser.h"
54 #include "gromacs/onlinehelp/helpformat.h"
55 #include "gromacs/onlinehelp/helpmanager.h"
56 #include "gromacs/onlinehelp/helptopic.h"
57 #include "gromacs/onlinehelp/helpwritercontext.h"
58 #include "gromacs/options/basicoptions.h"
59 #include "gromacs/options/options.h"
60 #include "gromacs/utility/arrayref.h"
61 #include "gromacs/utility/baseversion.h"
62 #include "gromacs/utility/exceptions.h"
63 #include "gromacs/utility/file.h"
64 #include "gromacs/utility/fileredirector.h"
65 #include "gromacs/utility/gmxassert.h"
66 #include "gromacs/utility/programcontext.h"
67 #include "gromacs/utility/stringutil.h"
69 #include "shellcompletions.h"
76 class HelpExportInterface;
80 /********************************************************************
81 * CommandLineHelpModuleImpl declaration
84 class CommandLineHelpModuleImpl
87 CommandLineHelpModuleImpl(const ProgramContextInterface &programContext,
88 const std::string &binaryName,
89 const CommandLineModuleMap &modules,
90 const CommandLineModuleGroupList &groups);
92 void exportHelp(HelpExportInterface *exporter);
94 boost::scoped_ptr<RootHelpTopic> rootTopic_;
95 const ProgramContextInterface &programContext_;
96 std::string binaryName_;
97 const CommandLineModuleMap &modules_;
98 const CommandLineModuleGroupList &groups_;
100 CommandLineHelpContext *context_;
101 const CommandLineModuleInterface *moduleOverride_;
104 FileOutputRedirectorInterface *outputRedirector_;
106 GMX_DISALLOW_COPY_AND_ASSIGN(CommandLineHelpModuleImpl);
112 /********************************************************************
113 * HelpExportInterface
117 * Callbacks for exporting help information for command-line modules.
119 * \ingroup module_commandline
121 class HelpExportInterface
124 //! Shorthand for a list of modules contained in a group.
125 typedef CommandLineModuleGroupData::ModuleList ModuleGroupContents;
127 virtual ~HelpExportInterface() {};
130 * Called once before exporting individual modules.
132 * Can, e.g., open shared output files (e.g., if the output is written
133 * into a single file, or if a separate index is required) and write
136 virtual void startModuleExport() = 0;
138 * Called to export the help for each module.
140 * \param[in] module Module for which the help should be exported.
141 * \param[in] tag Unique tag for the module (gmx-something).
142 * \param[in] displayName Display name for the module (gmx something).
144 virtual void exportModuleHelp(
145 const CommandLineModuleInterface &module,
146 const std::string &tag,
147 const std::string &displayName) = 0;
149 * Called after all modules have been exported.
151 * Can close files opened in startModuleExport(), write footers to them
154 virtual void finishModuleExport() = 0;
157 * Called once before exporting module groups.
159 * Can, e.g., open a single output file for listing all the groups.
161 virtual void startModuleGroupExport() = 0;
163 * Called to export the help for each module group.
165 * \param[in] title Title for the group.
166 * \param[in] modules List of modules in the group.
168 virtual void exportModuleGroup(const char *title,
169 const ModuleGroupContents &modules) = 0;
171 * Called after all module groups have been exported.
173 * Can close files opened in startModuleGroupExport(), write footers to them
176 virtual void finishModuleGroupExport() = 0;
179 * Called to export the help for a top-level topic.
181 * \param[in] topic Topic to export.
183 virtual void exportTopic(const HelpTopicInterface &topic) = 0;
186 /********************************************************************
192 static const char title[];
193 static const char *const text[];
196 // These are used for the gmx.1 man page.
197 // TODO: Do not hardcode them here, but pass them from the outside to make this
198 // code more generic.
199 const char RootHelpText::title[] = "molecular dynamics simulation suite";
200 const char *const RootHelpText::text[] = {
201 "|Gromacs| is a full-featured suite of programs to perform molecular",
202 "dynamics simulations, i.e., to simulate the behavior of systems with",
203 "hundreds to millions of particles using Newtonian equations of motion.",
204 "It is primarily used for research on proteins, lipids, and polymers, but",
205 "can be applied to a wide variety of chemical and biological research",
210 * Help topic that forms the root of the help tree for the help subcommand.
212 * \ingroup module_commandline
214 class RootHelpTopic : public AbstractCompositeHelpTopic
218 * Creates a root help topic.
222 explicit RootHelpTopic(const CommandLineHelpModuleImpl &helpModule)
223 : helpModule_(helpModule)
227 virtual const char *name() const { return helpModule_.binaryName_.c_str(); }
228 virtual const char *title() const { return title_.c_str(); }
230 //! Adds a top-level topic and optionally marks it as exported.
231 void addTopic(HelpTopicPointer topic, bool bExported)
235 exportedTopics_.push_back(topic->name());
237 addSubTopic(move(topic));
239 //! Exports all the top-level topics with the given exporter.
240 void exportHelp(HelpExportInterface *exporter);
242 virtual void writeHelp(const HelpWriterContext &context) const;
245 // unused because of the writeHelp() override
246 virtual std::string helpText() const { return ""; }
248 const CommandLineHelpModuleImpl &helpModule_;
250 std::vector<std::string> exportedTopics_;
252 GMX_DISALLOW_COPY_AND_ASSIGN(RootHelpTopic);
255 void RootHelpTopic::exportHelp(HelpExportInterface *exporter)
257 std::vector<std::string>::const_iterator topicName;
258 for (topicName = exportedTopics_.begin();
259 topicName != exportedTopics_.end();
262 const HelpTopicInterface *topic = findSubTopic(topicName->c_str());
263 GMX_RELEASE_ASSERT(topic != NULL, "Exported help topic no longer found");
264 exporter->exportTopic(*topic);
266 // For now, the title is only set for the export to make it not appear in
267 // console output, which makes things consistent for 'gmx help' and
268 // 'gmx help <command>'.
269 title_ = RootHelpText::title;
270 exporter->exportTopic(*this);
273 void RootHelpTopic::writeHelp(const HelpWriterContext &context) const
276 CommandLineCommonOptionsHolder optionsHolder;
277 boost::scoped_ptr<CommandLineHelpContext> cmdlineContext;
278 if (helpModule_.context_ != NULL)
280 cmdlineContext.reset(new CommandLineHelpContext(*helpModule_.context_));
284 cmdlineContext.reset(new CommandLineHelpContext(context));
286 cmdlineContext->setModuleDisplayName(helpModule_.binaryName_);
287 optionsHolder.initOptions();
288 Options &options = *optionsHolder.options();
289 options.setDescription(RootHelpText::text);
290 // TODO: Add <command> [<args>] into the synopsis.
291 CommandLineHelpWriter(options)
292 .setShowDescriptions(context.outputFormat() != eHelpOutputFormat_Console)
293 .writeHelp(*cmdlineContext);
295 if (context.outputFormat() == eHelpOutputFormat_Console)
297 // TODO: Consider printing a list of "core" commands. Would require someone
298 // to determine such a set...
299 writeSubTopicList(context,
300 "Additional help is available on the following topics:");
301 // TODO: Make these respect the binary name passed in, to make tests work better.
302 context.writeTextBlock("To access the help, use '[PROGRAM] help <topic>'.");
303 context.writeTextBlock("For help on a command, use '[PROGRAM] help <command>'.");
307 // TODO: This should not really end up on the HTML page.
308 context.writeTitle(formatString("%s commands", helpModule_.binaryName_.c_str()));
309 context.writeTextBlock(
310 "The following commands are available. Please refer to their "
311 "individual man pages or [TT][PROGRAM] help <command>[tt] "
312 "for further details.");
313 context.writeTextBlock("");
314 context.writeTextBlock(".. include:: /fragments/bytopic-man.rst");
318 /********************************************************************
323 * Help topic for listing the commands.
325 * \ingroup module_commandline
327 class CommandsHelpTopic : public HelpTopicInterface
331 * Creates a command list help topic.
333 * \param[in] helpModule Help module to get module information from.
337 explicit CommandsHelpTopic(const CommandLineHelpModuleImpl &helpModule)
338 : helpModule_(helpModule)
342 virtual const char *name() const { return "commands"; }
343 virtual const char *title() const { return "List of available commands"; }
344 virtual bool hasSubTopics() const { return false; }
345 virtual const HelpTopicInterface *findSubTopic(const char * /*name*/) const
350 virtual void writeHelp(const HelpWriterContext &context) const;
353 const CommandLineHelpModuleImpl &helpModule_;
355 GMX_DISALLOW_COPY_AND_ASSIGN(CommandsHelpTopic);
358 void CommandsHelpTopic::writeHelp(const HelpWriterContext &context) const
360 if (context.outputFormat() != eHelpOutputFormat_Console)
362 GMX_THROW(NotImplementedError(
363 "Module list is not implemented for this output format"));
365 int maxNameLength = 0;
366 const CommandLineModuleMap &modules = helpModule_.modules_;
367 CommandLineModuleMap::const_iterator module;
368 for (module = modules.begin(); module != modules.end(); ++module)
370 int nameLength = static_cast<int>(module->first.length());
371 if (module->second->shortDescription() != NULL
372 && nameLength > maxNameLength)
374 maxNameLength = nameLength;
377 context.writeTextBlock(
378 "Usage: [PROGRAM] [<options>] <command> [<args>][PAR]"
379 "Available commands:");
380 File &file = context.outputFile();
381 TextTableFormatter formatter;
382 formatter.addColumn(NULL, maxNameLength + 1, false);
383 formatter.addColumn(NULL, 72 - maxNameLength, true);
384 formatter.setFirstColumnIndent(4);
385 for (module = modules.begin(); module != modules.end(); ++module)
387 const char *name = module->first.c_str();
388 const char *description = module->second->shortDescription();
389 if (description != NULL)
392 formatter.addColumnLine(0, name);
393 formatter.addColumnLine(1, description);
394 file.writeString(formatter.formatRow());
397 context.writeTextBlock(
398 "For help on a command, use '[PROGRAM] help <command>'.");
401 /********************************************************************
406 * Help topic wrapper for a command-line module.
408 * This class implements HelpTopicInterface such that it wraps a
409 * CommandLineModuleInterface, allowing subcommand "help <command>"
410 * to produce the help for "<command>".
412 * \ingroup module_commandline
414 class ModuleHelpTopic : public HelpTopicInterface
417 //! Constructs a help topic for a specific module.
418 ModuleHelpTopic(const CommandLineModuleInterface &module,
419 const CommandLineHelpModuleImpl &helpModule)
420 : module_(module), helpModule_(helpModule)
424 virtual const char *name() const { return module_.name(); }
425 virtual const char *title() const { return NULL; }
426 virtual bool hasSubTopics() const { return false; }
427 virtual const HelpTopicInterface *findSubTopic(const char * /*name*/) const
431 virtual void writeHelp(const HelpWriterContext &context) const;
434 const CommandLineModuleInterface &module_;
435 const CommandLineHelpModuleImpl &helpModule_;
437 GMX_DISALLOW_COPY_AND_ASSIGN(ModuleHelpTopic);
440 void ModuleHelpTopic::writeHelp(const HelpWriterContext & /*context*/) const
442 CommandLineHelpContext context(*helpModule_.context_);
443 const char *const program = helpModule_.binaryName_.c_str();
444 context.setModuleDisplayName(formatString("%s %s", program, module_.name()));
445 module_.writeHelp(context);
448 /********************************************************************
449 * HelpExportReStructuredText
453 * Adds hyperlinks to modules within this binary.
455 * \param[in,out] links Links are added here.
456 * \param[in] helpModule Help module to get module information from.
457 * \throws std::bad_alloc if out of memory.
459 * Initializes a HelpLinks object with links to modules defined in
462 * \ingroup module_commandline
464 void initProgramLinks(HelpLinks *links, const CommandLineHelpModuleImpl &helpModule)
466 const char *const program = helpModule.binaryName_.c_str();
467 CommandLineModuleMap::const_iterator module;
468 for (module = helpModule.modules_.begin();
469 module != helpModule.modules_.end();
472 if (module->second->shortDescription() != NULL)
474 std::string linkName("[gmx-" + module->first + "]");
475 const char *name = module->first.c_str();
476 std::string reference(
477 formatString(":doc:`%s %s <%s-%s>`", program, name, program, name));
478 std::string displayName(
479 formatString("[TT]%s %s[tt]", program, name));
480 links->addLink(linkName, reference, displayName);
486 * Implements export for web pages as reStructuredText.
488 * \ingroup module_commandline
490 class HelpExportReStructuredText : public HelpExportInterface
493 //! Initializes reST exporter.
494 explicit HelpExportReStructuredText(
495 const CommandLineHelpModuleImpl &helpModule);
497 virtual void startModuleExport();
498 virtual void exportModuleHelp(
499 const CommandLineModuleInterface &module,
500 const std::string &tag,
501 const std::string &displayName);
502 virtual void finishModuleExport();
504 virtual void startModuleGroupExport();
505 virtual void exportModuleGroup(const char *title,
506 const ModuleGroupContents &modules);
507 virtual void finishModuleGroupExport();
509 virtual void exportTopic(const HelpTopicInterface &topic);
512 FileOutputRedirectorInterface *outputRedirector_;
513 const std::string &binaryName_;
515 boost::scoped_ptr<File> indexFile_;
516 boost::scoped_ptr<File> manPagesFile_;
519 HelpExportReStructuredText::HelpExportReStructuredText(
520 const CommandLineHelpModuleImpl &helpModule)
521 : outputRedirector_(helpModule.outputRedirector_),
522 binaryName_(helpModule.binaryName_),
523 links_(eHelpOutputFormat_Rst)
525 File linksFile("links.dat", "r");
527 while (linksFile.readLine(&line))
529 links_.addLink("[REF]." + line + "[ref]",
530 formatString(":ref:`.%s <%s>`", line.c_str(), line.c_str()),
532 links_.addLink("[REF]" + line + "[ref]", formatString(":ref:`%s`", line.c_str()), line);
535 initProgramLinks(&links_, helpModule);
538 void HelpExportReStructuredText::startModuleExport()
541 new File(outputRedirector_->openFileForWriting("fragments/byname.rst")));
542 indexFile_->writeLine(formatString("* :doc:`%s </onlinehelp/%s>` - %s",
543 binaryName_.c_str(), binaryName_.c_str(),
544 RootHelpText::title));
546 new File(outputRedirector_->openFileForWriting("conf-man.py")));
547 manPagesFile_->writeLine("man_pages = [");
550 void HelpExportReStructuredText::exportModuleHelp(
551 const CommandLineModuleInterface &module,
552 const std::string &tag,
553 const std::string &displayName)
555 // TODO: Ideally, the file would only be touched if it really changes.
556 // This would make Sphinx reruns much faster.
557 File file(outputRedirector_->openFileForWriting("onlinehelp/" + tag + ".rst"));
558 file.writeLine(formatString(".. _%s:", displayName.c_str()));
559 if (0 == displayName.compare(binaryName_ + " mdrun"))
561 // Make an extra link target for the convenience of
562 // MPI-specific documentation
563 file.writeLine(".. _mdrun_mpi:");
567 CommandLineHelpContext context(&file, eHelpOutputFormat_Rst, &links_);
568 context.enterSubSection(displayName);
569 context.setModuleDisplayName(displayName);
570 module.writeHelp(context);
573 file.writeLine(".. only:: man");
575 file.writeLine(" See also");
576 file.writeLine(" --------");
578 file.writeLine(formatString(" :manpage:`%s(1)`", binaryName_.c_str()));
580 file.writeLine(" More information about |Gromacs| is available at <http://www.gromacs.org/>.");
583 indexFile_->writeLine(formatString("* :doc:`%s </onlinehelp/%s>` - %s",
584 displayName.c_str(), tag.c_str(),
585 module.shortDescription()));
586 manPagesFile_->writeLine(
587 formatString(" ('programs/%s', '%s', \"%s\", '', 1),",
588 tag.c_str(), tag.c_str(), module.shortDescription()));
591 void HelpExportReStructuredText::finishModuleExport()
596 manPagesFile_->writeLine(
597 formatString(" ('programs/%s', '%s', '%s', '', 1)",
598 binaryName_.c_str(), binaryName_.c_str(),
599 RootHelpText::title));
600 manPagesFile_->writeLine("]");
601 manPagesFile_->close();
602 manPagesFile_.reset();
605 void HelpExportReStructuredText::startModuleGroupExport()
608 new File(outputRedirector_->openFileForWriting("fragments/bytopic.rst")));
610 new File(outputRedirector_->openFileForWriting("fragments/bytopic-man.rst")));
613 void HelpExportReStructuredText::exportModuleGroup(
615 const ModuleGroupContents &modules)
617 indexFile_->writeLine(title);
618 indexFile_->writeLine(std::string(std::strlen(title), '^'));
619 manPagesFile_->writeLine(title);
620 manPagesFile_->writeLine(std::string(std::strlen(title), '^'));
622 ModuleGroupContents::const_iterator module;
623 for (module = modules.begin(); module != modules.end(); ++module)
625 const std::string &tag(module->first);
626 std::string displayName(tag);
627 // TODO: This does not work if the binary name would contain a dash,
628 // but that is not currently the case.
629 const size_t dashPos = displayName.find('-');
630 GMX_RELEASE_ASSERT(dashPos != std::string::npos,
631 "There should always be at least one dash in the tag");
632 displayName[dashPos] = ' ';
633 indexFile_->writeLine(formatString(":doc:`%s </onlinehelp/%s>`\n %s",
634 displayName.c_str(), tag.c_str(),
636 manPagesFile_->writeLine(formatString(":manpage:`%s(1)`\n %s",
640 indexFile_->writeLine();
641 manPagesFile_->writeLine();
644 void HelpExportReStructuredText::finishModuleGroupExport()
648 manPagesFile_->close();
649 manPagesFile_.reset();
652 void HelpExportReStructuredText::exportTopic(const HelpTopicInterface &topic)
654 const std::string path("onlinehelp/" + std::string(topic.name()) + ".rst");
655 File file(outputRedirector_->openFileForWriting(path));
656 HelpWriterContext context(&file, eHelpOutputFormat_Rst, &links_);
657 HelpManager manager(topic, context);
658 manager.writeCurrentTopic();
661 /********************************************************************
662 * HelpExportCompletion
666 * Implements export for command-line completion.
668 * \ingroup module_commandline
670 class HelpExportCompletion : public HelpExportInterface
673 //! Initializes completion exporter.
674 explicit HelpExportCompletion(const CommandLineHelpModuleImpl &helpModule);
676 virtual void startModuleExport();
677 virtual void exportModuleHelp(
678 const CommandLineModuleInterface &module,
679 const std::string &tag,
680 const std::string &displayName);
681 virtual void finishModuleExport();
683 virtual void startModuleGroupExport() {}
684 virtual void exportModuleGroup(const char * /*title*/,
685 const ModuleGroupContents & /*modules*/) {}
686 virtual void finishModuleGroupExport() {}
688 virtual void exportTopic(const HelpTopicInterface & /*topic*/) {}
691 ShellCompletionWriter bashWriter_;
692 std::vector<std::string> modules_;
695 HelpExportCompletion::HelpExportCompletion(
696 const CommandLineHelpModuleImpl &helpModule)
697 : bashWriter_(helpModule.binaryName_, eShellCompletionFormat_Bash)
701 void HelpExportCompletion::startModuleExport()
703 bashWriter_.startCompletions();
706 void HelpExportCompletion::exportModuleHelp(
707 const CommandLineModuleInterface &module,
708 const std::string & /*tag*/,
709 const std::string & /*displayName*/)
711 modules_.push_back(module.name());
713 CommandLineHelpContext context(&bashWriter_);
714 // We use the display name to pass the name of the module to the
715 // completion writer.
716 context.setModuleDisplayName(module.name());
717 module.writeHelp(context);
721 void HelpExportCompletion::finishModuleExport()
723 CommandLineCommonOptionsHolder optionsHolder;
724 optionsHolder.initOptions();
725 bashWriter_.writeWrapperCompletions(modules_, *optionsHolder.options());
726 bashWriter_.finishCompletions();
731 /********************************************************************
732 * CommandLineHelpModuleImpl implementation
735 CommandLineHelpModuleImpl::CommandLineHelpModuleImpl(
736 const ProgramContextInterface &programContext,
737 const std::string &binaryName,
738 const CommandLineModuleMap &modules,
739 const CommandLineModuleGroupList &groups)
740 : rootTopic_(new RootHelpTopic(*this)), programContext_(programContext),
741 binaryName_(binaryName), modules_(modules), groups_(groups),
742 context_(NULL), moduleOverride_(NULL), bHidden_(false),
743 outputRedirector_(&defaultFileOutputRedirector())
747 void CommandLineHelpModuleImpl::exportHelp(HelpExportInterface *exporter)
749 // TODO: Would be nicer to have the file names supplied by the build system
750 // and/or export a list of files from here.
751 const char *const program = binaryName_.c_str();
753 exporter->startModuleExport();
754 CommandLineModuleMap::const_iterator module;
755 for (module = modules_.begin(); module != modules_.end(); ++module)
757 if (module->second->shortDescription() != NULL)
759 const char *const moduleName = module->first.c_str();
760 std::string tag(formatString("%s-%s", program, moduleName));
761 std::string displayName(formatString("%s %s", program, moduleName));
762 exporter->exportModuleHelp(*module->second, tag, displayName);
765 exporter->finishModuleExport();
767 exporter->startModuleGroupExport();
768 CommandLineModuleGroupList::const_iterator group;
769 for (group = groups_.begin(); group != groups_.end(); ++group)
771 exporter->exportModuleGroup((*group)->title(), (*group)->modules());
773 exporter->finishModuleGroupExport();
775 rootTopic_->exportHelp(exporter);
778 /********************************************************************
779 * CommandLineHelpModule
782 CommandLineHelpModule::CommandLineHelpModule(
783 const ProgramContextInterface &programContext,
784 const std::string &binaryName,
785 const CommandLineModuleMap &modules,
786 const CommandLineModuleGroupList &groups)
787 : impl_(new Impl(programContext, binaryName, modules, groups))
791 CommandLineHelpModule::~CommandLineHelpModule()
795 HelpTopicPointer CommandLineHelpModule::createModuleHelpTopic(
796 const CommandLineModuleInterface &module) const
798 return HelpTopicPointer(new ModuleHelpTopic(module, *impl_));
801 void CommandLineHelpModule::addTopic(HelpTopicPointer topic, bool bExported)
803 impl_->rootTopic_->addTopic(move(topic), bExported);
806 void CommandLineHelpModule::setShowHidden(bool bHidden)
808 impl_->bHidden_ = bHidden;
811 void CommandLineHelpModule::setModuleOverride(
812 const CommandLineModuleInterface &module)
814 impl_->moduleOverride_ = &module;
817 void CommandLineHelpModule::setOutputRedirector(
818 FileOutputRedirectorInterface *output)
820 impl_->outputRedirector_ = output;
823 int CommandLineHelpModule::run(int argc, char *argv[])
825 // Add internal topics lazily here.
826 addTopic(HelpTopicPointer(new CommandsHelpTopic(*impl_)), false);
828 const char *const exportFormats[] = { "rst", "completion" };
829 std::string exportFormat;
830 Options options(NULL, NULL);
831 options.addOption(StringOption("export").store(&exportFormat)
832 .enumValue(exportFormats));
833 CommandLineParser(&options).parse(&argc, argv);
834 if (!exportFormat.empty())
836 boost::scoped_ptr<HelpExportInterface> exporter;
837 if (exportFormat == "rst")
839 exporter.reset(new HelpExportReStructuredText(*impl_));
841 else if (exportFormat == "completion")
843 exporter.reset(new HelpExportCompletion(*impl_));
847 GMX_THROW(NotImplementedError("This help format is not implemented"));
849 impl_->exportHelp(exporter.get());
853 File &outputFile = impl_->outputRedirector_->standardOutput();
854 HelpLinks links(eHelpOutputFormat_Console);
855 initProgramLinks(&links, *impl_);
856 CommandLineHelpContext context(&outputFile, eHelpOutputFormat_Console, &links);
857 context.setShowHidden(impl_->bHidden_);
858 if (impl_->moduleOverride_ != NULL)
860 context.setModuleDisplayName(impl_->programContext_.displayName());
861 impl_->moduleOverride_->writeHelp(context);
864 impl_->context_ = &context;
866 HelpManager helpManager(*impl_->rootTopic_, context.writerContext());
869 for (int i = 1; i < argc; ++i)
871 helpManager.enterTopic(argv[i]);
874 catch (const InvalidInputError &ex)
876 fprintf(stderr, "%s\n", ex.what());
879 helpManager.writeCurrentTopic();
883 void CommandLineHelpModule::writeHelp(const CommandLineHelpContext &context) const
885 const HelpWriterContext &writerContext = context.writerContext();
887 if (writerContext.outputFormat() != eHelpOutputFormat_Console)
891 writerContext.writeTextBlock(
892 "Usage: [PROGRAM] help [<command>|<topic> [<subtopic> [...]]]");
893 // TODO: More information.