#include "gromacs/onlinehelp/helpwritercontext.h"
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/options.h"
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/baseversion.h"
#include "gromacs/utility/exceptions.h"
-#include "gromacs/utility/file.h"
#include "gromacs/utility/fileredirector.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textreader.h"
+#include "gromacs/utility/textwriter.h"
#include "shellcompletions.h"
const CommandLineModuleMap &modules,
const CommandLineModuleGroupList &groups);
- void exportHelp(HelpExportInterface *exporter) const;
+ void exportHelp(HelpExportInterface *exporter);
boost::scoped_ptr<RootHelpTopic> rootTopic_;
const ProgramContextInterface &programContext_;
struct RootHelpText
{
- static const char name[];
static const char title[];
static const char *const text[];
};
-// The first two are not used.
-const char RootHelpText::name[] = "";
-const char RootHelpText::title[] = "";
-const char *const RootHelpText::text[] = { "" };
+// These are used for the gmx.1 man page.
+// TODO: Do not hardcode them here, but pass them from the outside to make this
+// code more generic.
+const char RootHelpText::title[] = "molecular dynamics simulation suite";
+const char *const RootHelpText::text[] = {
+ "|Gromacs| is a full-featured suite of programs to perform molecular",
+ "dynamics simulations, i.e., to simulate the behavior of systems with",
+ "hundreds to millions of particles using Newtonian equations of motion.",
+ "It is primarily used for research on proteins, lipids, and polymers, but",
+ "can be applied to a wide variety of chemical and biological research",
+ "questions.",
+};
/*! \brief
* Help topic that forms the root of the help tree for the help subcommand.
*
* \ingroup module_commandline
*/
-class RootHelpTopic : public CompositeHelpTopic<RootHelpText>
+class RootHelpTopic : public AbstractCompositeHelpTopic
{
public:
/*! \brief
{
}
+ virtual const char *name() const { return helpModule_.binaryName_.c_str(); }
+ virtual const char *title() const { return title_.c_str(); }
+
//! Adds a top-level topic and optionally marks it as exported.
void addTopic(HelpTopicPointer topic, bool bExported)
{
addSubTopic(move(topic));
}
//! Exports all the top-level topics with the given exporter.
- void exportHelp(HelpExportInterface *exporter) const;
+ void exportHelp(HelpExportInterface *exporter);
virtual void writeHelp(const HelpWriterContext &context) const;
private:
+ // unused because of the writeHelp() override
+ virtual std::string helpText() const { return ""; }
+
const CommandLineHelpModuleImpl &helpModule_;
+ std::string title_;
std::vector<std::string> exportedTopics_;
GMX_DISALLOW_COPY_AND_ASSIGN(RootHelpTopic);
};
-void RootHelpTopic::exportHelp(HelpExportInterface *exporter) const
+void RootHelpTopic::exportHelp(HelpExportInterface *exporter)
{
std::vector<std::string>::const_iterator topicName;
for (topicName = exportedTopics_.begin();
GMX_RELEASE_ASSERT(topic != NULL, "Exported help topic no longer found");
exporter->exportTopic(*topic);
}
+ // For now, the title is only set for the export to make it not appear in
+ // console output, which makes things consistent for 'gmx help' and
+ // 'gmx help <command>'.
+ title_ = RootHelpText::title;
+ exporter->exportTopic(*this);
}
void RootHelpTopic::writeHelp(const HelpWriterContext &context) const
{
- if (context.outputFormat() != eHelpOutputFormat_Console)
{
- // TODO: Implement once the situation with Redmine issue #969 is more
- // clear.
- GMX_THROW(NotImplementedError(
- "Root help is not implemented for this output format"));
- }
- {
- CommandLineCommonOptionsHolder optionsHolder;
- CommandLineHelpContext cmdlineContext(*helpModule_.context_);
- cmdlineContext.setModuleDisplayName(helpModule_.binaryName_);
+ CommandLineCommonOptionsHolder optionsHolder;
+ boost::scoped_ptr<CommandLineHelpContext> cmdlineContext;
+ if (helpModule_.context_ != NULL)
+ {
+ cmdlineContext.reset(new CommandLineHelpContext(*helpModule_.context_));
+ }
+ else
+ {
+ cmdlineContext.reset(new CommandLineHelpContext(context));
+ }
+ cmdlineContext->setModuleDisplayName(helpModule_.binaryName_);
optionsHolder.initOptions();
+ Options &options = *optionsHolder.options();
+ options.setDescription(RootHelpText::text);
// TODO: Add <command> [<args>] into the synopsis.
- CommandLineHelpWriter(*optionsHolder.options())
- .writeHelp(cmdlineContext);
+ CommandLineHelpWriter(options)
+ .setShowDescriptions(context.outputFormat() != eHelpOutputFormat_Console)
+ .writeHelp(*cmdlineContext);
+ }
+ if (context.outputFormat() == eHelpOutputFormat_Console)
+ {
+ // TODO: Consider printing a list of "core" commands. Would require someone
+ // to determine such a set...
+ writeSubTopicList(context,
+ "Additional help is available on the following topics:");
+ context.writeTextBlock("To access the help, use '[PROGRAM] help <topic>'.");
+ context.writeTextBlock("For help on a command, use '[PROGRAM] help <command>'.");
+ }
+ else
+ {
+ // TODO: This should not really end up on the HTML page.
+ context.writeTitle(formatString("%s commands", helpModule_.binaryName_.c_str()));
+ context.writeTextBlock(
+ "The following commands are available. Please refer to their "
+ "individual man pages or [TT][PROGRAM] help <command>[tt] "
+ "for further details.");
+ context.writeTextBlock("");
+ context.writeTextBlock(".. include:: /fragments/bytopic-man.rst");
}
- // TODO: Consider printing a list of "core" commands. Would require someone
- // to determine such a set...
- writeSubTopicList(context,
- "Additional help is available on the following topics:");
- // TODO: Make these respect the binary name passed in, to make tests work better.
- context.writeTextBlock("To access the help, use '[PROGRAM] help <topic>'.");
- context.writeTextBlock("For help on a command, use '[PROGRAM] help <command>'.");
}
/********************************************************************
context.writeTextBlock(
"Usage: [PROGRAM] [<options>] <command> [<args>][PAR]"
"Available commands:");
- File &file = context.outputFile();
+ TextWriter &file = context.outputFile();
TextTableFormatter formatter;
formatter.addColumn(NULL, maxNameLength + 1, false);
formatter.addColumn(NULL, 72 - maxNameLength, true);
private:
FileOutputRedirectorInterface *outputRedirector_;
+ const std::string &binaryName_;
HelpLinks links_;
- boost::scoped_ptr<File> indexFile_;
- boost::scoped_ptr<File> manPagesFile_;
+ boost::scoped_ptr<TextWriter> indexFile_;
+ boost::scoped_ptr<TextWriter> manPagesFile_;
};
HelpExportReStructuredText::HelpExportReStructuredText(
const CommandLineHelpModuleImpl &helpModule)
: outputRedirector_(helpModule.outputRedirector_),
+ binaryName_(helpModule.binaryName_),
links_(eHelpOutputFormat_Rst)
{
- File linksFile("links.dat", "r");
- std::string line;
- while (linksFile.readLine(&line))
+ TextReader linksFile("links.dat");
+ std::string line;
+ while (linksFile.readLineTrimmed(&line))
{
links_.addLink("[REF]." + line + "[ref]",
formatString(":ref:`.%s <%s>`", line.c_str(), line.c_str()),
void HelpExportReStructuredText::startModuleExport()
{
indexFile_.reset(
- new File(outputRedirector_->openFileForWriting("programs/byname.rst")));
- indexFile_->writeLine("Tools by Name");
- indexFile_->writeLine("=============");
+ new TextWriter(
+ outputRedirector_->openTextOutputFile("fragments/byname.rst")));
+ indexFile_->writeLine(formatString("* :doc:`%s </onlinehelp/%s>` - %s",
+ binaryName_.c_str(), binaryName_.c_str(),
+ RootHelpText::title));
manPagesFile_.reset(
- new File(outputRedirector_->openFileForWriting("conf-man.py")));
+ new TextWriter(
+ outputRedirector_->openTextOutputFile("conf-man.py")));
manPagesFile_->writeLine("man_pages = [");
}
{
// TODO: Ideally, the file would only be touched if it really changes.
// This would make Sphinx reruns much faster.
- File file(outputRedirector_->openFileForWriting("programs/" + tag + ".rst"));
- file.writeLine(formatString(".. _%s:", displayName.c_str()));
- if (0 == displayName.compare("gmx mdrun"))
+ TextOutputStreamPointer file
+ = outputRedirector_->openTextOutputFile("onlinehelp/" + tag + ".rst");
+ TextWriter writer(file);
+ writer.writeLine(formatString(".. _%s:", displayName.c_str()));
+ if (0 == displayName.compare(binaryName_ + " mdrun"))
{
// Make an extra link target for the convenience of
// MPI-specific documentation
- file.writeLine(".. _mdrun_mpi:");
+ writer.writeLine(".. _mdrun_mpi:");
}
- file.writeLine();
+ writer.writeLine();
- CommandLineHelpContext context(&file, eHelpOutputFormat_Rst, &links_);
+ CommandLineHelpContext context(file.get(), eHelpOutputFormat_Rst, &links_, binaryName_);
context.enterSubSection(displayName);
context.setModuleDisplayName(displayName);
module.writeHelp(context);
- file.writeLine();
- file.writeLine(".. only:: man");
- file.writeLine();
- file.writeLine(" See also");
- file.writeLine(" --------");
- file.writeLine();
- file.writeLine(" :manpage:`gromacs(7)`");
- file.writeLine();
- file.writeLine(" More information about |Gromacs| is available at <http://www.gromacs.org/>.");
- file.close();
-
- indexFile_->writeLine(formatString("* :doc:`%s <%s>` - %s",
+ writer.writeLine();
+ writer.writeLine(".. only:: man");
+ writer.writeLine();
+ writer.writeLine(" See also");
+ writer.writeLine(" --------");
+ writer.writeLine();
+ writer.writeLine(formatString(" :manpage:`%s(1)`", binaryName_.c_str()));
+ writer.writeLine();
+ writer.writeLine(" More information about |Gromacs| is available at <http://www.gromacs.org/>.");
+ file->close();
+
+ indexFile_->writeLine(formatString("* :doc:`%s </onlinehelp/%s>` - %s",
displayName.c_str(), tag.c_str(),
module.shortDescription()));
manPagesFile_->writeLine(
- formatString(" ('programs/%s', '%s', \"%s\", '', 1),",
+ formatString(" ('onlinehelp/%s', '%s', \"%s\", '', 1),",
tag.c_str(), tag.c_str(), module.shortDescription()));
}
{
indexFile_->close();
indexFile_.reset();
- manPagesFile_->writeLine(" ('man/gromacs.7', 'gromacs', 'molecular dynamics simulation suite', '', 7)");
+ // TODO: Generalize.
+ manPagesFile_->writeLine(
+ formatString(" ('onlinehelp/%s', '%s', '%s', '', 1)",
+ binaryName_.c_str(), binaryName_.c_str(),
+ RootHelpText::title));
manPagesFile_->writeLine("]");
manPagesFile_->close();
manPagesFile_.reset();
void HelpExportReStructuredText::startModuleGroupExport()
{
indexFile_.reset(
- new File(outputRedirector_->openFileForWriting("programs/bytopic.rst")));
- indexFile_->writeLine("Tools by Topic");
- indexFile_->writeLine("==============");
+ new TextWriter(
+ outputRedirector_->openTextOutputFile("fragments/bytopic.rst")));
manPagesFile_.reset(
- new File(outputRedirector_->openFileForWriting("man/bytopic.rst")));
+ new TextWriter(
+ outputRedirector_->openTextOutputFile("fragments/bytopic-man.rst")));
}
void HelpExportReStructuredText::exportModuleGroup(
const ModuleGroupContents &modules)
{
indexFile_->writeLine(title);
- indexFile_->writeLine(std::string(std::strlen(title), '-'));
+ indexFile_->writeLine(std::string(std::strlen(title), '^'));
manPagesFile_->writeLine(title);
- manPagesFile_->writeLine(std::string(std::strlen(title), '+'));
+ manPagesFile_->writeLine(std::string(std::strlen(title), '^'));
ModuleGroupContents::const_iterator module;
for (module = modules.begin(); module != modules.end(); ++module)
GMX_RELEASE_ASSERT(dashPos != std::string::npos,
"There should always be at least one dash in the tag");
displayName[dashPos] = ' ';
- indexFile_->writeLine(formatString("| :doc:`%s <%s>` - %s",
+ indexFile_->writeLine(formatString(":doc:`%s </onlinehelp/%s>`\n %s",
displayName.c_str(), tag.c_str(),
module->second));
- manPagesFile_->writeLine(formatString("| ``%s`` - %s",
- displayName.c_str(),
+ manPagesFile_->writeLine(formatString(":manpage:`%s(1)`\n %s",
+ tag.c_str(),
module->second));
}
indexFile_->writeLine();
void HelpExportReStructuredText::exportTopic(const HelpTopicInterface &topic)
{
- const std::string path("programs/" + std::string(topic.name()) + ".rst");
- File file(outputRedirector_->openFileForWriting(path));
- HelpWriterContext context(&file, eHelpOutputFormat_Rst, &links_);
- HelpManager manager(topic, context);
+ const std::string path("onlinehelp/" + std::string(topic.name()) + ".rst");
+ TextOutputStreamPointer file(outputRedirector_->openTextOutputFile(path));
+ CommandLineHelpContext context(file.get(), eHelpOutputFormat_Rst, &links_,
+ binaryName_);
+ HelpManager manager(topic, context.writerContext());
manager.writeCurrentTopic();
+ file->close();
}
/********************************************************************
{
}
-void CommandLineHelpModuleImpl::exportHelp(HelpExportInterface *exporter) const
+void CommandLineHelpModuleImpl::exportHelp(HelpExportInterface *exporter)
{
// TODO: Would be nicer to have the file names supplied by the build system
// and/or export a list of files from here.
return 0;
}
- File &outputFile = impl_->outputRedirector_->standardOutput();
- HelpLinks links(eHelpOutputFormat_Console);
+ TextOutputStream &outputFile = impl_->outputRedirector_->standardOutput();
+ HelpLinks links(eHelpOutputFormat_Console);
initProgramLinks(&links, *impl_);
- boost::scoped_ptr<CommandLineHelpContext> context(
- new CommandLineHelpContext(&outputFile,
- eHelpOutputFormat_Console, &links));
- context->setShowHidden(impl_->bHidden_);
+ CommandLineHelpContext context(&outputFile, eHelpOutputFormat_Console, &links,
+ impl_->binaryName_);
+ context.setShowHidden(impl_->bHidden_);
if (impl_->moduleOverride_ != NULL)
{
- context->setModuleDisplayName(impl_->programContext_.displayName());
- impl_->moduleOverride_->writeHelp(*context);
+ context.setModuleDisplayName(impl_->programContext_.displayName());
+ impl_->moduleOverride_->writeHelp(context);
return 0;
}
- impl_->context_ = context.get();
+ impl_->context_ = &context;
- HelpManager helpManager(*impl_->rootTopic_, context->writerContext());
+ HelpManager helpManager(*impl_->rootTopic_, context.writerContext());
try
{
for (int i = 1; i < argc; ++i)