Add subsection depth to HelpWriterContext
authorTeemu Murtola <teemu.murtola@gmail.com>
Sun, 17 May 2015 18:27:17 +0000 (21:27 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Fri, 22 May 2015 03:03:23 +0000 (05:03 +0200)
Necessary for exporting, e.g., the selection help as rst (#679), and
cleans up the code by making more output go through HelpWriterContext
instead of directly writing to the output file.

Also, reorganize the way help topic titles are written: HelpManager is
now responsible for writing out the title for a topic.  This makes
things behave the same as with HelpWriterContext::createSubSection().

Change-Id: If7e0ee6d4c9dd313e1523fa457f64cf3c4f891f9

src/gromacs/commandline/cmdlinehelpcontext.cpp
src/gromacs/commandline/cmdlinehelpcontext.h
src/gromacs/commandline/cmdlinehelpmodule.cpp
src/gromacs/onlinehelp/helpmanager.cpp
src/gromacs/onlinehelp/helptopic.cpp
src/gromacs/onlinehelp/helptopic.h
src/gromacs/onlinehelp/helpwritercontext.cpp
src/gromacs/onlinehelp/helpwritercontext.h
src/gromacs/selection/selhelp.cpp

index e98997e5bf0aef0b68d44cc85f11d56bb82fcc2a..d18951146a7dbe98dc4c34385be6dc42f2cce18d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -136,6 +136,11 @@ void CommandLineHelpContext::setShowHidden(bool bHidden)
     impl_->bHidden_ = bHidden;
 }
 
+void CommandLineHelpContext::enterSubSection(const std::string &title)
+{
+    impl_->writerContext_.enterSubSection(title);
+}
+
 const HelpWriterContext &CommandLineHelpContext::writerContext() const
 {
     return impl_->writerContext_;
index f682e2206041db327ab38cc013d5e2e3ed54179c..e5e48e003c448530b5fec3ef0ba18c31686367fd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -94,6 +94,8 @@ class CommandLineHelpContext
         void setModuleDisplayName(const std::string &name);
         //! Sets whether hidden options should be shown in help output.
         void setShowHidden(bool bHidden);
+        //! \copydoc HelpWriterContext::enterSubSection()
+        void enterSubSection(const std::string &title);
 
         //! Returns the lower-level context for writing the help.
         const HelpWriterContext &writerContext() const;
index 17233eba548cdb64ba051179f94541742c33bb82..cbd5115d7e3292a2dda84bf115b744d0f102ec7e 100644 (file)
@@ -487,9 +487,9 @@ void HelpExportReStructuredText::exportModuleHelp(
         file.writeLine(".. _mdrun_mpi:");
     }
     file.writeLine();
-    file.writeLine(displayName);
-    file.writeLine(std::string(displayName.length(), '='));
+
     CommandLineHelpContext context(&file, eHelpOutputFormat_Rst, &links_);
+    context.enterSubSection(displayName);
     context.setModuleDisplayName(displayName);
     module.writeHelp(context);
 
index 45193dcd5115c697cec4b0bb49d3cbf0bab71d39..89cb7cc811c0f916505b13fc7d0b089f497562a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2014, by the GROMACS development team, led by
+ * Copyright (c) 2012,2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -47,6 +47,7 @@
 #include <vector>
 
 #include "gromacs/onlinehelp/helptopicinterface.h"
+#include "gromacs/onlinehelp/helpwritercontext.h"
 #include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/stringutil.h"
 
@@ -160,7 +161,10 @@ void HelpManager::enterTopic(const std::string &name)
 void HelpManager::writeCurrentTopic() const
 {
     const HelpTopicInterface &topic = impl_->currentTopic();
-    topic.writeHelp(impl_->rootContext_);
+    const char               *title = topic.title();
+    HelpWriterContext         context(impl_->rootContext_);
+    context.enterSubSection(title != NULL ? title : "");
+    topic.writeHelp(context);
 }
 
 } // namespace gmx
index 8bcaa6ac9443c44fadd5d74544de1e7990559583..1cf1585187ef3837339d3feb0562c1026780b584 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2012,2013,2014,2015, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 namespace gmx
 {
 
-/*! \cond libapi */
-void writeBasicHelpTopic(const HelpWriterContext  &context,
-                         const HelpTopicInterface &topic,
-                         const std::string        &text)
-{
-    const char *title = topic.title();
-    if (title != NULL && title[0] != '\0')
-    {
-        context.writeTitle(title);
-    }
-    context.writeTextBlock(text);
-}
-//! \endcond
-
 /********************************************************************
  * AbstractSimpleHelpTopic
  */
@@ -87,7 +73,7 @@ AbstractSimpleHelpTopic::findSubTopic(const char * /* name */) const
 
 void AbstractSimpleHelpTopic::writeHelp(const HelpWriterContext &context) const
 {
-    writeBasicHelpTopic(context, *this, helpText());
+    context.writeTextBlock(helpText());
 }
 
 /********************************************************************
@@ -144,7 +130,7 @@ AbstractCompositeHelpTopic::findSubTopic(const char *name) const
 
 void AbstractCompositeHelpTopic::writeHelp(const HelpWriterContext &context) const
 {
-    writeBasicHelpTopic(context, *this, helpText());
+    context.writeTextBlock(helpText());
     writeSubTopicList(context, "\nAvailable subtopics:");
 }
 
index d6e8293f8848fdf2174ed5ac586ed2377be65e08..3a49e39bd0dc0fd311680f283f272c35070e9ac2 100644 (file)
@@ -34,8 +34,7 @@
  */
 /*! \libinternal \file
  * \brief
- * Declares helper classes and functions for implementing
- * gmx::HelpTopicInterface.
+ * Declares helper classes for implementing gmx::HelpTopicInterface.
  *
  * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \inlibraryapi
 namespace gmx
 {
 
-/*! \cond libapi */
-/*! \libinternal \brief
- * Helper for writing simple help text.
- *
- * \param[in] context Context for writing the help.
- * \param[in] topic   Topic to write the help for (used for title).
- * \param[in] text    Text to write for the topic.
- * \throws    std::bad_alloc if out of memory.
- * \throws    FileIOError on any I/O error.
- *
- * Formats basic help by writing a title (obtained from \p topic), followed by
- * \p text with markup substituted and lines properly wrapped.
- *
- * \inlibraryapi
- */
-void writeBasicHelpTopic(const HelpWriterContext  &context,
-                         const HelpTopicInterface &topic,
-                         const std::string        &text);
-//! \endcond
-
 /*! \libinternal \brief
  * Abstract base class for help topics that have simple text and no subtopics.
  *
  * This class implements subtopic-related methods from HelpTopicInterface such
  * that there are no subtopics.  writeHelp() is also implemented such that it
- * uses writeBasicHelpTopic() to write out the text returned by a new virtual
- * method helpText().
+ * uses HelpTopicContext::writeTextBlock() to write out the text returned by a
+ * new virtual method helpText().
  *
  * \see SimpleHelpTopic
  *
@@ -114,8 +93,9 @@ class AbstractSimpleHelpTopic : public HelpTopicInterface
  * public methods for adding subtopics (as HelpTopicInterface objects).
  * Subtopic-related methods from HelpTopicInterface are implemented to access
  * the internal container.  writeHelp() is also implemented such that it
- * uses writeBasicHelpTopic() to write out the text returned by a new virtual
- * method helpText(), and a list of subtopics is written after the actual text.
+ * uses HelpTopicContext::writeTextBlock() to write out the text returned by a
+ * new virtual method helpText(), and a list of subtopics is written after the
+ * actual text.
  *
  * \see CompositeHelpTopic
  *
index b7bc9c2308e406f8ef40bae13a64221ec62b8e30..4c928e02ab955075938ce4d2c63326176eefbba6 100644 (file)
@@ -66,6 +66,9 @@ namespace
 //! \internal \addtogroup module_onlinehelp
 //! \{
 
+//! Characters used for reStructuredText title underlining.
+const char g_titleChars[] = "=-^*~+#'_.";
+
 struct t_sandr
 {
     const char *search;
@@ -465,9 +468,9 @@ class HelpWriterContext::Impl
         //! Shorthand for a list of markup/other replacements.
         typedef std::vector<ReplaceItem> ReplaceList;
 
-        //! Initializes the context with the given state.
-        explicit Impl(const StatePointer &state)
-            : state_(state)
+        //! Initializes the context with the given state and section depth.
+        Impl(const StatePointer &state, int sectionDepth)
+            : state_(state), sectionDepth_(sectionDepth)
         {
             initDefaultReplacements();
         }
@@ -500,6 +503,8 @@ class HelpWriterContext::Impl
         StatePointer            state_;
         //! List of markup/other replacements.
         ReplaceList             replacements_;
+        //! Number of subsections above this context.
+        int                     sectionDepth_;
 
     private:
         GMX_DISALLOW_ASSIGN(Impl);
@@ -672,13 +677,13 @@ void HelpWriterContext::Impl::processMarkup(const std::string &text,
  */
 
 HelpWriterContext::HelpWriterContext(File *file, HelpOutputFormat format)
-    : impl_(new Impl(Impl::StatePointer(new Impl::SharedState(file, format, NULL))))
+    : impl_(new Impl(Impl::StatePointer(new Impl::SharedState(file, format, NULL)), 0))
 {
 }
 
 HelpWriterContext::HelpWriterContext(File *file, HelpOutputFormat format,
                                      const HelpLinks *links)
-    : impl_(new Impl(Impl::StatePointer(new Impl::SharedState(file, format, links))))
+    : impl_(new Impl(Impl::StatePointer(new Impl::SharedState(file, format, links)), 0))
 {
     if (links != NULL)
     {
@@ -717,6 +722,14 @@ File &HelpWriterContext::outputFile() const
     return impl_->state_->file_;
 }
 
+void HelpWriterContext::enterSubSection(const std::string &title)
+{
+    GMX_RELEASE_ASSERT(impl_->sectionDepth_ - 1 < static_cast<int>(std::strlen(g_titleChars)),
+                       "Too deeply nested subsections");
+    writeTitle(title);
+    ++impl_->sectionDepth_;
+}
+
 std::string
 HelpWriterContext::substituteMarkupAndWrapToString(
         const TextLineWrapperSettings &settings, const std::string &text) const
@@ -737,6 +750,10 @@ HelpWriterContext::substituteMarkupAndWrapToVector(
 
 void HelpWriterContext::writeTitle(const std::string &title) const
 {
+    if (title.empty())
+    {
+        return;
+    }
     File &file = outputFile();
     switch (outputFormat())
     {
@@ -746,7 +763,8 @@ void HelpWriterContext::writeTitle(const std::string &title) const
             break;
         case eHelpOutputFormat_Rst:
             file.writeLine(title);
-            file.writeLine(std::string(title.length(), '-'));
+            file.writeLine(std::string(title.length(),
+                                       g_titleChars[impl_->sectionDepth_]));
             break;
         default:
             GMX_THROW(NotImplementedError(
index 167aa5c6495fae3cf0d74394180e10046f83b875..ed480bb818282d7d55de4ffd99cd7887cba254ff 100644 (file)
@@ -123,9 +123,7 @@ class HelpLinks
  *
  * The state of a context object (excluding the fact that the output file is
  * written to) does not change after initial construction of the object.
- * Copying creates a context object that shares state with the source.
- *
- * TODO: This class will need additional work as part of Redmine issue #969.
+ * Copying creates a context objects that share state with the source.
  *
  * \inlibraryapi
  * \ingroup module_onlinehelp
@@ -186,6 +184,28 @@ class HelpWriterContext
          */
         File &outputFile() const;
 
+        /*! \brief
+         * Creates a subsection in the output help.
+         *
+         * \param[in] title  Title for the subsection.
+         * \throws    std::bad_alloc if out of memory.
+         * \throws    FileIOError on any I/O error.
+         *
+         * Writes \p title using writeTitle() and makes any further
+         * writeTitle() calls write headings one level deeper.
+         *
+         * Typical use for writing a subsection is to create a copy of the
+         * context for the parent section, and then call enterSubSection() on
+         * the copy.
+         * The whole subsection should be written out using the returned
+         * context before calling any further methods in the parent context.
+         *
+         * This method is only necessary if the subsection will contain further
+         * subsections.  If there is only one level of subsections, it is
+         * possible to use writeTitle() directly.
+         */
+        void enterSubSection(const std::string &title);
+
         /*! \brief
          * Substitutes markup used in help text and wraps lines.
          *
index 2bcb6de49d48e86fcb26b32b103ff543e4e2d837..8487fafe69f59d003b334a717ef8c4bed7c8480e 100644 (file)
@@ -587,7 +587,7 @@ void KeywordsHelpTopic::writeHelp(const HelpWriterContext &context) const
     // TODO: The markup here is not really appropriate, and printKeywordList()
     // still prints raw text, but these are waiting for discussion of the
     // markup format in #969.
-    writeBasicHelpTopic(context, *this, helpText());
+    context.writeTextBlock(helpText());
     context.writeTextBlock("");
 
     // Print the list of keywords