4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief ParsedCommand public header */
31 #ifndef HH_SENF_Scheduler_Console_ParsedCommand_
32 #define HH_SENF_Scheduler_Console_ParsedCommand_ 1
36 #define BOOST_PARAMETER_MAX_ARITY 6
39 #include <boost/type_traits/function_traits.hpp>
40 #include <boost/type_traits/is_member_function_pointer.hpp>
41 #include <boost/mpl/if.hpp>
42 #include <boost/utility.hpp>
43 #include <boost/parameter/keyword.hpp>
44 #include <boost/parameter/parameters.hpp>
45 #include <senf/config.hh>
46 #include "OverloadedCommand.hh"
48 #include <senf/Utils/type_traits.hh>
50 #include "ParsedCommand.ih"
51 #include "ParsedCommand.mpp"
52 //-/////////////////////////////////////////////////////////////////////////////////////////////////
57 namespace detail { class ArgumentInfoBase; }
59 /** \brief CommandOverload implementation with automatic argument parsing
61 ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
62 parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to
63 an OverloadedCommandNode instance.
65 Automatic argument parsing and return value processing consists of several components:
66 \li \ref overload_add Adding overload instances to the tree
67 \li (Advanced) \ref overload_parse
68 \li (Advanced) \ref overload_format
70 \section overload_add Adding argument parsing callbacks to the tree
72 To add overloads to the tree, use the senf::console::factory::Command factory:
74 namespace fty = senf::console::factory;
76 std::string taskStatus(int id);
78 senf::console::root().add("taskStatus", fty::Command(&taskStatus));
81 There are quite a number of additional parameters available to be set. These parameters are
82 documented in ParsedArgumentAttributor. Parameters are set by adding them as additional
83 calls after adding the node:
86 senf::console::root().add("taskStatus", fty::Command(&taskStatus)
87 .doc("Query the current task status")
89 description = "numeric id of task to check, -1 for the current task."
90 default_value = -1 ) );
93 You may also add an additional \c std::ostream & Argument as first argument to the
94 callback. If this argument is present, the stream connected to the console which issued the
95 command will be passed there. This allows writing arbitrary messages to the console.
97 Additionally, overloading is supported by registering multiple commands under the same
98 name. So, elaborating on above example:
100 std::string taskStatus(int id);
101 std::string taskStatus(std::string const & name);
103 senf::console::root()
104 .add("taskStatus", fty::Command(static_cast<std::string (*)(int)>(
106 .doc("Query the current task status")
107 .overloadDoc("Query status by id")
109 description = "numeric id of task to check, -1 for the current task."
110 default_value = -1 ) );
111 senf::console::root()
112 .add("taskStatus", fty::Command(static_cast<std::string (*)(std::string const &)>(
114 .overloadDoc("Query status by name")
116 description = "name of task to check" ) );
119 We can see here, that taking the address of an overloaded function requires a cast. If you
120 can give unique names to each of the C++ overloads (not the overloads in the console), you
121 should do so to make the unwieldy casts unnecessary.
123 \section overload_parse Custom parameter parsers
125 By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
126 iostreams. This means, that any type which can be read from a stream can automatically be
127 used as argument type.
129 However, argument parsing can be configured by specializing
130 senf::console::ArgumentTraits. See that class for more information.
132 \section overload_format Custom return-value formatters
134 By default, return values are streamed to an ostream. This automatically allows any
135 streamable type to be used as return value. To add new types or customize the formating, the
136 senf::console::ReturnValueTraits template needs to be specialized for that type. See
137 that class for more information.
139 \ingroup console_commands
141 class ParsedCommandOverloadBase
142 : public CommandOverload
145 typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
147 detail::ArgumentInfoBase & arg(unsigned n) const;
149 void doc(std::string const & d);
152 ParsedCommandOverloadBase();
154 template <class Type> void addParameter();
157 virtual unsigned v_numArguments() const;
158 virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
159 virtual std::string v_doc() const;
161 typedef std::vector<detail::ArgumentInfoBase::ptr> Parameters;
162 Parameters parameters_;
166 /** \brief Parsed command overload
168 ParsedCommandOverload provides the command overload added to an OverloadedCommandNode for an
169 automatically parsed command.
171 This class is normally instantiated automatically when adding a function or member-function
172 pointer as callback to the tree. Manually instantiation this type of overload is \e not
173 simple, since the function signature has to be manipulated correctly to support the optional
174 \c std::ostream first argument.
176 \implementation This class is specialized for each supported number of command arguments.
178 \todo Implement automatic binding of member functions for parser and formatter
180 template <class FunctionTraits, class ReturnType, unsigned arity>
181 class ParsedCommandOverload : public ParsedCommandOverloadBase
184 typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
189 # define BOOST_PP_ITERATION_PARAMS_1 \
190 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
191 SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
193 # include BOOST_PP_ITERATE()
197 /** \brief Generic ParsedCommandOverloadBase attributes
199 Attributes for parsed commands are not set directly on the node. They are set via a special
200 attributor temporary returned when adding a parsed command to the tree.
202 This class is the base class for those attributors. It provides members which do not depend
203 in any way on the exact type of command added.
205 \see \ref console_autoparse
207 class ParsedCommandAttributorBase
208 : public detail::NodeFactory
211 typedef OverloadedCommandNode node_type;
212 typedef OverloadedCommandNode & result_type;
215 ParsedCommandAttributorBase(ParsedCommandOverloadBase::ptr overload, unsigned index);
216 ParsedCommandAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
218 void argName(std::string const & name);
219 void argDoc(std::string const & doc);
220 void typeName(std::string const & doc);
221 void defaultDoc(std::string const & doc);
223 ParsedCommandOverloadBase & overload() const;
224 void overloadDoc(std::string const & doc);
225 void nodeDoc(std::string const & doc);
226 void shortDoc(std::string const & doc);
229 OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
231 ParsedCommandOverloadBase::ptr overload_;
233 boost::optional<std::string> doc_;
234 boost::optional<std::string> shortdoc_;
236 friend class senf::console::DirectoryNode;
239 /** \brief Non argument dependent ParsedCommandBase attributes
241 Attributes for parsed commands are not set directly on the node. They are set via a special
242 attributor temporary returned when adding a parsed command to the tree.
244 This class adds all those members, which do depend on the type of command added (and thereby
245 on that commands signature) but do not depend on the type of any single argument.
247 \see \ref console_autoparse
249 template <class Overload>
250 class ParsedCommandAttributor
251 : public ParsedCommandAttributorBase
254 Overload & overload() const; ///< Get the command overload
257 ParsedCommandAttributor(typename Overload::ptr overload, unsigned index);
258 ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index);
263 /** \brief Keyword argument tags
265 The tags defined in this namespace are used as keyword arguments via the <a
266 href="http://www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html">Boost.Parameter</a>
269 For the keyword tags, the standard C++ scoping rules apply
271 namespace fty=senf::console::factory;
273 // Either qualify them with their complete namespace
274 dir.add(..., fty::Command(...)
275 .arg( senf::console::kw::name = "name" ) );
277 // Or use a namespace alias
278 namespace kw = senf::console::kw;
279 dir.add(..., fty::Command(...)
280 .arg( kw::name = "name" ) );
282 // Or import the keywords into the current namespace (beware of name collisions)
283 using namespace senf::console::kw;
284 dir.add(..., fty::Command(...)
285 .arg( name = "name" ) );
288 The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
289 long as the keyword names do not clash with another visible symbol.
291 \section kw_attributes Argument attribute values
293 The keywords are used to set argument attributes. The keywords \ref default_value and \ref
294 parser influence, how an argument is parsed/interpreted whereas \ref name, \ref description,
295 \ref type_name and \ref default_doc are used to change the arguments documentation:
299 dir.add("command", fty::Command(&command)
300 .arg( kw::name = "name",
301 kw::description = "description",
302 kw::default_value = 1,
303 kw::type_name = "type_name",
304 kw::default_doc = "default_doc" ) );
306 Will create the following documentation:
310 command [name:type_name]
318 \see \ref senf::console::ParsedArgumentAttributor::arg()
320 \ingroup console_commands
323 BOOST_PARAMETER_KEYWORD(type, name) ///< Argument name
324 /**< Sets the displayed name of the argument. */
325 BOOST_PARAMETER_KEYWORD(type, description) ///< One-line argument description
326 /**< This description is shown in the argument
327 reference. If several overloads have same-named
328 arguments, only one of them should be documented. This
329 documentation then applies to all arguments of that
331 BOOST_PARAMETER_KEYWORD(type, default_value) ///< Argument default value
332 /**< If a default value is specified for an argument, that
333 argument is optional. If an overload is called with
334 fewer arguments than defined, optional values will be
335 used beginning at the last optional argument and going
336 forward until all arguments have values assigned. E.g.,
337 an overload with 5 parameters \a a - \a e with two
340 command a:int [b:int] c:int [d:int] e:int
342 When calling the overload, the arguments will be
343 assigned in the following way:
344 <table class="senf fixedwidth">
346 <td style="whitespace:no-wrap"><tt>command 1 2</tt></td>
347 <td colspan="5">SyntaxErrorException: invalid number of
351 <td style="white-space:nowrap"><tt>command 1 2 3</tt></td>
352 <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>
355 <td style="white-space:nowrap"><tt>command 1 2 3 4</tt></td>
356 <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>
359 <td style="white-space:nowrap"><tt>command 1 2 3 4 5</tt></td>
360 <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>
363 <td style="white-space:nowrap"><tt>command 1 2 3 4 5 6</tt></td>
364 <td colspan="5">SyntaxErrorException: invalid number of
368 So, if you use default values as you are used to,
369 assigning default values to consecutive trailing
370 arguments, they work like they do in C++ and most other
372 BOOST_PARAMETER_KEYWORD(type, type_name) ///< Type name of this arguments type
373 /**< By default, the type of an argument is extracted from
374 the C++ type name by taking the last component of the
375 fully scoped name. This value can be changed by setting
377 BOOST_PARAMETER_KEYWORD(type, default_doc) ///< String rep of default value
378 /**< By default, the default value is documented by
379 converting the value to it's string representation
380 using the corresponding return value formatter which by
381 default uses \c boost::lexical_cast / \c iostreams. The
382 displayed value can be changed by setting this
384 BOOST_PARAMETER_KEYWORD(type, parser) ///< Argument parser
385 /**< The argument parser is used to convert the argument
386 token list returned by the console/config parser into
387 the appropriate value. If not set explicitly, this
388 conversion is supplied by the ArgumentTraits
391 Setting the \a parser attribute allows to use a custom
392 parser. The parser is an arbitrary callable object with
395 void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
397 where \c value_type is the type of the overload
398 parameter. The parser must read and parse the complete
399 \a tokens range and return the parsed value in \a
400 out. If the parser fails, it must raise a
401 senf::console::SyntaxErrorException. */
404 /** \brief Derived class dependent ParsedCommandBase attributes
406 Attributes for parsed commands are not set directly on the node. They are set via a special
407 attributor temporary returned when adding a parsed command to the tree.
409 This class adds all those members, which do not depend on any specific argument but which
410 need to return the correct attributor type.
412 \see \ref console_autoparse
414 template <class Overload, class Self, class ReturnType=typename Overload::traits::result_type>
415 class ParsedArgumentAttributorBase
416 : public ParsedCommandAttributor<Overload>
419 Self doc(std::string const & doc); ///< Set documentation for all overloads
420 Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
421 Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
422 Self formatter(typename Overload::Formatter formatter);
423 ///< Set return value formatter
424 /**< This member is only available, if the \a ReturnType of
425 the installed callback is not \c void.
427 If \a ReturnType is not \c void, the \a formatter must
428 be a callable with a signature compatible with
430 void formatter(ReturnType const & value, std::ostream & os);
432 The \a formatter takes the return value of the call \a
433 value and writes it properly formated to \a os. */
436 ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
437 ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
444 template <class Overload, class Self>
445 class ParsedArgumentAttributorBase<Overload, Self, void>
446 : public ParsedCommandAttributor<Overload>
449 Self doc(std::string const & doc); ///< Set documentation for all overloads
450 Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
451 Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
454 ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
455 ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
462 /** \brief Argument dependent ParsedCommandBase attributes
464 Attributes for parsed commands are not set directly on the node. They are set via a special
465 attributor temporary returned when adding a parsed command to the tree.
467 This class adds all those members, which depend on a specific argument. Each call to \c arg
468 will advance to the next argument.
470 \see \ref console_autoparse
472 template <class Overload, unsigned index, bool flag>
473 class ParsedArgumentAttributor
474 : public ParsedArgumentAttributorBase< Overload,
475 ParsedArgumentAttributor<Overload, index, flag> >
477 typedef boost::parameter::parameters<
479 kw::type::description,
480 kw::type::default_value,
482 kw::type::default_doc,
483 kw::type::parser> arg_params;
486 typedef typename senf::function_traits_arg_type<
487 typename Overload::traits, int(index) >::type arg_type;
488 typedef typename senf::remove_cvref< arg_type >::type value_type;
489 typedef ParsedArgumentAttributor<Overload, index+1> next_type;
491 next_type arg() const; ///< Set argument attributes
492 /**< This member changes the attributes for the current
493 argument. The attributes are passed to arg() as keyword
494 arguments using the <a
495 href="http://www.boost.org/doc/libs/release/libs/parameter/doc/html/index.html">Boost.Parameter</a>
499 .arg( kw::name = "name",
500 kw::default_value = 1 )
503 The valid keywords are defined in the senf::console::kw
506 Each call to arg() will increment the argument index
507 and advance to the next argument. This member is only
508 present, if there is an argument at the current
512 # define BOOST_PP_ITERATION_PARAMS_1 \
513 (4, (1, BOOST_PARAMETER_MAX_ARITY, \
514 SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
516 # include BOOST_PP_ITERATE()
520 explicit ParsedArgumentAttributor(typename Overload::ptr overload);
521 explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
523 template <class ArgumentPack>
524 next_type argInfo(ArgumentPack const & args);
525 template <class Kw, class ArgumentPack>
526 void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
528 template <class ArgumentPack>
529 void argInfo(boost::parameter::keyword<kw::type::name> const &,
530 ArgumentPack const & args, boost::mpl::true_);
531 template <class ArgumentPack>
532 void argInfo(boost::parameter::keyword<kw::type::description> const &,
533 ArgumentPack const & args, boost::mpl::true_);
534 template <class ArgumentPack>
535 void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
536 ArgumentPack const & args, boost::mpl::true_);
537 template <class ArgumentPack>
538 void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
539 ArgumentPack const & args, boost::mpl::true_);
540 template <class ArgumentPack>
541 void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
542 ArgumentPack const & args, boost::mpl::true_);
543 template <class ArgumentPack>
544 void argInfo(boost::parameter::keyword<kw::type::parser> const &,
545 ArgumentPack const & args, boost::mpl::true_);
547 next_type next() const;
549 void defaultValue(value_type const & value);
550 template <class Fn> void parser(Fn fn);
552 template <class O, unsigned i, bool f>
553 friend class ParsedArgumentAttributor;
555 friend class detail::ParsedCommandAddNodeAccess;
560 template <class Overload, unsigned index>
561 class ParsedArgumentAttributor<Overload, index, false>
562 : public ParsedArgumentAttributorBase< Overload,
563 ParsedArgumentAttributor<Overload, index, false> >
566 typedef OverloadedCommandNode node_type;
567 typedef ParsedArgumentAttributor return_type;
570 explicit ParsedArgumentAttributor(typename Overload::ptr overload);
571 explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
573 template <class O, unsigned i, bool f>
574 friend class ParsedArgumentAttributor;
576 friend class detail::ParsedCommandAddNodeAccess;
585 /** \brief OverloadedCommandNode factory
587 This factory will create new OverloadedCommandNode instances <em>or add new overloads</em>
588 to an existing OverloadedCommandNode. The factory supports automatic argument parsing.
590 Commands are added to the tree using
592 namespace fty = senf::console::factory;
593 node.add("name", fty::Command(function));
596 The Command factory supports the following features:
597 \li Automatic argument parsing
598 \li Automatic binding of member functions. Pass the owning instance as second argument to
600 \li Conversion to a compatible signature. Pass the signature as template argument to the
603 If the signature of the command added matches
605 void (std::ostream &, senf::console::ParsedCommandInfo const &)
607 The command is added using manual argument parsing, otherwise it is added using automatic
610 See the <a href="classsenf_1_1console_1_1factory_1_1Command-members.html">List of all
611 members</a> for additional attributes.
613 \note This class is for exposition only, the real interface consists of several overloaded
616 \see \ref console_manualparse \n
617 \ref console_autoparse
619 class Command : public ParsedArgumentAttributor
622 typedef OverloadedCommandNode node_type;
623 typedef unspecified result_type;
625 Command(unspecified fn); ///< Create a node calling \a fn
626 template <class Signature>
627 Command(unspecified fn); ///< Create a node calling \a fn with signature \a Signature
628 /**< The given \a Signature must be compatible with \a fn
629 for each argument and the return value. */
631 Command(member_function_pointer fn, Owner const * owner);
632 ///< Create a node calling member function \a fn on \a owner
633 template <class Signature>
634 Command(member_function_pointer fn, Owner const * owner);
635 ///< Create a node calling member function \a fn on \a owner
636 /// with the given \a Signature
637 /**< The given \a Signature must be compatible with \a fn
638 for each argument and the return value. */
644 template <class Signature>
645 SimpleOverloadAttributor
646 Command(boost::function<Signature> fn,
647 typename boost::enable_if_c<detail::ParsedCommandTraits<Signature>::is_simple>::type * = 0);
649 template <class Function>
650 SimpleOverloadAttributor
652 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_simple>::type * = 0);
654 template <class Owner, class Member>
655 SimpleOverloadAttributor
656 Command(Member memfn, Owner * owner,
657 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
658 typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
660 template <class Owner, class Member>
661 SimpleOverloadAttributor
662 Command(Member memfn, Owner const * owner,
663 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
664 typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
666 template <class CastTo, class Signature>
667 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
668 Command(boost::function<Signature> fn);
670 template <class CastTo, class Function>
671 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
673 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
674 typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
676 template <class Signature>
677 typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
678 Command(boost::function<Signature> fn);
680 template <class Function>
681 typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
683 typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
684 typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
686 template <class Owner, class Member>
687 typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
688 Command(Member memfn, Owner * owner,
689 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
691 template <class Owner, class Member>
692 typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
693 Command(Member memfn, Owner const * owner,
694 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
696 template <class CastTo, class Owner, class Member>
697 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
698 Command(Member memfn, Owner * owner,
699 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
701 template <class CastTo, class Owner, class Member>
702 typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
703 Command(Member memfn, Owner const * owner,
704 typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
710 //-/////////////////////////////////////////////////////////////////////////////////////////////////
711 #include "ParsedCommand.cci"
712 #include "ParsedCommand.ct"
713 #include "ParsedCommand.cti"
720 // comment-column: 40
721 // c-file-style: "senf"
722 // indent-tabs-mode: nil
723 // ispell-local-dictionary: "american"
724 // compile-command: "scons -u test"