30 if( type==
"compulsory" ){
32 }
else if( type==
"flag" ){
34 }
else if( type==
"optional" ){
36 }
else if( type.find(
"atoms")!=std::string::npos || type.find(
"residues")!=std::string::npos ){
38 }
else if( type==
"hidden" ){
41 plumed_massert(
false,
"invalid keyword specifier " + type);
46 if( type==
"compulsory" ){
48 }
else if( type==
"flag" ){
50 }
else if( type==
"optional" ){
52 }
else if( type.find(
"atoms")!=std::string::npos || type.find(
"residues")!=std::string::npos ){
54 }
else if( type==
"hidden" ){
57 plumed_massert(
false,
"invalid keyword specifier " + type);
62 newkeys.
copyData(
keys,
reserved_keys,
types,
allowmultiple,
documentation,
booldefs,
numdefs,
atomtags,
cnames,
ckey,
cdocs );
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) );
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) );
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) );
110 void Keywords::reserve(
const std::string & t,
const std::string & k,
const std::string & d,
const bool isvessel ){
112 std::string fd, lowkey=k;
113 std::transform(lowkey.begin(),lowkey.end(),lowkey.begin(),tolower);
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...";
122 fd = d +
" You can use multiple instances of this keyword i.e. " + k +
"1, " + k +
"2, " + k +
"3...";
125 types.insert( std::pair<std::string,KeyType>(k,
KeyType(
"optional")) );
128 fd = d +
" The final value can be referenced using <em>label</em>." + lowkey +
".";
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) );
136 documentation.insert( std::pair<std::string,std::string>(k,fd) );
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;
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) );
155 plumed_massert(
reserved(k),
"the " + k +
" keyword is not reserved");
163 (
types.find(k)->second).setStyle(style);
164 if( (
types.find(k)->second).isAtomList() )
atomtags.insert( std::pair<std::string,std::string>(k,style) );
167 void Keywords::add(
const std::string & t,
const std::string & k,
const std::string & d ){
171 fd=d +
" You can use multiple instances of this keyword i.e. " + k +
"1, " + k +
"2, " + k +
"3...";
173 types.insert( std::pair<std::string,KeyType>(k,
KeyType(
"optional")) );
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) );
180 documentation.insert( std::pair<std::string,std::string>(k,fd) );
184 void Keywords::add(
const std::string & t,
const std::string & k,
const std::string & def,
const std::string & d ){
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) );
194 plumed_massert( !
exists(k) && !
reserved(k),
"keyword " + k +
" has already been registered");
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) );
205 bool found=
false;
unsigned j=0;
208 for(j=0;j<
keys.size();j++)
if(
keys[j]==k)
break;
214 plumed_massert(found,
"You are trying to forbid " + k +
" a keyword that isn't there");
218 if(
style( k,
"atoms") )
return true;
219 plumed_massert(
allowmultiple.count(k),
"Did not find keyword " + k );
224 plumed_massert(
types.count(k),
"Did not find keyword " + k );
226 if( (
types.find(k)->second).toString()==t )
return true;
235 plumed_assert( i<
size() );
240 for(
unsigned i=0;i<
keys.size();++i){
241 if(
keys[i]==k )
return true;
255 printf(
"%s",actionname.c_str());
256 for(
unsigned i=0;i<
keys.size();++i){
257 if ( (
types.find(
keys[i])->second).isAtomList() ) nkeys++;
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() );
272 for(
unsigned i=0;i<
keys.size();++i){
273 if ( include_optional || \
274 (
types.find(
keys[i])->second).isCompulsory() ) nkeys++;
277 for(
unsigned i=0;i<
keys.size();++i){
278 if ( (
types.find(
keys[i])->second).isCompulsory() ){
281 printf(
" %s=%s ",
keys[i].c_str(), def.c_str() );
283 printf(
" %s= ",
keys[i].c_str() );
285 }
else if (include_optional) {
287 printf(
" [%s]",
keys[i].c_str() );
298 if(
ckey.find(
cnames[0])->second==
"default" ){
299 std::cout<<
"\\par Description of components\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" );
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() );
310 std::cout<<
"</table>\n\n";
313 for(
unsigned i=0;i<
cnames.size();++i){
317 std::cout<<
"\\par Description of components\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){
324 printf(
"<td width=5%%> <b> %s </b></td> <td width=10%%> <b> %s </b> </td> \n",
326 printf(
"<td> %s </td>\n",(
cdocs.find(
cnames[i])->second).c_str() );
330 std::cout<<
"</table>\n\n";
336 for(
unsigned i=0;i<
keys.size();++i){
337 if ( (
types.find(
keys[i])->second).isAtomList() ) nkeys++;
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";
356 std::cout<<
"</table>\n\n";
359 for(
unsigned i=0;i<
keys.size();++i){
360 if ( (
types.find(
keys[i])->second).isCompulsory() ) nkeys++;
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){
369 std::cout<<
"</table>\n\n";
372 for(
unsigned i=0;i<
keys.size();++i){
373 if ( (
types.find(
keys[i])->second).isFlag() ) nkeys++;
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){
384 std::cout<<
"</table>\n\n";
386 for(
unsigned i=0;i<
keys.size();++i){
387 if ( (
types.find(
keys[i])->second).isOptional() ) nkeys++;
390 std::cout<<
" <table align=center frame=void width=95%% cellpadding=5%%> \n";
391 for(
unsigned i=0;i<
keys.size();++i){
396 std::cout<<
"</table>\n\n";
401 for(
unsigned i=0;i<
keys.size();++i){
402 if ( (
types.find(
keys[i])->second).isAtomList() ) nkeys++;
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){
411 for(
unsigned i=0;i<
keys.size();++i){
412 if ( (
types.find(
keys[i])->second).isCompulsory() ) nkeys++;
414 unsigned ncompulsory=nkeys;
416 fprintf(out,
"\nThe following arguments are compulsory: \n\n");
417 for(
unsigned i=0;i<
keys.size();++i){
422 for(
unsigned i=0;i<
keys.size();++i){
423 if ( (
types.find(
keys[i])->second).isFlag() ) nkeys++;
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){
433 for(
unsigned i=0;i<
keys.size();++i){
434 if ( (
types.find(
keys[i])->second).isOptional() ) nkeys++;
437 for(
unsigned i=0;i<
keys.size();++i){
445 bool killdot=( (
documentation.find(key)->second).find(
"\\f$")!=std::string::npos );
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;
452 fprintf(out,
"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0;
454 fprintf(out,
"%s ", w[i].c_str() );
456 if( killdot && w[i].find(
".")!=std::string::npos )
break;
463 for(
unsigned i=0;i<
keys.size();++i){
464 if ( (
types.find(
keys[i])->second).isAtomList() ) nkeys++;
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){
473 for(
unsigned i=0;i<
keys.size();++i){
474 if ( (
types.find(
keys[i])->second).isCompulsory() ) nkeys++;
477 log.
printf(
"\n The compulsory keywords for this action are: \n\n");
478 for(
unsigned i=0;i<
keys.size();++i){
483 for(
unsigned i=0;i<
keys.size();++i){
484 if ( (
types.find(
keys[i])->second).isFlag() ) nkeys++;
487 log.
printf(
"\n The following options are available: \n\n");
488 for(
unsigned i=0;i<
keys.size();++i){
494 for(
unsigned i=0;i<
keys.size();++i){
495 if ( (
types.find(
keys[i])->second).isOptional() ) nkeys++;
498 for(
unsigned i=0;i<
keys.size();++i){
506 bool killdot=( (
documentation.find(key)->second).find(
"\\f$")!=std::string::npos );
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;
513 log.
printf(
"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0;
515 log.
printf(
"%s ", w[i].c_str() );
517 if( killdot && w[i].find(
".")!=std::string::npos )
break;
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() );
530 plumed_assert( k<
size() );
544 plumed_assert(
style(key,
"compulsory") ||
style(key,
"hidden") );
567 ckey.insert( std::pair<std::string,std::string>(name,key) );
568 cdocs.insert( std::pair<std::string,std::string>(name,descr) );
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;
void setComponentsIntroduction(const std::string &instr)
Set the text that introduces how the components for this action are introduced.
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.
std::vector< std::string > keys
The names of the allowed keywords.
void setStyle(const std::string &type)
void destroyData()
Clear everything from the keywords object.
std::vector< std::string > reserved_keys
The names of the reserved keywords.
std::map< std::string, std::string > documentation
The documentation for the keywords.
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.
std::map< std::string, std::string > atomtags
The tags for atoms - we use this so the manual can differentiate between different ways of specifying...
Class containing the log stream.
This class lets me pass keyword types easily.
bool getDefaultValue(std::string key, std::string &def) const
Get the value of the default for the keyword named key.
std::string cstring
The string that should be printed out to describe how the components work for this particular action...
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.
void print_html_item(const std::string &) const
Print the documentation for the jth keyword in html.
This class holds the keywords and their documentation.
std::string get(const unsigned k) const
Get the ith keyword.
void printKeyword(const std::string &j, Log &log) const
Print a particular keyword.
void print(Log &log) const
Print the documentation to the log file (used by PLMD::Action::error)
bool numbered(const std::string &k) const
Check if numbered keywords are allowed for this action.
int printf(const char *fmt,...)
Formatted output with explicit format - a la printf.
std::map< std::string, std::string > ckey
The keyword that turns on a particular component.
std::map< std::string, KeyType > types
Whether the keyword is compulsory, optional...
std::string getKeyword(const unsigned i) const
Return the ith keyword.
void reserve(const std::string &t, const std::string &k, const std::string &d, const bool isvessel=false)
Reserve a keyword.
bool style(const std::string &k, const std::string &t) const
Check if the keyword with name k has style t.
void use(const std::string &k)
Use one of the reserved keywords.
std::map< std::string, bool > booldefs
The default values for the flags (are they on or of)
void print_template(const std::string &actionname, bool include_optional) const
Print the template version for the documenation.
void remove(const std::string &k)
Remove the keyword with name k.
void reserveFlag(const std::string &k, const bool def, const std::string &d, const bool isvessel=false)
Reserve a flag.
std::map< std::string, std::string > numdefs
The default values (if there are default values) for compulsory keywords.
bool exists(const std::string &k) const
Check if there is a keyword with name k.
bool reserved(const std::string &k) const
Check the keyword k has been reserved.
std::map< std::string, bool > allowmultiple
Do we allow stuff like key1, key2 etc.
std::map< std::string, std::string > cdocs
The documentation for a particular component.
KeyType(const std::string &type)
bool outputComponentExists(const std::string &name, const bool &custom) const
Has a component with this name been added?
void print_html(const bool isaction) const
Print an html version of the documentation.
bool getLogicalDefault(std::string key, bool &def) const
find out whether flag key is on or off by default.
void reset_style(const std::string &k, const std::string &style)
Change the style of a keyword.
enum PLMD::Keywords::KeyType::@5 style
std::vector< std::string > cnames
The names of all the possible components for an action.
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.
unsigned size() const
Return the number of defined keywords.