Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2022,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 : #include "CLTool.h" 23 : #include "core/CLToolRegister.h" 24 : #include "tools/Tools.h" 25 : #include "config/Config.h" 26 : #include "core/ActionRegister.h" 27 : #include "core/GenericMolInfo.h" 28 : #include "core/ModuleMap.h" 29 : #include <cstdio> 30 : #include <string> 31 : #include <iostream> 32 : 33 : namespace PLMD { 34 : namespace cltools { 35 : 36 : //+PLUMEDOC TOOLS gen_json 37 : /* 38 : gen_json constructs a json file that includes a dictionary of actions, the keywords for those actions and the components and outputs this to standard output 39 : 40 : \par Examples 41 : 42 : The following command generates the json file 43 : \verbatim 44 : plumed gen_json 45 : \endverbatim 46 : 47 : 48 : */ 49 : //+ENDPLUMEDOC 50 : 51 : class GenJson : public CLTool { 52 : private: 53 : std::string version; 54 : void printHyperlink(std::string action ); 55 : public: 56 : static void registerKeywords( Keywords& keys ); 57 : explicit GenJson(const CLToolOptions& co ); 58 : int main(FILE* in, FILE*out,Communicator& pc) override; 59 4 : std::string description()const override { 60 4 : return "print out a json file that contains the pluemd syntax"; 61 : } 62 : }; 63 : 64 15953 : PLUMED_REGISTER_CLTOOL(GenJson,"gen_json") 65 : 66 5316 : void GenJson::registerKeywords( Keywords& keys ) { 67 5316 : CLTool::registerKeywords( keys ); 68 10632 : keys.add("compulsory","--actions","a file containing one line descriptions of the various actions"); 69 5316 : } 70 : 71 5 : GenJson::GenJson(const CLToolOptions& co ): 72 : CLTool(co), 73 5 : version("master") 74 : { 75 5 : inputdata=commandline; 76 10 : if( config::getVersionLong().find("dev")==std::string::npos ) version="v"+config::getVersion(); 77 5 : } 78 : 79 482 : void GenJson::printHyperlink( std::string action ) { 80 964 : std::cout<<" \"hyperlink\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/"; 81 6044 : std::transform(action.begin(), action.end(), action.begin(), [](unsigned char c) { return std::tolower(c); }); 82 : while(true) { 83 802 : std::size_t und=action.find_first_of("_"); 84 802 : if( und==std::string::npos ) break; 85 320 : std::string first=action.substr(0,und); 86 4192 : for(auto c : first ) { if( isdigit(c) ) std::cout<<c; else std::cout<<"_"<<c; } 87 640 : std::cout<<"_"; action=action.substr(und+1); 88 320 : } 89 7094 : for(auto c : action ) { if( isdigit(c) ) std::cout<<c; else std::cout<<"_"<<c; } 90 482 : std::cout<<".html\","<<std::endl; 91 482 : } 92 : 93 1 : int GenJson::main(FILE* in, FILE*out,Communicator& pc) { 94 1 : std::string line(""), actionfile; parse("--actions",actionfile); 95 1 : IFile myfile; myfile.open(actionfile); bool stat; 96 : std::map<std::string,std::string> action_map; 97 464 : while((stat=myfile.getline(line))) { 98 463 : std::size_t col = line.find_first_of(":"); std::string docs = line.substr(col+1); 99 463 : if( docs.find("\\")!=std::string::npos ) error("found invalid backslash character in first line of documentation for action " + line.substr(0,col) ); 100 926 : action_map.insert(std::pair<std::string,std::string>( line.substr(0,col), docs ) ); 101 : } 102 1 : myfile.close(); 103 : 104 : // Cycle over all the action names 105 1 : std::cout<<"{"<<std::endl; 106 : // Get the vimlink 107 2 : std::cout<<" \"vimlink\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/_vim_syntax.html\","<<std::endl; 108 : // And the replicas link 109 2 : std::cout<<" \"replicalink\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/special-replica-syntax.html\","<<std::endl; 110 : // Get the names of all the actions 111 1 : std::vector<std::string> action_names( actionRegister().getActionNames() ); std::vector<std::string> allmodules; 112 439 : for(unsigned i=0; i<action_names.size(); ++i) { 113 1314 : std::cout<<" \""<<action_names[i]<<'"'<<": {"<<std::endl; std::string action=action_names[i]; 114 : // Handle conversion of action names to links 115 438 : printHyperlink( action ); 116 876 : std::cout<<" \"description\" : \""<<action_map[action_names[i]]<<"\",\n"; 117 876 : bool found=false; std::string thismodule = getModuleMap().find(action_names[i])->second; 118 5780 : for(unsigned i=0; i<allmodules.size(); ++i) { 119 5736 : if( allmodules[i]==thismodule ) { found=true; break; } 120 : } 121 438 : if( !found ) allmodules.push_back( thismodule ); 122 876 : std::cout<<" \"module\" : \""<<thismodule<<"\",\n"; 123 : // Now output keyword information 124 438 : Keywords keys; actionRegister().getKeywords( action_names[i], keys ); 125 876 : std::cout<<" \"displayname\" : \""<<keys.getDisplayName()<<"\",\n"; 126 438 : std::cout<<" \"syntax\" : {"<<std::endl; 127 5464 : for(unsigned j=0; j<keys.size(); ++j) { 128 5026 : std::string defa = "", desc = keys.getKeywordDescription( keys.getKeyword(j) ); 129 5026 : if( desc.find("default=")!=std::string::npos ) { 130 1637 : std::size_t defstart = desc.find_first_of("="), brac=desc.find_first_of(")"); 131 4911 : defa = desc.substr(defstart+1,brac-defstart-2); desc = desc.substr(brac+1); 132 : } 133 5026 : std::size_t dot=desc.find_first_of("."); std::string mydescrip = desc.substr(0,dot); 134 5026 : if( mydescrip.find("\\")!=std::string::npos ) error("found invalid backslash character documentation for keyword " + keys.getKeyword(j) + " in action " + action_names[i] ); 135 10052 : std::string argtype = keys.getArgumentType( keys.getKeyword(j) ); 136 6116 : if( argtype.length()>0 ) std::cout<<" \""<<keys.getKeyword(j)<<"\" : { \"type\": \""<<keys.getStyle(keys.getKeyword(j))<<"\", \"description\": \""<<mydescrip<<"\", \"multiple\": "<<keys.numbered( keys.getKeyword(j) )<<", \"argtype\": \""<<argtype<<"\"}"; 137 12963 : else if( defa.length()>0 ) std::cout<<" \""<<keys.getKeyword(j)<<"\" : { \"type\": \""<<keys.getStyle(keys.getKeyword(j))<<"\", \"description\": \""<<mydescrip<<"\", \"multiple\": "<<keys.numbered( keys.getKeyword(j) )<<", \"default\": \""<<defa<<"\"}"; 138 15885 : else std::cout<<" \""<<keys.getKeyword(j)<<"\" : { \"type\": \""<<keys.getStyle(keys.getKeyword(j))<<"\", \"description\": \""<<mydescrip<<"\", \"multiple\": "<<keys.numbered( keys.getKeyword(j) )<<"}"; 139 5830 : if( j==keys.size()-1 && !keys.exists("HAS_VALUES") ) std::cout<<std::endl; else std::cout<<","<<std::endl; 140 : } 141 876 : if( keys.exists("HAS_VALUES") ) { 142 366 : std::cout<<" \"output\" : {"<<std::endl; 143 366 : std::vector<std::string> components( keys.getOutputComponents() ); 144 : // Check if we have a value 145 : bool hasvalue=true; 146 812 : for(unsigned k=0; k<components.size(); ++k) { 147 1600 : if( keys.getOutputComponentFlag( components[k] )=="default" ) { hasvalue=false; break; } 148 : } 149 1681 : for(unsigned k=0; k<components.size(); ++k) { 150 2630 : std::string compname=components[k]; if( components[k]==".#!value" ) { hasvalue=false; compname="value"; } 151 2630 : std::cout<<" \""<<compname<<"\" : {"<<std::endl; 152 2630 : std::cout<<" \"flag\": \""<<keys.getOutputComponentFlag( components[k] )<<"\","<<std::endl; 153 3945 : std::cout<<" \"type\": \""<<keys.getOutputComponentType( components[k] )<<"\","<<std::endl; 154 1315 : std::string desc=keys.getOutputComponentDescription( components[k] ); 155 1315 : std::size_t dot=desc.find_first_of("."); std::string mydescrip = desc.substr(0,dot); 156 1315 : if( mydescrip.find("\\")!=std::string::npos ) error("found invalid backslash character documentation for output component " + compname + " in action " + action_names[i] ); 157 2630 : std::cout<<" \"description\": \""<<mydescrip<<"\""<<std::endl; 158 1315 : if( k==components.size()-1 ) std::cout<<" }"<<std::endl; else std::cout<<" },"<<std::endl; 159 : } 160 366 : if( hasvalue && components.size()==0 ) printf("WARNING: no components have been registered for action %s \n", action_names[i].c_str() ); 161 366 : std::cout<<" }"<<std::endl; 162 : 163 366 : } 164 438 : std::cout<<" },"<<std::endl; 165 438 : if( keys.getNeededKeywords().size()>0 ) { 166 122 : std::vector<std::string> neededActions( keys.getNeededKeywords() ); 167 244 : std::cout<<" \"needs\" : ["<<"\""<<neededActions[0]<<"\""; 168 1006 : for(unsigned j=1; j<neededActions.size(); ++j) std::cout<<", \""<<neededActions[j]<<"\""; 169 122 : std::cout<<"],"<<std::endl; 170 122 : } 171 : // This ensures that \n is replaced by \\n 172 438 : std::string unsafen="\n", safen="\\n", helpstr = keys.getHelpString(); 173 438 : for( std::size_t pos = helpstr.find("\n"); 174 11106 : pos != std::string::npos; 175 10668 : pos = helpstr.find("\n", pos) 176 10668 : ) { helpstr.replace(pos, unsafen.size(), safen); pos += safen.size(); } 177 876 : std::cout<<" \"help\" : \""<<helpstr<<"\"\n"; 178 438 : std::cout<<" },"<<std::endl; 179 438 : } 180 : // Get all the special groups 181 1 : std::cout<<" \"groups\" : {"<<std::endl; 182 1 : std::cout<<" \"@allatoms\" : { \n"<<std::endl; 183 1 : std::cout<<" \"description\" : \"refers to all the MD codes atoms and PLUMEDs vatoms\","<<std::endl; 184 2 : std::cout<<" \"link\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/_group.html\""<<std::endl; 185 1 : std::cout<<" },"<<std::endl; 186 1 : std::cout<<" \"@mdatoms\" : { \n"<<std::endl; 187 1 : std::cout<<" \"description\" : \"refers to all the MD codes atoms but not PLUMEDs vatoms\","<<std::endl; 188 2 : std::cout<<" \"link\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/_group.html\""<<std::endl; 189 1 : std::cout<<" },"<<std::endl; 190 1 : std::cout<<" \"@ndx\" : { \n"<<std::endl; 191 1 : std::cout<<" \"description\" : \"load a group from a GROMACS index file\","<<std::endl; 192 2 : std::cout<<" \"link\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/_group.html\""<<std::endl; 193 : // Now print all the special keywords in molinfo 194 1 : std::map<std::string,std::string> specials( GenericMolInfo::getSpecialKeywords() ); 195 36 : for(auto const& s : specials ) { 196 35 : std::cout<<" },"<<std::endl; 197 70 : std::cout<<" \""<<s.first<<"\" : { \n"<<std::endl; 198 70 : std::cout<<" \"description\" : \""<<s.second<<"\","<<std::endl; 199 70 : std::cout<<" \"link\" : \"https://www.plumed.org/doc-"<<version<<"/user-doc/html/_m_o_l_i_n_f_o.html\""<<std::endl; 200 : } 201 1 : std::cout<<" }"<<std::endl; 202 1 : std::cout<<" },"<<std::endl; 203 1 : std::cout<<" \"modules\" : {"<<std::endl; 204 2 : std::cout<<" \""<<allmodules[0]<<"\" : { "<<std::endl; 205 1 : printHyperlink( allmodules[0] ); 206 1 : std::cout<<" \"description\" : \"A module that will be used for something\""<<std::endl; 207 44 : for(unsigned i=1; i<allmodules.size(); ++i) { 208 43 : std::cout<<" },"<<std::endl; 209 86 : std::cout<<" \""<<allmodules[i]<<"\" : { "<<std::endl; 210 43 : printHyperlink( allmodules[i] ); 211 43 : std::cout<<" \"description\" : \"A module that will be used for something\""<<std::endl; 212 : } 213 1 : std::cout<<" }"<<std::endl; 214 1 : std::cout<<" }"<<std::endl; 215 1 : std::cout<<"}"<<std::endl; 216 1 : return 0; 217 2 : } 218 : 219 : } // End of namespace 220 : }