Fix SCons 1.2.0 build failure
[senf.git] / senf / Utils / Console / ParsedCommand.hh
1 // $Id$
2 //
3 // Copyright (C) 2008 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program 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 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program 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 this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ParsedCommand public header */
25
26 #ifndef HH_SENF_Scheduler_Console_ParsedCommand_
27 #define HH_SENF_Scheduler_Console_ParsedCommand_ 1
28
29 // Custom includes
30
31 #define BOOST_PARAMETER_MAX_ARITY 6
32
33 #include <vector>
34 #include <boost/type_traits/function_traits.hpp>
35 #include <boost/type_traits/is_member_pointer.hpp>
36 #include <boost/mpl/if.hpp>
37 #include <boost/utility.hpp>
38 #include <boost/parameter/keyword.hpp>
39 #include <boost/parameter/parameters.hpp>
40 #include "../../config.hh"
41 #include "OverloadedCommand.hh"
42 #include "Traits.hh"
43 #include "../../Utils/type_traits.hh"
44
45 #include "ParsedCommand.ih"
46 #include "ParsedCommand.mpp"
47 ///////////////////////////////hh.p////////////////////////////////////////
48
49 namespace senf {
50 namespace console {
51
52     namespace detail { class ArgumentInfoBase; }
53
54     /** \brief CommandOverload implementation with automatic argument parsing
55
56         ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
57         parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to
58         an OverloadedCommandNode instance.
59
60         Automatic argument parsing and return value processing consists of several components:
61         \li \ref overload_add Adding overload instances to the tree
62         \li (Advanced) \ref overload_parse
63         \li (Advanced) \ref overload_format
64
65         \section overload_add Adding argument parsing callbacks to the tree
66
67         Adding appropriate callbacks to the tree is very simple: just path a function pointer to
68         DirectoryNode::add() or a member function pointer to ScopedDirectory::add().
69         \code
70         std::string taskStatus(int id);
71
72         senf::console::root().add("taskStatus", &taskStatus);
73         \endcode
74
75         There are quite a number of additional parameters available to be set. These parameters are
76         documented in ParsedArgumentAttributor. Parameters are set by adding them as additional
77         calls after adding the node:
78
79         \code
80         senf::console::root().add("taskStatus", &taskStatus)
81             .doc("Query the current task status")
82             .arg( name = "id",
83                   description = "numeric id of task to check, -1 for the current task."
84                   default_value = -1 );
85         \endcode
86
87         You may also add an additional \c std::ostream & Argument as first argument to the
88         callback. If this argument is present, the stream connected to the console which issued the
89         command will be passed there. This allows writing arbitrary messages to the console.
90
91         Additionally, overloading is supported by registering multiple commands under the same
92         name. So, elaborating on above example:
93         \code
94         std::string taskStatus(int id);
95         std::string taskStatus(std::string const & name);
96
97         senf::console::root()
98             .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
99             .doc("Query the current task status")
100             .overloadDoc("Query status by id")
101             .arg( name = "id",
102                   description = "numeric id of task to check, -1 for the current task."
103                   default_value = -1 );
104         senf::console::root()
105             .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
106             .overloadDoc("Query status by name")
107             .arg( name = "name",
108                   description = "name of task to check" );
109         \endcode
110
111         We can see here, that taking the address of an overloaded function requires a cast. If you
112         can give unique names to each of the C++ overloads (not the overloads in the console), you
113         should do so to make the unwieldy casts unnecessary.
114
115         \section overload_parse Custom parameter parsers
116         
117         By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
118         iostreams. This means, that any type which can be read from a stream can automatically be
119         used as argument type.
120
121         However, argument parsing can be configured by specializing
122         senf::console::ArgumentTraits. See that class for more information.
123
124         \section overload_format Custom return-value formatters
125
126         By default, return values are streamed to an ostream. This automatically allows any
127         streamable type to be used as return value. To add new types or customize the formating, the
128         senf::console::ReturnValueTraits template needs to be specialized for that type. See
129         that class for more information.
130
131         \ingroup console_commands
132      */
133     class ParsedCommandOverloadBase
134         : public CommandOverload
135     {
136     public:
137         typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
138
139         detail::ArgumentInfoBase & arg(unsigned n) const;
140
141         void doc(std::string const & d);
142
143     protected:
144         ParsedCommandOverloadBase();
145
146         template <class Type> void addParameter();
147
148     private:
149         virtual unsigned v_numArguments() const;
150         virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
151         virtual std::string v_doc() const;
152
153         typedef std::vector<detail::ArgumentInfoBase::ptr> Parameters;
154         Parameters parameters_;
155         std::string doc_;
156     };
157
158     /** \brief Parsed command overload
159
160         ParsedCommandOverload provides the command overload added to an OverloadedCommandNode for an
161         automatically parsed command.
162
163         This class is normally instantiated automatically when adding a function or member-function
164         pointer as callback to the tree. Manually instantiation this type of overload is \e not
165         simple, since the function signature has to be manipulated correctly to support the optional
166         \c std::ostream first argument.
167
168         \implementation This class is specialized for each supported number of command arguments.
169
170         \todo Implement automatic binding of member functions for parser and formatter
171      */
172     template <class FunctionTraits, class ReturnType, unsigned arity>
173     class ParsedCommandOverload : public ParsedCommandOverloadBase
174     {
175     public:
176         typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
177
178 #ifdef DOXYGEN
179         static ptr create(Function fn);
180 #endif
181     };
182
183 #ifndef DOXYGEN
184
185 #   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
186                                             SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
187                                             1))
188 #   include BOOST_PP_ITERATE()
189
190 #endif
191
192     /** \brief Generic ParsedCommandOverladBase attributes
193
194         Attributes for parsed commands are not set directly on the node. They are set via a special
195         attributor temporary returned when adding a parsed command to the tree.
196         
197         This class is the base class for those attributors. It provides members which do not depend
198         in any way on the exact type of command added.
199
200         \see \ref console_autoparse
201      */
202     class ParsedCommandAttributorBase
203     {
204     public:
205         OverloadedCommandNode & node() const; ///< Return the node object
206         operator OverloadedCommandNode & () const; ///< Automatically convert to node object
207
208     protected:
209         ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
210
211         void argName(std::string const & name) const;
212         void argDoc(std::string const & doc) const;
213         void typeName(std::string const & doc) const;
214         void defaultDoc(std::string const & doc) const;
215
216         ParsedCommandOverloadBase & overload() const;
217         void overloadDoc(std::string const & doc) const;
218         void nodeDoc(std::string const & doc) const;
219         void shortDoc(std::string const & doc) const;
220         
221     private:
222         ParsedCommandOverloadBase & overload_;
223         unsigned index_;
224     };
225
226     /** \brief Non argument dependent ParsedCommandBase attributes 
227         
228         Attributes for parsed commands are not set directly on the node. They are set via a special
229         attributor temporary returned when adding a parsed command to the tree.
230
231         This class adds all those members, which do depend on the type of command added (and thereby
232         on that commands signature) but do not depend on the type of any single argument.
233
234         \see \ref console_autoparse
235      */
236     template <class Overload>
237     class ParsedCommandAttributor
238         : public ParsedCommandAttributorBase
239     {
240     public:
241         Overload & overload() const;    ///< Get the command overload
242
243     protected:
244         ParsedCommandAttributor(Overload & overload, unsigned index);
245
246     private:
247     };
248
249     /** \brief Keyword argument tags
250
251         The tags defined in this namespace are used as keyword arguments via the <a
252         href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
253         library.
254
255         For the keyword tags, the standard C++ scoping rules apply
256         \code
257         // Either qualify them with their complete namespace
258         dir.add(...)
259             .arg( senf::console::kw::name = "name" );
260         
261         // Or use a namespace alias
262         namespace kw = senf::console::kw;
263         dir.add(...)
264             .arg( kw::name = "name" );
265
266         // Or import the keywords into the current namespace (beware of name collisions)
267         using namespace senf::console::kw;
268         dir.add(...)
269             .arg( name = "name" );
270         \endcode
271
272         The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
273         long as the keyword names do not clash with another visible symbol.
274
275         \section kw_attributes Argument attribute values
276
277         The keywords are used to set argument attributes.  The keywords \ref default_value and \ref
278         parser influence, how an argument is parsed/interpreted whereas \ref name, \ref description,
279         \ref type_name and \ref default_doc are used to change the arguments documentation:
280         \code
281         void command(int);
282
283         dir.add("command", &command)
284             .arg( kw::name          = "name",
285                   kw::description   = "description",
286                   kw::default_value = 1,
287                   kw::type_name     = "type_name",
288                   kw::default_doc   = "default_doc" );
289         \endcode
290         Will create the following documentation:
291         \htmlonly
292         <pre>
293         Usage:
294             command [name:type_name]
295         
296         With:
297             name      description
298                 default: default_doc
299         </pre>
300         \endhtmlonly
301
302         \see \ref senf::console::ParsedArgumentAttributor::arg()
303      */
304     namespace kw {
305         BOOST_PARAMETER_KEYWORD(type, name) ///< Argument name
306                                         /**< Sets the displayed name of the argument. */
307         BOOST_PARAMETER_KEYWORD(type, description) ///< One-line argument description
308                                         /**< This description is shown in the argument
309                                              reference. If several overloads have same-named
310                                              arguments, only one of them should be documented. This
311                                              documentation then applies to all arguments of that
312                                              name. */
313         BOOST_PARAMETER_KEYWORD(type, default_value) ///< Argument default value
314                                         /**< If a default value is specified for an argument, that
315                                              argument is optional. If an overload is called with
316                                              fewer arguments than defined, optional values will be
317                                              used beginning at the last optional argument and going
318                                              forward until all arguments have values assigned. E.g.,
319                                              an overload with 5 parameters \a a - \a e with two
320                                              defaults attached:
321                                              <pre>
322                                              command a:int [b:int] c:int [d:int] e:int
323                                              </pre>
324                                              When calling the overload, the arguments will be
325                                              assigned in the following way:
326                                              <table class="senf fixedwidth">
327                                              <tr>
328                                                <td style="whitespace:no-wrap"><tt>command 1 2</tt></td>
329                                                <td colspan="5">SyntaxErrorException: invalid number of
330                                                  arguments</td>
331                                              </tr>
332                                              <tr>
333                                                <td style="white-space:nowrap"><tt>command 1 2 3</tt></td>
334                                                <td style="width:6em">\a a = 1</td><td style="width:6em">\a b = \e default</td><td style="width:6em">\a c = 2</td><td style="width:6em">\a d = \e default</td><td style="width:6em">\a e = 3</td>
335                                              </tr>
336                                              <tr>
337                                                <td style="white-space:nowrap"><tt>command 1 2 3 4</tt></td>
338                                                <td>\a a = 1</td><td>\a b = 2</td><td>\a c = 3</td><td>\a d = \e default</td><td>\a e = 4</td>
339                                              </tr>
340                                              <tr>
341                                                <td style="white-space:nowrap"><tt>command 1 2 3 4 5</tt></td>
342                                                <td>\a a = 1</td><td>\a b = 2</td><td>\a c = 3</td><td>\a d = 4</td><td>\a e = 5</td>
343                                              </tr>
344                                              <tr>
345                                                <td style="white-space:nowrap"><tt>command 1 2 3 4 5 6</tt></td>
346                                                <td colspan="5">SyntaxErrorException: invalid number of
347                                                  arguments</td>
348                                              </tr>
349                                              </table>
350                                              So, if you use default values as you are used to,
351                                              assigning default values to consecutive trailing
352                                              arguments, they work like they do in C++ and most other
353                                              languages */
354         BOOST_PARAMETER_KEYWORD(type, type_name) ///< Type name of this arguments type
355                                         /**< By default, the type of an argument is extracted from
356                                              the C++ type name by taking the last component of the
357                                              fully scoped name. This value can be changed by setting
358                                              this attribute. */
359         BOOST_PARAMETER_KEYWORD(type, default_doc) ///< String rep of default value
360                                         /**< By default, the default value is documented by
361                                              converting the value to it's string representation
362                                              using the corresponding return value formatter which by
363                                              default uses \c boost::lexical_cast / \c iostreams. The
364                                              displayed value can be changed by setting this
365                                              attribute. */
366         BOOST_PARAMETER_KEYWORD(type, parser) ///< Argument parser
367                                         /**< The argument parser is used to convert the argument
368                                              token list returned by the console/config parser into
369                                              the appropriate value. If not set explicitly, this
370                                              conversion is supplied by the ArgumentTraits
371                                              class. 
372
373                                              Setting the \a parser attribute allows to use a custom
374                                              parser. The parser is an arbitrary callable object with
375                                              the signature
376                                              \code
377                                              void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
378                                              \endcode
379                                              where \c value_type is the type of the overload
380                                              parameter. The parser must read and parse the complete
381                                              \a tokens range and return the parsed value in \a
382                                              out. If the parser fails, it must raise a
383                                              senf::console::SyntaxErrorException. */
384     }
385
386     /** \brief Derived class dependent ParsedCommandBase attributes
387
388         Attributes for parsed commands are not set directly on the node. They are set via a special
389         attributor temporary returned when adding a parsed command to the tree.
390         
391         This class adds all those members, which do not depend on any specific argument but which
392         need to return the correct attributor type.
393
394         \see \ref console_autoparse
395      */
396     template <class Overload, class Self, class ReturnType=typename Overload::traits::result_type>
397     class ParsedArgumentAttributorBase
398         : public ParsedCommandAttributor<Overload>
399     {
400     public:
401         Self doc(std::string const & doc) const; ///< Set documentation for all overloads
402         Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
403         Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
404         Self formatter(typename Overload::Formatter formatter) const; 
405                                         ///< Set return value formatter
406                                         /**< This member is only available, if the \a ReturnType of
407                                              the installed callback is not \c void.
408
409                                              If \a ReturnType is not \c void, the \a formatter must
410                                              be a callable with a signature compatible with
411                                              \code
412                                              void formatter(ReturnType const & value, std::ostream & os);
413                                              \endcode
414                                              The \a formatter takes the return value of the call \a
415                                              value and writes it properly formated to \a os. */
416
417     protected:
418         ParsedArgumentAttributorBase(Overload & overload, unsigned index);
419
420     private:
421     };
422
423 #ifndef DOXYGEN
424
425     template <class Overload, class Self>
426     class ParsedArgumentAttributorBase<Overload, Self, void>
427         : public ParsedCommandAttributor<Overload>
428     {
429     public:
430         Self doc(std::string const & doc) const; ///< Set documentation for all overloads
431         Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
432         Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
433
434     protected:
435         ParsedArgumentAttributorBase(Overload & overload, unsigned index);
436
437     private:
438     };
439
440 #endif
441     
442     /** \brief Argument dependent ParsedCommandBase attributes
443
444         Attributes for parsed commands are not set directly on the node. They are set via a special
445         attributor temporary returned when adding a parsed command to the tree.
446         
447         This class adds all those members, which depend on a specific argument. Each call to \c arg
448         will advance to the next argument.
449
450         \see \ref console_autoparse
451      */
452     template < class Overload, unsigned index, bool flag>
453     class ParsedArgumentAttributor
454         : public ParsedArgumentAttributorBase< Overload, 
455                                                 ParsedArgumentAttributor<Overload, index, flag> >
456     {
457         typedef boost::parameter::parameters<
458             kw::type::name,
459             kw::type::description,
460             kw::type::default_value,
461             kw::type::type_name,
462             kw::type::default_doc,
463             kw::type::parser> arg_params;
464
465     public:
466         typedef OverloadedCommandNode node_type;
467         typedef ParsedArgumentAttributor return_type;
468
469         typedef typename senf::function_traits_arg_type< 
470             typename Overload::traits, int(index) >::type arg_type;
471         typedef typename senf::remove_cvref< arg_type >::type value_type;
472         typedef ParsedArgumentAttributor<Overload, index+1> next_type;
473
474         next_type arg() const;          ///< Set argument attributes
475                                         /**< This member changes the attributes for the current
476                                              argument. The attributes are passed to arg() as keyword
477                                              arguments using the <a
478                                              href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
479                                              library. 
480                                              \code
481                                              ...
482                                                  .arg( kw::name          = "name", 
483                                                        kw::default_value = 1 )
484                                              ...
485                                              \endcode
486                                              The valid keywords are defined in the senf::console::kw
487                                              namespace.
488                                              
489                                              Each call to arg() will increment the argument index
490                                              and advance to the next argument. This member is only
491                                              present, if there is an argument at the current
492                                              index. */
493
494 #ifndef DOXYVEN
495
496 #       define BOOST_PP_ITERATION_PARAMS_1                                                        \
497             (4, (1, BOOST_PARAMETER_MAX_ARITY,                                                    \
498                  SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp),                     \
499                  5))
500 #       include BOOST_PP_ITERATE()
501
502 #endif
503
504     private:
505         explicit ParsedArgumentAttributor(Overload & overload);
506
507         template <class ArgumentPack>
508         next_type argInfo(ArgumentPack const & args) const;
509         template <class Kw, class ArgumentPack>
510         void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_) 
511             const;
512
513         template <class ArgumentPack>
514         void argInfo(boost::parameter::keyword<kw::type::name> const &, 
515                      ArgumentPack const & args, boost::mpl::true_) 
516             const;
517         template <class ArgumentPack>
518         void argInfo(boost::parameter::keyword<kw::type::description> const &, 
519                      ArgumentPack const & args, boost::mpl::true_) 
520             const;
521         template <class ArgumentPack>
522         void argInfo(boost::parameter::keyword<kw::type::default_value> const &, 
523                      ArgumentPack const & args, boost::mpl::true_) 
524             const;
525         template <class ArgumentPack>
526         void argInfo(boost::parameter::keyword<kw::type::type_name> const &, 
527                      ArgumentPack const & args, boost::mpl::true_) 
528             const;
529         template <class ArgumentPack>
530         void argInfo(boost::parameter::keyword<kw::type::default_doc> const &, 
531                      ArgumentPack const & args, boost::mpl::true_) 
532             const;
533         template <class ArgumentPack>
534         void argInfo(boost::parameter::keyword<kw::type::parser> const &, 
535                      ArgumentPack const & args, boost::mpl::true_) 
536             const;
537
538         next_type next() const;
539
540         void defaultValue(value_type const & value) const;
541         template <class Fn> void parser(Fn fn) const;
542
543         template <class O, unsigned i, bool f>
544         friend class ParsedArgumentAttributor;
545
546         friend class detail::ParsedCommandAddNodeAccess;
547     };
548
549 #ifndef DOXYGEN
550
551     template <class Overload, unsigned index>
552     class ParsedArgumentAttributor<Overload, index, false>
553         : public ParsedArgumentAttributorBase< Overload, 
554                                                 ParsedArgumentAttributor<Overload, index, false> >
555     {
556     public:
557         typedef OverloadedCommandNode node_type;
558         typedef ParsedArgumentAttributor return_type;
559
560     private:
561         explicit ParsedArgumentAttributor(Overload & overload);
562
563         template <class O, unsigned i, bool f>
564         friend class ParsedArgumentAttributor;
565
566         friend class detail::ParsedCommandAddNodeAccess;
567     };
568
569     template <class Function>
570     typename detail::ParsedCommandTraits<Function>::Attributor
571     senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int,
572                           typename boost::enable_if_c<
573                               detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
574
575     template <class Signature>
576     typename detail::ParsedCommandTraits<Signature>::Attributor
577     senf_console_add_node(DirectoryNode & node, std::string const & name, 
578                           boost::function<Signature> fn, int);
579
580     template <class Owner, class Function>
581     typename detail::ParsedCommandTraits<Function>::Attributor
582     senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
583                           Function fn, int,
584                           typename boost::enable_if_c<
585                               detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
586
587 #endif
588
589 }}
590
591 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
592
593 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
594 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedArgumentAttributor, (class, unsigned, bool))
595 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
596
597 ///////////////////////////////hh.e////////////////////////////////////////
598 #include "ParsedCommand.cci"
599 #include "ParsedCommand.ct"
600 #include "ParsedCommand.cti"
601 #endif
602
603 \f
604 // Local Variables:
605 // mode: c++
606 // fill-column: 100
607 // comment-column: 40
608 // c-file-style: "senf"
609 // indent-tabs-mode: nil
610 // ispell-local-dictionary: "american"
611 // compile-command: "scons -u test"
612 // End: