/*
* 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.
#include "selhelp.h"
+#include <set>
#include <string>
#include <utility>
#include <vector>
#include "gromacs/onlinehelp/helptopic.h"
#include "gromacs/onlinehelp/helpwritercontext.h"
#include "gromacs/utility/exceptions.h"
-#include "gromacs/utility/file.h"
+#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
+#include "gromacs/utility/textwriter.h"
#include "selmethod.h"
#include "symrec.h"
const char *const CommonHelpText::text[] = {
"Selections are used to select atoms/molecules/residues for analysis.",
"In contrast to traditional index files, selections can be dynamic, i.e.,",
- "select different atoms for different trajectory frames.[PAR]",
+ "select different atoms for different trajectory frames. The GROMACS",
+ "manual contains a short introductory section to selections in the",
+ "Analysis chapter, including suggestions on how to get familiar with",
+ "selections if you are new to the concept. The subtopics listed below",
+ "provide more details on the technical and syntactic aspects of",
+ "selections.[PAR]",
"Each analysis tool requires a different number of selections and the",
"selections are interpreted differently. The general idea is still the",
"can be an atom position or center-of-mass or center-of-geometry of",
"a set of atoms. The tool then uses these positions for its analysis to",
"allow very flexible processing. Some analysis tools may have limitations",
- "on the types of selections allowed.[PAR]",
-
- "To get started with selections, run, e.g., [TT][PROGRAM] select[tt]",
- "without specifying selections on the command-line and use the interactive",
- "prompt to try out different selections.",
- "This tool provides output options that allow one to see what is actually",
- "selected by the given selections, and the interactive prompt reports",
- "syntax errors immediately, allowing one to try again.",
- "The subtopics listed below give more details on different aspects of",
- "selections.",
+ "on the types of selections allowed."
};
struct ArithmeticHelpText
"if they are complex or for scripting.[PAR]",
"Each tool has different command-line arguments for specifying selections",
- "(listed by [TT][PROGRAM] help <tool>[tt]).",
+ "(see the help for the individual tools).",
"You can either pass a single string containing all selections (separated",
"by semicolons), or multiple strings, each containing one selection.",
"Note that you need to quote the selections to protect them from the",
"To use groups from a traditional index file, use argument [TT]-n[tt]",
"to provide a file. See the \"syntax\" subtopic for how to use them.",
"If this option is not provided, default groups are generated.",
- "The default groups are generated by reading selections from a file",
- "[TT]defselection.dat[tt]. If such a file is found in the current",
- "directory, it is used instead of the one provided by default.[PAR]",
-
+ "The default groups are generated with the same logic as for",
+ "non-selection tools.",
+ "",
"Depending on the tool, two additional command-line arguments may be",
- "available to control the behavior:[BR]",
- "1. [TT]-seltype[tt] can be used to specify the default type of",
- "positions to calculate for each selection.[BR]",
- "2. [TT]-selrpos[tt] can be used to specify the default type of",
- "positions used in selecting atoms by coordinates.[BR]",
+ "available to control the behavior:",
+ "",
+ "* [TT]-seltype[tt] can be used to specify the default type of",
+ " positions to calculate for each selection.",
+ "* [TT]-selrpos[tt] can be used to specify the default type of",
+ " positions used in selecting atoms by coordinates.",
+ "",
"See the \"positions\" subtopic for more information on these options.",
};
"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",
const char ExamplesHelpText::title[] =
"Selection examples";
const char *const ExamplesHelpText::text[] = {
- // TODO: Once there are more tools available, use examples that invoke
- // 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]",
- " resname SOL and name OW",
- "[PAR]",
-
- "Centers of mass of residues 1 to 5 and 10:[BR]",
- " res_com of resnr 1 to 5 10",
- "[PAR]",
-
- "All atoms farther than 1 nm of a fixed position:[BR]",
- " 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]",
- " \"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]",
- " 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]",
- " 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]",
- " name \"C[1-8]\" merge name \"C[2-9]\"",
+ "Below, examples of different types of selections are given.",
+ "",
+ "* Selection of all water oxygens::",
+ "",
+ " resname SOL and name OW",
+ "",
+ "* Centers of mass of residues 1 to 5 and 10::",
+ "",
+ " res_com of resnr 1 to 5 10",
+ "",
+ "* All atoms farther than 1 nm of a fixed position::",
+ "",
+ " not within 1 of [1.2, 3.1, 2.4]",
+ "",
+ "* 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\"",
+ "",
+ "* 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",
+ "",
+ "* 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",
+ "",
+ // TODO: Make it possible to use links below.
+ "* Selection like with duplicate atoms like C1 C2 C2 C3 C3 C4 ... C8 C9::",
+ "",
+ " name \"C[1-8]\" merge name \"C[2-9]\"",
+ "",
+ " This can be used with [TT]gmx distance[tt] to compute C1-C2, C2-C3 etc.",
+ " distances.",
+ "",
+ "* Selection with atoms in order C2 C1::",
+ "",
+ " name C1 C2 permute 2 1",
+ "",
+ " This can be used with [TT]gmx gangle[tt] to get C2->C1 vectors instead of",
+ " C1->C2.",
+ "",
+ "* Selection with COMs of two index groups::",
+ "",
+ " com of group 1 plus com of group 2",
+ "",
+ " This can be used with [TT]gmx distance[tt] to compute the distance between",
+ " these two COMs.",
+ "",
+ "* Fixed vector along x (can be used as a reference with [TT]gmx gangle[tt])::",
+ "",
+ " [0, 0, 0] plus [1, 0, 0]",
+ "",
+ "* The following examples explain the difference between the various",
+ " position types. This selection selects a position for each residue",
+ " where any of the three atoms C[123] has [TT]x < 2[tt]. The positions",
+ " are computed as the COM of all three atoms.",
+ " This is the default behavior if you just write [TT]res_com of[tt]. ::",
+ "",
+ " part_res_com of name C1 C2 C3 and x < 2",
+ "",
+ " This selection does the same, but the positions are computed as COM",
+ " positions of whole residues::",
+ "",
+ " whole_res_com of name C1 C2 C3 and x < 2",
+ "",
+ " Finally, this selection selects the same residues, but the positions",
+ " are computed as COM of exactly those atoms atoms that match the",
+ " [TT]x < 2[tt] criterion::",
+ "",
+ " dyn_res_com of name C1 C2 C3 and x < 2",
+ "",
+ "* Without the [TT]of[tt] keyword, the default behavior is different from",
+ " above, but otherwise the rules are the same::",
+ "",
+ " name C1 C2 C3 and res_com x < 2",
+ "",
+ " works as if [TT]whole_res_com[tt] was specified, and selects the three",
+ " atoms from residues whose COM satisfiex [TT]x < 2[tt].",
+ " Using ::",
+ "",
+ " name C1 C2 C3 and part_res_com x < 2",
+ "",
+ " instead selects residues based on the COM computed from the C[123] atoms.",
};
struct KeywordsHelpText
"Selection keywords";
const char *const KeywordsHelpText::text[] = {
"The following selection keywords are currently available.",
- "For keywords marked with a star, additional help is available through",
+ "For keywords marked with a plus, additional help is available through",
"a subtopic KEYWORD, where KEYWORD is the name of the keyword.",
};
const char LimitationsHelpText::title[] =
"Selection limitations";
const char *const LimitationsHelpText::text[] = {
- "Some analysis programs may require a special structure for the input",
- "selections (e.g., [TT]gmx angle[tt] requires the index group to be made",
- "of groups of three or four atoms).",
- "For such programs, it is up to the user to provide a proper selection",
- "expression that always returns such positions.",
- "[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]",
- "instead.[PAR]",
-
- "When [TT]name[tt] selection keyword is used together with PDB input",
- "files, the behavior may be unintuitive. When Gromacs reads in a PDB",
- "file, 4 character atom names that start with a digit are transformed",
- "such that, e.g., 1HG2 becomes HG21, and the latter is what is matched",
- "by the [TT]name[tt] keyword. Use [TT]pdbname[tt] to match the atom name",
- "as it appears in the input PDB file.",
+ "* Some analysis programs may require a special structure for the input",
+ " selections (e.g., some options of [TT]gmx gangle[tt] require the index",
+ " group to be made of groups of three or four atoms).",
+ " For such programs, it is up to the user to provide a proper selection",
+ " expression that always returns such positions.",
+ "",
+ "* All selection keywords select atoms in increasing order, i.e., you can",
+ " consider them as set operations that in the end return the atoms in",
+ " sorted numerical order. For example, the following selections select",
+ " the same atoms in the same order::",
+ "",
+ " resname RA RB RC",
+ " resname RB RC RA",
+ "",
+ " ::",
+ "",
+ " atomnr 10 11 12 13",
+ " atomnr 12 13 10 11",
+ " atomnr 10 to 13",
+ " atomnr 13 to 10",
+ "",
+ " If you need atoms/positions in a different order, you can:",
+ "",
+ " * use external index groups (for some static selections),",
+ " * use the [TT]permute[tt] keyword to change the final order, or",
+ " * use the [TT]merge[tt] or [TT]plus[tt] keywords to compose the",
+ " final selection from multiple distinct selections.",
+ "",
+ "* Due to technical reasons, having a negative value as the first value in",
+ " expressions like ::",
+ "",
+ " charge -1 to -0.7",
+ "",
+ " result in a syntax error. A workaround is to write ::",
+ "",
+ " charge {-1 to -0.7}",
+ "",
+ " instead.",
+ "",
+ "* When [TT]name[tt] selection keyword is used together with PDB input",
+ " files, the behavior may be unintuitive. When GROMACS reads in a PDB",
+ " file, 4 character atom names that start with a digit are transformed",
+ " such that, e.g., 1HG2 becomes HG21, and the latter is what is matched",
+ " by the [TT]name[tt] keyword. Use [TT]pdbname[tt] to match the atom name",
+ " as it appears in the input PDB file.",
};
struct PositionsHelpText
const char PositionsHelpText::title[] =
"Specifying positions in selections";
const char *const PositionsHelpText::text[] = {
- "Possible ways of specifying positions in selections are:[PAR]",
-
+ "Possible ways of specifying positions in selections are:",
+ "",
"1. A constant position can be defined as [TT][XX, YY, ZZ][tt], where",
- "[TT]XX[tt], [TT]YY[tt] and [TT]ZZ[tt] are real numbers.[PAR]",
-
+ " [TT]XX[tt], [TT]YY[tt] and [TT]ZZ[tt] are real numbers.[PAR]",
+ "",
"2. [TT]com of ATOM_EXPR [pbc][tt] or [TT]cog of ATOM_EXPR [pbc][tt]",
- "calculate the center of mass/geometry of [TT]ATOM_EXPR[tt]. If",
- "[TT]pbc[tt] is specified, the center is calculated iteratively to try",
- "to deal with cases where [TT]ATOM_EXPR[tt] wraps around periodic",
- "boundary conditions.[PAR]",
-
+ " calculate the center of mass/geometry of [TT]ATOM_EXPR[tt]. If",
+ " [TT]pbc[tt] is specified, the center is calculated iteratively to try",
+ " to deal with cases where [TT]ATOM_EXPR[tt] wraps around periodic",
+ " boundary conditions.",
+ "",
"3. [TT]POSTYPE of ATOM_EXPR[tt] calculates the specified positions for",
- "the atoms in [TT]ATOM_EXPR[tt].",
- "[TT]POSTYPE[tt] can be [TT]atom[tt], [TT]res_com[tt], [TT]res_cog[tt],",
- "[TT]mol_com[tt] or [TT]mol_cog[tt], with an optional prefix [TT]whole_[tt]",
- "[TT]part_[tt] or [TT]dyn_[tt].",
- "[TT]whole_[tt] calculates the centers for the whole residue/molecule,",
- "even if only part of it is selected.",
- "[TT]part_[tt] prefix calculates the centers for the selected atoms, but",
- "uses always the same atoms for the same residue/molecule. The used atoms",
- "are determined from the the largest group allowed by the selection.",
- "[TT]dyn_[tt] calculates the centers strictly only for the selected atoms.",
- "If no prefix is specified, whole selections default to [TT]part_[tt] and",
- "other places default to [TT]whole_[tt].",
- "The latter is often desirable to select the same molecules in different",
- "tools, while the first is a compromise between speed ([TT]dyn_[tt]",
- "positions can be slower to evaluate than [TT]part_[tt]) and intuitive",
- "behavior.[PAR]",
-
+ " the atoms in [TT]ATOM_EXPR[tt].",
+ " [TT]POSTYPE[tt] can be [TT]atom[tt], [TT]res_com[tt], [TT]res_cog[tt],",
+ " [TT]mol_com[tt] or [TT]mol_cog[tt], with an optional prefix [TT]whole_[tt]",
+ " [TT]part_[tt] or [TT]dyn_[tt].",
+ " [TT]whole_[tt] calculates the centers for the whole residue/molecule,",
+ " even if only part of it is selected.",
+ " [TT]part_[tt] prefix calculates the centers for the selected atoms, but",
+ " uses always the same atoms for the same residue/molecule. The used atoms",
+ " are determined from the the largest group allowed by the selection.",
+ " [TT]dyn_[tt] calculates the centers strictly only for the selected atoms.",
+ " If no prefix is specified, whole selections default to [TT]part_[tt] and",
+ " other places default to [TT]whole_[tt].",
+ " The latter is often desirable to select the same molecules in different",
+ " tools, while the first is a compromise between speed ([TT]dyn_[tt]",
+ " positions can be slower to evaluate than [TT]part_[tt]) and intuitive",
+ " behavior.",
+ "",
"4. [TT]ATOM_EXPR[tt], when given for whole selections, is handled as 3.",
- "above, using the position type from the command-line argument",
- "[TT]-seltype[tt].[PAR]",
-
+ " above, using the position type from the command-line argument",
+ " [TT]-seltype[tt].",
+ "",
"Selection keywords that select atoms based on their positions, such as",
"[TT]dist from[tt], use by default the positions defined by the",
"[TT]-selrpos[tt] command-line option.",
"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]",
"Selections are composed of three main types of expressions, those that",
- "define atoms ([TT]ATOM_EXPR[tt]s), those that define positions",
- "([TT]POS_EXPR[tt]s), and those that evaluate to numeric values",
- "([TT]NUM_EXPR[tt]s). Each selection should be a [TT]POS_EXPR[tt]",
+ "define atoms ([TT]ATOM_EXPR[tt]), those that define positions",
+ "([TT]POS_EXPR[tt]), and those that evaluate to numeric values",
+ "([TT]NUM_EXPR[tt]). Each selection should be a [TT]POS_EXPR[tt]",
"or a [TT]ATOM_EXPR[tt] (the latter is automatically converted to",
- "positions). The basic rules are as follows:[BR]",
- "1. An expression like [TT]NUM_EXPR1 < NUM_EXPR2[tt] evaluates to an",
- "[TT]ATOM_EXPR[tt] that selects all the atoms for which the comparison",
- "is true.[BR]",
- "2. Atom expressions can be combined with boolean operations such as",
- "[TT]not ATOM_EXPR[tt], [TT]ATOM_EXPR and ATOM_EXPR[tt], or",
- "[TT]ATOM_EXPR or ATOM_EXPR[tt]. Parentheses can be used to alter the",
- "evaluation order.[BR]",
- "3. [TT]ATOM_EXPR[tt] expressions can be converted into [TT]POS_EXPR[tt]",
- "expressions in various ways, see the \"positions\" subtopic for more",
- "details.[BR]",
- "4. [TT]POS_EXPR[tt] can be converted into [TT]NUM_EXPR[tt] using syntax",
- "like \"x of POS_EXPR\". Currently, this is only supported for single",
- "positions like in expression \"x of cog of ATOM_EXPR\".[PAR]",
+ "positions). The basic rules are as follows:",
+ "",
+ "* An expression like [TT]NUM_EXPR1 < NUM_EXPR2[tt] evaluates to an",
+ " [TT]ATOM_EXPR[tt] that selects all the atoms for which the comparison",
+ " is true.",
+ "* Atom expressions can be combined with boolean operations such as",
+ " [TT]not ATOM_EXPR[tt], [TT]ATOM_EXPR and ATOM_EXPR[tt], or",
+ " [TT]ATOM_EXPR or ATOM_EXPR[tt]. Parentheses can be used to alter the",
+ " evaluation order.",
+ "* [TT]ATOM_EXPR[tt] expressions can be converted into [TT]POS_EXPR[tt]",
+ " expressions in various ways, see the \"positions\" subtopic for more",
+ " details.",
+ "* [TT]POS_EXPR[tt] can be converted into [TT]NUM_EXPR[tt] using syntax",
+ " like \"[TT]x of POS_EXPR[tt]\". Currently, this is only supported for single",
+ " positions like in expression \"[TT]x of cog of ATOM_EXPR[tt]\".",
+ "",
"Some keywords select atoms based on string values such as the atom name.",
"For these keywords, it is possible to use wildcards ([TT]name \"C*\"[tt])",
}
virtual const char *title() const
{
- return NULL;
+ return method_.help.helpTitle;
}
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:
const gmx_ana_selmethod_t *> >
MethodList;
+ /*! \brief
+ * Prints markup for starting a list of keywords.
+ */
+ void writeKeywordListStart(const HelpWriterContext &context,
+ const char *heading) const;
+ /*! \brief
+ * Prints markup for ending a list of keywords.
+ */
+ void writeKeywordListEnd(const HelpWriterContext &context,
+ const char *extraInfo) const;
+
/*! \brief
* Prints a brief list of keywords (selection methods) available.
*
void printKeywordList(const HelpWriterContext &context,
e_selvalue_t type, bool bModifiers) const;
+ /*! \brief
+ * Prints the detailed help for keywords for rst export.
+ */
+ void writeKeywordSubTopics(const HelpWriterContext &context) const;
+
MethodList methods_;
};
void KeywordsHelpTopic::writeHelp(const HelpWriterContext &context) const
{
- if (context.outputFormat() != eHelpOutputFormat_Console)
- {
- GMX_THROW(NotImplementedError(
- "Selection help is not implemented for this output format"));
- }
- // TODO: The markup here is not really appropriate, and printKeywordList()
- // still prints raw text, but these are waiting for discussion of the
- // markup format in #969.
- writeBasicHelpTopic(context, *this, helpText());
- context.writeTextBlock("[BR]");
+ context.writeTextBlock(helpText());
+ 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]");
+ writeKeywordListStart(context, "Keywords that select atoms by an integer property:");
printKeywordList(context, INT_VALUE, false);
- context.writeTextBlock("[BR]");
+ writeKeywordListEnd(context, "(use in expressions or like \"atomnr 1 to 5 7 9\")");
- context.writeTextBlock(
- "Keywords that select atoms by a numeric property:[BR]"
- "(use in expressions or like \"occupancy 0.5 to 1\")[BR]");
+ writeKeywordListStart(context, "Keywords that select atoms by a numeric property:");
printKeywordList(context, REAL_VALUE, false);
- context.writeTextBlock("[BR]");
+ writeKeywordListEnd(context, "(use in expressions or like \"occupancy 0.5 to 1\")");
- context.writeTextBlock(
- "Keywords that select atoms by a string property:[BR]"
- "(use like \"name PATTERN [PATTERN] ...\")[BR]");
+ writeKeywordListStart(context, "Keywords that select atoms by a string property:");
printKeywordList(context, STR_VALUE, false);
- context.writeTextBlock("[BR]");
+ writeKeywordListEnd(context, "(use like \"name PATTERN [PATTERN] ...\")");
- context.writeTextBlock(
- "Additional keywords that directly select atoms:[BR]");
+ writeKeywordListStart(context, "Additional keywords that directly select atoms:");
printKeywordList(context, GROUP_VALUE, false);
- context.writeTextBlock("[BR]");
+ writeKeywordListEnd(context, NULL);
- context.writeTextBlock(
- "Keywords that directly evaluate to positions:[BR]"
- "(see also \"positions\" subtopic)[BR]");
+ writeKeywordListStart(context, "Keywords that directly evaluate to positions:");
printKeywordList(context, POS_VALUE, false);
- context.writeTextBlock("[BR]");
+ writeKeywordListEnd(context, "(see also \"positions\" subtopic)");
- context.writeTextBlock("Additional keywords:[BR]");
+ writeKeywordListStart(context, "Additional keywords:");
printKeywordList(context, POS_VALUE, true);
printKeywordList(context, NO_VALUE, true);
+ writeKeywordListEnd(context, NULL);
+
+ writeKeywordSubTopics(context);
+}
+
+void KeywordsHelpTopic::writeKeywordListStart(const HelpWriterContext &context,
+ const char *heading) const
+{
+ std::string fullHeading("* ");
+ fullHeading.append(heading);
+ context.writeTextBlock(fullHeading);
+ if (context.outputFormat() == eHelpOutputFormat_Rst)
+ {
+ context.writeTextBlock("");
+ context.writeTextBlock(" ::");
+ context.writeTextBlock("");
+ }
+}
+
+void KeywordsHelpTopic::writeKeywordListEnd(const HelpWriterContext &context,
+ const char *extraInfo) const
+{
+ if (context.outputFormat() == eHelpOutputFormat_Rst)
+ {
+ context.writeTextBlock("");
+ }
+ if (!isNullOrEmpty(extraInfo))
+ {
+ std::string fullInfo(" ");
+ fullInfo.append(extraInfo);
+ context.writeTextBlock(fullInfo);
+ }
+ context.writeTextBlock("");
}
void KeywordsHelpTopic::printKeywordList(const HelpWriterContext &context,
e_selvalue_t type,
bool bModifiers) const
{
- File &file = context.outputFile();
+ TextWriter &file = context.outputFile();
MethodList::const_iterator iter;
for (iter = methods_.begin(); iter != methods_.end(); ++iter)
{
const gmx_ana_selmethod_t &method = *iter->second;
- bool bIsModifier = (method.flags & SMETH_MODIFIER) != 0;
+ const bool bIsModifier
+ = (method.flags & SMETH_MODIFIER) != 0;
if (method.type == type && bModifiers == bIsModifier)
{
- bool bHasHelp = (method.help.nlhelp > 0 && method.help.help != NULL);
- file.writeString(formatString(" %c ", bHasHelp ? '*' : ' '));
+ const bool bHasHelp = (method.help.nlhelp > 0 && method.help.help != NULL);
+ const bool bPrintHelpMark
+ = bHasHelp && context.outputFormat() == eHelpOutputFormat_Console;
+ file.writeString(formatString(" %c ", bPrintHelpMark ? '+' : ' '));
if (method.help.syntax != NULL)
{
file.writeLine(method.help.syntax);
}
}
+void KeywordsHelpTopic::writeKeywordSubTopics(const HelpWriterContext &context) const
+{
+ if (context.outputFormat() != eHelpOutputFormat_Rst)
+ {
+ return;
+ }
+ std::set<std::string> usedSymbols;
+ MethodList::const_iterator iter;
+ for (iter = methods_.begin(); iter != methods_.end(); ++iter)
+ {
+ const gmx_ana_selmethod_t &method = *iter->second;
+ const bool bHasHelp
+ = (method.help.nlhelp > 0 && method.help.help != NULL);
+ if (!bHasHelp || usedSymbols.count(iter->first) > 0)
+ {
+ continue;
+ }
+
+ std::string title;
+ if (method.help.helpTitle != NULL)
+ {
+ title = method.help.helpTitle;
+ title.append(" - ");
+ }
+ title.append(iter->first);
+ MethodList::const_iterator mergeIter = iter;
+ for (++mergeIter; mergeIter != methods_.end(); ++mergeIter)
+ {
+ if (mergeIter->second->help.help == method.help.help)
+ {
+ title.append(", ");
+ title.append(mergeIter->first);
+ usedSymbols.insert(mergeIter->first);
+ }
+ }
+
+ const IHelpTopic *subTopic = findSubTopic(iter->first.c_str());
+ GMX_RELEASE_ASSERT(subTopic != NULL, "Keyword subtopic no longer exists");
+ HelpWriterContext subContext(context);
+ subContext.enterSubSection(title);
+ subTopic->writeHelp(subContext);
+ context.writeTextBlock("");
+ }
+}
+
} // namespace
//! \cond libapi */
HelpTopicPointer createSelectionHelpTopic()
{
CompositeHelpTopicPointer root(new CompositeHelpTopic<CommonHelpText>);
- root->registerSubTopic<SimpleHelpTopic<ArithmeticHelpText> >();
root->registerSubTopic<SimpleHelpTopic<CmdLineHelpText> >();
- root->registerSubTopic<SimpleHelpTopic<EvaluationHelpText> >();
- root->registerSubTopic<SimpleHelpTopic<ExamplesHelpText> >();
+ root->registerSubTopic<SimpleHelpTopic<SyntaxHelpText> >();
+ root->registerSubTopic<SimpleHelpTopic<PositionsHelpText> >();
+ root->registerSubTopic<SimpleHelpTopic<ArithmeticHelpText> >();
root->registerSubTopic<KeywordsHelpTopic>();
+ root->registerSubTopic<SimpleHelpTopic<EvaluationHelpText> >();
root->registerSubTopic<SimpleHelpTopic<LimitationsHelpText> >();
- root->registerSubTopic<SimpleHelpTopic<PositionsHelpText> >();
- root->registerSubTopic<SimpleHelpTopic<SyntaxHelpText> >();
+ root->registerSubTopic<SimpleHelpTopic<ExamplesHelpText> >();
return move(root);
}
//! \endcond