LCOV - code coverage report
Current view: top level - tools - Keywords.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 16 18 88.9 %
Date: 2026-11-05 10:19:04 Functions: 2 2 100.0 %

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

Generated by: LCOV version 1.16