All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Keywords.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 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-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
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 "Keywords.h"
23 #include "Log.h"
24 #include "Tools.h"
25 #include <iostream>
26 
27 namespace PLMD{
28 
29 Keywords::KeyType::KeyType( const std::string& type ){
30  if( type=="compulsory" ){
32  } else if( type=="flag" ){
33  style=flag;
34  } else if( type=="optional" ){
36  } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){
37  style=atoms;
38  } else if( type=="hidden" ){
39  style=hidden;
40  } else {
41  plumed_massert(false,"invalid keyword specifier " + type);
42  }
43 }
44 
45 void Keywords::KeyType::setStyle( const std::string& type ){
46  if( type=="compulsory" ){
47  style=compulsory;
48  } else if( type=="flag" ){
49  style=flag;
50  } else if( type=="optional" ){
51  style=optional;
52  } else if( type.find("atoms")!=std::string::npos || type.find("residues")!=std::string::npos ){
53  style=atoms;
54  } else if( type=="hidden" ){
55  style=hidden;
56  } else {
57  plumed_massert(false,"invalid keyword specifier " + type);
58  }
59 }
60 
61 void Keywords::add( const Keywords& newkeys ){
63 }
64 
65 void Keywords::copyData( std::vector<std::string>& kk, std::vector<std::string>& rk, std::map<std::string,KeyType>& tt, std::map<std::string,bool>& am,
66  std::map<std::string,std::string>& docs, std::map<std::string,bool>& bools, std::map<std::string,std::string>& nums,
67  std::map<std::string,std::string>& atags, std::vector<std::string>& cnam, std::map<std::string,std::string>& ck,
68  std::map<std::string,std::string>& cd ) const {
69  for(unsigned i=0;i<keys.size();++i){
70  std::string thiskey=keys[i];
71  for(unsigned j=0;j<kk.size();++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
72  for(unsigned j=0;j<rk.size();++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
73  kk.push_back( thiskey );
74  plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
75  tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
76  if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
77  plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
78  am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
79  plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
80  docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
81  if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
82  if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
83  }
84  for(unsigned i=0;i<reserved_keys.size();++i){
85  std::string thiskey=reserved_keys[i];
86  for(unsigned j=0;j<kk.size();++j) plumed_massert( thiskey!=kk[j], "keyword " + thiskey + " is in twice" );
87  for(unsigned j=0;j<rk.size();++j) plumed_massert( thiskey!=rk[j], "keyword " + thiskey + " is in twice" );
88  rk.push_back( thiskey );
89  plumed_massert( types.count( thiskey ), "no type data on keyword " + thiskey + " to copy" );
90  tt.insert( std::pair<std::string,KeyType>( thiskey,types.find(thiskey)->second) );
91  if( (types.find(thiskey)->second).isAtomList() ) atags.insert( std::pair<std::string,std::string>( thiskey,atomtags.find(thiskey)->second) );
92  plumed_massert( allowmultiple.count( thiskey ), "no numbered data on keyword " + thiskey + " to copy" );
93  am.insert( std::pair<std::string,bool>(thiskey,allowmultiple.find(thiskey)->second) );
94  plumed_massert( documentation.count( thiskey ), "no documentation for keyword " + thiskey + " to copy" );
95  docs.insert( std::pair<std::string,std::string>(thiskey,documentation.find(thiskey)->second) );
96  if( booldefs.count( thiskey ) ) bools.insert( std::pair<std::string,bool>( thiskey,booldefs.find(thiskey)->second) );
97  if( numdefs.count( thiskey ) ) nums.insert( std::pair<std::string,std::string>( thiskey,numdefs.find(thiskey)->second) );
98  }
99  for(unsigned i=0;i<cnames.size();++i){
100  std::string thisnam=cnames[i];
101  for(unsigned j=0;j<cnam.size();++j) plumed_massert( thisnam!=cnam[j], "component " + thisnam + " is in twice" );
102  cnam.push_back( thisnam );
103  plumed_massert( ckey.count( thisnam ), "no keyword data on component " + thisnam + " to copy" );
104  ck.insert( std::pair<std::string,std::string>( thisnam, ckey.find(thisnam)->second) );
105  plumed_massert( cdocs.count( thisnam ), "no documentation on component " + thisnam + " to copy" );
106  cd.insert( std::pair<std::string,std::string>( thisnam, cdocs.find(thisnam)->second) );
107  }
108 }
109 
110 void Keywords::reserve( const std::string & t, const std::string & k, const std::string & d, const bool isvessel ){
111  plumed_assert( !exists(k) && !reserved(k) );
112  std::string fd, lowkey=k;
113  std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
114  if( t=="numbered" ){
115  if(isvessel){
116  fd = d + " The final value can be referenced using <em>label</em>." + lowkey +
117  ". You can use multiple instances of this keyword i.e. " +
118  k +"1, " + k + "2, " + k + "3... The corresponding values are then "
119  "referenced using <em>label</em>."+ lowkey +"-1, <em>label</em>." + lowkey +
120  "-2, <em>label</em>." + lowkey + "-3...";
121  } else {
122  fd = d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
123  }
124  allowmultiple.insert( std::pair<std::string,bool>(k,true) );
125  types.insert( std::pair<std::string,KeyType>(k,KeyType("optional")) );
126  } else {
127  if(isvessel){
128  fd = d + " The final value can be referenced using <em>label</em>." + lowkey + ".";
129  } else {
130  fd = d;
131  }
132  allowmultiple.insert( std::pair<std::string,bool>(k,false) );
133  types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
134  if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
135  }
136  documentation.insert( std::pair<std::string,std::string>(k,fd) );
137  reserved_keys.push_back(k);
138 }
139 
140 void Keywords::reserveFlag( const std::string & k, const bool def, const std::string & d, const bool isvessel ){
141  plumed_assert( !exists(k) && !reserved(k) );
142  std::string defstr;
143  if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
144  types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
145  std::string fd,lowkey=k; std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
146  if(isvessel) fd=defstr + d + " The final value can be referenced using <em>label</em>." + lowkey;
147  else fd=defstr + d;
148  documentation.insert( std::pair<std::string,std::string>(k,fd) );
149  allowmultiple.insert( std::pair<std::string,bool>(k,false) );
150  booldefs.insert( std::pair<std::string,bool>(k,def) );
151  reserved_keys.push_back(k);
152 }
153 
154 void Keywords::use( const std::string & k ){
155  plumed_massert( reserved(k), "the " + k + " keyword is not reserved");
156  for(unsigned i=0;i<reserved_keys.size();++i){
157  if(reserved_keys[i]==k) keys.push_back( reserved_keys[i] );
158  }
159 }
160 
161 void Keywords::reset_style( const std::string & k, const std::string & style ){
162  plumed_assert( exists(k) || reserved(k) );
163  (types.find(k)->second).setStyle(style);
164  if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,style) );
165 }
166 
167 void Keywords::add( const std::string & t, const std::string & k, const std::string & d ){
168  plumed_assert( !exists(k) && t!="flag" && !reserved(k) );
169  std::string fd;
170  if( t=="numbered" ){
171  fd=d + " You can use multiple instances of this keyword i.e. " + k +"1, " + k + "2, " + k + "3...";
172  allowmultiple.insert( std::pair<std::string,bool>(k,true) );
173  types.insert( std::pair<std::string,KeyType>(k, KeyType("optional")) );
174  } else {
175  fd=d;
176  allowmultiple.insert( std::pair<std::string,bool>(k,false) );
177  types.insert( std::pair<std::string,KeyType>(k,KeyType(t)) );
178  if( (types.find(k)->second).isAtomList() ) atomtags.insert( std::pair<std::string,std::string>(k,t) );
179  }
180  documentation.insert( std::pair<std::string,std::string>(k,fd) );
181  keys.push_back(k);
182 }
183 
184 void Keywords::add( const std::string & t, const std::string & k, const std::string & def, const std::string & d ){
185  plumed_assert( !exists(k) && !reserved(k) && t=="compulsory" ); // An optional keyword can't have a default
186  types.insert( std::pair<std::string,KeyType>(k, KeyType(t)) );
187  documentation.insert( std::pair<std::string,std::string>(k,"( default=" + def + " ) " + d) );
188  allowmultiple.insert( std::pair<std::string,bool>(k,false) );
189  numdefs.insert( std::pair<std::string,std::string>(k,def) );
190  keys.push_back(k);
191 }
192 
193 void Keywords::addFlag( const std::string & k, const bool def, const std::string & d ){
194  plumed_massert( !exists(k) && !reserved(k), "keyword " + k + " has already been registered");
195  std::string defstr;
196  if( def ) { defstr="( default=on ) "; } else { defstr="( default=off ) "; }
197  types.insert( std::pair<std::string,KeyType>(k,KeyType("flag")) );
198  documentation.insert( std::pair<std::string,std::string>(k,defstr + d) );
199  allowmultiple.insert( std::pair<std::string,bool>(k,false) );
200  booldefs.insert( std::pair<std::string,bool>(k,def) );
201  keys.push_back(k);
202 }
203 
204 void Keywords::remove( const std::string & k ){
205  bool found=false; unsigned j=0;
206 
207  while(true){
208  for(j=0;j<keys.size();j++) if(keys[j]==k)break;
209  if(j<keys.size()){
210  keys.erase(keys.begin()+j);
211  found=true;
212  } else break;
213  }
214  plumed_massert(found,"You are trying to forbid " + k + " a keyword that isn't there"); // You have tried to forbid a keyword that isn't there
215 }
216 
217 bool Keywords::numbered( const std::string & k ) const {
218  if( style( k,"atoms") ) return true;
219  plumed_massert( allowmultiple.count(k), "Did not find keyword " + k );
220  return allowmultiple.find(k)->second;
221 }
222 
223 bool Keywords::style( const std::string & k, const std::string & t ) const {
224  plumed_massert( types.count(k), "Did not find keyword " + k );
225 
226  if( (types.find(k)->second).toString()==t ) return true;
227  return false;
228 }
229 
230 unsigned Keywords::size() const {
231  return keys.size();
232 }
233 
234 std::string Keywords::getKeyword( const unsigned i ) const {
235  plumed_assert( i<size() );
236  return keys[i];
237 }
238 
239 bool Keywords::exists( const std::string & k ) const {
240  for(unsigned i=0;i<keys.size();++i){
241  if( keys[i]==k ) return true;
242  }
243  return false;
244 }
245 
246 bool Keywords::reserved( const std::string & k ) const {
247  for(unsigned i=0;i<reserved_keys.size();++i){
248  if( reserved_keys[i]==k ) return true;
249  }
250  return false;
251 }
252 
253 void Keywords::print_template(const std::string& actionname, bool include_optional) const {
254  unsigned nkeys=0;
255  printf("%s",actionname.c_str());
256  for(unsigned i=0;i<keys.size();++i){
257  if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
258  }
259  if( nkeys>0 ){
260  std::string prevtag="start";
261  for(unsigned i=0;i<keys.size();++i){
262  if( (types.find(keys[i])->second).isAtomList() ){
263  plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
264  if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second ) break;
265  if( (atomtags.find(keys[i])->second).find("residues")!=std::string::npos) printf(" %s=<residue selection>", keys[i].c_str() );
266  else printf(" %s=<atom selection>", keys[i].c_str() );
267  prevtag=atomtags.find(keys[i])->second;
268  }
269  }
270  }
271  nkeys=0;
272  for(unsigned i=0;i<keys.size();++i){
273  if ( include_optional || \
274  (types.find(keys[i])->second).isCompulsory() ) nkeys++;
275  }
276  if( nkeys>0 ){
277  for(unsigned i=0;i<keys.size();++i){
278  if ( (types.find(keys[i])->second).isCompulsory() ){
279  std::string def;
280  if( getDefaultValue( keys[i], def) ){
281  printf(" %s=%s ", keys[i].c_str(), def.c_str() );
282  } else {
283  printf(" %s= ", keys[i].c_str() );
284  }
285  } else if (include_optional) {
286  // TG no defaults for optional keywords?
287  printf(" [%s]", keys[i].c_str() );
288  }
289  }
290  }
291  printf("\n");
292 }
293 
294 void Keywords::print_html( const bool isaction ) const {
295 
296 // This is the part that outputs the details of the components
297  if( cnames.size()>0 ){
298  if( ckey.find(cnames[0])->second=="default" ){
299  std::cout<<"\\par Description of components\n\n";
300  std::cout<<cstring<<"\n\n";
301  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
302  printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Description </b> </td> </tr>\n");
303  for(unsigned i=0;i<cnames.size();++i){
304  plumed_assert( ckey.find(cnames[i])->second=="default" );
305  printf("<tr>\n");
306  printf("<td width=15%%> <b> %s </b></td>\n",cnames[i].c_str() );
307  printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
308  printf("</tr>\n");
309  }
310  std::cout<<"</table>\n\n";
311  } else {
312  unsigned nregs=0;
313  for(unsigned i=0;i<cnames.size();++i){
314  if( exists(ckey.find(cnames[i])->second) ) nregs++;
315  }
316  if( nregs>0 ){
317  std::cout<<"\\par Description of components\n\n";
318  std::cout<<cstring<<"\n\n";
319  std::cout<<" <table align=center frame=void width=60%% cellpadding=5%%> \n";
320  printf("<tr> <td width=5%%> <b> Quantity </b> </td> <td> <b> Keyword </b> </td> <td> <b> Description </b> </td> </tr>\n");
321  for(unsigned i=0;i<cnames.size();++i){
322  if( exists(ckey.find(cnames[i])->second) ){
323  printf("<tr>\n");
324  printf("<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
325  cnames[i].c_str(),(ckey.find(cnames[i])->second).c_str() );
326  printf("<td> %s </td>\n",(cdocs.find(cnames[i])->second).c_str() );
327  printf("</tr>\n");
328  }
329  }
330  std::cout<<"</table>\n\n";
331  }
332  }
333  }
334 
335  unsigned nkeys=0;
336  for(unsigned i=0;i<keys.size();++i){
337  if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
338  }
339  if( nkeys>0 ){
340  if(isaction) std::cout<<"\\par The atoms involved can be specified using\n\n";
341  else std::cout<<"\\par The input trajectory is specified using one of the following\n\n";
342  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
343  std::string prevtag="start";
344  for(unsigned i=0;i<keys.size();++i){
345  if ( (types.find(keys[i])->second).isAtomList() ){
346  plumed_massert( atomtags.count(keys[i]), "keyword " + keys[i] + " allegedly specifies atoms but no tag has been specified. Please email Gareth Tribello");
347  if( prevtag!="start" && prevtag!=atomtags.find(keys[i])->second && isaction ){
348  std::cout<<"</table>\n\n";
349  std::cout<<"\\par Or alternatively by using\n\n";
350  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
351  }
352  print_html_item( keys[i] );
353  prevtag=atomtags.find(keys[i])->second;
354  }
355  }
356  std::cout<<"</table>\n\n";
357  }
358  nkeys=0;
359  for(unsigned i=0;i<keys.size();++i){
360  if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
361  }
362  if( nkeys>0 ){
363  if(isaction) std::cout<< "\\par Compulsory keywords\n\n";
364  else std::cout<<"\\par The following must be present\n\n";
365  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
366  for(unsigned i=0;i<keys.size();++i){
367  if ( (types.find(keys[i])->second).isCompulsory() ) print_html_item( keys[i] );
368  }
369  std::cout<<"</table>\n\n";
370  }
371  nkeys=0;
372  for(unsigned i=0;i<keys.size();++i){
373  if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
374  }
375  if( nkeys>0 ){
376  if(isaction) std::cout<<"\\par Options\n\n";
377  else std::cout<<"\\par The following options are available\n\n";
378  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
379  for(unsigned i=0;i<keys.size();++i){
380  if ( (types.find(keys[i])->second).isFlag() ) print_html_item( keys[i] );
381  }
382  std::cout<<"\n";
383  }
384  std::cout<<"</table>\n\n";
385  nkeys=0;
386  for(unsigned i=0;i<keys.size();++i){
387  if ( (types.find(keys[i])->second).isOptional() ) nkeys++;
388  }
389  if( nkeys>0 ){
390  std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n";
391  for(unsigned i=0;i<keys.size();++i){
392  if ( (types.find(keys[i])->second).isOptional() ) print_html_item( keys[i] );
393  }
394  std::cout<<"\n";
395  }
396  std::cout<<"</table>\n\n";
397 }
398 
399 void Keywords::print( FILE* out ) const {
400  unsigned nkeys=0;
401  for(unsigned i=0;i<keys.size();++i){
402  if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
403  }
404  if( nkeys>0 ){
405  fprintf(out,"The input trajectory can be in any of the following formats: \n\n");
406  for(unsigned i=0;i<keys.size();++i){
407  if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out );
408  }
409  }
410  nkeys=0;
411  for(unsigned i=0;i<keys.size();++i){
412  if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
413  }
414  unsigned ncompulsory=nkeys;
415  if( nkeys>0 ){
416  fprintf(out,"\nThe following arguments are compulsory: \n\n");
417  for(unsigned i=0;i<keys.size();++i){
418  if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] );
419  }
420  }
421  nkeys=0;
422  for(unsigned i=0;i<keys.size();++i){
423  if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
424  }
425  if( nkeys>0 ){
426  if(ncompulsory>0) fprintf( out,"\nIn addition you may use the following options: \n\n");
427  else fprintf( out,"\nThe following options are available\n\n");
428  for(unsigned i=0;i<keys.size();++i){
429  if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] );
430  }
431  }
432  nkeys=0;
433  for(unsigned i=0;i<keys.size();++i){
434  if ( (types.find(keys[i])->second).isOptional() ) nkeys++;
435  }
436  if( nkeys>0 ){
437  for(unsigned i=0;i<keys.size();++i){
438  if ( (types.find(keys[i])->second).isOptional() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] );
439  }
440  fprintf(out,"\n");
441  }
442 }
443 
444 void Keywords::printKeyword( const std::string& key, FILE* out ) const {
445  bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
446  std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
447  fprintf(out,"%23s - ", key.c_str() );
448  unsigned nl=0; std::string blank=" ";
449  for(unsigned i=0;i<w.size();++i){
450  nl+=w[i].length() + 1;
451  if( nl>60 ){
452  fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0;
453  } else {
454  fprintf(out,"%s ", w[i].c_str() );
455  }
456  if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
457  }
458  fprintf(out,"\n");
459 }
460 
461 void Keywords::print( Log& log ) const {
462  unsigned nkeys=0;
463  for(unsigned i=0;i<keys.size();++i){
464  if ( (types.find(keys[i])->second).isAtomList() ) nkeys++;
465  }
466  if (nkeys>0 ){
467  log.printf( "The input for this keyword can be specified using one of the following \n\n");
468  for(unsigned i=0;i<keys.size();++i){
469  if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] );
470  }
471  }
472  nkeys=0;
473  for(unsigned i=0;i<keys.size();++i){
474  if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++;
475  }
476  if( nkeys>0 ){
477  log.printf( "\n The compulsory keywords for this action are: \n\n");
478  for(unsigned i=0;i<keys.size();++i){
479  if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] );
480  }
481  }
482  nkeys=0;
483  for(unsigned i=0;i<keys.size();++i){
484  if ( (types.find(keys[i])->second).isFlag() ) nkeys++;
485  }
486  if( nkeys>0 ){
487  log.printf( "\n The following options are available: \n\n");
488  for(unsigned i=0;i<keys.size();++i){
489  if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] );
490  }
491  log.printf("\n");
492  }
493  nkeys=0;
494  for(unsigned i=0;i<keys.size();++i){
495  if ( (types.find(keys[i])->second).isOptional() ) nkeys++;
496  }
497  if( nkeys>0 ){
498  for(unsigned i=0;i<keys.size();++i){
499  if ( (types.find(keys[i])->second).isOptional() ) printKeyword( keys[i], log ); //log.printKeyword( keys[i], documentation[i] );
500  }
501  log.printf("\n");
502  }
503 }
504 
505 void Keywords::printKeyword( const std::string& key, Log& log ) const {
506  bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex
507  std::vector<std::string> w=Tools::getWords( documentation.find(key)->second );
508  log.printf("%23s - ", key.c_str() );
509  unsigned nl=0; std::string blank=" ";
510  for(unsigned i=0;i<w.size();++i){
511  nl+=w[i].length() + 1;
512  if( nl>60 ){
513  log.printf("\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0;
514  } else {
515  log.printf("%s ", w[i].c_str() );
516  }
517  if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot
518  }
519  log.printf("\n");
520 }
521 
522 void Keywords::print_html_item( const std::string& key ) const {
523  printf("<tr>\n");
524  printf("<td width=15%%> <b> %s </b></td>\n",key.c_str() );
525  printf("<td> %s </td>\n",(documentation.find(key)->second).c_str() );
526  printf("</tr>\n");
527 }
528 
529 std::string Keywords::get( const unsigned k ) const {
530  plumed_assert( k<size() );
531  return keys[k];
532 }
533 
534 bool Keywords::getLogicalDefault( std::string key, bool& def ) const {
535  if( booldefs.find(key)!=booldefs.end() ){
536  def=booldefs.find(key)->second;
537  return true;
538  } else {
539  return false;
540  }
541 }
542 
543 bool Keywords::getDefaultValue( std::string key, std::string& def ) const {
544  plumed_assert( style(key,"compulsory") || style(key,"hidden") );
545 
546  if( numdefs.find(key)!=numdefs.end() ){
547  def=numdefs.find(key)->second;
548  return true;
549  } else {
550  return false;
551  }
552 }
553 
555  keys.clear(); reserved_keys.clear(); types.clear();
556  allowmultiple.clear(); documentation.clear();
557  booldefs.clear(); numdefs.clear(); atomtags.clear();
558  ckey.clear(); cdocs.clear(); ckey.clear();
559 }
560 
561 void Keywords::setComponentsIntroduction( const std::string& instr ){
562  cstring = instr;
563 }
564 
565 void Keywords::addOutputComponent( const std::string& name, const std::string& key, const std::string& descr ){
566  plumed_assert( !outputComponentExists( name, false ) );
567  ckey.insert( std::pair<std::string,std::string>(name,key) );
568  cdocs.insert( std::pair<std::string,std::string>(name,descr) );
569  cnames.push_back(name);
570 }
571 
572 bool Keywords::outputComponentExists( const std::string& name, const bool& custom ) const {
573  if( custom && cstring.find("customizable")!=std::string::npos ) return true;
574  for(unsigned i=0;i<cnames.size();++i){
575  if( name==cnames[i] ) return true;
576  }
577  return false;
578 }
579 
580 }
void setComponentsIntroduction(const std::string &instr)
Set the text that introduces how the components for this action are introduced.
Definition: Keywords.cpp:561
void copyData(std::vector< std::string > &kk, std::vector< std::string > &rk, std::map< std::string, KeyType > &tt, std::map< std::string, bool > &am, std::map< std::string, std::string > &docs, std::map< std::string, bool > &bools, std::map< std::string, std::string > &nums, std::map< std::string, std::string > &atags, std::vector< std::string > &cnam, std::map< std::string, std::string > &ck, std::map< std::string, std::string > &cd) const
Copy the keywords data.
Definition: Keywords.cpp:65
std::vector< std::string > keys
The names of the allowed keywords.
Definition: Keywords.h:60
void setStyle(const std::string &type)
Definition: Keywords.cpp:45
void destroyData()
Clear everything from the keywords object.
Definition: Keywords.cpp:554
std::vector< std::string > reserved_keys
The names of the reserved keywords.
Definition: Keywords.h:62
std::map< std::string, std::string > documentation
The documentation for the keywords.
Definition: Keywords.h:68
void add(const std::string &t, const std::string &k, const std::string &d)
Add a new keyword of type t with name k and description d.
Definition: Keywords.cpp:167
std::map< std::string, std::string > atomtags
The tags for atoms - we use this so the manual can differentiate between different ways of specifying...
Definition: Keywords.h:74
Class containing the log stream.
Definition: Log.h:35
This class lets me pass keyword types easily.
Definition: Keywords.h:38
bool getDefaultValue(std::string key, std::string &def) const
Get the value of the default for the keyword named key.
Definition: Keywords.cpp:543
std::string cstring
The string that should be printed out to describe how the components work for this particular action...
Definition: Keywords.h:76
void addOutputComponent(const std::string &name, const std::string &key, const std::string &descr)
Add a potential component which can be output by this particular action.
Definition: Keywords.cpp:565
void print_html_item(const std::string &) const
Print the documentation for the jth keyword in html.
Definition: Keywords.cpp:522
This class holds the keywords and their documentation.
Definition: Keywords.h:36
std::string get(const unsigned k) const
Get the ith keyword.
Definition: Keywords.cpp:529
void printKeyword(const std::string &j, Log &log) const
Print a particular keyword.
Definition: Keywords.cpp:505
static std::vector< std::string > getWords(const std::string &line, const char *sep=NULL, int *parlevel=NULL, const char *parenthesis="{")
Split the line in words using separators.
Definition: Tools.cpp:112
void print(Log &log) const
Print the documentation to the log file (used by PLMD::Action::error)
Definition: Keywords.cpp:461
bool numbered(const std::string &k) const
Check if numbered keywords are allowed for this action.
Definition: Keywords.cpp:217
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
Definition: OFile.cpp:82
std::map< std::string, std::string > ckey
The keyword that turns on a particular component.
Definition: Keywords.h:80
std::map< std::string, KeyType > types
Whether the keyword is compulsory, optional...
Definition: Keywords.h:64
std::string getKeyword(const unsigned i) const
Return the ith keyword.
Definition: Keywords.cpp:234
void reserve(const std::string &t, const std::string &k, const std::string &d, const bool isvessel=false)
Reserve a keyword.
Definition: Keywords.cpp:110
bool style(const std::string &k, const std::string &t) const
Check if the keyword with name k has style t.
Definition: Keywords.cpp:223
void use(const std::string &k)
Use one of the reserved keywords.
Definition: Keywords.cpp:154
std::map< std::string, bool > booldefs
The default values for the flags (are they on or of)
Definition: Keywords.h:70
void const char const char int double int double double int int double int double * w
Definition: Matrix.h:42
void print_template(const std::string &actionname, bool include_optional) const
Print the template version for the documenation.
Definition: Keywords.cpp:253
void remove(const std::string &k)
Remove the keyword with name k.
Definition: Keywords.cpp:204
void reserveFlag(const std::string &k, const bool def, const std::string &d, const bool isvessel=false)
Reserve a flag.
Definition: Keywords.cpp:140
std::map< std::string, std::string > numdefs
The default values (if there are default values) for compulsory keywords.
Definition: Keywords.h:72
bool exists(const std::string &k) const
Check if there is a keyword with name k.
Definition: Keywords.cpp:239
bool reserved(const std::string &k) const
Check the keyword k has been reserved.
Definition: Keywords.cpp:246
std::map< std::string, bool > allowmultiple
Do we allow stuff like key1, key2 etc.
Definition: Keywords.h:66
std::map< std::string, std::string > cdocs
The documentation for a particular component.
Definition: Keywords.h:82
KeyType(const std::string &type)
Definition: Keywords.cpp:29
bool outputComponentExists(const std::string &name, const bool &custom) const
Has a component with this name been added?
Definition: Keywords.cpp:572
void print_html(const bool isaction) const
Print an html version of the documentation.
Definition: Keywords.cpp:294
bool getLogicalDefault(std::string key, bool &def) const
find out whether flag key is on or off by default.
Definition: Keywords.cpp:534
void reset_style(const std::string &k, const std::string &style)
Change the style of a keyword.
Definition: Keywords.cpp:161
enum PLMD::Keywords::KeyType::@5 style
std::vector< std::string > cnames
The names of all the possible components for an action.
Definition: Keywords.h:78
void addFlag(const std::string &k, const bool def, const std::string &d)
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.
Definition: Keywords.cpp:193
unsigned size() const
Return the number of defined keywords.
Definition: Keywords.cpp:230