Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/io/cmdline.h

Go to the documentation of this file.
00001 //  Copyright (C) 2000--2002  Petter Urkedal (petter.urkedal@matfys.lth.se)
00002 //
00003 //  This file is free software; you can redistribute it and/or modify
00004 //  it under the terms of the GNU General Public License as published by
00005 //  the Free Software Foundation; either version 2 of the License, or
00006 //  (at your option) any later version.
00007 //
00008 //  This file is distributed in the hope that it will be useful,
00009 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 //  GNU General Public License for more details.
00012 //
00013 //  You should have received a copy of the GNU General Public License
00014 //  along with this program; if not, write to the Free Software
00015 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00016 //
00017 //  As a special exception, you may use this file as part of a free
00018 //  software library without restriction.  Specifically, if other files
00019 //  instantiate templates or use macros or inline functions from this
00020 //  file, or you compile this file and link it with other files to
00021 //  produce an executable, this file does not by itself cause the
00022 //  resulting executable to be covered by the GNU General Public
00023 //  License.  This exception does not however invalidate any other
00024 //  reasons why the executable file might be covered by the GNU General
00025 //  Public License.
00026 //
00027 //  $Id: cmdline.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $
00028 
00029 
00030 
00031 //  This is a new command-line parser, simplified compared to
00032 //  command.h, but still very general.
00033 
00034 //  TODO:
00035 //  * Some way to give specify that options are required and arguments
00036 //  are optional.  One way to to this is to delimit required and
00037 //  optional inserts by a call to some member function (like
00038 //  `cmdl.the_rest_is_optional()').  It is probably better to specify
00039 //  this as a bool arg to the inserters.
00040 //  * Unifty with parsing of resources.
00041 //    `some.resource' refers to `progname.some.resource' in RC file
00042 //    `shortopt.c' is a synonym for `-c'
00043 //    `longopt.name' is a synonym for `--name'
00044 //  Alternatively, we call the above `r:some.resource', `s:c' and `l:name'.
00045 //  Or, `r.some.resource', `s.c', `l.name'.
00046 //  * An option argument to the ctor, allow ignoring unparse args
00047 //  * Maybe implement insert_passthrough(std::string, std::string)
00048 //  * If the user overrides --help, this shall not be treated specially.
00049 
00050 #ifndef MORE_IO_CMDLINE_H
00051 #define MORE_IO_CMDLINE_H
00052 
00053 
00054 #include <iostream>
00055 #include <functional>
00056 #include <map>
00057 #include <list>
00058 #include <more/gen/closure.h>
00059 #include <stdexcept>
00060 #include <string>
00061 #include <cstdlib>
00062 
00063 
00064 namespace more {
00065 namespace io {
00066 
00067   template<typename T>
00068     struct cmdline_arg_parser
00069         : std::unary_function<std::istream&, void>
00070     {
00071         cmdline_arg_parser(T& x, bool& ntf)
00072             : m_x(x), m_notify(ntf) {}
00073 
00074         void operator()(std::istream& is)
00075         {
00076             if (is >> m_x)
00077                 m_notify = true;
00078         }
00079 
00080       private:
00081         T& m_x;
00082         bool& m_notify;
00083     };
00084 
00085   template<>
00086     struct cmdline_arg_parser<std::string>
00087         : std::unary_function<std::istream&, void>
00088     {
00089         cmdline_arg_parser(std::string& x, bool& f)
00090             : m_x(x), m_notify(f) {}
00091         void operator()(std::istream& is);
00092 
00093       private:
00094         std::string& m_x;
00095         bool& m_notify;
00096     };
00097 
00098   template<typename T>
00099     struct cmdline_setter : std::unary_function<std::istream&, void>
00100     {
00101         cmdline_setter(T& x, T const& v) : ref(x), value(v) {}
00102         void operator()(std::istream& is) { ref = value; }
00103 
00104       private:
00105         T& ref;
00106         T value;
00107     };
00108 
00109   template<typename T, typename OutputIterator>
00110     struct cmdline_copier : std::unary_function<std::istream&, void>
00111     {
00112         cmdline_copier(OutputIterator it) : m_it(it) {}
00113 
00114         void operator()(std::istream& is)
00115         {
00116             T x;
00117             is >> x;
00118             *m_it = x;
00119             ++m_it;
00120         }
00121 
00122       private:
00123         OutputIterator m_it;
00124     };
00125 
00126 
00127   /** \class cmdline cmdline.h more/io/cmdline.h
00128    **
00129    ** A command line parser.  Make sure to catch the \c relax
00130    ** exception.  If you need to take control of the <tt>--help</tt>
00131    ** option, you may alternatively detect it before calling \c parse
00132    ** and possibly call \c print_help within your own help printing
00133    ** code.
00134    **
00135    ** The following environment variables are handled by
00136    ** <tt>cmdline::parse</tt> and causes <tt>set_tslang</tt> to be called
00137    ** on the standard output streams.
00138    ** <ul>
00139    **   <li><tt>MORE_IO_MARKUP</tt> is the default markup language to use</li>
00140    **   <li><tt>MORE_IO_COUT_MARKUP</tt> overrides the ML for stdout.</li>
00141    **   <li><tt>MORE_IO_CERR_MARKUP</tt> overrides the ML for stderr.</li>
00142    ** </ul>
00143    ** Also, if <tt>MORE_IO_CMDLINE_ASSIGN</tt> is set to <tt>true</tt>
00144    ** or is unset <tt>parse</tt> accepts assignment style long-options
00145    ** without the “<tt>--</tt>” prefix, and if it is set to <tt>false</tt> the
00146    ** “<tt>--</tt>” prefix is required. */
00147   struct cmdline
00148   {
00149       typedef std::size_t size_type;
00150       typedef gen::unary_closure<std::istream&, void> closure_type;
00151 
00152       typedef unsigned int flag_type;
00153       static flag_type const enable_assignment_style = 1;
00154       static flag_type const disable_assignment_style = 2;
00155 
00156     private:
00157       typedef std::map<std::string, closure_type> opt_map_type;
00158       typedef std::list<closure_type> arg_list_type;
00159       typedef std::list< std::pair<std::string, std::string> > opt_doc_type;
00160       typedef std::list< std::string > arg_doc_type;
00161 
00162     public:
00163       /** An exception thrown when the command line options are
00164        ** ill-formed.  You should catch it and exit the program with
00165        ** non-zero status. */
00166       struct failure : std::runtime_error
00167       {
00168           failure(std::string const& what_)
00169               : std::runtime_error(what_+" (Try `--help'.)") {}
00170       };
00171 
00172       /** An exception thrown when the user has requested help.
00173        ** This is not an error, and you have to catch this exception
00174        ** and exit the program with status 0.  You may print
00175        ** additional help in the catch block. */
00176       struct relax : std::exception
00177       {
00178           relax(std::string const& what_) : msg(what_) {}
00179           virtual ~relax() throw() {}
00180           virtual const char* what() const throw() {
00181               return msg.c_str();
00182           }
00183         private:
00184           std::string msg;
00185       };
00186 
00187       /** Construct the parser. */
00188       explicit cmdline(flag_type fl = 0);
00189 
00190       /** Insert an option which will call \a f with its argument.
00191        ** This is the general form.  */
00192       template<typename UnaryFunction>
00193         void insert_functional(std::string const& opt,
00194                                std::string const& doc, UnaryFunction f)
00195         {
00196             priv_insert(opt, doc, closure_type(f));
00197         }
00198 
00199       /** Insert an option which will set \a x to its argument. */
00200       template<typename T>
00201         void insert_reference(std::string const& opt,
00202                               std::string const& doc, T& x,
00203                               bool& notify = null_notify)
00204         {
00205             notify = false;
00206             priv_insert(opt, doc,
00207                         closure_type(cmdline_arg_parser<T>(x, notify)));
00208         }
00209 
00210       /** Insert an option which takes no arugment and causes
00211        ** <tt>x=v</tt>. */
00212       template<typename T>
00213         void insert_setter(std::string const& opt,
00214                            std::string const& doc, T& x, T const& v)
00215         {
00216             priv_insert(opt, doc, closure_type(cmdline_setter<T>(x, v)));
00217         }
00218 
00219       /** Insert a reader which will copy each argument to \a opt to
00220        ** \a it. */
00221       template<typename T, typename OutputIterator>
00222         void insert_copier(std::string const& opt,
00223                            std::string const& doc, OutputIterator it)
00224         {
00225             priv_insert(opt, doc,
00226                         closure_type(cmdline_copier<T, OutputIterator>(it)));
00227         }
00228 
00229       /** Make the remaining arguments optional. */
00230       void optional()
00231       {
00232           n_required = arg_list.size();
00233       }
00234 
00235       /** Parse (\a arg, \a argv) as given to \c main. */
00236       void parse(int argc, char** argv);
00237 
00238       /** Print the documentation for the options.  This is done
00239        ** automatically when the <tt>--help</tt> option is given,
00240        ** provided you catch \c relax. */
00241       void print_help(std::ostream&) const;
00242 
00243       /** Return \c argv[0] as passed to \c parse. */
00244       static std::string const& program_name() { return prgname; }
00245 
00246     private:
00247       void priv_insert(std::string const&, std::string const&,
00248                        closure_type);
00249       opt_map_type      opt_map;
00250       arg_list_type     arg_list;
00251       opt_doc_type      opt_doc;
00252       arg_doc_type      arg_doc;
00253       int               n_required;
00254       flag_type         m_flags;
00255 
00256       static bool null_notify;
00257       static std::string prgname;
00258 
00259       // Common options
00260     public:
00261       static int verbose() { return s_opt_verb; }
00262       static int debug() { return s_opt_debug; }
00263     private:
00264       static int s_opt_verb;
00265       static int s_opt_debug;
00266   };
00267 
00268 }} // more::io
00269 
00270 
00271 #endif
00272 
00273 // Local Variables:
00274 // coding: utf-8
00275 // End:

Generated on Sat Sep 7 19:11:15 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.