Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 : Copyright (c) 2012-2023 The plumed team
3 : (see the PEOPLE file at the root of the distribution for a list of names)
4 :
5 : See http://www.plumed.org for more information.
6 :
7 : This file is part of plumed, version 2.
8 :
9 : plumed is free software: you can redistribute it and/or modify
10 : it under the terms of the GNU Lesser General Public License as published by
11 : the Free Software Foundation, either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : plumed is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU Lesser General Public License for more details.
18 :
19 : You should have received a copy of the GNU Lesser General Public License
20 : along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 : #ifndef __PLUMED_tools_Keywords_h
23 : #define __PLUMED_tools_Keywords_h
24 : #include <vector>
25 : #include <string>
26 : #include <string_view>
27 : #include <map>
28 : #include <variant>
29 :
30 : #include "Exception.h"
31 : #include "BitmaskEnum.h"
32 :
33 : namespace PLMD {
34 :
35 : class Log;
36 :
37 : /// This class holds the keywords and their documentation
38 : class Keywords {
39 : /// This class lets me pass keyword types easily
40 : struct KeyType {
41 : enum class keyStyle {hidden,compulsory,flag,optional,atoms,unknown};
42 : keyStyle style;
43 : static keyStyle keyStyleFromString(std::string_view type );
44 : explicit KeyType( keyStyle type );
45 : explicit KeyType( std::string_view type );
46 : void setStyle( std::string_view type );
47 : bool isCompulsory() const {
48 464418 : return (style==keyStyle::compulsory);
49 : }
50 : bool isFlag() const {
51 1045027 : return (style==keyStyle::flag);
52 : }
53 : bool isOptional() const {
54 18086 : return (style==keyStyle::optional);
55 : }
56 : bool isAtomList() const {
57 1278702 : return (style==keyStyle::atoms);
58 : }
59 : bool isHidden() const {
60 : return (style==keyStyle::hidden);
61 : }
62 1886971 : std::string toString() const {
63 : //if you add a style and you forget to update this function the compiler will refuse to compile
64 1886971 : switch(style) {
65 : case keyStyle::compulsory:
66 145798 : return "compulsory";
67 : case keyStyle::optional:
68 658023 : return "optional";
69 : case keyStyle::atoms:
70 319358 : return "atoms";
71 : case keyStyle::flag:
72 653162 : return "flag";
73 : case keyStyle::hidden:
74 110630 : return "hidden";
75 0 : default:
76 0 : plumed_massert(false,"unknown keyword type");
77 : }
78 : return "unknown";
79 : }
80 : };
81 :
82 : public:
83 : enum class argType {scalar=1,vector=1<<2,matrix=1<<3,grid=1<<4};
84 : enum class componentType {scalar=1,vector=1<<2,matrix=1<<3,grid=1<<4,atoms=1<<5,atom=1<<6};
85 : private:
86 : /// Is this an action or driver (this bool affects what style==atoms does in print)
87 : bool isaction=true;
88 : /// This allows us to overwrite the behavior of the atoms type in analysis actions
89 : bool isatoms=true;
90 : /// The name of the action that has this set of keywords
91 : std::string thisactname;
92 : /// The action to use in place of this deprecated action
93 : std::string replaceaction="none";
94 :
95 : struct keyInfo {
96 : /// Whether the keyword is compulsory, optional...
97 : KeyType type{KeyType::keyStyle::unknown};
98 : /// The documentation for the keyword
99 : std::string docstring;
100 : /// The default values (if there are default values) for compulsory keywords or flags
101 : std::variant<std::monostate,std::string,bool> defaultValue;
102 : ///The type of the argument if this keywords accepts arguments
103 : std::variant<std::monostate,argType>argument_type;
104 : /// The tags for atoms - we use this so the manual can differentiate between different ways of specifying atoms
105 : std::string atomtag;//no noeed for optional, since the type will state if this is needed
106 : ///This stores any action documentation that we should link to
107 : std::string linkaction;
108 : /// Do we allow stuff like key1, key2 etc
109 : bool allowmultiple;
110 : keyInfo();
111 : //these functions are not neeeded (this is a struct), but are useful in constructing the key
112 : keyInfo& setType(KeyType t);
113 : keyInfo& setDocString(std::string_view d);
114 : keyInfo& setDefaultValue(std::string_view d);
115 : keyInfo& setDefaultFlag(bool a);
116 : keyInfo& setArgumentType(argType a);
117 : keyInfo& setAllowMultiple(bool a);
118 : keyInfo& setLinkedAction(std::string_view a);
119 : bool isArgument() const;
120 : };
121 : ///Add o reserve a new keyword (internal tool)
122 : void addOrReserve( std::string_view keytype, std::string_view key, std::string_view docstring, bool reserve );
123 : //std::less<void> make some magic and makes find and [] work with string_view
124 : /// Stores the keywords along with their settings
125 : std::map<std::string,keyInfo,std::less<void>> keywords;
126 : /// The names of the allowed keywords, in order of declaration
127 : std::vector<std::string> keys;
128 : /// The names of the reserved keywords, in order of declaration
129 : std::vector<std::string> reserved_keys;
130 : struct component {
131 : /// The keyword that turns on this component
132 : std::string key;
133 : /// The documentation for the component
134 : std::string docstring;
135 : /// The type of the component
136 : componentType type;
137 : component();
138 : //these functions are not neeeded (this is a struct), but are useful in constructing the component
139 : component& setKey(std::string_view k);
140 : component& setDocstring(std::string_view d);
141 : component& setType(componentType t);
142 : };
143 : //the "exists component" is stored in the map keys
144 : std::map<std::string,component,std::less<void>> components;
145 : /// The string that should be printed out to describe how the components work for this particular action
146 : std::string cstring;
147 : /// The names of all the possible components for an action, in order of their (first) declaration
148 : std::vector<std::string> cnames;
149 : /// The list of actions that are needed by this action
150 : std::vector<std::string> neededActions;
151 : /// List of suffixes that can be used with this action
152 : std::vector<std::string> actionNameSuffixes;
153 : /// List of doi's that should appear in the manual
154 : std::vector<std::string> doilist;
155 : /// Print the documentation for the named keyword in html
156 : void print_html_item( const std::string& ) const;
157 : public:
158 : /// Constructor
159 187743 : Keywords() {}
160 : ///
161 : void isDriver() {
162 10836 : isaction=false;
163 : }
164 : ///
165 : void isAnalysis() {
166 : isatoms=false;
167 : }
168 : /// find out whether flag key is on or off by default.
169 : bool getLogicalDefault(const std::string & key, bool& def ) const ;
170 : /// Get the value of the default for the keyword named key
171 : bool getDefaultValue(const std::string & key, std::string& def ) const ;
172 : /// Return the number of defined keywords
173 : unsigned size() const;
174 : /// Check if numbered keywords are allowed for this action
175 : bool numbered( const std::string & k ) const;
176 : /// Get the ordered list of active keywords (not the reserved ones)
177 : const std::vector<std::string>& getKeys() const {
178 : return keys;
179 : }
180 : //Get the ordered list of arguments
181 : std::vector<std::string> getArgumentKeys() const;
182 : /// Return the ith keyword
183 : std::string getKeyword( const unsigned i ) const;
184 : /// Get the documentation for a particular keyword
185 : std::string getKeywordDocs( const std::string& key ) const;
186 : /// Print the documentation to the log file (used by PLMD::Action::error)
187 : void print( Log& log ) const ;
188 : /// Print the documentation to a file (use by PLUMED::CLTool::readCommandLineArgs)
189 : void print( FILE* out ) const ;
190 : /// Get the help string
191 : std::string getHelpString() const ;
192 : /// Print a file containing the list of keywords for a particular action (used for spell checking)
193 : void print_spelling() const ;
194 : /// Reserve a keyword
195 : void reserve( std::string_view keytype, std::string_view key, std::string_view docstring );
196 : /// Reserve a flag
197 : void reserveFlag( const std::string & key, bool defaultValue, const std::string & docstring );
198 : /// Use one of the reserved keywords
199 : void use( std::string_view k );
200 : /// append the data from another Keywords object (**only** keywords, reserved keywords and components)
201 : void add( const Keywords& keys );
202 : /// Add a new keyword of type t with name k and description d
203 : void add( std::string_view keytype, std::string_view key, std::string_view docstring );
204 : /// Add a new compulsory keyword (t must equal compulsory) with name k, default value def and description d
205 : void add( std::string_view keytype, std::string_view key, std::string_view defaultValue, std::string_view docstring );
206 : /// Add a falg with name k that is by default on if def is true and off if def is false. d should provide a description of the flag
207 : void addFlag(std::string_view key, bool defaultValue, std::string_view docstring);
208 : /// Remove the keyword with name k
209 : void remove( const std::string & k );
210 : /// Check if there is a keyword with name k
211 : bool exists( std::string_view k ) const ;
212 : /// Check the keyword k has been reserved
213 : bool reserved( std::string_view k ) const ;
214 : /// Get the type for the keyword with string k
215 : std::string getStyle(const std::string & k ) const ;
216 : /// Check if the keyword with name k has style t
217 : bool style( const std::string & k, const std::string & t ) const ;
218 : /// Print an html version of the documentation
219 : void print_html() const ;
220 : /// Print keywords in form readable by vim
221 : void print_vim() const ;
222 : /// Print the template version for the documentation
223 : void print_template( const std::string& actionname, bool include_optional) const ;
224 : /// Change part of the style of a keyword
225 : ///
226 : /// The standard usecase for this method is creating a compulsory or an atom(s) numbered keyword.
227 : /// For example:
228 : /// @code{.cpp}
229 : /// keys.add("numbered","ATOMS","the atoms involved in each of the contacts you wish to calculate. "
230 : /// "Keywords like ATOMS1, ATOMS2, ATOMS3,... should be listed and one contact will be "
231 : /// "calculated for each ATOM keyword you specify.");
232 : /// keys.reset_style("ATOMS","atoms");
233 : /// keys.add("numbered","SWITCH","The switching functions to use for each of the contacts in your map. "
234 : /// "You can either specify a global switching function using SWITCH or one "
235 : /// "switching function for each contact. Details of the various switching "
236 : /// "functions you can use are provided on \\ref switchingfunction.");
237 : /// keys.reset_style("SWITCH","compulsory");
238 : /// @endcode
239 : /// @note Note that some option of the selected keyword may not change. In particular:
240 : /// - A numbered keyword will change the style but the keyInfo::allowmultiple
241 : /// will remain set to `true`
242 : /// - An eventual keyInfo::atomtag will not be changed unless the style is set to
243 : /// an atomlist
244 : void reset_style( const std::string & k, const std::string & style );
245 : /// Clear everything from the keywords object.
246 : /// Not actually needed if your Keywords object is going out of scope.
247 : void destroyData();
248 : /// Set the text that introduces how the components for this action are introduced
249 : void setComponentsIntroduction( const std::string& instr );
250 : /// Add the description of the value
251 : void setValueDescription( const std::string& type, const std::string& descr );
252 : /// @todo prepend[[deprecated("Please specify the data type for the argument from scalar/vector/matrix/grid with the Keywords::argType enum")]]
253 : void setValueDescription( componentType type, const std::string& descr );
254 : /// Add a potential component which can be output by this particular action
255 : [[deprecated("Use addOutputComponent with four argument and specify valid types for value from scalar/vector/matrix/grid")]]
256 : void addOutputComponent( const std::string& name, const std::string& key, const std::string& descr );
257 : /// @todo prepend[[deprecated("Please specify the data type for the argument from scalar/vector/matrix/grid with the Keywords::argType enum")]]
258 : void addOutputComponent( const std::string& name, const std::string& key, const std::string& type, const std::string& descr );
259 : /// Add a potential component which can be output by this particular action
260 : void addOutputComponent( const std::string& name, const std::string& key, componentType type, const std::string& descr );
261 : /// Remove a component that can be output by this particular action
262 : void removeOutputComponent( const std::string& name );
263 : /// Has a component with this name been added?
264 : bool outputComponentExists( const std::string& name ) const ;
265 : /// Check that type for component has been documented correctly
266 : bool componentHasCorrectType( const std::string& name, const std::size_t& rank, const bool& hasderiv ) const ;
267 : /// Create the documentation for a keyword that reads arguments
268 : /// @todo prepend [[deprecated("Please specify the data type for the argument from scalar/vector/matrix/grid with the Keywords::argType enum")]]
269 : void addInputKeyword( const std::string & keyType, const std::string & key, const std::string & dataType, const std::string & docstring );
270 : /// Create the documentation for a keyword that reads arguments
271 : void addInputKeyword( const std::string & keyType, const std::string & key, argType dataType, const std::string & docstring );
272 : /// Create the documentation for a keyword that reads arguments
273 : /// @todo prepend[[deprecated("Please specify the data type for the argument from scalar/vector/matrix/grid with the Keywords::argType enum")]]
274 : void addInputKeyword( const std::string & keyType, const std::string & key, const std::string & dataType, const std::string& defaultValue, const std::string & docstring );
275 : /// Create the documentation for a keyword that reads arguments
276 : void addInputKeyword( const std::string & keyType, const std::string & key, argType dataType, const std::string& defaultValue, const std::string & docstring );
277 : /// Check the documentation of the argument types
278 : bool checkArgumentType( const std::size_t& rank, const bool& hasderiv ) const ;
279 : /// Get the valid types that can be used as argument for this keyword
280 : std::string getArgumentType( const std::string& name ) const ;
281 : /// Get the flag that forces thie named component to be calculated
282 : std::string getOutputComponentFlag( const std::string& name ) const ;
283 : /// Get the type for the named output component
284 : std::string getOutputComponentType( const std::string& name ) const ;
285 : /// Get the description of the named component
286 : std::string getOutputComponentDescription( const std::string& name ) const ;
287 : /// Get the full ordered list of output components
288 : const std::vector<std::string>& getOutputComponents() const {
289 4726 : return cnames;
290 : }
291 : /// Get the description of a particular keyword
292 : std::string getKeywordDescription( const std::string& name ) const ;
293 : /// Get the description of a particular keyword
294 : std::string getTooltip( const std::string& name ) const ;
295 : /// Note that another actions is required to create this shortcut
296 : void needsAction( const std::string& name );
297 : /// Check if the requested action is in the list of the needed actions
298 : bool isActionNeeded( std::string_view name ) const ;
299 : /// Add a suffix to the list of possible action name suffixes
300 : void addActionNameSuffix( const std::string& suffix );
301 : /** @brief checks that name is is a composition of basename and one of the possible suffixes
302 :
303 : Cycles on the registered suffixed and return true if the combination
304 : `basename+suffix` equals to the passed name
305 : */
306 : bool isActionSuffixed( std::string_view name, std::string_view basename) const ;
307 : /// Get the list of keywords that are needed by this action
308 : const std::vector<std::string>& getNeededKeywords() const ;
309 : /// Return the name of the action that has this set of keywords
310 : std::string getDisplayName() const ;
311 : /// Set the display name
312 : void setDisplayName( const std::string& name );
313 : /// Get the action that should be used to replace this one if action has been deprecated
314 : std::string getReplacementAction() const ;
315 : /// Note that this action has been deprecated
316 : void setDeprecated( const std::string& name );
317 : /// Add a DOI to the list in the manual page for this action
318 : void addDOI( const std::string& doi );
319 : /// Get the list of DOI
320 : const std::vector<std::string>& getDOIList() const ;
321 : /// Create a link to this action in the documentation for it
322 : void linkActionInDocs( const std::string& k, const std::string& action );
323 : /// Get any actions that are linked to this keyword
324 : std::string getLinkedActions( const std::string& key ) const ;
325 : };
326 :
327 : //the following templates specializations make the bitmask enum work with the
328 : // bitwise operators `|`, `&` and the "valid" function (valid converts to bool the result of a "mask operation")
329 : template<>
330 : struct enum_traits::BitmaskEnum< Keywords::componentType > {
331 : static constexpr bool has_valid = true;
332 : static constexpr bool has_bit_or = true;
333 : static constexpr bool has_bit_and = true;
334 : };
335 :
336 : template<>
337 : struct enum_traits::BitmaskEnum< Keywords::argType > {
338 : static constexpr bool has_valid = true;
339 : static constexpr bool has_bit_or = true;
340 : static constexpr bool has_bit_and = true;
341 : };
342 :
343 : std::string toString(Keywords::argType at);
344 : /**
345 : * Converts a string to the corresponding Keywords::argType.
346 : *
347 : * @param str The string to convert.
348 : * @return The Keywords::argType corresponding to the string.
349 : * @throws std::invalid_argument If the string does not match any enum value.
350 : */
351 : Keywords::argType stoat(std::string_view str);
352 : std::string toString(Keywords::componentType at);
353 :
354 : /**
355 : * Converts a string to the corresponding Keywords::componentType.
356 : * @param str The string to convert.
357 : * @return The Keywords::componentType corresponding to the string.
358 : * @throws std::invalid_argument if the string does not match any enum value.
359 : */
360 : Keywords::componentType stoct(std::string_view str) ;
361 :
362 : } // namespace PLMD
363 :
364 : #endif
|