cli.h

00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006, 2007, 2008, 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       See the \ref cli class for more details.
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       See the \ref cli class for more details.
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       See the \ref cli class for more details.
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       Somewhat experimental.
00196 
00197       Default commands: help, get/set, quit, exit, '!', verbose, license,
00198       warranty, alias, run.
00199 
00200       Note that if the shell command is allowed (as it is by default)
00201       there are some potential security issues which are not 
00202       solved here.
00203       
00204       Commands which begin with a '#' character are ignored.
00205   */
00206   class cli {
00207 
00208 #ifndef DOXYGEN_INTERNAL
00209 
00210   protected:
00211   
00212     /// Replace all occurences of \c sold with \c snew in \c s
00213     int apply_alias(std::string &s, std::string sold, std::string snew);
00214 
00215     /// Separate a string into words
00216     int separate(std::string str, std::vector<std::string> &sv);
00217   
00218     /// Control screen output
00219     int verbose;
00220 
00221     /// Pointer to collection for parameters
00222     collection *cop;
00223     
00224     /// \name The hard-coded command functions
00225     //@{
00226     int comm_option_run(std::vector<std::string> &sv, bool itive_com);
00227     int comm_option_get(std::vector<std::string> &sv, bool itive_com);
00228     int comm_option_set(std::vector<std::string> &sv, bool itive_com);
00229     int comm_option_help(std::vector<std::string> &sv, bool itive_com);
00230     int comm_option_license(std::vector<std::string> &sv, bool itive_com);
00231     int comm_option_warranty(std::vector<std::string> &sv, bool itive_com);
00232     int comm_option_no_intro(std::vector<std::string> &sv, bool itive_com);
00233     int comm_option_alias(std::vector<std::string> &sv, bool itive_com);
00234     //@}
00235 
00236     /// Storage for getline
00237     char buf[300];
00238 
00239     /// Storage for the function to call after setting a parameter
00240     comm_option_funct *user_set_func;
00241     
00242     /// List of commands
00243     std::vector<comm_option *> clist;
00244   
00245     /// \name Help for parameters
00246     //@{
00247     std::vector<std::string> ph_name, ph_desc;
00248     //@}
00249 
00250     /// \name Aliases
00251     //@{
00252     std::vector<std::string> al1, al2;
00253     //@}
00254     
00255     /// Compare two strings, treating dashes as underscores
00256     bool string_equal(std::string s1, std::string s2);
00257 
00258 #endif
00259   
00260   public:
00261 
00262     cli();
00263 
00264     virtual ~cli();
00265 
00266     /** \brief If true, output the usual GNU intro when run_interactive() 
00267         is called.
00268 
00269         In order to conform to GNU standards, this ought not be set to
00270         false by default.
00271     */
00272     bool gnu_intro;
00273 
00274     /// Function to call when a \c set command is issued
00275     int set_function(comm_option_funct &usf) {
00276       user_set_func=&usf;
00277       return 0;
00278     }
00279 
00280     /// \name The hard-coded command objects
00281     //@{
00282     comm_option c_help;
00283     comm_option c_quit;
00284     comm_option c_exit;
00285     comm_option c_license;
00286     comm_option c_warranty;
00287     comm_option c_set;
00288     comm_option c_get;
00289     comm_option c_run;
00290     comm_option c_no_intro;
00291     comm_option c_alias;
00292     //@}
00293     
00294     /// If true, then sync ::verbose, with a parameter of the same name
00295     bool sync_verbose;
00296 
00297     /** \brief If true, allow the user to use ! to execute a shell command 
00298         (default true)
00299     */
00300     bool shell_cmd_allowed;
00301 
00302     /// The prompt (default \c "> ")
00303     std::string prompt;
00304     
00305     /// A one- or two-line description (default is empty string)
00306     std::string desc;
00307 
00308     /// The name of the command
00309     std::string cmd_name;
00310 
00311     /// Additional help text for interactive mode (default is empty string)
00312     std::string addl_help_cmd;
00313 
00314     /// Additional help text for command-line (default is empty string)
00315     std::string addl_help_cli;
00316 
00317     /* A static variable for holding the line for \ref sn_cli */
00318     char *line_read;
00319 
00320     virtual char *cli_gets(const char *c) {
00321       std::cout << c << std::flush;
00322       std::cin.getline(buf,300);
00323       return buf;
00324     }
00325     
00326     /// Call functions corresponding to command-line args
00327     int call_args(std::vector<cmd_line_arg> &ca);
00328 
00329     /// Process command-line arguments
00330     int process_args(int argv, const char *argc[], 
00331                      std::vector<cmd_line_arg> &ca, int debug=0);
00332     
00333     /// Process command-line arguments
00334     int process_args(std::string s, std::vector<cmd_line_arg> &ca, 
00335                      int debug=0) {
00336       std::vector<std::string> sv;
00337       separate(s,sv);
00338       int argv=sv.size();
00339       const char **argc=new const char *[argv];
00340       for(int i=0;i<argv;i++) argc[i]=sv[i].c_str();
00341       int ret=process_args(argv,argc,ca,debug);
00342       delete[] argc;
00343       return ret;
00344     }
00345 
00346     /** 
00347         \brief Set verbosity
00348         
00349         Most errors are output to the screen even if verbose is zero.
00350     */
00351     int set_verbose(int v);
00352 
00353     /// Run the interactive mode
00354     int run_interactive();
00355     
00356     /** 
00357         \brief Add a new command
00358         
00359         Each command/option must have either a short form in
00360         comm_option::shrt or a long from in comm_option::lng,
00361         which is unique from the other commands/options already
00362         present. You cannot add two commands/options with the same
00363         short form, even if they have different long forms, and vice
00364         versa.
00365 
00366      */
00367     int set_comm_option(comm_option &ic);
00368 
00369     /// Create a new command
00370     //    int replace_command(comm_option &ic);
00371 
00372     /// Set the parameters with a collection
00373     int set_parameters(collection &co);
00374 
00375     /// Set one-line help text for a parameter named \c param
00376     int set_param_help(std::string param, std::string help);
00377 
00378     /** 
00379         \brief Set an alias \c alias for the string \c str
00380 
00381         Aliases can also be set using the command \c 'alias', but 
00382         that version allows only one-word aliases. 
00383      */
00384     int set_alias(std::string alias, std::string str) {
00385       al1.push_back(alias);
00386       al2.push_back(str);
00387       return 0;
00388     }
00389   
00390   };
00391 
00392 #ifndef DOXYGENP
00393 }
00394 #endif
00395 
00396 #endif

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

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page