4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief ParsedCommand public header */
26 #ifndef HH_SENF_Scheduler_Console_ParsedCommand_
27 #define HH_SENF_Scheduler_Console_ParsedCommand_ 1
31 #define BOOST_PARAMETER_MAX_ARITY 6
34 #include <boost/type_traits/function_traits.hpp>
35 #include <boost/type_traits/is_member_function_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 <senf/config.hh>
41 #include "OverloadedCommand.hh"
43 #include <senf/Utils/type_traits.hh>
45 #include "ParsedCommand.ih"
46 #include "ParsedCommand.mpp"
47 ///////////////////////////////hh.p////////////////////////////////////////
52 namespace detail { class ArgumentInfoBase; }
54 /** \brief CommandOverload implementation with automatic argument parsing
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.
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
65 \section overload_add Adding argument parsing callbacks to the tree
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().
70 std::string taskStatus(int id);
72 senf::console::root().add("taskStatus", &taskStatus);
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:
80 senf::console::root().add("taskStatus", &taskStatus)
81 .doc("Query the current task status")
83 description = "numeric id of task to check, -1 for the current task."
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.
91 Additionally, overloading is supported by registering multiple commands under the same
92 name. So, elaborating on above example:
94 std::string taskStatus(int id);
95 std::string taskStatus(std::string const & name);
98 .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
99 .doc("Query the current task status")
100 .overloadDoc("Query status by 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")
108 description = "name of task to check" );
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.
115 \section overload_parse Custom parameter parsers
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.
121 However, argument parsing can be configured by specializing
122 senf::console::ArgumentTraits. See that class for more information.
124 \section overload_format Custom return-value formatters
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.
131 \ingroup console_commands
133 class ParsedCommandOverloadBase
134 : public CommandOverload
137 typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
139 detail::ArgumentInfoBase & arg(unsigned n) const;
141 void doc(std::string const & d);
144 ParsedCommandOverloadBase();
146 template <class Type> void addParameter();
149 virtual unsigned v_numArguments() const;
150 virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
151 virtual std::string v_doc() const;
153 typedef std::vector<detail::ArgumentInfoBase::ptr> Parameters;
154 Parameters parameters_;
158 /** \brief Parsed command overload
160 ParsedCommandOverload provides the command overload added to an OverloadedCommandNode for an
161 automatically parsed command.
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.
168 \implementation This class is specialized for each supported number of command arguments.
170 \todo Implement automatic binding of member functions for parser and formatter
172 template <class FunctionTraits, class ReturnType, unsigned arity>
173 class ParsedCommandOverload : public ParsedCommandOverloadBase
176 typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
179 static ptr create(Function fn);
185 # define BOOST_PP_ITERATION_PARAMS_1 \
186 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
187 SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
189 # include BOOST_PP_ITERATE()
193 /** \brief Generic ParsedCommandOverloadBase attributes
195 Attributes for parsed commands are not set directly on the node. They are set via a special
196 attributor temporary returned when adding a parsed command to the tree.
198 This class is the base class for those attributors. It provides members which do not depend
199 in any way on the exact type of command added.
201 \see \ref console_autoparse
203 class ParsedCommandAttributorBase
204 : public detail::NodeFactory
207 typedef OverloadedCommandNode node_type;
208 typedef OverloadedCommandNode & result_type;
210 OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
213 ParsedCommandAttributorBase(ParsedCommandOverloadBase::ptr overload, unsigned index);
214 ParsedCommandAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
216 void argName(std::string const & name);
217 void argDoc(std::string const & doc);
218 void typeName(std::string const & doc);
219 void defaultDoc(std::string const & doc);
221 ParsedCommandOverloadBase & overload() const;
222 void overloadDoc(std::string const & doc);
223 void nodeDoc(std::string const & doc);
224 void shortDoc(std::string const & doc);
227 ParsedCommandOverloadBase::ptr overload_;
229 boost::optional<std::string> doc_;
230 boost::optional<std::string> shortdoc_;
233 /** \brief Non argument dependent ParsedCommandBase attributes
235 Attributes for parsed commands are not set directly on the node. They are set via a special
236 attributor temporary returned when adding a parsed command to the tree.
238 This class adds all those members, which do depend on the type of command added (and thereby
239 on that commands signature) but do not depend on the type of any single argument.
241 \see \ref console_autoparse
243 template <class Overload>
244 class ParsedCommandAttributor
245 : public ParsedCommandAttributorBase
248 Overload & overload() const; ///< Get the command overload
251 ParsedCommandAttributor(typename Overload::ptr overload, unsigned index);
252 ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index);
257 /** \brief Keyword argument tags
259 The tags defined in this namespace are used as keyword arguments via the <a
260 href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
263 For the keyword tags, the standard C++ scoping rules apply
265 // Either qualify them with their complete namespace
267 .arg( senf::console::kw::name = "name" );
269 // Or use a namespace alias
270 namespace kw = senf::console::kw;
272 .arg( kw::name = "name" );
274 // Or import the keywords into the current namespace (beware of name collisions)
275 using namespace senf::console::kw;
277 .arg( name = "name" );
280 The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
281 long as the keyword names do not clash with another visible symbol.
283 \section kw_attributes Argument attribute values
285 The keywords are used to set argument attributes. The keywords \ref default_value and \ref
286 parser influence, how an argument is parsed/interpreted whereas \ref name, \ref description,
287 \ref type_name and \ref default_doc are used to change the arguments documentation:
291 dir.add("command", &command)
292 .arg( kw::name = "name",
293 kw::description = "description",
294 kw::default_value = 1,
295 kw::type_name = "type_name",
296 kw::default_doc = "default_doc" );
298 Will create the following documentation:
302 command [name:type_name]
310 \see \ref senf::console::ParsedArgumentAttributor::arg()
313 BOOST_PARAMETER_KEYWORD(type, name) ///< Argument name
314 /**< Sets the displayed name of the argument. */
315 BOOST_PARAMETER_KEYWORD(type, description) ///< One-line argument description
316 /**< This description is shown in the argument
317 reference. If several overloads have same-named
318 arguments, only one of them should be documented. This
319 documentation then applies to all arguments of that
321 BOOST_PARAMETER_KEYWORD(type, default_value) ///< Argument default value
322 /**< If a default value is specified for an argument, that
323 argument is optional. If an overload is called with
324 fewer arguments than defined, optional values will be
325 used beginning at the last optional argument and going
326 forward until all arguments have values assigned. E.g.,
327 an overload with 5 parameters \a a - \a e with two
330 command a:int [b:int] c:int [d:int] e:int
332 When calling the overload, the arguments will be
333 assigned in the following way:
334 <table class="senf fixedwidth">
336 <td style="whitespace:no-wrap"><tt>command 1 2</tt></td>
337 <td colspan="5">SyntaxErrorException: invalid number of
341 <td style="white-space:nowrap"><tt>command 1 2 3</tt></td>
342 <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>
345 <td style="white-space:nowrap"><tt>command 1 2 3 4</tt></td>
346 <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>
349 <td style="white-space:nowrap"><tt>command 1 2 3 4 5</tt></td>
350 <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>
353 <td style="white-space:nowrap"><tt>command 1 2 3 4 5 6</tt></td>
354 <td colspan="5">SyntaxErrorException: invalid number of
358 So, if you use default values as you are used to,
359 assigning default values to consecutive trailing
360 arguments, they work like they do in C++ and most other
362 BOOST_PARAMETER_KEYWORD(type, type_name) ///< Type name of this arguments type
363 /**< By default, the type of an argument is extracted from
364 the C++ type name by taking the last component of the
365 fully scoped name. This value can be changed by setting
367 BOOST_PARAMETER_KEYWORD(type, default_doc) ///< String rep of default value
368 /**< By default, the default value is documented by
369 converting the value to it's string representation
370 using the corresponding return value formatter which by
371 default uses \c boost::lexical_cast / \c iostreams. The
372 displayed value can be changed by setting this
374 BOOST_PARAMETER_KEYWORD(type, parser) ///< Argument parser
375 /**< The argument parser is used to convert the argument
376 token list returned by the console/config parser into
377 the appropriate value. If not set explicitly, this
378 conversion is supplied by the ArgumentTraits
381 Setting the \a parser attribute allows to use a custom
382 parser. The parser is an arbitrary callable object with
385 void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
387 where \c value_type is the type of the overload
388 parameter. The parser must read and parse the complete
389 \a tokens range and return the parsed value in \a
390 out. If the parser fails, it must raise a
391 senf::console::SyntaxErrorException. */
394 /** \brief Derived class dependent ParsedCommandBase attributes
396 Attributes for parsed commands are not set directly on the node. They are set via a special
397 attributor temporary returned when adding a parsed command to the tree.
399 This class adds all those members, which do not depend on any specific argument but which
400 need to return the correct attributor type.
402 \see \ref console_autoparse
404 template <class Overload, class Self, class ReturnType=typename Overload::traits::result_type>
405 class ParsedArgumentAttributorBase
406 : public ParsedCommandAttributor<Overload>
409 Self doc(std::string const & doc); ///< Set documentation for all overloads
410 Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
411 Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
412 Self formatter(typename Overload::Formatter formatter);
413 ///< Set return value formatter
414 /**< This member is only available, if the \a ReturnType of
415 the installed callback is not \c void.
417 If \a ReturnType is not \c void, the \a formatter must
418 be a callable with a signature compatible with
420 void formatter(ReturnType const & value, std::ostream & os);
422 The \a formatter takes the return value of the call \a
423 value and writes it properly formated to \a os. */
426 ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
427 ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
434 template <class Overload, class Self>
435 class ParsedArgumentAttributorBase<Overload, Self, void>
436 : public ParsedCommandAttributor<Overload>
439 Self doc(std::string const & doc); ///< Set documentation for all overloads
440 Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
441 Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
444 ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
445 ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
452 /** \brief Argument dependent ParsedCommandBase attributes
454 Attributes for parsed commands are not set directly on the node. They are set via a special
455 attributor temporary returned when adding a parsed command to the tree.
457 This class adds all those members, which depend on a specific argument. Each call to \c arg
458 will advance to the next argument.
460 \see \ref console_autoparse
462 template <class Overload, unsigned index, bool flag>
463 class ParsedArgumentAttributor
464 : public ParsedArgumentAttributorBase< Overload,
465 ParsedArgumentAttributor<Overload, index, flag> >
467 typedef boost::parameter::parameters<
469 kw::type::description,
470 kw::type::default_value,
472 kw::type::default_doc,
473 kw::type::parser> arg_params;
476 typedef typename senf::function_traits_arg_type<
477 typename Overload::traits, int(index) >::type arg_type;
478 typedef typename senf::remove_cvref< arg_type >::type value_type;
479 typedef ParsedArgumentAttributor<Overload, index+1> next_type;
481 next_type arg() const; ///< Set argument attributes
482 /**< This member changes the attributes for the current
483 argument. The attributes are passed to arg() as keyword
484 arguments using the <a
485 href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
489 .arg( kw::name = "name",
490 kw::default_value = 1 )
493 The valid keywords are defined in the senf::console::kw
496 Each call to arg() will increment the argument index
497 and advance to the next argument. This member is only
498 present, if there is an argument at the current
503 # define BOOST_PP_ITERATION_PARAMS_1 \
504 (4, (1, BOOST_PARAMETER_MAX_ARITY, \
505 SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
507 # include BOOST_PP_ITERATE()
512 explicit ParsedArgumentAttributor(typename Overload::ptr overload);
513 explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
515 template <class ArgumentPack>
516 next_type argInfo(ArgumentPack const & args);
517 template <class Kw, class ArgumentPack>
518 void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
520 template <class ArgumentPack>
521 void argInfo(boost::parameter::keyword<kw::type::name> const &,
522 ArgumentPack const & args, boost::mpl::true_);
523 template <class ArgumentPack>
524 void argInfo(boost::parameter::keyword<kw::type::description> const &,
525 ArgumentPack const & args, boost::mpl::true_);
526 template <class ArgumentPack>
527 void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
528 ArgumentPack const & args, boost::mpl::true_);
529 template <class ArgumentPack>
530 void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
531 ArgumentPack const & args, boost::mpl::true_);
532 template <class ArgumentPack>
533 void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
534 ArgumentPack const & args, boost::mpl::true_);
535 template <class ArgumentPack>
536 void argInfo(boost::parameter::keyword<kw::type::parser> const &,
537 ArgumentPack const & args, boost::mpl::true_);
539 next_type next() const;
541 void defaultValue(value_type const & value);
542 template <class Fn> void parser(Fn fn);
544 template <class O, unsigned i, bool f>
545 friend class ParsedArgumentAttributor;
547 friend class detail::ParsedCommandAddNodeAccess;
552 template <class Overload, unsigned index>
553 class ParsedArgumentAttributor<Overload, index, false>
554 : public ParsedArgumentAttributorBase< Overload,
555 ParsedArgumentAttributor<Overload, index, false> >
558 typedef OverloadedCommandNode node_type;
559 typedef ParsedArgumentAttributor return_type;
562 explicit ParsedArgumentAttributor(typename Overload::ptr overload);
563 explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
565 template <class O, unsigned i, bool f>
566 friend class ParsedArgumentAttributor;
568 friend class detail::ParsedCommandAddNodeAccess;
575 template <class Signature>
576 SimpleOverloadAttributor
577 Command(boost::function<Signature> fn,
578 typename boost::enable_if_c<detail::ParsedCommandTraits<Signature>::is_simple>::type * = 0);
580 template <class Function>
581 SimpleOverloadAttributor
583 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_simple>::type * = 0);
585 template <class Owner, class Member>
586 SimpleOverloadAttributor
587 Command(Member memfn, Owner * owner,
588 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
589 typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
591 template <class Owner, class Member>
592 SimpleOverloadAttributor
593 Command(Member memfn, Owner const * owner,
594 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
595 typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
597 template <class CastTo, class Signature>
598 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
599 Command(boost::function<Signature> fn);
601 template <class CastTo, class Function>
602 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
604 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
605 typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
607 template <class Signature>
608 typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
609 Command(boost::function<Signature> fn);
611 template <class Function>
612 typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
614 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
615 typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
617 template <class Owner, class Member>
618 typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
619 Command(Member memfn, Owner * owner,
620 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
622 template <class Owner, class Member>
623 typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
624 Command(Member memfn, Owner const * owner,
625 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
627 template <class CastTo, class Owner, class Member>
628 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
629 Command(Member memfn, Owner * owner,
630 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
632 template <class CastTo, class Owner, class Member>
633 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
634 Command(Member memfn, Owner const * owner,
635 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
640 ///////////////////////////////hh.e////////////////////////////////////////
641 #include "ParsedCommand.cci"
642 #include "ParsedCommand.ct"
643 #include "ParsedCommand.cti"
650 // comment-column: 40
651 // c-file-style: "senf"
652 // indent-tabs-mode: nil
653 // ispell-local-dictionary: "american"
654 // compile-command: "scons -u test"