// 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>'.");
}
/********************************************************************
if (header_ != NULL)
{
context_.writeTextBlock(header_);
+ context_.writeTextBlock("");
}
context_.writeOptionListStart();
}
"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",
"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]",
"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,",
"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;
"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",
"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[] =
"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",
"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].",
/* "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]",
"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)",
*
* 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.
"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;
"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 */
"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",
"* 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.",
" 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",
"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]",
"[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 ",
"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 ",
"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]"
"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]",
/*
* 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.
protected:
virtual std::string helpText() const
{
- return concatenateStrings(HelpText::text);
+ return joinStrings(HelpText::text, "\n");
}
};
protected:
virtual std::string helpText() const
{
- return concatenateStrings(HelpText::text);
+ return joinStrings(HelpText::text, "\n");
}
};
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
{
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:
{
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"));
#
# 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.
gmx_add_unit_test(OnlineHelpUnitTests onlinehelp-test
helpformat.cpp
helpmanager.cpp
+ helpwritercontext.cpp
$<TARGET_OBJECTS:onlinehelp-test-shared>)
--- /dev/null
+/*
+ * 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
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>
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)
"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",
// 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]\"",
};
"[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",
"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]",
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:
// 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);
}
/*
* 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.
/** 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",
/*
* 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.
/** 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",
"that are both too high."
};
- options->setDescription(concatenateStrings(desc));
+ options->setDescription(desc);
options->addOption(FileNameOption("o").filetype(eftPlot).outputFile().required()
.store(&fnArea_).defaultBasename("area")
/*
* 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.
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
{
TextLineWrapperSettings::TextLineWrapperSettings()
: maxLength_(0), indent_(0), firstLineIndent_(-1),
- bStripLeadingWhitespace_(true), continuationChar_('\0')
+ bStripLeadingWhitespace_(false), continuationChar_('\0')
{
}
}
/*! \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
*
* 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)
{
+++ /dev/null
-<?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>
/*
* 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.
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, "-"));
}
/********************************************************************