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"
40 #include "ParseParameter.hh"
41 #include "../Utils/type_traits.hh"
43 #include "ParsedCommand.ih"
44 #include "ParsedCommand.mpp"
45 ///////////////////////////////hh.p////////////////////////////////////////
50 /** \brief CommandOverload implementation with automatic argument parsing
52 ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
53 parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to
54 an OverloadedCommandNode instance.
56 Automatic argument parsing and return value processing consists of several components:
57 \li \ref overload_add Adding overload instances to the tree
58 \li (Advanced) \ref overload_parse
59 \li (Advanced) \ref overload_format
61 \section overload_add Adding argument parsing callbacks to the tree
63 Adding appropriate callbacks to the tree is very simple: just path a function pointer to
64 DirectoryNode::add() or a member function pointer to ScopedDirectory::add().
66 std::string taskStatus(int id);
68 senf::console::root().add("taskStatus", &taskStatus);
71 There are quite a number of additional parameters available to be set. These parameters are
72 documented in ParsedAttributeAttributor. Parameters are set by adding them as additional
73 calls after adding the node:
76 senf::console::root().add("taskStatus", &taskStatus)
77 .doc("Query the current task status")
79 description = "numeric id of task to check, -1 for the current task."
83 You may also add an additional \c std::ostream & Argument as first argument to the
84 callback. If this argument is present, the stream connected to the console which issued the
85 command will be passed there. This allows writing arbitrary messages to the console.
87 Additionally, overloading is supported by registering multiple commands under the same
88 name. So, elaborating on above example:
90 std::string taskStatus(int id);
91 std::string taskStatus(std::string const & name);
94 .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
95 .doc("Query the current task status")
96 .overloadDoc("Query status by id")
98 description = "numeric id of task to check, -1 for the current task."
100 senf::console::root()
101 .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
102 .overloadDoc("Query status by name")
104 description = "name of task to check" );
107 We can see here, that taking the address of an overloaded function requires a cast. If you
108 can give unique names to each of the C++ overloads (not the overloads in the console), you
109 should do so to make the unwieldy casts unnecessary.
111 \section overload_parse Custom parameter parsers
113 By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
114 iostreams. This means, that any type which can be read from a stream can automatically be
115 used as argument type.
117 However, argument parsing can be configured by specializing
118 senf::console::detail::ParameterTraits. See that class for more information.
120 \section overload_format Custom return-value formatters
122 By default, return values are streamed to an ostream. This automatically allows any
123 streamable type to be used as return value. To add new types or customize the formating, the
124 senf::console::detail::ReturnValueTraits template needs to be specialized for that type. See
125 that class for more information.
127 \ingroup console_commands
129 class ParsedCommandOverloadBase
130 : public CommandOverload
133 typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
135 detail::ParameterInfoBase & arg(unsigned n) const;
136 template <class Type> detail::ParameterInfo<Type> & arg(unsigned n) const;
138 void doc(std::string const & d);
141 ParsedCommandOverloadBase();
143 template <class Type>
147 virtual unsigned v_numArguments() const;
148 virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
149 virtual std::string v_doc() const;
151 typedef std::vector<detail::ParameterInfoBase::ptr> Parameters;
152 Parameters parameters_;
156 template <class FunctionTraits, unsigned arity=FunctionTraits::arity>
157 class ParsedCommandOverload {};
159 # define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
160 SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), \
162 # include BOOST_PP_ITERATE()
164 class ParsedCommandAttributorBase
167 OverloadedCommandNode & node() const;
168 operator OverloadedCommandNode & () const;
171 ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
173 void argName(std::string const & name) const;
174 void argDoc(std::string const & doc) const;
175 template <class Type> void defaultValue(Type const & value) const;
177 ParsedCommandOverloadBase & overload() const;
178 void overloadDoc(std::string const & doc) const;
180 void nodeDoc(std::string const & doc) const;
183 ParsedCommandOverloadBase & overload_;
187 template <class Overload>
188 class ParsedCommandAttributor
189 : public ParsedCommandAttributorBase
192 Overload & overload() const;
195 ParsedCommandAttributor(Overload & overload, unsigned index);
201 BOOST_PARAMETER_KEYWORD(type, name);
202 BOOST_PARAMETER_KEYWORD(type, description);
203 BOOST_PARAMETER_KEYWORD(type, default_value);
206 template <class Overload, class Self>
207 class ParsedAttributeAttributorBase
208 : public ParsedCommandAttributor<Overload>
211 Self doc(std::string const & doc) const;
212 Self overloadDoc(std::string const & doc) const;
215 ParsedAttributeAttributorBase(Overload & overload, unsigned index);
220 template < class Overload,
222 bool flag=(index < unsigned(Overload::traits::arity)) >
223 class ParsedAttributeAttributor
224 : public ParsedAttributeAttributorBase< Overload,
225 ParsedAttributeAttributor<Overload, index, flag> >
228 typedef typename senf::function_traits_arg_type<
229 typename Overload::traits, int(index) >::type arg_type;
230 typedef typename senf::remove_cvref< arg_type >::type value_type;
231 typedef ParsedAttributeAttributor<Overload, index+1> next_type;
233 typedef OverloadedCommandNode node_type;
234 typedef ParsedAttributeAttributor return_type;
236 typedef boost::parameter::parameters<
238 kw::type::description,
239 kw::type::default_value> arg_params;
241 next_type arg() const;
243 # define BOOST_PP_ITERATION_PARAMS_1 \
244 (4, (1, 3, SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), 5))
245 # include BOOST_PP_ITERATE()
248 explicit ParsedAttributeAttributor(Overload & overload);
250 template <class ArgumentPack>
251 next_type argInfo(ArgumentPack const & args) const;
253 template <class Kw, class ArgumentPack>
254 void argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
256 template <class ArgumentPack>
257 void argInfo(boost::parameter::keyword<kw::type::name> const &,
258 ArgumentPack const & args, boost::mpl::false_)
260 template <class ArgumentPack>
261 void argInfo(boost::parameter::keyword<kw::type::description> const &,
262 ArgumentPack const & args, boost::mpl::false_)
264 template <class ArgumentPack>
265 void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
266 ArgumentPack const & args, boost::mpl::false_)
269 next_type next() const;
271 void defaultValue(value_type const & value) const;
273 template <class O, unsigned i, bool f>
274 friend class ParsedAttributeAttributor;
276 template <class Function>
277 friend ParsedAttributeAttributor<
278 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
279 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
281 template <class Owner, class Function>
282 friend ParsedAttributeAttributor<
283 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
284 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
286 typename boost::enable_if_c<
287 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
290 template <class Overload, unsigned index>
291 class ParsedAttributeAttributor<Overload, index, false>
292 : public ParsedAttributeAttributorBase< Overload,
293 ParsedAttributeAttributor<Overload, index, false> >
296 typedef OverloadedCommandNode node_type;
297 typedef ParsedAttributeAttributor return_type;
300 explicit ParsedAttributeAttributor(Overload & overload);
302 template <class O, unsigned i, bool f>
303 friend class ParsedAttributeAttributor;
305 template <class Function>
306 friend ParsedAttributeAttributor<
307 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
308 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
310 template <class Owner, class Function>
311 friend ParsedAttributeAttributor<
312 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
313 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
315 typename boost::enable_if_c<
316 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
321 template <class Function>
322 ParsedAttributeAttributor<
323 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
324 senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
326 template <class Owner, class Function>
327 ParsedAttributeAttributor<
328 ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
329 senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
331 typename boost::enable_if_c<
332 detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
338 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
340 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
341 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedAttributeAttributor, (class, unsigned, bool))
342 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
344 ///////////////////////////////hh.e////////////////////////////////////////
345 #include "ParsedCommand.cci"
346 #include "ParsedCommand.ct"
347 #include "ParsedCommand.cti"
354 // comment-column: 40
355 // c-file-style: "senf"
356 // indent-tabs-mode: nil
357 // ispell-local-dictionary: "american"
358 // compile-command: "scons -u test"