/*
+ * 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"
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[] = {
"Selections are used to select atoms/molecules/residues for analysis.",
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.",
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[] = {
"If no selections are provided on the command line, you are prompted to",
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",
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
"[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]",
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.",
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.",
"[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]",
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",
"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",
{
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
{
}
private:
+ std::string name_;
const gmx_ana_selmethod_t &method_;
GMX_DISALLOW_COPY_AND_ASSIGN(KeywordDetailsHelpTopic);
public:
KeywordsHelpTopic();
- virtual void writeHelp(File *file) const;
+ virtual void writeHelp(const HelpWriterContext &context) const;
private:
/*! \brief
*/
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_;
};
// 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 \"positions\" subtopic)");
- 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>);
root->registerSubTopic<SimpleHelpTopic<SyntaxHelpText> >();
return move(root);
}
-//! \cond
+//! \endcond
} // namespace gmx