cli.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2017, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 /** \file cli.h
24  \brief File defining command-line interface in \ref o2scl::cli
25 */
26 #ifndef O2SCL_CLI_H
27 #define O2SCL_CLI_H
28 
29 #include <iostream>
30 #include <vector>
31 #include <algorithm>
32 #include <sstream>
33 #include <map>
34 
35 #include <o2scl/columnify.h>
36 #include <o2scl/vector.h>
37 #include <o2scl/string_conv.h>
38 
39 #ifndef DOXYGEN_NO_O2NS
40 namespace o2scl {
41 #endif
42 
43  /** \brief Base for \ref o2scl::cli command function
44 
45  See the \ref o2scl::cli class for more details.
46  */
48 
49  public:
50 
52 
53  virtual ~comm_option_funct() {}
54 
55  /// The basic function called by \ref o2scl::cli
56  virtual int operator()(std::vector<std::string> &cstr, bool itive_com)=0;
57 
58  };
59 
60  /// Function pointer for \ref o2scl::cli command function
62 
63  public:
64 
65  /// Create from a member function pointer from the specified class
66  comm_option_fptr(int (*fp)(std::vector<std::string> &, bool)) {
67  fptr=fp;
68  }
69 
70  virtual ~comm_option_fptr() {}
71 
72  /// The basic function called by \ref o2scl::cli
73  virtual int operator()(std::vector<std::string> &cstr, bool itive_com) {
74  return (*fptr)(cstr,itive_com);
75  }
76 
77 #ifndef DOXYGEN_INTERNAL
78 
79  protected:
80 
81  /// The pointer to the member function
82  int (*fptr)(std::vector<std::string> &cstr, bool itive_com);
83 
84  // Copy constructor
85  //comm_option_fptr(const comm_option_fptr &f) {
86  //fptr=f.fptr;
87  //}
88 
89  /// Copy constructor
91  fptr=f.fptr;
92  return *this;
93  }
94 
95 #endif
96 
97  };
98 
99  /// Member function pointer for \ref o2scl::cli command function
100  template<class tclass> class comm_option_mfptr : public comm_option_funct {
101 
102  public:
103 
104  /// Create from a member function pointer from the specified class
105  comm_option_mfptr(tclass *tp, int (tclass::*fp)(std::vector<std::string> &,
106  bool)) {
107  tptr=tp;
108  fptr=fp;
109  }
110 
111  virtual ~comm_option_mfptr() {}
112 
113  /// The basic function called by \ref o2scl::cli
114  virtual int operator()(std::vector<std::string> &cstr, bool itive_com) {
115  return (*tptr.*fptr)(cstr,itive_com);
116  }
117 
118 #ifndef DOXYGEN_INTERNAL
119 
120  protected:
121 
122  /// The pointer to the member function
123  int (tclass::*fptr)(std::vector<std::string> &cstr, bool itive_com);
124 
125  /// The pointer to the class
126  tclass *tptr;
127 
128  /// Copy constructor
130  fptr=f.fptr;
131  tptr=f.tptr;
132  }
133 
134  /// Copy constructor
136  fptr=f.fptr;
137  tptr=f.tptr;
138  return *this;
139  }
140 
141 #endif
142 
143  };
144 
145  /** \brief Command for interactive mode in \ref o2scl::cli
146 
147  See the \ref o2scl::cli class for more details.
148 
149  \comment
150  This was at one point converted into a class, but it wasn't that
151  easy to use, in comparison to structs which are easy to
152  initialize in aggregate.
153  \endcomment
154  */
155  typedef struct {
156 
157  /// Short option (\c '\\0' for none, must be unique if present)
158  char shrt;
159  /// Long option (must be specified and must be unique)
160  std::string lng;
161  /// Description for help
162  std::string desc;
163  /// Minimum number of parameters (0 for none, -1 for variable)
165  /// Maximum number of parameters (0 for none, -1 for variable)
167  /// Description of parameters
168  std::string parm_desc;
169  /// The help description
170  std::string help;
171  /// The pointer to the function to be called (or 0 for no function)
173  /// Type: command-line parameter, command, or both
174  int type;
175 
176  } comm_option_s;
177 
178  /** \brief A command-line argument for \ref o2scl::cli
179 
180  This is the internal structure that \ref o2scl::cli uses to package
181  command-line arguments.
182  */
183  typedef struct {
184  /// The argument
185  std::string arg;
186  /// Is an option?
187  bool is_option;
188  /// Is a properly formatted option
189  bool is_valid;
190  /// List of parameters (empty, unless it's an option)
191  std::vector<std::string> parms;
192  /// A pointer to the appropriate option (0, unless it's an option)
194  } cmd_line_arg;
195 
196  /** \brief Configurable command-line interface
197 
198  This class is experimental.
199 
200  Default commands: help, get/set, quit, exit, '!', verbose, license,
201  warranty, alias, run.
202 
203  Note that if the shell command is allowed (as it is by default)
204  there are some potential security issues which are not solved
205  here.
206 
207  Commands which begin with a '#' character are ignored.
208 
209  \note In interactive mode, commands are limited to 300 characters.
210 
211  \future Warn in run_interactive() when extra parameters are given
212  \future Include a "remove command" function
213  \future A replace command function, there's already some code
214  in cli.cpp for this.
215  \future There's some code duplication between comm_option_run()
216  and run_interactive()
217  \future Allow the user to set the tilde string
218  \future Disallow direct access to \ref o2scl::cli::par_list in order to
219  ensure parameter names do not contain whitespace
220 
221  <b>Concepts</b>
222 
223  As a matter of definition, the command-line arguments are simply
224  called arguments. These arguments may be options (in which case
225  they begin with either one dash or two) or parameters to these
226  options. When run in interactive mode, these options are also
227  commands.
228 
229  */
230  class cli {
231 
232  public:
233 
234  /// Parameter for \ref o2scl::cli
235  class parameter {
236 
237  public:
238 
239  virtual ~parameter() {}
240 
241  /// Help description
242  std::string help;
243 
244  /// Set from string
245  virtual int set(std::string s)=0;
246 
247  /// Convert to string
248  virtual std::string get()=0;
249 
250  };
251 
252  /// String parameter for \ref o2scl::cli
253  class parameter_string : public parameter {
254 
255  public:
256 
257  virtual ~parameter_string() {}
258 
259  /// Parameter
260  std::string *str;
261 
262  /// Set from string
263  virtual int set(std::string s) {
264  *str=s;
265  return 0;
266  }
267 
268  /// Convert to string
269  virtual std::string get() {
270  return *str;
271  }
272 
273  };
274 
275  /// String parameter for \ref o2scl::cli
276  class parameter_bool : public parameter {
277 
278  public:
279 
280  virtual ~parameter_bool() {}
281 
282  /// Parameter
283  bool *b;
284 
285  /// Set from string
286  virtual int set(std::string s) {
287  *b=o2scl::stob(s);
288  return 0;
289  }
290 
291  /// Convert to string
292  virtual std::string get() {
293  return btos(*b);
294  }
295 
296  };
297 
298  /// Double parameter for \ref o2scl::cli
299  class parameter_double : public parameter {
300 
301  public:
302 
303  parameter_double() {
304  parse_strings=true;
305  }
306 
307  virtual ~parameter_double() {}
308 
309  /// Parameter
310  double *d;
311 
312  /// If true,
314 
315  /// Set from string
316  virtual int set(std::string s) {
317  if (parse_strings) {
318  *d=function_to_double(s,false);
319  } else {
320  *d=o2scl::stod(s);
321  }
322  return 0;
323  }
324 
325  /// Convert to string
326  virtual std::string get() {
327  return dtos(*d);
328  }
329 
330  };
331 
332  /// Integer parameter for \ref o2scl::cli
333  class parameter_int : public parameter {
334 
335  public:
336 
337  virtual ~parameter_int() {}
338 
339  /// Parameter
340  int *i;
341 
342  /// Set from string
343  virtual int set(std::string s) {
344  *i=o2scl::stoi(s);
345  return 0;
346  }
347 
348  /// Convert to string
349  virtual std::string get() {
350  return itos(*i);
351  }
352 
353  };
354 
355  /// Integer parameter for \ref o2scl::cli
356  class parameter_size_t : public parameter {
357 
358  public:
359 
360  virtual ~parameter_size_t() {}
361 
362  /// Parameter
363  size_t *s;
364 
365  /// Set from string
366  virtual int set(std::string st) {
367  *s=o2scl::stoszt(st,false);
368  return 0;
369  }
370 
371  /// Convert to string
372  virtual std::string get() {
373  return szttos(*s);
374  }
375 
376  };
377 
378  /// \name Parameter storage and associated iterator type
379  //@{
380  /// Parameter list
381  std::map<std::string,parameter *,std::less<std::string> > par_list;
382  /// List iterator
383  typedef std::map<std::string,parameter *,
384  std::greater<std::string> >::iterator par_t;
385  //@}
386 
387 #ifndef DOXYGEN_NO_O2NS_INTERNAL
388 
389  protected:
390 
391  /// Output the parameter list
392  int output_param_list();
393 
394  /** \brief Attempt to expand a tilde to a user's home directory
395 
396  Experimental and currently unused.
397  */
398  int expand_tilde(std::vector<std::string> &sv);
399 
400  /// Replace all occurences of \c sold with \c snew in \c sv
401  int apply_alias(std::vector<std::string> &sv,
402  std::string sold, std::string snew);
403 
404  /// Control screen output
405  int verbose;
406 
407  /// \name The hard-coded command functions
408  //@{
409  int comm_option_alias(std::vector<std::string> &sv, bool itive_com);
410  int comm_option_commands(std::vector<std::string> &sv, bool itive_com);
411  int comm_option_get(std::vector<std::string> &sv, bool itive_com);
412  int comm_option_help(std::vector<std::string> &sv, bool itive_com);
413  int comm_option_license(std::vector<std::string> &sv, bool itive_com);
414  int comm_option_no_intro(std::vector<std::string> &sv, bool itive_com);
415  int comm_option_run(std::vector<std::string> &sv, bool itive_com);
416  int comm_option_set(std::vector<std::string> &sv, bool itive_com);
417  int comm_option_warranty(std::vector<std::string> &sv, bool itive_com);
418  //@}
419 
420  /// Storage for getline
421  char buf[300];
422 
423  /// Storage for the function to call after setting a parameter
425 
426  /// List of commands
427  std::vector<comm_option_s> clist;
428 
429  /// \name Help for parameters
430  //@{
431  std::vector<std::string> ph_name, ph_desc;
432  //@}
433 
434  /// \name Aliases
435  //@{
436  std::map<std::string,std::string,std::greater<std::string> > als;
437  typedef std::map<std::string,std::string,
438  std::greater<std::string> >::iterator al_it;
439  //@}
440 
441  /// Compare two strings, treating dashes and underscores as equivalent
442  bool string_equal_dash(std::string s1, std::string s2);
443 
444 #endif
445 
446  public:
447 
448  cli();
449 
450  virtual ~cli();
451 
452  /// String to replace tildes with
453  std::string tilde_string;
454 
455  /** \brief If true, output the usual GNU intro when run_interactive()
456  is called (default true).
457 
458  In order to conform to GNU standards, this ought not be set to
459  false by default.
460  */
461  bool gnu_intro;
462 
463  /// Function to call when a \c set command is issued
465  user_set_func=&usf;
466  return 0;
467  }
468 
469  /// \name Value to indicate whether commands are also command-line options
470  //@{
471  static const int comm_option_command=0;
472  static const int comm_option_cl_param=1;
473  static const int comm_option_both=2;
474  //@}
475 
476  /// \name The default command objects
477  //@{
478  comm_option_s c_commands;
479  comm_option_s c_help;
480  comm_option_s c_quit;
481  comm_option_s c_exit;
482  comm_option_s c_license;
483  comm_option_s c_warranty;
484  comm_option_s c_set;
485  comm_option_s c_get;
486  comm_option_s c_run;
487  comm_option_s c_no_intro;
488  comm_option_s c_alias;
489  //@}
490 
491  /// If true, then sync cli::verbose, with a parameter of the same name
493 
494  /** \brief If true, allow the user to use ! to execute a shell command
495  (default true)
496  */
498 
499  /// The prompt (default <tt>"> "</tt>)
500  std::string prompt;
501 
502  /// A one- or two-line description (default is empty string)
503  std::string desc;
504 
505  /// The name of the command
506  std::string cmd_name;
507 
508  /// Additional help text for interactive mode (default is empty string)
509  std::string addl_help_cmd;
510 
511  /// Additional help text for command-line (default is empty string)
512  std::string addl_help_cli;
513 
514  /// \name Basic operation
515  //@{
516  /** \brief Add a new command
517 
518  Each command/option must have either a short form in
519  comm_option_s::shrt or a long from in comm_option_s::lng,
520  which is unique from the other commands/options already
521  present. You cannot add two commands/options with the same
522  short form, even if they have different long forms, and vice
523  versa.
524 
525  */
526  int set_comm_option(comm_option_s &ic);
527 
528  /// Add a vector containing new commands/options
529  template<class vec_t> int set_comm_option_vec
530  (size_t list_size, vec_t &option_list) {
531 
532  for(size_t k=0;k<list_size;k++) {
533 
534  if (option_list[k].lng.length()<2) {
535  std::string str=((std::string)"Long option '")+option_list[k].lng+
536  "' does not have at "+
537  "least two characters in cli::set_comm_option().";
538  O2SCL_ERR(str.c_str(),exc_efailed);
539  }
540 
541  bool found=false;
542  for(size_t i=0;found==false && i<clist.size();i++) {
543  // If short or long options match
544  if ((option_list[k].shrt!=0 &&
545  clist[i].shrt==option_list[k].shrt) ||
546  (option_list[k].lng.length()>0 &&
547  clist[i].lng==option_list[k].lng)) {
548  found=true;
549  }
550  }
551  if (found==true) {
552  // Call the error handler
553  if (option_list[k].shrt!=0) {
554  std::string err="Option ";
555  err+=option_list[k].shrt;
556  err+=((std::string)" , ")+option_list[k].lng+" already present.";
557  O2SCL_ERR(err.c_str(),exc_einval);
558  } else {
559  std::string err="Option ";
560  err+=option_list[k].lng+" already present.";
561  O2SCL_ERR(err.c_str(),exc_einval);
562  }
563  }
564  // Add the option to the option list
565  clist.push_back(option_list[k]);
566  }
567 
568  return 0;
569  }
570 
571  /// Set one-line help text for a parameter named \c param
572  int set_param_help(std::string param, std::string help);
573 
574  /** \brief Automatically parse arguments to main and
575  call interactive mode if required
576  */
577  int run_auto(int argc, char *argv[], int debug=0);
578  //@}
579 
580  /** \brief The function which obtains input from the user
581 
582  \future Think about whether or not this should be protected?
583  (Possibly not, as it's extensively used by acolm.cpp)
584  */
585  virtual char *cli_gets(const char *c);
586 
587  /// Call functions corresponding to command-line args
588  int call_args(std::vector<cmd_line_arg> &ca);
589 
590  /** \brief Process command-line arguments from a const char array
591 
592  This doesn't actually execute the functions for the
593  corresponding options, but simply processes the parameters \c
594  argv and \c argv and packs the information into \c ca.
595 
596  This function assumes that <tt>argc[0]</tt> just contains
597  the name of the command, and should thus be ignored.
598  */
599  int process_args(int argc, char *argv[],
600  std::vector<cmd_line_arg> &ca, int debug=0);
601 
602  int process_args(std::vector<std::string> &sv,
603  std::vector<cmd_line_arg> &ca, int debug);
604 
605  /** \brief Process command-line arguments from a string
606 
607  \future There's a typecast in this function to (char *)
608  from (const char *) which needs reworking.
609  */
610  int process_args(std::string s, std::vector<cmd_line_arg> &ca,
611  int debug=0);
612 
613  /** \brief Set verbosity
614 
615  Most errors are output to the screen even if verbose is zero.
616  */
617  int set_verbose(int v);
618 
619  /// Run the interactive mode
620  int run_interactive();
621 
622  // Create a new command
623  // int replace_command(comm_option &ic);
624 
625  /** \brief Set an alias \c alias for the string \c str
626 
627  Aliases can also be set using the command \c 'alias', but
628  that version allows only one-word aliases.
629  */
630  int set_alias(std::string alias, std::string str);
631 
632  /** \brief Set an alias \c alias for the string \c str
633 
634  Aliases can also be set using the command \c 'alias', but
635  that version allows only one-word aliases.
636  */
637  std::string get_alias(std::string alias);
638 
639  };
640 
641 #ifndef DOXYGEN_NO_O2NS
642 }
643 #endif
644 
645 #endif
comm_option_mfptr(const comm_option_mfptr &f)
Copy constructor.
Definition: cli.h:129
Double parameter for o2scl::cli.
Definition: cli.h:299
comm_option_fptr(int(*fp)(std::vector< std::string > &, bool))
Create from a member function pointer from the specified class.
Definition: cli.h:66
std::string cmd_name
The name of the command.
Definition: cli.h:506
The main O<span style=&#39;position: relative; top: 0.3em; font-size: 0.8em&#39;>2</span>scl O$_2$scl names...
Definition: anneal.h:42
int * i
Parameter.
Definition: cli.h:340
Integer parameter for o2scl::cli.
Definition: cli.h:356
std::string help
The help description.
Definition: cli.h:170
int verbose
Control screen output.
Definition: cli.h:405
String parameter for o2scl::cli.
Definition: cli.h:253
invalid argument supplied by user
Definition: err_hnd.h:59
std::string desc
A one- or two-line description (default is empty string)
Definition: cli.h:503
std::string lng
Long option (must be specified and must be unique)
Definition: cli.h:160
comm_option_fptr & operator=(const comm_option_fptr &f)
Copy constructor.
Definition: cli.h:90
Parameter for o2scl::cli.
Definition: cli.h:235
std::string parm_desc
Description of parameters.
Definition: cli.h:168
tclass * tptr
The pointer to the class.
Definition: cli.h:126
std::string btos(bool b)
Convert a boolean value to a string.
comm_option_funct * func
The pointer to the function to be called (or 0 for no function)
Definition: cli.h:172
int set_function(comm_option_funct &usf)
Function to call when a set command is issued.
Definition: cli.h:464
std::string addl_help_cli
Additional help text for command-line (default is empty string)
Definition: cli.h:512
std::string prompt
The prompt (default "> ")
Definition: cli.h:500
generic failure
Definition: err_hnd.h:61
std::string tilde_string
String to replace tildes with.
Definition: cli.h:453
int type
Type: command-line parameter, command, or both.
Definition: cli.h:174
Configurable command-line interface.
Definition: cli.h:230
virtual int operator()(std::vector< std::string > &cstr, bool itive_com)
The basic function called by o2scl::cli.
Definition: cli.h:73
std::string help
Help description.
Definition: cli.h:242
virtual int operator()(std::vector< std::string > &cstr, bool itive_com)=0
The basic function called by o2scl::cli.
std::map< std::string, parameter *, std::greater< std::string > >::iterator par_t
List iterator.
Definition: cli.h:384
int stoi(std::string s, bool err_on_fail=true)
Convert a string to an integer.
bool stob(std::string s, bool err_on_fail=true)
Convert a string to a boolean value.
int(tclass::* fptr)(std::vector< std::string > &cstr, bool itive_com)
The pointer to the member function.
Definition: cli.h:123
bool is_valid
Is a properly formatted option.
Definition: cli.h:189
int(* fptr)(std::vector< std::string > &cstr, bool itive_com)
The pointer to the member function.
Definition: cli.h:82
bool shell_cmd_allowed
If true, allow the user to use ! to execute a shell command (default true)
Definition: cli.h:497
comm_option_mfptr(tclass *tp, int(tclass::*fp)(std::vector< std::string > &, bool))
Create from a member function pointer from the specified class.
Definition: cli.h:105
size_t * s
Parameter.
Definition: cli.h:363
comm_option_mfptr & operator=(const comm_option_mfptr &f)
Copy constructor.
Definition: cli.h:135
A command-line argument for o2scl::cli.
Definition: cli.h:183
Member function pointer for o2scl::cli command function.
Definition: cli.h:100
std::string dtos(double x, int prec=6, bool auto_prec=false)
Convert a double to a string.
int min_parms
Minimum number of parameters (0 for none, -1 for variable)
Definition: cli.h:164
String parameter for o2scl::cli.
Definition: cli.h:276
bool * b
Parameter.
Definition: cli.h:283
Base for o2scl::cli command function.
Definition: cli.h:47
std::string * str
Parameter.
Definition: cli.h:260
std::map< std::string, parameter *, std::less< std::string > > par_list
Parameter list.
Definition: cli.h:381
std::vector< comm_option_s > clist
List of commands.
Definition: cli.h:427
Function pointer for o2scl::cli command function.
Definition: cli.h:61
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
double * d
Parameter.
Definition: cli.h:310
Integer parameter for o2scl::cli.
Definition: cli.h:333
int max_parms
Maximum number of parameters (0 for none, -1 for variable)
Definition: cli.h:166
Command for interactive mode in o2scl::cli.
Definition: cli.h:155
char shrt
Short option (&#39;\0&#39; for none, must be unique if present)
Definition: cli.h:158
std::string addl_help_cmd
Additional help text for interactive mode (default is empty string)
Definition: cli.h:509
bool gnu_intro
If true, output the usual GNU intro when run_interactive() is called (default true).
Definition: cli.h:461
size_t stoszt(std::string s, bool err_on_fail=true)
Convert a string to a size_t.
comm_option_s * cop
A pointer to the appropriate option (0, unless it&#39;s an option)
Definition: cli.h:193
bool is_option
Is an option?
Definition: cli.h:187
bool sync_verbose
If true, then sync cli::verbose, with a parameter of the same name.
Definition: cli.h:492
virtual int operator()(std::vector< std::string > &cstr, bool itive_com)
The basic function called by o2scl::cli.
Definition: cli.h:114
double stod(std::string s, bool err_on_fail=true)
Convert a string to a double.
bool parse_strings
If true,.
Definition: cli.h:313
std::string itos(int x)
Convert an integer to a string.
comm_option_funct * user_set_func
Storage for the function to call after setting a parameter.
Definition: cli.h:424
double function_to_double(std::string s, bool err_on_fail=true)
Convert a formula to a double.
std::string szttos(size_t x)
Convert a size_t to a string.
std::string desc
Description for help.
Definition: cli.h:162
std::vector< std::string > parms
List of parameters (empty, unless it&#39;s an option)
Definition: cli.h:191
std::string arg
The argument.
Definition: cli.h:185

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).