Basic support for titles within tool help
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 27 May 2015 10:12:35 +0000 (13:12 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Thu, 4 Jun 2015 03:32:13 +0000 (05:32 +0200)
Preserve reStructuredText title formatting within tool help texts when
printing to console.  For now, manual care is needed to properly nest
the sections in the rst help export (which means that the first
subsection needs to use an underline of ^'s).  This allows removal of
all remaining [BR] tags, improving the HTML help.

Remove extra indentation from gmx wham bullet lists; they result in
unnecessary indentation in the HTML output that looks bad.

Fix formatting of the known issues bullet list by just using the
existing formatting engine, now that bullet lists are properly
supported.

Change-Id: I38a4f442f590515dde724c0cf60f0a862dc9cde7

src/gromacs/commandline/cmdlinehelpwriter.cpp
src/gromacs/gmxana/gmx_anaeig.c
src/gromacs/gmxana/gmx_spatial.c
src/gromacs/gmxana/gmx_wham.cpp
src/gromacs/onlinehelp/helpwritercontext.cpp
src/gromacs/onlinehelp/tests/helpwritercontext.cpp
src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsTitles.xml [new file with mode: 0644]

index 06dfbd53d5b26429b08ae34b887e4a7fbd2cb5d7..788991565a568be7469f4f055d455342f2646cd4 100644 (file)
@@ -629,13 +629,7 @@ void CommandLineHelpWriter::Impl::formatBugs(const HelpWriterContext &context)
     for (i = bugs_.begin(); i != bugs_.end(); ++i)
     {
         const char *const       bug = *i;
-        TextLineWrapperSettings settings;
-        settings.setIndent(2);
-        settings.setFirstLineIndent(0);
-        settings.setLineLength(78);
-        context.outputFile().writeLine(
-                context.substituteMarkupAndWrapToString(
-                        settings, formatString("* %s", bug)));
+        context.writeTextBlock(formatString("* %s", bug));
     }
 }
 
index 102e79f2e0e552aee18d2b18f03c9b1f6f0e034e..9f1ae46c1477189b0b37042259d419c287639b42 100644 (file)
@@ -995,9 +995,11 @@ int gmx_anaeig(int argc, char *argv[])
         "when writing a [REF].pdb[ref] file with two or three structures (you",
         "can use [TT]rasmol -nmrpdb[tt] to view such a [REF].pdb[ref] file).[PAR]",
 
-        "  Overlap calculations between covariance analysis:[BR]",
-        "  [BB]Note:[bb] the analysis should use the same fitting structure[PAR]",
-
+        "Overlap calculations between covariance analysis",
+        "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^",
+        "",
+        "[BB]Note:[bb] the analysis should use the same fitting structure",
+        "",
         "[TT]-over[tt]: calculate the subspace overlap of the eigenvectors in",
         "file [TT]-v2[tt] with eigenvectors [TT]-first[tt] to [TT]-last[tt]",
         "in file [TT]-v[tt].[PAR]",
index 600608d2e322611aba964abde422bf08db57bc9b..beeaf0d0e86b14fdcef437a7f9e86c48d52d8d13 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 2007,2008,2009,2010,2011,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.
@@ -54,43 +54,53 @@ static const double bohr = 0.529177249;  /* conversion factor to compensate for
 int gmx_spatial(int argc, char *argv[])
 {
     const char     *desc[] = {
-        "[THISMODULE] calculates the spatial distribution function and ",
-        "outputs it in a form that can be read by VMD as Gaussian98 cube format. ",
-        "For a system of 32,000 atoms and a 50 ns trajectory, the SDF can be generated ",
-        "in about 30 minutes, with most of the time dedicated to the two runs through ",
-        "[TT]trjconv[tt] that are required to center everything properly. ",
-        "This also takes a whole bunch of space (3 copies of the trajectory file). ",
-        "Still, the pictures are pretty and very informative when the fitted selection is properly made. ",
-        "3-4 atoms in a widely mobile group (like a free amino acid in solution) works ",
-        "well, or select the protein backbone in a stable folded structure to get the SDF ",
-        "of solvent and look at the time-averaged solvation shell. ",
-        "It is also possible using this program to generate the SDF based on some arbitrary ",
-        "Cartesian coordinate. To do that, simply omit the preliminary [gmx-trjconv] steps. \n",
-        "USAGE: \n",
-        "1. Use [gmx-make_ndx] to create a group containing the atoms around which you want the SDF \n",
-        "2. [TT]gmx trjconv -s a.tpr -f a.tng -o b.tng -boxcenter tric -ur compact -pbc none[tt] \n",
-        "3. [TT]gmx trjconv -s a.tpr -f b.tng -o c.tng -fit rot+trans[tt] \n",
-        "4. run [THISMODULE] on the [TT]c.tng[tt] output of step #3. \n",
-        "5. Load [TT]grid.cube[tt] into VMD and view as an isosurface. \n",
-        "[BB]Note[bb] that systems such as micelles will require [TT]gmx trjconv -pbc cluster[tt] between steps 1 and 2\n",
-        "WARNINGS:[BR]",
-        "The SDF will be generated for a cube that contains all bins that have some non-zero occupancy. ",
-        "However, the preparatory [TT]-fit rot+trans[tt] option to [gmx-trjconv] implies that your system will be rotating ",
-        "and translating in space (in order that the selected group does not). Therefore the values that are ",
-        "returned will only be valid for some region around your central group/coordinate that has full overlap ",
-        "with system volume throughout the entire translated/rotated system over the course of the trajectory. ",
-        "It is up to the user to ensure that this is the case. \n",
-        "BUGS:[BR]",
-        "When the allocated memory is not large enough, a segmentation fault may occur. This is usually detected ",
-        "and the program is halted prior to the fault while displaying a warning message suggesting the use of the [TT]-nab[tt] (Number of Additional Bins)",
-        "option. However, the program does not detect all such events. If you encounter a segmentation fault, run it again ",
-        "with an increased [TT]-nab[tt] value. \n",
-        "RISKY OPTIONS:[BR]",
-        "To reduce the amount of space and time required, you can output only the coords ",
-        "that are going to be used in the first and subsequent run through [gmx-trjconv]. ",
-        "However, be sure to set the [TT]-nab[tt] option to a sufficiently high value since ",
-        "memory is allocated for cube bins based on the initial coordinates and the [TT]-nab[tt] ",
-        "option value. \n"
+        "[THISMODULE] calculates the spatial distribution function and",
+        "outputs it in a form that can be read by VMD as Gaussian98 cube format.",
+        "For a system of 32,000 atoms and a 50 ns trajectory, the SDF can be generated",
+        "in about 30 minutes, with most of the time dedicated to the two runs through",
+        "[TT]trjconv[tt] that are required to center everything properly.",
+        "This also takes a whole bunch of space (3 copies of the trajectory file).",
+        "Still, the pictures are pretty and very informative when the fitted selection is properly made.",
+        "3-4 atoms in a widely mobile group (like a free amino acid in solution) works",
+        "well, or select the protein backbone in a stable folded structure to get the SDF",
+        "of solvent and look at the time-averaged solvation shell.",
+        "It is also possible using this program to generate the SDF based on some arbitrary",
+        "Cartesian coordinate. To do that, simply omit the preliminary [gmx-trjconv] steps.",
+        "",
+        "Usage:",
+        "",
+        "1. Use [gmx-make_ndx] to create a group containing the atoms around which you want the SDF",
+        "2. [TT]gmx trjconv -s a.tpr -f a.tng -o b.tng -boxcenter tric -ur compact -pbc none[tt]",
+        "3. [TT]gmx trjconv -s a.tpr -f b.tng -o c.tng -fit rot+trans[tt]",
+        "4. run [THISMODULE] on the [TT]c.tng[tt] output of step #3.",
+        "5. Load [TT]grid.cube[tt] into VMD and view as an isosurface.",
+        "",
+        "[BB]Note[bb] that systems such as micelles will require [TT]gmx trjconv -pbc cluster[tt] between steps 1 and 2.",
+        "",
+        "Warnings",
+        "^^^^^^^^",
+        "",
+        "The SDF will be generated for a cube that contains all bins that have some non-zero occupancy.",
+        "However, the preparatory [TT]-fit rot+trans[tt] option to [gmx-trjconv] implies that your system will be rotating",
+        "and translating in space (in order that the selected group does not). Therefore the values that are",
+        "returned will only be valid for some region around your central group/coordinate that has full overlap",
+        "with system volume throughout the entire translated/rotated system over the course of the trajectory.",
+        "It is up to the user to ensure that this is the case.",
+        "",
+        "Risky options",
+        "^^^^^^^^^^^^^",
+        "",
+        "To reduce the amount of space and time required, you can output only the coords",
+        "that are going to be used in the first and subsequent run through [gmx-trjconv].",
+        "However, be sure to set the [TT]-nab[tt] option to a sufficiently high value since",
+        "memory is allocated for cube bins based on the initial coordinates and the [TT]-nab[tt]",
+        "option value."
+    };
+    const char     *bugs[] = {
+        "When the allocated memory is not large enough, a segmentation fault may occur. This is usually detected "
+        "and the program is halted prior to the fault while displaying a warning message suggesting the use of the [TT]-nab[tt] (Number of Additional Bins) "
+        "option. However, the program does not detect all such events. If you encounter a segmentation fault, run it again "
+        "with an increased [TT]-nab[tt] value."
     };
 
     static gmx_bool bPBC         = FALSE;
@@ -155,7 +165,7 @@ int gmx_spatial(int argc, char *argv[])
     /* This is the routine responsible for adding default options,
      * calling the X/motif interface, etc. */
     if (!parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW,
-                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL, &oenv))
+                           NFILE, fnm, asize(pa), pa, asize(desc), desc, asize(bugs), bugs, &oenv))
     {
         return 0;
     }
index cdcd4bcac2c316fa125a3ca0ce2e6b50e423b68a..9e71686b393f3ebe718940a562df1fcdf617ee9a 100644 (file)
@@ -3222,36 +3222,36 @@ int gmx_wham(int argc, char *argv[])
         "",
         "At present, three input modes are supported.",
         "",
-        " * With option [TT]-it[tt], the user provides a file which contains the",
-        "   file names of the umbrella simulation run-input files ([REF].tpr[ref] files),",
-        "   AND, with option [TT]-ix[tt], a file which contains file names of",
-        "   the pullx [TT]mdrun[tt] output files. The [REF].tpr[ref] and pullx files must",
-        "   be in corresponding order, i.e. the first [REF].tpr[ref] created the",
-        "   first pullx, etc.",
-        " * Same as the previous input mode, except that the the user",
-        "   provides the pull force output file names ([TT]pullf.xvg[tt]) with option [TT]-if[tt].",
-        "   From the pull force the position in the umbrella potential is",
-        "   computed. This does not work with tabulated umbrella potentials.",
-        " * With option [TT]-ip[tt], the user provides file names of (gzipped) [REF].pdo[ref] files, i.e.",
-        "   the GROMACS 3.3 umbrella output files. If you have some unusual"
-        "   reaction coordinate you may also generate your own [REF].pdo[ref] files and",
-        "   feed them with the [TT]-ip[tt] option into to [THISMODULE]. The [REF].pdo[ref] file header",
-        "   must be similar to the following::",
+        "* With option [TT]-it[tt], the user provides a file which contains the",
+        "  file names of the umbrella simulation run-input files ([REF].tpr[ref] files),",
+        "  AND, with option [TT]-ix[tt], a file which contains file names of",
+        "  the pullx [TT]mdrun[tt] output files. The [REF].tpr[ref] and pullx files must",
+        "  be in corresponding order, i.e. the first [REF].tpr[ref] created the",
+        "  first pullx, etc.",
+        "* Same as the previous input mode, except that the the user",
+        "  provides the pull force output file names ([TT]pullf.xvg[tt]) with option [TT]-if[tt].",
+        "  From the pull force the position in the umbrella potential is",
+        "  computed. This does not work with tabulated umbrella potentials.",
+        "* With option [TT]-ip[tt], the user provides file names of (gzipped) [REF].pdo[ref] files, i.e.",
+        "  the GROMACS 3.3 umbrella output files. If you have some unusual"
+        "  reaction coordinate you may also generate your own [REF].pdo[ref] files and",
+        "  feed them with the [TT]-ip[tt] option into to [THISMODULE]. The [REF].pdo[ref] file header",
+        "  must be similar to the following::",
         "",
-        "     # UMBRELLA      3.0",
-        "     # Component selection: 0 0 1",
-        "     # nSkip 1",
-        "     # Ref. Group 'TestAtom'",
-        "     # Nr. of pull groups 2",
-        "     # Group 1 'GR1'  Umb. Pos. 5.0 Umb. Cons. 1000.0",
-        "     # Group 2 'GR2'  Umb. Pos. 2.0 Umb. Cons. 500.0",
-        "     #####",
+        "    # UMBRELLA      3.0",
+        "    # Component selection: 0 0 1",
+        "    # nSkip 1",
+        "    # Ref. Group 'TestAtom'",
+        "    # Nr. of pull groups 2",
+        "    # Group 1 'GR1'  Umb. Pos. 5.0 Umb. Cons. 1000.0",
+        "    # Group 2 'GR2'  Umb. Pos. 2.0 Umb. Cons. 500.0",
+        "    #####",
         "",
-        "   The number of pull groups, umbrella positions, force constants, and names ",
-        "   may (of course) differ. Following the header, a time column and ",
-        "   a data column for each pull group follows (i.e. the displacement",
-        "   with respect to the umbrella center). Up to four pull groups are possible ",
-        "   per [REF].pdo[ref] file at present.",
+        "  The number of pull groups, umbrella positions, force constants, and names ",
+        "  may (of course) differ. Following the header, a time column and ",
+        "  a data column for each pull group follows (i.e. the displacement",
+        "  with respect to the umbrella center). Up to four pull groups are possible ",
+        "  per [REF].pdo[ref] file at present.",
         "",
         "By default, all pull groups found in all pullx/pullf files are used in WHAM. If only ",
         "some of the pull groups should be used, a pull group selection file (option [TT]-is[tt]) can ",
@@ -3267,20 +3267,22 @@ int gmx_wham(int argc, char *argv[])
         "",
         "By default, the output files are",
         "",
-        " * [TT]-o[tt]      PMF output file",
-        " * [TT]-hist[tt]   Histograms output file",
+        "* [TT]-o[tt]      PMF output file",
+        "* [TT]-hist[tt]   Histograms output file",
         "",
         "Always check whether the histograms sufficiently overlap.[PAR]",
         "The umbrella potential is assumed to be harmonic and the force constants are ",
         "read from the [REF].tpr[ref] or [REF].pdo[ref] files. If a non-harmonic umbrella force was applied ",
-        "a tabulated potential can be provided with [TT]-tab[tt].[PAR]",
-        "WHAM OPTIONS[BR]------------[BR]",
+        "a tabulated potential can be provided with [TT]-tab[tt].",
         "",
-        " * [TT]-bins[tt]   Number of bins used in analysis",
-        " * [TT]-temp[tt]   Temperature in the simulations",
-        " * [TT]-tol[tt]    Stop iteration if profile (probability) changed less than tolerance",
-        " * [TT]-auto[tt]   Automatic determination of boundaries",
-        " * [TT]-min,-max[tt]   Boundaries of the profile",
+        "WHAM options",
+        "^^^^^^^^^^^^",
+        "",
+        "* [TT]-bins[tt]   Number of bins used in analysis",
+        "* [TT]-temp[tt]   Temperature in the simulations",
+        "* [TT]-tol[tt]    Stop iteration if profile (probability) changed less than tolerance",
+        "* [TT]-auto[tt]   Automatic determination of boundaries",
+        "* [TT]-min,-max[tt]   Boundaries of the profile",
         "",
         "The data points that are used to compute the profile",
         "can be restricted with options [TT]-b[tt], [TT]-e[tt], and [TT]-dt[tt]. ",
@@ -3297,10 +3299,16 @@ int gmx_wham(int argc, char *argv[])
         "periodicity of the system and generate a periodic PMF. The first and the last bin of the",
         "reaction coordinate will assumed be be neighbors.[PAR]",
         "Option [TT]-sym[tt] symmetrizes the profile around z=0 before output, ",
-        "which may be useful for, e.g. membranes.[PAR]",
-        "PARALLELIZATION[BR]----------------[BR]",
-        "If available, the number of OpenMP threads used by g_wham is controlled with [TT]-nt[tt].[PAR]",
-        "AUTOCORRELATIONS[BR]----------------[BR]",
+        "which may be useful for, e.g. membranes.",
+        "",
+        "Parallelization",
+        "^^^^^^^^^^^^^^^",
+        "",
+        "If available, the number of OpenMP threads used by g_wham is controlled with [TT]-nt[tt].",
+        "",
+        "Autocorrelations",
+        "^^^^^^^^^^^^^^^^",
+        "",
         "With [TT]-ac[tt], [THISMODULE] estimates the integrated autocorrelation ",
         "time (IACT) [GRK]tau[grk] for each umbrella window and weights the respective ",
         "window with 1/[1+2*[GRK]tau[grk]/dt]. The IACTs are written ",
@@ -3315,8 +3323,11 @@ int gmx_wham(int argc, char *argv[])
         "less robust) method such as fitting to a double exponential, you can ",
         "compute the IACTs with [gmx-analyze] and provide them to [THISMODULE] with the file ",
         "[TT]iact-in.dat[tt] (option [TT]-iiact[tt]), which should contain one line per ",
-        "input file ([REF].pdo[ref] or pullx/f file) and one column per pull group in the respective file.[PAR]",
-        "ERROR ANALYSIS[BR]--------------[BR]",
+        "input file ([REF].pdo[ref] or pullx/f file) and one column per pull group in the respective file.",
+        "",
+        "Error analysis",
+        "^^^^^^^^^^^^^^",
+        "",
         "Statistical errors may be estimated with bootstrap analysis. Use it with care, ",
         "otherwise the statistical error may be substantially underestimated. ",
         "More background and examples for the bootstrap technique can be found in ",
@@ -3325,36 +3336,36 @@ int gmx_wham(int argc, char *argv[])
         "Four bootstrapping methods are supported and ",
         "selected with [TT]-bs-method[tt].",
         "",
-        " * [TT]b-hist[tt]   Default: complete histograms are considered as independent ",
-        "   data points, and the bootstrap is carried out by assigning random weights to the ",
-        "   histograms (\"Bayesian bootstrap\"). Note that each point along the reaction coordinate",
-        "   must be covered by multiple independent histograms (e.g. 10 histograms), otherwise the ",
-        "   statistical error is underestimated.",
-        " * [TT]hist[tt]    Complete histograms are considered as independent data points. ",
-        "   For each bootstrap, N histograms are randomly chosen from the N given histograms ",
-        "   (allowing duplication, i.e. sampling with replacement).",
-        "   To avoid gaps without data along the reaction coordinate blocks of histograms ",
-        "   ([TT]-histbs-block[tt]) may be defined. In that case, the given histograms are ",
-        "   divided into blocks and only histograms within each block are mixed. Note that ",
-        "   the histograms within each block must be representative for all possible histograms, ",
-        "   otherwise the statistical error is underestimated.",
-        " * [TT]traj[tt]  The given histograms are used to generate new random trajectories,",
-        "   such that the generated data points are distributed according the given histograms ",
-        "   and properly autocorrelated. The autocorrelation time (ACT) for each window must be ",
-        "   known, so use [TT]-ac[tt] or provide the ACT with [TT]-iiact[tt]. If the ACT of all ",
-        "   windows are identical (and known), you can also provide them with [TT]-bs-tau[tt]. ",
-        "   Note that this method may severely underestimate the error in case of limited sampling, ",
-        "   that is if individual histograms do not represent the complete phase space at ",
-        "   the respective positions.",
-        " * [TT]traj-gauss[tt]  The same as method [TT]traj[tt], but the trajectories are ",
-        "   not bootstrapped from the umbrella histograms but from Gaussians with the average ",
-        "   and width of the umbrella histograms. That method yields similar error estimates ",
-        "   like method [TT]traj[tt].",
+        "* [TT]b-hist[tt]   Default: complete histograms are considered as independent ",
+        "  data points, and the bootstrap is carried out by assigning random weights to the ",
+        "  histograms (\"Bayesian bootstrap\"). Note that each point along the reaction coordinate",
+        "  must be covered by multiple independent histograms (e.g. 10 histograms), otherwise the ",
+        "  statistical error is underestimated.",
+        "* [TT]hist[tt]    Complete histograms are considered as independent data points. ",
+        "  For each bootstrap, N histograms are randomly chosen from the N given histograms ",
+        "  (allowing duplication, i.e. sampling with replacement).",
+        "  To avoid gaps without data along the reaction coordinate blocks of histograms ",
+        "  ([TT]-histbs-block[tt]) may be defined. In that case, the given histograms are ",
+        "  divided into blocks and only histograms within each block are mixed. Note that ",
+        "  the histograms within each block must be representative for all possible histograms, ",
+        "  otherwise the statistical error is underestimated.",
+        "* [TT]traj[tt]  The given histograms are used to generate new random trajectories,",
+        "  such that the generated data points are distributed according the given histograms ",
+        "  and properly autocorrelated. The autocorrelation time (ACT) for each window must be ",
+        "  known, so use [TT]-ac[tt] or provide the ACT with [TT]-iiact[tt]. If the ACT of all ",
+        "  windows are identical (and known), you can also provide them with [TT]-bs-tau[tt]. ",
+        "  Note that this method may severely underestimate the error in case of limited sampling, ",
+        "  that is if individual histograms do not represent the complete phase space at ",
+        "  the respective positions.",
+        "* [TT]traj-gauss[tt]  The same as method [TT]traj[tt], but the trajectories are ",
+        "  not bootstrapped from the umbrella histograms but from Gaussians with the average ",
+        "  and width of the umbrella histograms. That method yields similar error estimates ",
+        "  like method [TT]traj[tt].",
         "",
         "Bootstrapping output:",
         "",
-        " * [TT]-bsres[tt]   Average profile and standard deviations",
-        " * [TT]-bsprof[tt]  All bootstrapping profiles",
+        "* [TT]-bsres[tt]   Average profile and standard deviations",
+        "* [TT]-bsprof[tt]  All bootstrapping profiles",
         "",
         "With [TT]-vbs[tt] (verbose bootstrapping), the histograms of each bootstrap are written, ",
         "and, with bootstrap method [TT]traj[tt], the cumulative distribution functions of ",
index 4b6ad5ab2613adc447b6cb8df68f99ed855f7231..680828df70bc38938f65f5a5c1d67e7a4aaea06e 100644 (file)
@@ -131,7 +131,6 @@ const t_sandr sandrTty[] = {
     { "[TANH]", "tanh(" },
     { "[tanh]", ")" },
     { "[PAR]", "\n\n" },
-    { "[BR]", "\n"},
     { "[GRK]", "" },
     { "[grk]", "" }
 };
@@ -181,8 +180,6 @@ const t_sandr sandrRst[] = {
     { "[TANH]", "tanh(" },
     { "[tanh]", ")" },
     { "[PAR]", "\n\n" },
-    // [BR] is fundamentally incompatible with rst
-    { "[BR]", "\n\n"},
     { "[GRK]", "" },
     { "[grk]", "" }
 };
@@ -410,6 +407,29 @@ bool startsTable(const std::string &text, size_t index)
     return false;
 }
 
+/*! \brief
+ * Returns `true` if a line in \p text starting at \p index is a title underline.
+ *
+ * Does not throw.
+ */
+bool isTitleUnderline(const std::string &text, size_t index)
+{
+    const char firstChar = text[index];
+    if (std::ispunct(firstChar))
+    {
+        while (index < text.length() && text[index] != '\n')
+        {
+            if (text[index] != firstChar)
+            {
+                return false;
+            }
+            ++index;
+        }
+        return true;
+    }
+    return false;
+}
+
 //! \}
 
 }   // namespace
@@ -702,6 +722,16 @@ void HelpWriterContext::Impl::processMarkup(const std::string &text,
                         {
                             bLiteral = true;
                         }
+                        else if (currentLine == 1 && isTitleUnderline(result, i))
+                        {
+                            // TODO: Nicer formatting that shares
+                            // implementation with writeTitle() and honors the
+                            // nesting depths etc.
+                            if (i > 0)
+                            {
+                                paragraph[paragraph.length() - 1] = '\n';
+                            }
+                        }
                         bLineStart = false;
                     }
                     paragraph.push_back(result[i]);
index b1daa1697f4a15b80060bded2bad34d78b0ead3a..1b2c4acf681baa786fe16a37d36551feb203c1ac 100644 (file)
@@ -241,4 +241,22 @@ TEST_F(HelpWriterContextTest, FormatsGridTable)
     testFormatting(text);
 }
 
+TEST_F(HelpWriterContextTest, FormatsTitles)
+{
+    // Console formatting does not currently work without the paragraph breaks
+    // after the title.
+    const char *const text[] = {
+        "Title",
+        "=====",
+        "",
+        "Some text without spacing",
+        "",
+        "Subtitle",
+        "++++++++",
+        "",
+        "More text",
+    };
+    testFormatting(text);
+}
+
 } // namespace
diff --git a/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsTitles.xml b/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsTitles.xml
new file mode 100644 (file)
index 0000000..b5eadeb
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="Console"><![CDATA[
+Title
+=====
+
+Some text without spacing
+
+Subtitle
+++++++++
+
+More text]]></String>
+  <String Name="reStructuredText"><![CDATA[
+Title
+=====
+
+Some text without spacing
+
+Subtitle
+++++++++
+
+More text]]></String>
+</ReferenceData>