Replace some [BR] in help texts with rst literals
authorTeemu Murtola <teemu.murtola@gmail.com>
Mon, 9 Feb 2015 16:08:24 +0000 (18:08 +0200)
committerTeemu Murtola <teemu.murtola@gmail.com>
Fri, 13 Feb 2015 14:39:39 +0000 (15:39 +0100)
[BR] cannot really be implemented in rst, so replace those [BR]
instances that were used to implement literal blocks with rst literal
blocks.  Refactor the help output formatting such that line breaks in
the input string get transfered literally to rst output, and make the
console output aware of the line breaks in the input string so that it
can do wrapping as required.  Fix cases that do not produce valid rst
now that leading whitespaces are no longer stripped.

As a side effect of this change, remaining [BR] instances in the help
are now somewhat uglier in the console output, but that can hopefully be
fixed in the future.  On the other hand, the literal blocks look much
nicer on the html and man pages.

Change-Id: If67106c74f84de04d55a2e8c300949c5a297f909

34 files changed:
src/gromacs/commandline/cmdlinehelpmodule.cpp
src/gromacs/commandline/cmdlinehelpwriter.cpp
src/gromacs/gmxana/gmx_anaeig.c
src/gromacs/gmxana/gmx_analyze.c
src/gromacs/gmxana/gmx_cluster.c
src/gromacs/gmxana/gmx_density.c
src/gromacs/gmxana/gmx_editconf.c
src/gromacs/gmxana/gmx_enemat.c
src/gromacs/gmxana/gmx_energy.c
src/gromacs/gmxana/gmx_hbond.c
src/gromacs/gmxana/gmx_make_edi.c
src/gromacs/gmxana/gmx_nmtraj.c
src/gromacs/gmxana/gmx_order.c
src/gromacs/gmxana/gmx_trjcat.c
src/gromacs/gmxana/gmx_trjconv.c
src/gromacs/gmxana/gmx_wham.cpp
src/gromacs/gmxpreprocess/grompp.c
src/gromacs/onlinehelp/helptopic.h
src/gromacs/onlinehelp/helpwritercontext.cpp
src/gromacs/onlinehelp/tests/CMakeLists.txt
src/gromacs/onlinehelp/tests/helpwritercontext.cpp [new file with mode: 0644]
src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_CleansUpExtraWhitespace.xml [new file with mode: 0644]
src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsLiteralText.xml [new file with mode: 0644]
src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsParagraphs.xml [new file with mode: 0644]
src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsRstStyleParagraphs.xml [new file with mode: 0644]
src/gromacs/options/options.cpp
src/gromacs/selection/selhelp.cpp
src/gromacs/selection/sm_distance.cpp
src/gromacs/selection/sm_merge.cpp
src/gromacs/trajectoryanalysis/modules/sasa.cpp
src/gromacs/utility/stringutil.cpp
src/gromacs/utility/stringutil.h
src/gromacs/utility/tests/refdata/ConcatenateStringsTest_HandlesDifferentStringEndings.xml [deleted file]
src/gromacs/utility/tests/stringutil.cpp

index 78903210dc785edc1955b9d6b7d584e859152ad6..383bdb971ab071ea2549196c4360dff5bddb4721 100644 (file)
@@ -171,9 +171,8 @@ void RootHelpTopic::writeHelp(const HelpWriterContext &context) const
     // 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>'.[BR]"
-            "For help on a command, use '[PROGRAM] help <command>'.");
+    context.writeTextBlock("To access the help, use '[PROGRAM] help <topic>'.");
+    context.writeTextBlock("For help on a command, use '[PROGRAM] help <command>'.");
 }
 
 /********************************************************************
index 85536ba8a01990e3921bb6881d1bf0fbcdd9fde0..06dfbd53d5b26429b08ae34b887e4a7fbd2cb5d7 100644 (file)
@@ -497,6 +497,7 @@ class OptionsListFormatter : public OptionsFormatterInterface
                 if (header_ != NULL)
                 {
                     context_.writeTextBlock(header_);
+                    context_.writeTextBlock("");
                 }
                 context_.writeOptionListStart();
             }
index b6e2e59a2a316ff79a02048e7449ef4f5e820674..102e79f2e0e552aee18d2b18f03c9b1f6f0e034e 100644 (file)
@@ -1009,10 +1009,12 @@ int gmx_anaeig(int argc, char *argv[])
 
         "When [TT]-v[tt], [TT]-eig[tt], [TT]-v2[tt] and [TT]-eig2[tt] are given,",
         "a single number for the overlap between the covariance matrices is",
-        "generated. The formulas are:[BR]",
-        "        difference = sqrt(tr((sqrt(M1) - sqrt(M2))^2))[BR]",
-        "normalized overlap = 1 - difference/sqrt(tr(M1) + tr(M2))[BR]",
-        "     shape overlap = 1 - sqrt(tr((sqrt(M1/tr(M1)) - sqrt(M2/tr(M2)))^2))[BR]",
+        "generated. The formulas are::",
+        "",
+        "         difference = sqrt(tr((sqrt(M1) - sqrt(M2))^2))",
+        " normalized overlap = 1 - difference/sqrt(tr(M1) + tr(M2))",
+        "      shape overlap = 1 - sqrt(tr((sqrt(M1/tr(M1)) - sqrt(M2/tr(M2)))^2))",
+        "",
         "where M1 and M2 are the two covariance matrices and tr is the trace",
         "of a matrix. The numbers are proportional to the overlap of the square",
         "root of the fluctuations. The normalized overlap is the most useful",
index e02ce3650f1fd899f9928c201b5f3920179f4b90..02742476b16918e2fb355bccb18601736dd01ccf 100644 (file)
@@ -1032,8 +1032,10 @@ int gmx_analyze(int argc, char *argv[])
         "much shorter than the time scale of the autocorrelation.[PAR]",
 
         "Option [TT]-cc[tt] plots the resemblance of set i with a cosine of",
-        "i/2 periods. The formula is:[BR]"
-        "[MATH]2 ([INT][FROM]0[from][TO]T[to][int] y(t) [COS]i [GRK]pi[grk] t[cos] dt)^2 / [INT][FROM]0[from][TO]T[to][int] y^2(t) dt[math][BR]",
+        "i/2 periods. The formula is::",
+        "",
+        "  [MATH]2 ([INT][FROM]0[from][TO]T[to][int] y(t) [COS]i [GRK]pi[grk] t[cos] dt)^2 / [INT][FROM]0[from][TO]T[to][int] y^2(t) dt[math]",
+        "",
         "This is useful for principal components obtained from covariance",
         "analysis, since the principal components of random diffusion are",
         "pure cosines.[PAR]",
@@ -1057,9 +1059,11 @@ int gmx_analyze(int argc, char *argv[])
         "These errors are plotted as a function of the block size.",
         "Also an analytical block average curve is plotted, assuming",
         "that the autocorrelation is a sum of two exponentials.",
-        "The analytical curve for the block average is:[BR]",
-        "[MATH]f(t) = [GRK]sigma[grk][TT]*[tt][SQRT]2/T (  [GRK]alpha[grk]   ([GRK]tau[grk][SUB]1[sub] (([EXP]-t/[GRK]tau[grk][SUB]1[sub][exp] - 1) [GRK]tau[grk][SUB]1[sub]/t + 1)) +[BR]",
-        "                       (1-[GRK]alpha[grk]) ([GRK]tau[grk][SUB]2[sub] (([EXP]-t/[GRK]tau[grk][SUB]2[sub][exp] - 1) [GRK]tau[grk][SUB]2[sub]/t + 1)))[sqrt][math],[BR]"
+        "The analytical curve for the block average is::",
+        "",
+        "  [MATH]f(t) = [GRK]sigma[grk][TT]*[tt][SQRT]2/T (  [GRK]alpha[grk]   ([GRK]tau[grk][SUB]1[sub] (([EXP]-t/[GRK]tau[grk][SUB]1[sub][exp] - 1) [GRK]tau[grk][SUB]1[sub]/t + 1)) +",
+        "                         (1-[GRK]alpha[grk]) ([GRK]tau[grk][SUB]2[sub] (([EXP]-t/[GRK]tau[grk][SUB]2[sub][exp] - 1) [GRK]tau[grk][SUB]2[sub]/t + 1)))[sqrt][math],",
+        "",
         "where T is the total time.",
         "[GRK]alpha[grk], [GRK]tau[grk][SUB]1[sub] and [GRK]tau[grk][SUB]2[sub] are obtained by fitting f^2(t) to error^2.",
         "When the actual block average is very close to the analytical curve,",
index 25d15e548c7b1fbe98ef8737c9eb83e64feef622..e265d2ca43abb1f6b106d4625ceaf224737b6654 100644 (file)
@@ -1407,7 +1407,7 @@ int gmx_cluster(int argc, char *argv[])
         "for a selected set of clusters (with option [TT]-wcl[tt], depends on",
         "[TT]-nst[tt] and [TT]-rmsmin[tt]). The center of a cluster is the",
         "structure with the smallest average RMSD from all other structures",
-        "of the cluster.[BR]",
+        "of the cluster.",
     };
 
     FILE              *fp, *log;
index 7d30ccce8eabcde7bbbacfca4091deb2ca2bbbfd..ef83a98a784bece17bfb3943fb9cb708c84c6385 100644 (file)
@@ -579,10 +579,12 @@ int gmx_density(int argc, char *argv[])
         "Densities are in kg/m^3, and number densities or electron densities can also be",
         "calculated. For electron densities, a file describing the number of",
         "electrons for each type of atom should be provided using [TT]-ei[tt].",
-        "It should look like:[BR]",
-        "   [TT]2[tt][BR]",
-        "   [TT]atomname = nrelectrons[tt][BR]",
-        "   [TT]atomname = nrelectrons[tt][BR]",
+        "It should look like::",
+        "",
+        "   2",
+        "   atomname = nrelectrons",
+        "   atomname = nrelectrons",
+        "",
         "The first line contains the number of lines to read from the file.",
         "There should be one line for each unique atom name in your system.",
         "The number of electrons for each atom is modified by its atomic",
index eead66b8bf8fe46d61ebade156e97ec29b471e98..76945173633be528722f8e33264e675c70b41eac 100644 (file)
@@ -601,8 +601,10 @@ int gmx_editconf(int argc, char *argv[])
         "to a [REF].pdb[ref] file, which can be useful for analysis with e.g. Rasmol.",
         "[PAR]",
         "To convert a truncated octrahedron file produced by a package which uses",
-        "a cubic box with the corners cut off (such as GROMOS), use:[BR]",
-        "[TT]gmx editconf -f in -rotate 0 45 35.264 -bt o -box veclen -o out[tt][BR]",
+        "a cubic box with the corners cut off (such as GROMOS), use::",
+        "",
+        "  gmx editconf -f in -rotate 0 45 35.264 -bt o -box veclen -o out",
+        "",
         "where [TT]veclen[tt] is the size of the cubic box times [SQRT]3[sqrt]/2."
     };
     const char     *bugs[] =
index 4eacc7347fc7c19de49fb0bf558f086381897565..acd82d595146d35a43bb1c48f5f89ef207f218d4 100644 (file)
@@ -86,10 +86,12 @@ int gmx_enemat(int argc, char *argv[])
         "line a group of atoms to be used. For these groups matrix of",
         "interaction energies will be extracted from the energy file",
         "by looking for energy groups with names corresponding to pairs",
-        "of groups of atoms, e.g. if your [TT]-groups[tt] file contains:[BR]",
-        "[TT]2[tt][BR]",
-        "[TT]Protein[tt][BR]",
-        "[TT]SOL[tt][BR]",
+        "of groups of atoms, e.g. if your [TT]-groups[tt] file contains::",
+        "",
+        "    2",
+        "    Protein",
+        "    SOL",
+        "",
         "then energy groups with names like 'Coul-SR:Protein-SOL' and ",
         "'LJ:Protein-SOL' are expected in the energy file (although",
         "[THISMODULE] is most useful if many groups are analyzed",
index e5c51fd950dc49217fb18150908b3f3d6eeccd1b..89db7f316e087c8d76bd94d86c55b77cd36485d5 100644 (file)
@@ -1915,21 +1915,27 @@ int gmx_energy(int argc, char *argv[])
         "from the [TT]ener.edr[tt] file.[PAR]",
 
         "With [TT]-fee[tt] an estimate is calculated for the free-energy",
-        "difference with an ideal gas state: [BR]",
-        "  [GRK]Delta[grk] A = A(N,V,T) - A[SUB]idealgas[sub](N,V,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln][BR]",
-        "  [GRK]Delta[grk] G = G(N,p,T) - G[SUB]idealgas[sub](N,p,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln][BR]",
+        "difference with an ideal gas state::",
+        "",
+        "  [GRK]Delta[grk] A = A(N,V,T) - A[SUB]idealgas[sub](N,V,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln]",
+        "  [GRK]Delta[grk] G = G(N,p,T) - G[SUB]idealgas[sub](N,p,T) = kT [LN][CHEVRON][EXP]U[SUB]pot[sub]/kT[exp][chevron][ln]",
+        "",
         "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
         "the average is over the ensemble (or time in a trajectory).",
         "Note that this is in principle",
         "only correct when averaging over the whole (Boltzmann) ensemble",
         "and using the potential energy. This also allows for an entropy",
-        "estimate using:[BR]",
-        "  [GRK]Delta[grk] S(N,V,T) = S(N,V,T) - S[SUB]idealgas[sub](N,V,T) = ([CHEVRON]U[SUB]pot[sub][chevron] - [GRK]Delta[grk] A)/T[BR]",
+        "estimate using::",
+        "",
+        "  [GRK]Delta[grk] S(N,V,T) = S(N,V,T) - S[SUB]idealgas[sub](N,V,T) = ([CHEVRON]U[SUB]pot[sub][chevron] - [GRK]Delta[grk] A)/T",
         "  [GRK]Delta[grk] S(N,p,T) = S(N,p,T) - S[SUB]idealgas[sub](N,p,T) = ([CHEVRON]U[SUB]pot[sub][chevron] + pV - [GRK]Delta[grk] G)/T",
-        "[PAR]",
+        "",
 
         "When a second energy file is specified ([TT]-f2[tt]), a free energy",
-        "difference is calculated [BR] dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
+        "difference is calculated::",
+        "",
+        "  dF = -kT [LN][CHEVRON][EXP]-(E[SUB]B[sub]-E[SUB]A[sub])/kT[exp][chevron][SUB]A[sub][ln] ,",
+        "",
         "where E[SUB]A[sub] and E[SUB]B[sub] are the energies from the first and second energy",
         "files, and the average is over the ensemble A. The running average",
         "of the free energy difference is printed to a file specified by [TT]-ravg[tt].",
index be97bc149cec7dd67be9c17a46a1e84f7c10fb93..28c138b47af45651def969609a1a59fa3db61a92 100644 (file)
@@ -3556,13 +3556,13 @@ int gmx_hbond(int argc, char *argv[])
 
         /*    "It is also possible to analyse specific hydrogen bonds with",
               "[TT]-sel[tt]. This index file must contain a group of atom triplets",
-              "Donor Hydrogen Acceptor, in the following way:[PAR]",
-           "[TT]",
-           "[ selected ][BR]",
-           "     20    21    24[BR]",
-           "     25    26    29[BR]",
-           "      1     3     6[BR]",
-           "[tt][BR]",
+              "Donor Hydrogen Acceptor, in the following way::",
+           "",
+           "[ selected ]",
+           "     20    21    24",
+           "     25    26    29",
+           "      1     3     6",
+           "",
            "Note that the triplets need not be on separate lines.",
            "Each atom triplet specifies a hydrogen bond to be analyzed,",
            "note also that no check is made for the types of atoms.[PAR]",
index 093c8fdd3cfcff259930b360d3a2a18621092e66..2564b156dc802ecb1cf70c18773c3ba3ea1f06ed 100644 (file)
@@ -579,14 +579,14 @@ int gmx_make_edi(int argc, char *argv[])
         "to keep the position along a certain (set of) coordinate(s) fixed ([TT]-linfix[tt]),",
         "or to only monitor the projections of the positions onto",
         "these coordinates ([TT]-mon[tt]).[PAR]",
-        "References:[BR]",
+        "References:[PAR]",
         "A. Amadei, A.B.M. Linssen, B.L. de Groot, D.M.F. van Aalten and ",
         "H.J.C. Berendsen; An efficient method for sampling the essential subspace ",
-        "of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[BR]",
+        "of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[PAR]",
         "B.L. de Groot, A. Amadei, D.M.F. van Aalten and H.J.C. Berendsen; ",
         "Towards an exhaustive sampling of the configurational spaces of the ",
         "two forms of the peptide hormone guanylin,",
-        "J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[BR]",
+        "J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[PAR]",
         "B.L. de Groot, A.Amadei, R.M. Scheek, N.A.J. van Nuland and H.J.C. Berendsen; ",
         "An extended sampling of the configurational space of HPr from E. coli",
         "Proteins: Struct. Funct. Gen. 26: 314-322 (1996)",
index 2fbe5cdb1f5ba111e9f4cca0d500fa5696835b89..008e3cc58e16693fd223788d2d5a9dfa18c13ce2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
  * Copyright (c) 2001-2004, The GROMACS development team.
- * 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.
@@ -73,7 +73,7 @@ int gmx_nmtraj(int argc, char *argv[])
         "However, be aware that both the linear Cartesian displacements and mass weighting will ",
         "lead to serious structure deformation for high amplitudes - this is is simply a limitation ",
         "of the Cartesian normal mode model. By default the selected eigenvector is set to 7, since ",
-        " the first six normal modes are the translational and rotational degrees of freedom."
+        "the first six normal modes are the translational and rotational degrees of freedom."
     };
 
     static real        refamplitude = 0.25;
index 2c2bf83c4ab3a2cf2f9c71f863ab9615c09e7078..81323175247e429135131a1f26ae4a2be9789639 100644 (file)
@@ -914,8 +914,7 @@ int gmx_order(int argc, char *argv[])
         "The tetrahedrality order parameters can be determined",
         "around an atom. Both angle an distance order parameters are calculated. See",
         "P.-L. Chau and A.J. Hardwick, Mol. Phys., 93, (1998), 511-518.",
-        "for more details.[BR]",
-        ""
+        "for more details."
     };
 
     static int         nslices       = 1;     /* nr of slices defined       */
index 08bc82fe7f34b901989fecd7fd3f7b7cf58a2054..a651272a226dc4d5ff68fdc86fc150074797cb69 100644 (file)
@@ -427,10 +427,12 @@ int gmx_trjcat(int argc, char *argv[])
         "time since one can only append at the end of a file.[PAR]",
         "If the [TT]-demux[tt] option is given, the N trajectories that are",
         "read, are written in another order as specified in the [REF].xvg[ref] file.",
-        "The [REF].xvg[ref] file should contain something like:[PAR]",
-        "[TT]0  0  1  2  3  4  5[tt][BR]",
-        "[TT]2  1  0  2  3  5  4[tt][BR]",
-        "Where the first number is the time, and subsequent numbers point to",
+        "The [REF].xvg[ref] file should contain something like::",
+        "",
+        "    0  0  1  2  3  4  5",
+        "    2  1  0  2  3  5  4",
+        "",
+        "The first number is the time, and subsequent numbers point to",
         "trajectory indices.",
         "The frames corresponding to the numbers present at the first line",
         "are collected into the output trajectory. If the number of frames in",
index 90fa3a9a612122ca6ad859f5389bfeba7e063ad0..4fa6fd76b6ee00560785bc8ef7ebc9f15fc4650c 100644 (file)
@@ -592,15 +592,14 @@ int gmx_trjconv(int argc, char *argv[])
         "* center atoms in the box[BR]",
         "* fit atoms to reference structure[BR]",
         "* reduce the number of frames[BR]",
-        "* change the timestamps of the frames ",
-        "([TT]-t0[tt] and [TT]-timestep[tt])[BR]",
-        "* cut the trajectory in small subtrajectories according",
+        "* change the timestamps of the frames ([TT]-t0[tt] and [TT]-timestep[tt])[BR]",
+        "[TT]*[tt] cut the trajectory in small subtrajectories according",
         "to information in an index file. This allows subsequent analysis of",
         "the subtrajectories that could, for example, be the result of a",
         "cluster analysis. Use option [TT]-sub[tt].",
         "This assumes that the entries in the index file are frame numbers and",
         "dumps each group in the index file to a separate trajectory file.[BR]",
-        "* select frames within a certain range of a quantity given",
+        "[TT]*[tt] select frames within a certain range of a quantity given",
         "in an [REF].xvg[ref] file.[PAR]",
 
         "[gmx-trjcat] is better suited for concatenating multiple trajectory files.",
index 2e6c0fc27b76fc797136ff9d3baf21017c881092..6110cf64cbb3df79630ea8544a3eaad90eb05989 100644 (file)
@@ -3145,15 +3145,17 @@ int gmx_wham(int argc, char *argv[])
         " 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:[PAR]",
-        "# UMBRELLA      3.0[BR]",
-        "# Component selection: 0 0 1[BR]",
-        "# nSkip 1[BR]",
-        "# Ref. Group 'TestAtom'[BR]",
-        "# Nr. of pull groups 2[BR]",
-        "# Group 1 'GR1'  Umb. Pos. 5.0 Umb. Cons. 1000.0[BR]",
-        "# Group 2 'GR2'  Umb. Pos. 2.0 Umb. Cons. 500.0[BR]",
-        "#####[PAR]",
+        " 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",
+        "    #####",
+        "",
         "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",
@@ -3165,10 +3167,12 @@ int gmx_wham(int argc, char *argv[])
         "Each of these lines must contain one digit (0 or 1) for each pull group in the tpr file. ",
         "Here, 1 indicates that the pull group is used in WHAM, and 0 means it is omitted. Example:",
         "If you have three tpr files, each containing 4 pull groups, but only pull group 1 and 2 should be ",
-        "used, groupsel.dat looks like this:[BR]",
-        "1 1 0 0[BR]",
-        "1 1 0 0[BR]",
-        "1 1 0 0[PAR]",
+        "used, groupsel.dat looks like this::",
+        "",
+        "    1 1 0 0",
+        "    1 1 0 0",
+        "    1 1 0 0",
+        "",
         "By default, the output files are[BR]",
         "  [TT]-o[tt]      PMF output file[BR]",
         "  [TT]-hist[tt]   Histograms output file[BR]",
@@ -3222,12 +3226,12 @@ int gmx_wham(int argc, char *argv[])
         "[TT]-nBootstrap[tt] defines the number of bootstraps (use, e.g., 100). ",
         "Four bootstrapping methods are supported and ",
         "selected with [TT]-bs-method[tt].[BR]",
-        "  (1) [TT]b-hist[tt]   Default: complete histograms are considered as independent ",
+        "(1) [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.[BR]",
-        "  (2) [TT]hist[tt]    Complete histograms are considered as independent data points. ",
+        "(2) [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 ",
@@ -3235,7 +3239,7 @@ int gmx_wham(int argc, char *argv[])
         "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.[BR]",
-        "  (3) [TT]traj[tt]  The given histograms are used to generate new random trajectories,",
+        "(3) [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 ",
@@ -3243,7 +3247,7 @@ int gmx_wham(int argc, char *argv[])
         "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.[BR]",
-        "  (4) [TT]traj-gauss[tt]  The same as method [TT]traj[tt], but the trajectories are ",
+        "(4) [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].[PAR]"
index 9f0efa57986a1796847a92770a3707df409bd7c1..edd40cf3630fc783c08180ead821f6895ae902cb 100644 (file)
@@ -1436,19 +1436,23 @@ int gmx_grompp(int argc, char *argv[])
         "only the atom types are used for generating interaction parameters.[PAR]",
 
         "[THISMODULE] uses a built-in preprocessor to resolve includes, macros, ",
-        "etc. The preprocessor supports the following keywords:[PAR]",
-        "#ifdef VARIABLE[BR]",
-        "#ifndef VARIABLE[BR]",
-        "#else[BR]",
-        "#endif[BR]",
-        "#define VARIABLE[BR]",
-        "#undef VARIABLE[BR]"
-        "#include \"filename\"[BR]",
-        "#include <filename>[PAR]",
+        "etc. The preprocessor supports the following keywords::",
+        "",
+        "    #ifdef VARIABLE",
+        "    #ifndef VARIABLE",
+        "    #else",
+        "    #endif",
+        "    #define VARIABLE",
+        "    #undef VARIABLE",
+        "    #include \"filename\"",
+        "    #include <filename>",
+        "",
         "The functioning of these statements in your topology may be modulated by",
-        "using the following two flags in your [REF].mdp[ref] file:[PAR]",
-        "[TT]define = -DVARIABLE1 -DVARIABLE2[tt][BR]",
-        "[TT]include = -I/home/john/doe[tt][BR]",
+        "using the following two flags in your [REF].mdp[ref] file::",
+        "",
+        "    define = -DVARIABLE1 -DVARIABLE2",
+        "    include = -I/home/john/doe",
+        "",
         "For further information a C-programming textbook may help you out.",
         "Specifying the [TT]-pp[tt] flag will get the pre-processed",
         "topology file written out so that you can verify its contents.[PAR]",
index 86343697ae57ffcb709343c2a927ff8208aaa917..d6e8293f8848fdf2174ed5ac586ed2377be65e08 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.
@@ -255,7 +255,7 @@ class SimpleHelpTopic : public AbstractSimpleHelpTopic
     protected:
         virtual std::string helpText() const
         {
-            return concatenateStrings(HelpText::text);
+            return joinStrings(HelpText::text, "\n");
         }
 };
 
@@ -288,7 +288,7 @@ class CompositeHelpTopic : public AbstractCompositeHelpTopic
     protected:
         virtual std::string helpText() const
         {
-            return concatenateStrings(HelpText::text);
+            return joinStrings(HelpText::text, "\n");
         }
 };
 
index d549ffda7965f194a0bd0613401918f2bfe96066..19eae3db9131034672193166889e64bbe08ca071 100644 (file)
@@ -300,6 +300,45 @@ std::string toUpperCase(const std::string &text)
     return result;
 }
 
+/*! \brief
+ * Removes extra newlines from reStructuredText.
+ *
+ * \param[in] text  Input text.
+ * \returns   \p text with all sequences of more than two newlines replaced
+ *     with just two newlines.
+ *
+ * Does not throw.
+ */
+std::string removeExtraNewlinesRst(const std::string &text)
+{
+    // Start from 2, so that all newlines in the beginning get stripped off.
+    int         newlineCount = 2;
+    std::string result;
+    result.reserve(text.length());
+    for (size_t i = 0; i < text.length(); ++i)
+    {
+        if (text[i] == '\n')
+        {
+            ++newlineCount;
+            if (newlineCount > 2)
+            {
+                continue;
+            }
+        }
+        else
+        {
+            newlineCount = 0;
+        }
+        result.push_back(text[i]);
+    }
+    size_t last = result.find_last_not_of('\n');
+    if (last != std::string::npos)
+    {
+        result.resize(last + 1);
+    }
+    return result;
+}
+
 //! \}
 
 }   // namespace
@@ -502,7 +541,69 @@ void HelpWriterContext::Impl::processMarkup(const std::string &text,
         {
             result = repall(result, sandrTty);
             result = replaceLinks(result);
-            return wrapper->wrap(result);
+            std::string paragraph;
+            paragraph.reserve(result.length());
+            size_t      i        = 0;
+            bool        bFirst   = true;
+            bool        bLiteral = false;
+            while (i < result.length())
+            {
+                while (i < result.length() && result[i] == '\n')
+                {
+                    ++i;
+                }
+                if (i == result.length())
+                {
+                    break;
+                }
+                paragraph.clear();
+                for (; i < result.length(); ++i)
+                {
+                    if (result[i] == '\n')
+                    {
+                        if (i + 1 == result.length() || result[i + 1] == '\n')
+                        {
+                            break;
+                        }
+                        if (!bLiteral)
+                        {
+                            if (!std::isspace(result[i - 1]))
+                            {
+                                paragraph.push_back(' ');
+                            }
+                            continue;
+                        }
+                    }
+                    paragraph.push_back(result[i]);
+                }
+                if (endsWith(paragraph, "::"))
+                {
+                    bLiteral = true;
+                    if (paragraph.length() == 2)
+                    {
+                        continue;
+                    }
+                    if (paragraph[paragraph.length() - 3] == ' ')
+                    {
+                        paragraph.resize(paragraph.length() - 3);
+                    }
+                    else
+                    {
+                        paragraph.resize(paragraph.length() - 1);
+                    }
+                }
+                else
+                {
+                    bLiteral = false;
+                }
+                if (!bFirst)
+                {
+                    wrapper->wrap("\n\n");
+                }
+                wrapper->wrap(paragraph);
+                bFirst = false;
+            }
+            break;
         }
         case eHelpOutputFormat_Rst:
         {
@@ -510,7 +611,9 @@ void HelpWriterContext::Impl::processMarkup(const std::string &text,
             result = replaceLinks(result);
             result = replaceAll(result, "[REF]", "");
             result = replaceAll(result, "[ref]", "");
-            return wrapper->wrap(result);
+            result = removeExtraNewlinesRst(result);
+            wrapper->wrap(result);
+            break;
         }
         default:
             GMX_THROW(InternalError("Invalid help output format"));
index 1e47c92f7b594acfba944f0fb27d7800927d42a8..0d7a3842f8700d6929a57b6e0589991395ec1e0b 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.
@@ -45,4 +45,5 @@ endif()
 gmx_add_unit_test(OnlineHelpUnitTests onlinehelp-test
                   helpformat.cpp
                   helpmanager.cpp
+                  helpwritercontext.cpp
                   $<TARGET_OBJECTS:onlinehelp-test-shared>)
diff --git a/src/gromacs/onlinehelp/tests/helpwritercontext.cpp b/src/gromacs/onlinehelp/tests/helpwritercontext.cpp
new file mode 100644 (file)
index 0000000..184e6e7
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 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.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+/*! \internal \file
+ * \brief
+ * Tests for help text formatting.
+ *
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
+ * \ingroup module_onlinehelp
+ */
+#include "gmxpre.h"
+
+#include "gromacs/onlinehelp/helpwritercontext.h"
+
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/stringutil.h"
+
+#include "testutils/stringtest.h"
+
+namespace
+{
+
+/********************************************************************
+ * Tests for HelpWriterContext
+ */
+
+class HelpWriterContextTest : public gmx::test::StringTestBase
+{
+    public:
+        void testFormatting(const std::string     &text,
+                            gmx::HelpOutputFormat  format,
+                            const char            *id)
+        {
+            gmx::HelpWriterContext context(NULL, format);
+            std::string            result
+                = context.substituteMarkupAndWrapToString(settings_, text);
+            if (id == NULL)
+            {
+                switch (format)
+                {
+                    case gmx::eHelpOutputFormat_Console:
+                        id = "Console";
+                        break;
+                    case gmx::eHelpOutputFormat_Rst:
+                        id = "reStructuredText";
+                        break;
+                    default:
+                        GMX_RELEASE_ASSERT(false, "Help output format testing not implemented");
+                }
+            }
+            checkText(result, id);
+        }
+        void testFormatting(const gmx::ConstArrayRef<const char *> &text)
+        {
+            std::string testText = gmx::joinStrings(text, "\n");
+            testFormatting(testText, gmx::eHelpOutputFormat_Console, NULL);
+            testFormatting(testText, gmx::eHelpOutputFormat_Rst, NULL);
+        }
+
+        gmx::TextLineWrapperSettings settings_;
+};
+
+TEST_F(HelpWriterContextTest, FormatsParagraphs)
+{
+    const char *const text[] = {
+        "A quick",
+        "brown fox",
+        "jumps over a lazy dog.[PAR]",
+        "A quick brown fox",
+        "jumps over",
+        "a lazy dog."
+    };
+    settings_.setLineLength(13);
+    testFormatting(text);
+}
+
+TEST_F(HelpWriterContextTest, FormatsRstStyleParagraphs)
+{
+    const char *const text[] = {
+        "A quick",
+        "brown fox",
+        "jumps over a lazy dog.",
+        "",
+        "A quick brown fox",
+        "jumps over",
+        "a lazy dog."
+    };
+    settings_.setLineLength(13);
+    testFormatting(text);
+}
+
+TEST_F(HelpWriterContextTest, CleansUpExtraWhitespace)
+{
+    const char *const text[] = {
+        "",
+        "A quick ",
+        "brown fox ",
+        "jumps over a lazy dog.",
+        "[PAR]",
+        "A quick brown fox",
+        "jumps over",
+        "a lazy dog.[PAR]"
+    };
+    settings_.setLineLength(13);
+    testFormatting(text);
+}
+
+TEST_F(HelpWriterContextTest, FormatsLiteralText)
+{
+    const char *const text[] = {
+        "Sample paragraph::",
+        "",
+        "    literal block",
+        "    another line",
+        "",
+        "Normal paragraph",
+        "with wrapping"
+    };
+    testFormatting(text);
+}
+
+} // namespace
diff --git a/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_CleansUpExtraWhitespace.xml b/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_CleansUpExtraWhitespace.xml
new file mode 100644 (file)
index 0000000..6122bc0
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="Console"><![CDATA[
+A quick brown
+fox jumps
+over a lazy
+dog.
+
+A quick brown
+fox jumps
+over a lazy
+dog.]]></String>
+  <String Name="reStructuredText"><![CDATA[
+A quick
+brown fox
+jumps over a
+lazy dog.
+
+A quick brown
+fox
+jumps over
+a lazy dog.]]></String>
+</ReferenceData>
diff --git a/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsLiteralText.xml b/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsLiteralText.xml
new file mode 100644 (file)
index 0000000..bee0131
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="Console"><![CDATA[
+Sample paragraph:
+
+    literal block
+    another line
+
+Normal paragraph with wrapping]]></String>
+  <String Name="reStructuredText"><![CDATA[
+Sample paragraph::
+
+    literal block
+    another line
+
+Normal paragraph
+with wrapping]]></String>
+</ReferenceData>
diff --git a/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsParagraphs.xml b/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsParagraphs.xml
new file mode 100644 (file)
index 0000000..6122bc0
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="Console"><![CDATA[
+A quick brown
+fox jumps
+over a lazy
+dog.
+
+A quick brown
+fox jumps
+over a lazy
+dog.]]></String>
+  <String Name="reStructuredText"><![CDATA[
+A quick
+brown fox
+jumps over a
+lazy dog.
+
+A quick brown
+fox
+jumps over
+a lazy dog.]]></String>
+</ReferenceData>
diff --git a/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsRstStyleParagraphs.xml b/src/gromacs/onlinehelp/tests/refdata/HelpWriterContextTest_FormatsRstStyleParagraphs.xml
new file mode 100644 (file)
index 0000000..6122bc0
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="Console"><![CDATA[
+A quick brown
+fox jumps
+over a lazy
+dog.
+
+A quick brown
+fox jumps
+over a lazy
+dog.]]></String>
+  <String Name="reStructuredText"><![CDATA[
+A quick
+brown fox
+jumps over a
+lazy dog.
+
+A quick brown
+fox
+jumps over
+a lazy dog.]]></String>
+</ReferenceData>
index cd6732ec6b99ac4abdef8ebb593baac7e33b28ad..3b587bef104e5c369d3468ac16eb838607bd4e09 100644 (file)
@@ -154,7 +154,7 @@ void Options::setDescription(const std::string &desc)
 
 void Options::setDescription(const ConstArrayRef<const char *> &descArray)
 {
-    impl_->description_ = concatenateStrings(descArray.data(), descArray.size());
+    impl_->description_ = joinStrings(descArray, "\n");
 }
 
 void Options::addManager(OptionManagerInterface *manager)
index ae95feb913d150054787f4b775f13fde250f3186..4171382bbe9d94b4db71b0e54b2ad33bd8525d6a 100644 (file)
@@ -187,11 +187,13 @@ const char *const EvaluationHelpText::text[] = {
     "Another point for optimization is in common subexpressions: they are not",
     "automatically recognized, but can be manually optimized by the use of",
     "variables. This can have a big impact on the performance of complex",
-    "selections, in particular if you define several index groups like this:",
-    "  [TT]rdist = distance from com of resnr 1 to 5;[tt][BR]",
-    "  [TT]resname RES and rdist < 2;[tt][BR]",
-    "  [TT]resname RES and rdist < 4;[tt][BR]",
-    "  [TT]resname RES and rdist < 6;[tt][BR]",
+    "selections, in particular if you define several index groups like this::",
+    "",
+    "  rdist = distance from com of resnr 1 to 5;",
+    "  resname RES and rdist < 2;",
+    "  resname RES and rdist < 4;",
+    "  resname RES and rdist < 6;",
+    "",
     "Without the variable assignment, the distances would be evaluated three",
     "times, although they are exactly the same within each selection.",
     "Anything assigned into a variable becomes a common subexpression that",
@@ -217,32 +219,39 @@ const char *const ExamplesHelpText::text[] = {
     // tools and explain what the selections do in those tools.
     "Below, examples of increasingly complex selections are given.[PAR]",
 
-    "Selection of all water oxygens:[BR]",
+    "Selection of all water oxygens::",
+    "",
     "  resname SOL and name OW",
-    "[PAR]",
+    "",
 
-    "Centers of mass of residues 1 to 5 and 10:[BR]",
+    "Centers of mass of residues 1 to 5 and 10::",
+    ""
     "  res_com of resnr 1 to 5 10",
-    "[PAR]",
+    "",
 
-    "All atoms farther than 1 nm of a fixed position:[BR]",
+    "All atoms farther than 1 nm of a fixed position::",
+    "",
     "  not within 1 of [1.2, 3.1, 2.4]",
-    "[PAR]",
+    "",
 
-    "All atoms of a residue LIG within 0.5 nm of a protein (with a custom name):[BR]",
+    "All atoms of a residue LIG within 0.5 nm of a protein (with a custom name)::",
+    "",
     "  \"Close to protein\" resname LIG and within 0.5 of group \"Protein\"",
-    "[PAR]",
+    "",
 
-    "All protein residues that have at least one atom within 0.5 nm of a residue LIG:[BR]",
+    "All protein residues that have at least one atom within 0.5 nm of a residue LIG::",
+    "",
     "  group \"Protein\" and same residue as within 0.5 of resname LIG",
-    "[PAR]",
+    "",
 
-    "All RES residues whose COM is between 2 and 4 nm from the COM of all of them:[BR]",
-    "  rdist = res_com distance from com of resname RES[BR]",
+    "All RES residues whose COM is between 2 and 4 nm from the COM of all of them::",
+    "",
+    "  rdist = res_com distance from com of resname RES",
     "  resname RES and rdist >= 2 and rdist <= 4",
-    "[PAR]",
+    "",
 
-    "Selection like C1 C2 C2 C3 C3 C4 ... C8 C9 (e.g., for g_bond):[BR]",
+    "Selection like C1 C2 C2 C3 C3 C4 ... C8 C9 (e.g., for g_bond)::",
+    "",
     "  name \"C[1-8]\" merge name \"C[2-9]\"",
 };
 
@@ -281,10 +290,14 @@ const char *const LimitationsHelpText::text[] = {
     "[PAR]",
 
     "Due to technical reasons, having a negative value as the first value in",
-    "expressions like[BR]",
-    "[TT]charge -1 to -0.7[tt][BR]",
-    "result in a syntax error. A workaround is to write[BR]",
-    "[TT]charge {-1 to -0.7}[tt][BR]",
+    "expressions like ::",
+    "",
+    "  charge -1 to -0.7",
+    "",
+    "result in a syntax error. A workaround is to write ::",
+    "",
+    "  charge {-1 to -0.7}",
+    "",
     "instead.[PAR]",
 
     "When [TT]name[tt] selection keyword is used together with PDB input",
@@ -373,8 +386,10 @@ const char *const SyntaxHelpText::text[] = {
     "not if you provide the selections, e.g., from a pipe.[PAR]",
 
     "It is possible to use variables to store selection expressions.",
-    "A variable is defined with the following syntax:[BR]",
-    "[TT]VARNAME = EXPR ;[tt][BR]",
+    "A variable is defined with the following syntax::",
+    "",
+    "  VARNAME = EXPR ;",
+    "",
     "where [TT]EXPR[tt] is any valid selection expression.",
     "After this, [TT]VARNAME[tt] can be used anywhere where [TT]EXPR[tt]",
     "would be valid.[PAR]",
@@ -461,7 +476,8 @@ class KeywordDetailsHelpTopic : public AbstractSimpleHelpTopic
     protected:
         virtual std::string helpText() const
         {
-            return concatenateStrings(method_.help.help, method_.help.nlhelp);
+            return joinStrings(method_.help.help,
+                               method_.help.help + method_.help.nlhelp, "\n");
         }
 
     private:
@@ -547,39 +563,34 @@ void KeywordsHelpTopic::writeHelp(const HelpWriterContext &context) const
     // still prints raw text, but these are waiting for discussion of the
     // markup format in #969.
     writeBasicHelpTopic(context, *this, helpText());
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
     // Print the list of keywords
-    context.writeTextBlock(
-            "Keywords that select atoms by an integer property:[BR]"
-            "(use in expressions or like \"atomnr 1 to 5 7 9\")[BR]");
+    context.writeTextBlock("Keywords that select atoms by an integer property:");
+    context.writeTextBlock("(use in expressions or like \"atomnr 1 to 5 7 9\")");
     printKeywordList(context, INT_VALUE, false);
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
-    context.writeTextBlock(
-            "Keywords that select atoms by a numeric property:[BR]"
-            "(use in expressions or like \"occupancy 0.5 to 1\")[BR]");
+    context.writeTextBlock("Keywords that select atoms by a numeric property:");
+    context.writeTextBlock("(use in expressions or like \"occupancy 0.5 to 1\")");
     printKeywordList(context, REAL_VALUE, false);
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
-    context.writeTextBlock(
-            "Keywords that select atoms by a string property:[BR]"
-            "(use like \"name PATTERN [PATTERN] ...\")[BR]");
+    context.writeTextBlock("Keywords that select atoms by a string property:");
+    context.writeTextBlock("(use like \"name PATTERN [PATTERN] ...\")");
     printKeywordList(context, STR_VALUE, false);
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
-    context.writeTextBlock(
-            "Additional keywords that directly select atoms:[BR]");
+    context.writeTextBlock("Additional keywords that directly select atoms:");
     printKeywordList(context, GROUP_VALUE, false);
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
-    context.writeTextBlock(
-            "Keywords that directly evaluate to positions:[BR]"
-            "(see also \"positions\" subtopic)[BR]");
+    context.writeTextBlock("Keywords that directly evaluate to positions:");
+    context.writeTextBlock("(see also \"positions\" subtopic)");
     printKeywordList(context, POS_VALUE, false);
-    context.writeTextBlock("[BR]");
+    context.writeTextBlock("");
 
-    context.writeTextBlock("Additional keywords:[BR]");
+    context.writeTextBlock("Additional keywords:");
     printKeywordList(context, POS_VALUE, true);
     printKeywordList(context, NO_VALUE, true);
 }
index 449dd9bcd12e9bcda548cbfd409962da3b819381..14b055c7fbfe6ff23c7f156a1205c39d8c19544f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 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.
@@ -155,12 +155,14 @@ static gmx_ana_selparam_t smparams_within[] = {
 
 /** Help text for the distance selection methods. */
 static const char *help_distance[] = {
-    "DISTANCE-BASED SELECTION KEYWORDS[PAR]",
-
-    "[TT]distance from POS [cutoff REAL][tt][BR]",
-    "[TT]mindistance from POS_EXPR [cutoff REAL][tt][BR]",
-    "[TT]within REAL of POS_EXPR[tt][PAR]",
-
+    "DISTANCE-BASED SELECTION KEYWORDS",
+    "",
+    "::",
+    "",
+    "  distance from POS [cutoff REAL]",
+    "  mindistance from POS_EXPR [cutoff REAL]",
+    "  within REAL of POS_EXPR",
+    "",
     "[TT]distance[tt] and [TT]mindistance[tt] calculate the distance from the",
     "given position(s), the only difference being in that [TT]distance[tt]",
     "only accepts a single position, while any number of positions can be",
index 47b91ee886be084e8e94b546b1ea37866cba7049..4b9a50c5555e09eccc00b5cf9a08d412704b7b49 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 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.
@@ -123,11 +123,13 @@ static gmx_ana_selparam_t smparams_merge[] = {
 /** Help text for the merging selection modifiers. */
 static const char *help_merge[] = {
     "MERGING SELECTIONS[PAR]",
-
-    "[TT]POSEXPR merge POSEXPR [stride INT][tt][BR]",
-    "[TT]POSEXPR merge POSEXPR [merge POSEXPR ...][tt][BR]",
-    "[TT]POSEXPR plus POSEXPR [plus POSEXPR ...][tt][PAR]",
-
+    "",
+    "::",
+    "",
+    "  POSEXPR merge POSEXPR [stride INT]",
+    "  POSEXPR merge POSEXPR [merge POSEXPR ...]",
+    "  POSEXPR plus POSEXPR [plus POSEXPR ...]",
+    "",
     "Basic selection keywords can only create selections where each atom",
     "occurs at most once. The [TT]merge[tt] and [TT]plus[tt] selection",
     "keywords can be used to work around this limitation. Both create",
index 8f13208304f77600174b41fe18420c67ecafdd96..674a5fa265aabb5bbe24e0b3c29a136022ce11ce 100644 (file)
@@ -445,7 +445,7 @@ Sasa::initOptions(Options *options, TrajectoryAnalysisSettings *settings)
         "that are both too high."
     };
 
-    options->setDescription(concatenateStrings(desc));
+    options->setDescription(desc);
 
     options->addOption(FileNameOption("o").filetype(eftPlot).outputFile().required()
                            .store(&fnArea_).defaultBasename("area")
index 5b2c725017a6e585b14e9d6d3832f76a58571d8a..dbcb951486f652c23680744fc9a30abef2ccd000 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2011,2012,2013,2014, by the GROMACS development team, led by
+ * Copyright (c) 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.
@@ -153,26 +153,6 @@ std::vector<std::string> splitString(const std::string &str)
     return result;
 }
 
-std::string concatenateStrings(const char *const *sarray, size_t count)
-{
-    std::string result;
-
-    for (size_t i = 0; i < count && sarray[i] != NULL; ++i)
-    {
-        if (sarray[i][0] != '\0')
-        {
-            result.append(sarray[i]);
-            char lastchar = sarray[i][std::strlen(sarray[i])-1];
-            if (!std::isspace(lastchar))
-            {
-                result.append(" ");
-            }
-        }
-    }
-    result.resize(result.find_last_not_of(" \n\r\t") + 1);
-    return result;
-}
-
 namespace
 {
 
@@ -267,7 +247,7 @@ replaceAllWords(const std::string &input, const std::string &from,
 
 TextLineWrapperSettings::TextLineWrapperSettings()
     : maxLength_(0), indent_(0), firstLineIndent_(-1),
-      bStripLeadingWhitespace_(true), continuationChar_('\0')
+      bStripLeadingWhitespace_(false), continuationChar_('\0')
 {
 }
 
index e74d6c990532d0224f000322e9c0306daa9e4bf6..e7e11a6d9ef5c9bf5d1d3a04a7a7dd22add7df77 100644 (file)
@@ -244,34 +244,19 @@ std::string joinStrings(const ContainerType &container, const char *separator)
 }
 
 /*! \brief
- * Joins strings in an array to a single string.
+ * Joins strings from an array with a separator in between.
  *
- * \param[in] sarray  Array of strings to concatenate.
- * \param[in] count   Number of elements in \p sarray to concatenate.
- * \returns   All strings in \p sarray joined, ensuring at least one space
- *      between the strings.
- * \throws    std::bad_alloc if out of memory.
- *
- * The strings in the \p sarray array are concatenated, adding a single space
- * between the strings if there is no whitespace in the end of a string.
- * Terminal whitespace is removed.
- */
-std::string concatenateStrings(const char * const *sarray, size_t count);
-/*! \brief
- * Convenience overload for joining strings in a C array (static data).
- *
- * \param[in] sarray  Array of strings to concatenate.
- * \tparam    count   Deduced number of elements in \p sarray.
- * \returns   All strings in \p sarray joined, ensuring at least one space
- *      between the strings.
+ * \param[in] array      Array of strings to join.
+ * \param[in] separator  String to put in between the joined strings.
+ * \tparam    count      Deduced number of elements in \p array.
+ * \returns   All strings from `aray` concatenated with `separator`
+ *     between each pair.
  * \throws    std::bad_alloc if out of memory.
- *
- * \see concatenateStrings(const char * const *, size_t)
  */
 template <size_t count>
-std::string concatenateStrings(const char * const (&sarray)[count])
+std::string joinStrings(const char *const (&array)[count], const char *separator)
 {
-    return concatenateStrings(sarray, count);
+    return joinStrings(array, array + count, separator);
 }
 
 /*! \brief
@@ -387,7 +372,7 @@ class TextLineWrapperSettings
          *
          * If not removed, the space is added to the indentation set with
          * setIndent().
-         * The default is to strip such whitespace.
+         * The default is to not strip such whitespace.
          */
         void setStripLeadingWhitespace(bool bStrip)
         {
diff --git a/src/gromacs/utility/tests/refdata/ConcatenateStringsTest_HandlesDifferentStringEndings.xml b/src/gromacs/utility/tests/refdata/ConcatenateStringsTest_HandlesDifferentStringEndings.xml
deleted file mode 100644 (file)
index 1d9ba80..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
-<ReferenceData>
-  <String Name="CombinedStrings"><![CDATA[
-First string Second string Third string
-Fourth string]]></String>
-</ReferenceData>
index 068df9246845c5e86be08216470f59bcb261f4f1..5f9fb1e31a997da846fdaa56c6994bec502f671d 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.
@@ -179,25 +179,7 @@ TEST(JoinStringsTest, Works)
     gmx::ConstArrayRef<const char *> refToWords(words);
     EXPECT_EQ("The; quick; brown; fox", gmx::joinStrings(refToWords.begin(), refToWords.end(), "; "));
     EXPECT_EQ("The-quick-brown-fox", gmx::joinStrings(refToWords, "-"));
-}
-
-/********************************************************************
- * Tests for concatenateStrings()
- */
-
-//! Test fixture for gmx::concatenateStrings().
-typedef gmx::test::StringTestBase ConcatenateStringsTest;
-
-TEST_F(ConcatenateStringsTest, HandlesDifferentStringEndings)
-{
-    static const char * const strings[] = {
-        "First string",
-        "Second string ",
-        "Third string\n",
-        "Fourth string",
-        ""
-    };
-    checkText(gmx::concatenateStrings(strings), "CombinedStrings");
+    EXPECT_EQ("The-quick-brown-fox", gmx::joinStrings(words, "-"));
 }
 
 /********************************************************************