Sort all includes in src/gromacs
[alexxy/gromacs.git] / src / gromacs / selection / selhelp.cpp
index 9fe10e525996f9adf4e572e4a50a2ea3f689e93b..4a52815f378e9bc15b1bf8cc47196309d4dc19ff 100644 (file)
@@ -1,51 +1,60 @@
 /*
+ * This file is part of the GROMACS molecular simulation package.
  *
- *                This source code is part of
+ * Copyright (c) 2009,2010,2011,2012,2013,2014, 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.
  *
- *                 G   R   O   M   A   C   S
+ * 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.
  *
- *          GROningen MAchine for Chemical Simulations
+ * 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.
  *
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2009, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * 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, 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 www.gromacs.org.
+ * 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 papers on the package - you can find them in the top README file.
- *
- * For more info, check our website at http://www.gromacs.org
+ * the research papers on the package. Check out http://www.gromacs.org.
  */
 /*! \internal \file
  * \brief
  * Implements functions in selhelp.h.
  *
- * \author Teemu Murtola <teemu.murtola@cbr.su.se>
+ * \author Teemu Murtola <teemu.murtola@gmail.com>
  * \ingroup module_selection
  */
+#include "gmxpre.h"
+
+#include "selhelp.h"
+
 #include <string>
-#include <vector>
 #include <utility>
+#include <vector>
 
-#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
 
 #include "gromacs/onlinehelp/helptopic.h"
+#include "gromacs/onlinehelp/helpwritercontext.h"
+#include "gromacs/utility/exceptions.h"
 #include "gromacs/utility/file.h"
-#include "gromacs/utility/format.h"
+#include "gromacs/utility/stringutil.h"
 
-#include "selhelp.h"
 #include "selmethod.h"
 #include "symrec.h"
 
@@ -54,35 +63,46 @@ namespace
 
 struct CommonHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char CommonHelpText::name[] = "selections";
-const char CommonHelpText::title[] =
+const char        CommonHelpText::name[]  = "selections";
+const char        CommonHelpText::title[] =
     "Selection syntax and usage";
 const char *const CommonHelpText::text[] = {
-    "This program supports selections in addition to traditional index files.",
-    "Please read the subtopic pages (available through \"help topic\") for",
-    "more information.",
-    "Explanation of command-line arguments for specifying selections can be",
-    "found under the \"cmdline\" subtopic, and general selection syntax is",
-    "described under \"syntax\". Available keywords can be found under",
-    "\"keywords\", and concrete examples under \"examples\".",
-    "Other subtopics give more details on certain aspects.",
-    "\"help all\" prints the help for all subtopics.",
+    "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]",
+
+    "Each analysis tool requires a different number of selections and the",
+    "selections are interpreted differently. The general idea is still the",
+    "same: each selection evaluates to a set of positions, where a position",
+    "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.",
 };
 
 struct ArithmeticHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char ArithmeticHelpText::name[] = "arithmetic";
-const char ArithmeticHelpText::title[] =
+const char        ArithmeticHelpText::name[]  = "arithmetic";
+const char        ArithmeticHelpText::title[] =
     "Arithmetic expressions in selections";
 const char *const ArithmeticHelpText::text[] = {
     "Basic arithmetic evaluation is supported for numeric expressions.",
@@ -93,31 +113,47 @@ const char *const ArithmeticHelpText::text[] = {
 
 struct CmdLineHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char CmdLineHelpText::name[] = "cmdline";
-const char CmdLineHelpText::title[] =
+const char        CmdLineHelpText::name[]  = "cmdline";
+const char        CmdLineHelpText::title[] =
     "Specifying selections from command line";
 const char *const CmdLineHelpText::text[] = {
-    "There are two alternative command-line arguments for specifying",
-    "selections:[BR]",
-    "1. [TT]-select[tt] can be used to specify the complete selection as a",
-    "string on the command line.[BR]",
-    "2. [TT]-sf[tt] can be used to specify a file name from which the",
-    "selection is read.[BR]",
-    "If both options are specified, [TT]-select[tt] takes precedence.",
-    "If neither of the above is present, the user is prompted to type the",
-    "selection on the standard input (a pipe can also be used to provide",
-    "the selections in this case).",
-    "This is also done if an empty string is passed to [TT]-select[tt].[PAR]",
-
-    "Option [TT]-n[tt] can be used to provide an index file.",
-    "If no index file is provided, default groups are generated.",
-    "In both cases, the user can also select an index group instead of",
-    "writing a full selection.",
+    "If no selections are provided on the command line, you are prompted to",
+    "type the selections interactively (a pipe can also be used to provide",
+    "the selections in this case for most tools). While this works well for",
+    "testing, it is easier to provide the selections from the command line",
+    "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]).",
+    "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",
+    "shell.[PAR]",
+
+    "If you set a selection command-line argument, but do not provide any",
+    "selections, you are prompted to type the selections for that argument",
+    "interactively. This is useful if that selection argument is optional,",
+    "in which case it is not normally prompted for.[PAR]",
+
+    "To provide selections from a file, use [TT]-sf file.dat[tt] in the place",
+    "of the selection for a selection argument (e.g.,",
+    "[TT]-select -sf file.dat[tt]). In general, the [TT]-sf[tt] argument reads",
+    "selections from the provided file and assigns them to selection arguments",
+    "that have been specified up to that point, but for which no selections",
+    "have been provided.",
+    "As a special case, [TT]-sf[tt] provided on its own, without preceding",
+    "selection arguments, assigns the selections to all (yet unset) required",
+    "selections (i.e., those that would be promted interactively if no",
+    "selections are provided on the command line).[PAR]",
+
+    "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]",
@@ -128,18 +164,18 @@ const char *const CmdLineHelpText::text[] = {
     "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]",
-    "See \"help positions\" for more information on these options.",
+    "See the \"positions\" subtopic for more information on these options.",
 };
 
 struct EvaluationHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char EvaluationHelpText::name[] = "evaluation";
-const char EvaluationHelpText::title[] =
+const char        EvaluationHelpText::name[]  = "evaluation";
+const char        EvaluationHelpText::title[] =
     "Selection evaluation and optimization";
 const char *const EvaluationHelpText::text[] = {
     "Boolean evaluation proceeds from left to right and is short-circuiting",
@@ -172,15 +208,17 @@ const char *const EvaluationHelpText::text[] = {
 
 struct ExamplesHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char ExamplesHelpText::name[] = "examples";
-const char ExamplesHelpText::title[] =
+const char        ExamplesHelpText::name[]  = "examples";
+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]",
@@ -192,7 +230,7 @@ const char *const ExamplesHelpText::text[] = {
     "[PAR]",
 
     "All atoms farther than 1 nm of a fixed position:[BR]",
-    "  not within 1 of (1.2, 3.1, 2.4)",
+    "  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]",
@@ -214,33 +252,33 @@ const char *const ExamplesHelpText::text[] = {
 
 struct KeywordsHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char KeywordsHelpText::name[] = "keywords";
-const char KeywordsHelpText::title[] =
+const char        KeywordsHelpText::name[]  = "keywords";
+const char        KeywordsHelpText::title[] =
     "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",
-    "\"help KEYWORD\", where KEYWORD is the name of the keyword.",
+    "a subtopic KEYWORD, where KEYWORD is the name of the keyword.",
 };
 
 struct LimitationsHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char LimitationsHelpText::name[] = "limitations";
-const char LimitationsHelpText::title[] =
+const char        LimitationsHelpText::name[]  = "limitations";
+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]g_angle[tt] requires the index group to be made",
+    "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.",
@@ -251,18 +289,25 @@ const char *const LimitationsHelpText::text[] = {
     "[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.",
+    "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.",
 };
 
 struct PositionsHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char PositionsHelpText::name[] = "positions";
-const char PositionsHelpText::title[] =
+const char        PositionsHelpText::name[]  = "positions";
+const char        PositionsHelpText::title[] =
     "Specifying positions in selections";
 const char *const PositionsHelpText::text[] = {
     "Possible ways of specifying positions in selections are:[PAR]",
@@ -309,13 +354,13 @@ const char *const PositionsHelpText::text[] = {
 
 struct SyntaxHelpText
 {
-    static const char name[];
-    static const char title[];
+    static const char        name[];
+    static const char        title[];
     static const char *const text[];
 };
 
-const char SyntaxHelpText::name[] = "syntax";
-const char SyntaxHelpText::title[] =
+const char        SyntaxHelpText::name[]  = "syntax";
+const char        SyntaxHelpText::title[] =
     "Selection syntax";
 const char *const SyntaxHelpText::text[] = {
     "A set of selections consists of one or more selections, separated by",
@@ -352,7 +397,8 @@ const char *const SyntaxHelpText::text[] = {
     "[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 \"help positions\" for more details.[PAR]",
+    "expressions in various ways, see the \"positions\" subtopic for more",
+    "details.[PAR]",
 
     "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])",
@@ -360,6 +406,11 @@ const char *const SyntaxHelpText::text[] = {
     "The match type is automatically guessed from the string: if it contains",
     "other characters than letters, numbers, '*', or '?', it is interpreted",
     "as a regular expression.",
+    "To force the matching to use literal string matching, use",
+    "[TT]name = \"C*\"[tt] to match a literal C*.",
+    "To force other type of matching, use '?' or '~' in place of '=' to force",
+    "wildcard or regular expression matching, respectively.[PAR]",
+
     "Strings that contain non-alphanumeric characters should be enclosed in",
     "double quotes as in the examples. For other strings, the quotes are",
     "optional, but if the value conflicts with a reserved keyword, a syntax",
@@ -393,14 +444,15 @@ class KeywordDetailsHelpTopic : public AbstractSimpleHelpTopic
 {
     public:
         //! Initialize help topic for the given selection method.
-        explicit KeywordDetailsHelpTopic(const gmx_ana_selmethod_t &method)
-            : method_(method)
+        KeywordDetailsHelpTopic(const std::string         &name,
+                                const gmx_ana_selmethod_t &method)
+            : name_(name), method_(method)
         {
         }
 
         virtual const char *name() const
         {
-            return method_.name;
+            return name_.c_str();
         }
         virtual const char *title() const
         {
@@ -414,6 +466,7 @@ class KeywordDetailsHelpTopic : public AbstractSimpleHelpTopic
         }
 
     private:
+        std::string                name_;
         const gmx_ana_selmethod_t &method_;
 
         GMX_DISALLOW_COPY_AND_ASSIGN(KeywordDetailsHelpTopic);
@@ -429,7 +482,7 @@ class KeywordsHelpTopic : public CompositeHelpTopic<KeywordsHelpText>
     public:
         KeywordsHelpTopic();
 
-        virtual void writeHelp(File *file) const;
+        virtual void writeHelp(const HelpWriterContext &context) const;
 
     private:
         /*! \brief
@@ -443,17 +496,18 @@ class KeywordsHelpTopic : public CompositeHelpTopic<KeywordsHelpText>
          */
         typedef std::vector<std::pair<std::string,
                                       const gmx_ana_selmethod_t *> >
-                MethodList;
+            MethodList;
 
         /*! \brief
          * Prints a brief list of keywords (selection methods) available.
          *
-         * \param[in] file  Where to write the list.
-         * \param[in] type  Only methods that return this type are printed.
+         * \param[in] context  Context for printing the help.
+         * \param[in] type     Only methods that return this type are printed.
          * \param[in] bModifiers  If false, \ref SMETH_MODIFIER methods are
          *      excluded, otherwise only them are printed.
          */
-        void printKeywordList(File *file, e_selvalue_t type, bool bModifiers) const;
+        void printKeywordList(const HelpWriterContext &context,
+                              e_selvalue_t type, bool bModifiers) const;
 
         MethodList              methods_;
 };
@@ -463,93 +517,108 @@ KeywordsHelpTopic::KeywordsHelpTopic()
     // TODO: This is not a very elegant way of getting the list of selection
     // methods, but this needs to be rewritten in any case if/when #652 is
     // implemented.
-    gmx_sel_symtab_t *symtab;
-    _gmx_sel_symtab_create(&symtab);
-    gmx_ana_selmethod_register_defaults(symtab);
-    boost::shared_ptr<gmx_sel_symtab_t> symtabGuard(symtab, &_gmx_sel_symtab_free);
+    boost::scoped_ptr<SelectionParserSymbolTable> symtab(
+            new SelectionParserSymbolTable);
+    gmx_ana_selmethod_register_defaults(symtab.get());
 
-    gmx_sel_symrec_t *symbol = _gmx_sel_first_symbol(symtab, SYMBOL_METHOD);
-    while (symbol)
+    SelectionParserSymbolIterator symbol
+        = symtab->beginIterator(SelectionParserSymbol::MethodSymbol);
+    while (symbol != symtab->endIterator())
     {
-        const char *symname = _gmx_sel_sym_name(symbol);
-        const gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
+        const std::string         &symname = symbol->name();
+        const gmx_ana_selmethod_t *method  = symbol->methodValue();
         methods_.push_back(std::make_pair(std::string(symname), method));
         if (method->help.nlhelp > 0 && method->help.help != NULL)
         {
-            addSubTopic(HelpTopicPointer(new KeywordDetailsHelpTopic(*method)));
+            addSubTopic(HelpTopicPointer(
+                                new KeywordDetailsHelpTopic(symname, *method)));
         }
-        symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
+        ++symbol;
     }
 }
 
-void KeywordsHelpTopic::writeHelp(File *file) const
+void KeywordsHelpTopic::writeHelp(const HelpWriterContext &context) const
 {
-    writeBasicHelpTopic(file, *this, helpText());
-
-    /* Print the list of keywords */
-    file->writeLine();
-    file->writeLine("Keywords that select atoms by an integer property:");
-    file->writeLine("(use in expressions or like \"atomnr 1 to 5 7 9\")");
-    printKeywordList(file, INT_VALUE, false);
-
-    file->writeLine();
-    file->writeLine("Keywords that select atoms by a numeric property:");
-    file->writeLine("(use in expressions or like \"occupancy 0.5 to 1\")");
-    printKeywordList(file, REAL_VALUE, false);
-
-    file->writeLine();
-    file->writeLine("Keywords that select atoms by a string property:");
-    file->writeLine("(use like \"name PATTERN [PATTERN] ...\")");
-    printKeywordList(file, STR_VALUE, false);
-
-    file->writeLine();
-    file->writeLine("Additional keywords that directly select atoms:");
-    printKeywordList(file, GROUP_VALUE, false);
-
-    file->writeLine();
-    file->writeLine("Keywords that directly evaluate to positions:");
-    file->writeLine("(see also \"help positions\")");
-    printKeywordList(file, POS_VALUE, false);
-
-    file->writeLine();
-    file->writeLine("Additional keywords:");
-    printKeywordList(file, POS_VALUE, true);
-    printKeywordList(file, NO_VALUE, true);
+    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]");
+
+    // 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]");
+    printKeywordList(context, INT_VALUE, false);
+    context.writeTextBlock("[BR]");
+
+    context.writeTextBlock(
+            "Keywords that select atoms by a numeric property:[BR]"
+            "(use in expressions or like \"occupancy 0.5 to 1\")[BR]");
+    printKeywordList(context, REAL_VALUE, false);
+    context.writeTextBlock("[BR]");
+
+    context.writeTextBlock(
+            "Keywords that select atoms by a string property:[BR]"
+            "(use like \"name PATTERN [PATTERN] ...\")[BR]");
+    printKeywordList(context, STR_VALUE, false);
+    context.writeTextBlock("[BR]");
+
+    context.writeTextBlock(
+            "Additional keywords that directly select atoms:[BR]");
+    printKeywordList(context, GROUP_VALUE, false);
+    context.writeTextBlock("[BR]");
+
+    context.writeTextBlock(
+            "Keywords that directly evaluate to positions:[BR]"
+            "(see also \"positions\" subtopic)[BR]");
+    printKeywordList(context, POS_VALUE, false);
+    context.writeTextBlock("[BR]");
+
+    context.writeTextBlock("Additional keywords:[BR]");
+    printKeywordList(context, POS_VALUE, true);
+    printKeywordList(context, NO_VALUE, true);
 }
 
-void KeywordsHelpTopic::printKeywordList(File *file, e_selvalue_t type,
-                                         bool bModifiers) const
+void KeywordsHelpTopic::printKeywordList(const HelpWriterContext &context,
+                                         e_selvalue_t             type,
+                                         bool                     bModifiers) const
 {
+    File &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;
+        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 ? '*' : ' '));
+            file.writeString(formatString(" %c ", bHasHelp ? '*' : ' '));
             if (method.help.syntax != NULL)
             {
-                file->writeLine(method.help.syntax);
+                file.writeLine(method.help.syntax);
             }
             else
             {
-                const std::string &symname = iter->first;
-                file->writeString(symname);
+                std::string symname = iter->first;
                 if (symname != method.name)
                 {
-                    file->writeString(formatString(" (synonym for %s)", method.name));
+                    symname.append(formatString(" (synonym for %s)", method.name));
                 }
-                file->writeLine();
+                file.writeLine(symname);
             }
         }
     }
 }
 
-} // namespace
+}   // namespace
 
-/*! \cond internal */
+//! \cond libapi */
 HelpTopicPointer createSelectionHelpTopic()
 {
     CompositeHelpTopicPointer root(new CompositeHelpTopic<CommonHelpText>);
@@ -563,6 +632,6 @@ HelpTopicPointer createSelectionHelpTopic()
     root->registerSubTopic<SimpleHelpTopic<SyntaxHelpText> >();
     return move(root);
 }
-//! \cond
+//! \endcond
 
 } // namespace gmx