cli.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl is free software; you can redistribute it and/or modify
00009   it under the terms of the GNU General Public License as published by
00010   the Free Software Foundation; either version 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl is distributed in the hope that it will be useful,
00014   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016   GNU General Public License for more details.
00017   
00018   You should have received a copy of the GNU General Public License
00019   along with O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_CLI_H
00024 #define O2SCL_CLI_H
00025 
00026 #include <iostream>
00027 #include <vector>
00028 #include <algorithm>
00029 #include <sstream>
00030 
00031 #include <o2scl/collection.h>
00032 #include <o2scl/columnify.h>
00033 
00034 #ifndef DOXYGENP
00035 namespace o2scl {
00036 #endif
00037 
00038   /** 
00039       \brief Base for \ref cli command function
00040 
00041 
00042   */
00043   class comm_option_funct {
00044 
00045   public:
00046 
00047     comm_option_funct() {}
00048 
00049     virtual ~comm_option_funct() {}
00050 
00051     /// The basic function called by \ref cli
00052     virtual int operator()(std::vector<std::string> &cstr, bool itive_com) {
00053       return 0;
00054     }
00055 
00056 #ifndef DOXYGENP
00057 
00058   private:
00059     comm_option_funct(const comm_option_funct &);
00060     comm_option_funct& operator=(const comm_option_funct&);
00061 
00062 #endif
00063 
00064   };
00065 
00066   /// Member function pointer for \ref cli command function
00067   template<class tclass> class comm_option_mfptr : public comm_option_funct {
00068 
00069   public:
00070 
00071     /// Create from a member function pointer from the specified class
00072     comm_option_mfptr(tclass *tp, int (tclass::*fp)(std::vector<std::string> &,
00073                                                 bool)) {
00074       tptr=tp;
00075       fptr=fp;
00076     }
00077 
00078     virtual ~comm_option_mfptr() {}
00079 
00080     /// The basic function called by \ref cli
00081     virtual int operator()(std::vector<std::string> &cstr, bool itive_com) {
00082       return (*tptr.*fptr)(cstr,itive_com);
00083     }
00084 
00085 #ifndef DOXYGEN_INTERNAL
00086 
00087   protected:
00088     
00089     /// The pointer to the member function
00090     int (tclass::*fptr)(std::vector<std::string> &cstr, bool itive_com);
00091 
00092     /// The pointer to the class 
00093     tclass *tptr;
00094 
00095 #endif
00096 
00097 #ifndef DOXYGENP
00098 
00099   private:
00100     comm_option_mfptr(const comm_option_mfptr &);
00101     comm_option_mfptr& operator=(const comm_option_mfptr&);
00102 
00103 #endif
00104     
00105   };
00106 
00107   /** 
00108       \brief Command for interactive mode in \ref cli
00109 
00110 
00111   */
00112   typedef struct {
00113 
00114     /// Short option (\c '\\0' for none)
00115     char shrt;
00116     /// Long option (must be specified)
00117     std::string lng;
00118     /// Description for help (default is empty string)
00119     std::string desc;
00120     /// Minimum number of parameters (0 for none, -1 for variable)
00121     int min_parms;
00122     /// Maximum number of parameters (0 for none, -1 for variable)
00123     int max_parms;
00124     /// Description of parameters (default is empty string)
00125     std::string parm_desc;
00126     /// The help description (default is empty string)
00127     std::string help;
00128     /// The pointer to the function to be called (or 0 for no function)
00129     comm_option_funct *func;
00130     /// Type: command-line parameter, command, or both (default command)
00131     int type;
00132 
00133   } comm_option_s;
00134   
00135   /** 
00136       \brief Command for interactive mode in \ref cli
00137 
00138 
00139   */
00140   class comm_option : public comm_option_s {
00141     
00142   public:
00143 
00144     comm_option() {
00145       shrt=0;
00146       lng="";
00147       desc="";
00148       min_parms=0;
00149       max_parms=0;
00150       parm_desc="";
00151       help="";
00152       func=0;
00153       type=command;
00154     }
00155 
00156     comm_option(comm_option_s c) {
00157       shrt=c.shrt;
00158       lng=c.lng;
00159       desc=c.desc;
00160       min_parms=c.min_parms;
00161       max_parms=c.max_parms;
00162       parm_desc=c.parm_desc;
00163       help=c.help;
00164       func=c.func;
00165       type=c.type;
00166     }
00167     
00168     /// \name Possible values of ::type
00169     //@{
00170     static const int command=0;
00171     static const int cl_param=1;
00172     static const int both=2;
00173     //@}
00174 
00175   }; 
00176 
00177   /** \brief A command-line argument
00178    */
00179   typedef struct {
00180     /// The argument
00181     std::string arg;
00182     /// Is an option?
00183     bool is_option;
00184     /// Is a properly formatted option
00185     bool is_valid;
00186     /// List of parameters (empty, unless it's an option)
00187     std::vector<std::string> parms;
00188     /// A pointer to the appropriate (0, unless it's an option)
00189     comm_option *cop;
00190   } cmd_line_arg;
00191 
00192   /** 
00193       \brief Configurable command-line interface
00194 
00195 
00196 
00197       Default commands: help, get/set, quit, exit, '!', verbose, license,
00198       warranty, alias.
00199 
00200       Note that if the shell command is allowed (as it is by default)
00201       there are serious security issues which arise.
00202       
00203       Commands which begin with a '#' character are ignored.
00204   */
00205   class cli {
00206 
00207 #ifndef DOXYGEN_INTERNAL
00208 
00209   protected:
00210   
00211     /// Replace all occurences of \c sold with \c snew in \c s
00212     int apply_alias(std::string &s, std::string sold, std::string snew);
00213 
00214     /// Separate a string into words
00215     int separate(std::string str, std::vector<std::string> &sv);
00216   
00217     /// Control screen output
00218     int verbose;
00219 
00220     /// Pointer to collection for parameters
00221     collection *cop;
00222     
00223     /// \name The hard-coded command functions
00224     //@{
00225     int comm_option_get(std::vector<std::string> &sv, bool itive_com);
00226     int comm_option_set(std::vector<std::string> &sv, bool itive_com);
00227     int comm_option_help(std::vector<std::string> &sv, bool itive_com);
00228     int comm_option_license(std::vector<std::string> &sv, bool itive_com);
00229     int comm_option_warranty(std::vector<std::string> &sv, bool itive_com);
00230     int comm_option_no_intro(std::vector<std::string> &sv, bool itive_com);
00231     int comm_option_alias(std::vector<std::string> &sv, bool itive_com);
00232     //@}
00233 
00234     /// Storage for getline
00235     char buf[300];
00236 
00237     /// Storage for the function to call after setting a parameter
00238     comm_option_funct *user_set_func;
00239     
00240     /// List of commands
00241     std::vector<comm_option *> clist;
00242   
00243     /// \name Help for parameters
00244     //@{
00245     std::vector<std::string> ph_name, ph_desc;
00246     //@}
00247 
00248     /// \name Aliases
00249     //@{
00250     std::vector<std::string> al1, al2;
00251     //@}
00252     
00253     /// Compare two strings, treating dashes as underscores
00254     bool string_equal(std::string s1, std::string s2);
00255 
00256 #endif
00257   
00258   public:
00259 
00260     cli();
00261 
00262     virtual ~cli();
00263 
00264     /** \brief If true, output the usual GNU intro when run_interactive() 
00265         is called.
00266 
00267         In order to conform to GNU standards, this ought not be set to
00268         false by default.
00269     */
00270     bool gnu_intro;
00271 
00272     /// Function to call when a \c set command is issued
00273     int set_function(comm_option_funct &usf) {
00274       user_set_func=&usf;
00275       return 0;
00276     }
00277 
00278     /// \name The hard-coded command objects
00279     //@{
00280     comm_option c_help;
00281     comm_option c_quit;
00282     comm_option c_exit;
00283     comm_option c_license;
00284     comm_option c_warranty;
00285     comm_option c_set;
00286     comm_option c_get;
00287     comm_option c_no_intro;
00288     comm_option c_alias;
00289     //@}
00290     
00291     /// If true, then sync ::verbose, with a parameter of the same name
00292     bool sync_verbose;
00293 
00294     /** \brief If true, allow the user to use ! to execute a shell command 
00295         (default true)
00296     */
00297     bool shell_cmd_allowed;
00298 
00299     /// The prompt (default \c "> ")
00300     std::string prompt;
00301     
00302     /// A one- or two-line description (default is empty string)
00303     std::string desc;
00304 
00305     /// The name of the command
00306     std::string cmd_name;
00307 
00308     /// Additional help text for interactive mode (default is empty string)
00309     std::string addl_help_cmd;
00310 
00311     /// Additional help text for command-line (default is empty string)
00312     std::string addl_help_cli;
00313 
00314     /* A static variable for holding the line for \ref sn_cli */
00315     char *line_read;
00316 
00317     virtual char *cli_gets(const char *c) {
00318       std::cout << c << std::flush;
00319       std::cin.getline(buf,300);
00320       return buf;
00321     }
00322     
00323     /// Call functions corresponding to command-line args
00324     int call_args(std::vector<cmd_line_arg> &ca);
00325 
00326     /// Process command-line arguments
00327     int process_args(int argv, const char *argc[], 
00328                      std::vector<cmd_line_arg> &ca, int debug=0);
00329     
00330     /// Process command-line arguments
00331     int process_args(std::string s, std::vector<cmd_line_arg> &ca, 
00332                      int debug=0) {
00333       std::vector<std::string> sv;
00334       separate(s,sv);
00335       int argv=sv.size();
00336       const char **argc=new const char *[argv];
00337       for(int i=0;i<argv;i++) argc[i]=sv[i].c_str();
00338       int ret=process_args(argv,argc,ca,debug);
00339       delete[] argc;
00340       return ret;
00341     }
00342 
00343     /** 
00344         \brief Set verbosity
00345         
00346         Most errors are output to the screen even if verbose is zero.
00347     */
00348     int set_verbose(int v);
00349 
00350     /// Run the interactive mode
00351     int run_interactive();
00352     
00353     /** 
00354         \brief Add a new command
00355         
00356         Each command/option must have either a short form in
00357         comm_option::shrt or a long from in comm_option::lng,
00358         which is unique from the other commands/options already
00359         present. You cannot add two commands/options with the same
00360         short form, even if they have different long forms, and vice
00361         versa.
00362 
00363      */
00364     int set_comm_option(comm_option &ic);
00365 
00366     /// Create a new command
00367     //    int replace_command(comm_option &ic);
00368 
00369     /// Set the parameters with a collection
00370     int set_parameters(collection &co);
00371 
00372     /// Set one-line help text for a parameter named \c param
00373     int set_param_help(std::string param, std::string help);
00374 
00375     /** 
00376         \brief Set an alias \c alias for the string \c str
00377 
00378         Aliases can also be set using the command \c 'alias', but 
00379         that version allows only one-word aliases. 
00380      */
00381     int set_alias(std::string alias, std::string str) {
00382       al1.push_back(alias);
00383       al2.push_back(str);
00384       return 0;
00385     }
00386   
00387   };
00388 
00389 #ifndef DOXYGENP
00390 }
00391 #endif
00392 
00393 #endif

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.