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_ParsedCommand_
27 #define HH_ParsedCommand_ 1
31 #include <boost/type_traits/function_traits.hpp>
32 #include <boost/type_traits/is_member_pointer.hpp>
33 #include <boost/type_traits/is_same.hpp>
34 #include <boost/mpl/if.hpp>
35 #include <boost/utility.hpp>
36 #include <boost/parameter/keyword.hpp>
37 #include <boost/parameter/parameters.hpp>
38 #include "../config.hh"
39 #include "OverloadedCommand.hh"
41 #include "../Utils/type_traits.hh"
43 #include "ParsedCommand.ih"
44 #include "ParsedCommand.mpp"
45 ///////////////////////////////hh.p////////////////////////////////////////
50 namespace detail { class ArgumentInfoBase; }
52 /** \brief CommandOverload implementation with automatic argument parsing
54 ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
55 parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to
56 an OverloadedCommandNode instance.
58 Automatic argument parsing and return value processing consists of several components:
59 \li \ref overload_add Adding overload instances to the tree
60 \li (Advanced) \ref overload_parse
61 \li (Advanced) \ref overload_format
63 \section overload_add Adding argument parsing callbacks to the tree
65 Adding appropriate callbacks to the tree is very simple: just path a function pointer to
66 DirectoryNode::add() or a member function pointer to ScopedDirectory::add().
68 std::string taskStatus(int id);
70 senf::console::root().add("taskStatus", &taskStatus);
73 There are quite a number of additional parameters available to be set. These parameters are
74 documented in ParsedArgumentAttributor. Parameters are set by adding them as additional
75 calls after adding the node:
78 senf::console::root().add("taskStatus", &taskStatus)
79 .doc("Query the current task status")
81 description = "numeric id of task to check, -1 for the current task."
85 You may also add an additional \c std::ostream & Argument as first argument to the
86 callback. If this argument is present, the stream connected to the console which issued the
87 command will be passed there. This allows writing arbitrary messages to the console.
89 Additionally, overloading is supported by registering multiple commands under the same
90 name. So, elaborating on above example:
92 std::string taskStatus(int id);
93 std::string taskStatus(std::string const & name);
96 .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
97 .doc("Query the current task status")
98 .overloadDoc("Query status by id")
100 description = "numeric id of task to check, -1 for the current task."
101 default_value = -1 );
102 senf::console::root()
103 .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
104 .overloadDoc("Query status by name")
106 description = "name of task to check" );
109 We can see here, that taking the address of an overloaded function requires a cast. If you
110 can give unique names to each of the C++ overloads (not the overloads in the console), you
111 should do so to make the unwieldy casts unnecessary.
113 \section overload_parse Custom parameter parsers
115 By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
116 iostreams. This means, that any type which can be read from a stream can automatically be
117 used as argument type.
119 However, argument parsing can be configured by specializing
120 senf::console::ArgumentTraits. See that class for more information.
122 \section overload_format Custom return-value formatters
124 By default, return values are streamed to an ostream. This automatically allows any
125 streamable type to be used as return value. To add new types or customize the formating, the
126 senf::console::ReturnValueTraits template needs to be specialized for that type. See
127 that class for more information.
129 \ingroup console_commands
131 class ParsedCommandOverloadBase
132 : public CommandOverload
135 typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
137 detail::ArgumentInfoBase & arg(unsigned n) const;
138 template <class Type> detail::ArgumentInfo<Type> & arg(unsigned n) const;
140 void doc(std::string const & d);
143 ParsedCommandOverloadBase();
145 template <class Type>
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 template <class FunctionTraits, unsigned arity=FunctionTraits::arity>
171 class ParsedCommandOverload : public ParsedCommandOverloadBase
174 typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
177 static ptr create(Function fn);
183 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
184 SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), \
186 # include BOOST_PP_ITERATE()
190 /** \brief Generic ParsedCommandOverladBase attributes
192 Attributes for parsed commands are not set directly on the node. They are set via a special
193 attributor temporary returned when adding a parsed command to the tree.
195 This class is the base class for those attributors. It provides members which do not depend
196 in any way on the exact type of command added.
198 class ParsedCommandAttributorBase
201 OverloadedCommandNode & node() const; ///< Return the node object
202 operator OverloadedCommandNode & () const; ///< Automatically convert to node object
205 ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
207 void argName(std::string const & name) const;
208 void argDoc(std::string const & doc) const;
209 template <class Type> void defaultValue(Type const & value) const;
211 ParsedCommandOverloadBase & overload() const;
212 void overloadDoc(std::string const & doc) const;
214 void nodeDoc(std::string const & doc) const;
217 ParsedCommandOverloadBase & overload_;
221 /** \brief Non argument dependent ParsedCommandBase attributes
223 Attributes for parsed commands are not set directly on the node. They are set via a special
224 attributor temporary returned when adding a parsed command to the tree.
226 This class adds all those members, which do depend on the type of command added (and thereby
227 on that commands signature) but do not depend on the type of any single argument.
229 \fixme Implement compile-time checking, that after a defaulted arg only defaulted args are
232 template <class Overload>
233 class ParsedCommandAttributor
234 : public ParsedCommandAttributorBase
237 Overload & overload() const; ///< Get the command overload
240 ParsedCommandAttributor(Overload & overload, unsigned index);
245 /** \brief Keyword argument tags
247 The tags defined in this namespace are used as keyword arguments via the <a
248 href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
251 For the keyword tags, the standard C++ scoping rules apply:
252 \li Either qualify them with their complete namespace: <tt>arg( senf::console::kw::name =
254 \li or use a namespace alias: <tt>namespace kw = senf::console::kw; arg( kw::name = "name"
256 \li import the keywords into your namespace: <tt>using namespace senf::console::kw; arg(
259 The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
260 long as the keyword names do not clash with another visible symbol.
263 BOOST_PARAMETER_KEYWORD(type, name) ///< Argument name
264 BOOST_PARAMETER_KEYWORD(type, description) ///< One-line Argument description
265 BOOST_PARAMETER_KEYWORD(type, default_value) ///< Argument default value
268 /** \brief Derived class dependent ParsedCommandBase attributes
270 Attributes for parsed commands are not set directly on the node. They are set via a special
271 attributor temporary returned when adding a parsed command to the tree.
273 This class adds all those members, which do not depend on any specific argument but which
274 need to return the correct attributor type.
276 template <class Overload, class Self>
277 class ParsedArgumentAttributorBase
278 : public ParsedCommandAttributor<Overload>
281 Self doc(std::string const & doc) const; ///< Set documentation for all overloads
282 Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
285 ParsedArgumentAttributorBase(Overload & overload, unsigned index);
291 /** \brief Argument dependent ParsedCommandBase attributes
293 Attributes for parsed commands are not set directly on the node. They are set via a special
294 attributor temporary returned when adding a parsed command to the tree.
296 This class adds all those members, which depend on a specific argument. Each call to \c arg
297 will advance to the next argument.
299 template < class Overload,
301 bool flag=(index < unsigned(Overload::traits::arity)) >
302 class ParsedArgumentAttributor
303 : public ParsedArgumentAttributorBase< Overload,
304 ParsedArgumentAttributor<Overload, index, flag> >
306 typedef boost::parameter::parameters<
308 kw::type::description,
309 kw::type::default_value> arg_params;
312 typedef OverloadedCommandNode node_type;
313 typedef ParsedArgumentAttributor return_type;
315 typedef typename senf::function_traits_arg_type<
316 typename Overload::traits, int(index) >::type arg_type;
317 typedef typename senf::remove_cvref< arg_type >::type value_type;
318 typedef ParsedArgumentAttributor<Overload, index+1> next_type;
320 next_type arg() const; ///< Set argument attributes
321 /**< This member changes the attributes for the current
322 argument. The attributes are passed to arg() as keyword
323 arguments using the <a
324 href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
325 library. The valid keywords are defined in the
326 senf::console::kw namespace.
328 This member is only present, if there is an argument at
329 the current index. */
333 # define BOOST_PP_ITERATION_PARAMS_1 \
334 (4, (1, 3, SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), 5))
335 # include BOOST_PP_ITERATE()
340 explicit ParsedArgumentAttributor(Overload & overload);
342 template <class ArgumentPack>
343 next_type argInfo(ArgumentPack const & args) const;
344 template <class Kw, class ArgumentPack>
345 void argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
348 template <class ArgumentPack>
349 void argInfo(boost::parameter::keyword<kw::type::name> const &,
350 ArgumentPack const & args, boost::mpl::false_)
352 template <class ArgumentPack>
353 void argInfo(boost::parameter::keyword<kw::type::description> const &,
354 ArgumentPack const & args, boost::mpl::false_)
356 template <class ArgumentPack>
357 void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
358 ArgumentPack const & args, boost::mpl::false_)
361 next_type next() const;
363 void defaultValue(value_type const & value) const;
365 template <class O, unsigned i, bool f>
366 friend class ParsedArgumentAttributor;
370 template <class Function>
371 friend ParsedArgumentAttributor<
372 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
373 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
375 template <class Owner, class Function>
376 friend ParsedArgumentAttributor<
377 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
378 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
380 typename boost::enable_if_c<
381 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
388 template <class Overload, unsigned index>
389 class ParsedArgumentAttributor<Overload, index, false>
390 : public ParsedArgumentAttributorBase< Overload,
391 ParsedArgumentAttributor<Overload, index, false> >
394 typedef OverloadedCommandNode node_type;
395 typedef ParsedArgumentAttributor return_type;
398 explicit ParsedArgumentAttributor(Overload & overload);
400 template <class O, unsigned i, bool f>
401 friend class ParsedArgumentAttributor;
403 template <class Function>
404 friend ParsedArgumentAttributor<
405 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
406 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
408 template <class Owner, class Function>
409 friend ParsedArgumentAttributor<
410 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
411 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
413 typename boost::enable_if_c<
414 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
417 template <class Function>
418 ParsedArgumentAttributor<
419 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
420 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
422 template <class Owner, class Function>
423 ParsedArgumentAttributor<
424 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
425 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
427 typename boost::enable_if_c<
428 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
434 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
436 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
437 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedArgumentAttributor, (class, unsigned, bool))
438 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
440 ///////////////////////////////hh.e////////////////////////////////////////
441 #include "ParsedCommand.cci"
442 #include "ParsedCommand.ct"
443 #include "ParsedCommand.cti"
450 // comment-column: 40
451 // c-file-style: "senf"
452 // indent-tabs-mode: nil
453 // ispell-local-dictionary: "american"
454 // compile-command: "scons -u test"