X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FParsedCommand.hh;h=7df4366b4b98118f64a8dce0b1ae215e424ce007;hb=8025a3e571ed9de108f7203907baa4cabc801ea9;hp=14d63a02ce173d1e8956ba35dad042bc1b2be209;hpb=01e02e262ea327678dfa0c3f7a66d50ed91924d5;p=senf.git diff --git a/Console/ParsedCommand.hh b/Console/ParsedCommand.hh index 14d63a0..7df4366 100644 --- a/Console/ParsedCommand.hh +++ b/Console/ParsedCommand.hh @@ -47,6 +47,85 @@ namespace senf { namespace console { + /** \brief CommandOverload implementation with automatic argument parsing + + ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic + parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to + an OverloadedCommandNode instance. + + Automatic argument parsing and return value processing consists of several components: + \li \ref overload_add Adding overload instances to the tree + \li (Advanced) \ref overload_parse + \li (Advanced) \ref overload_format + + \section overload_add Adding argument parsing callbacks to the tree + + Adding appropriate callbacks to the tree is very simple: just path a function pointer to + DirectoryNode::add() or a member function pointer to ScopedDirectory::add(). + \code + std::string taskStatus(int id); + + senf::console::root().add("taskStatus", &taskStatus); + \endcode + + There are quite a number of additional parameters available to be set. These parameters are + documented in ParsedAttributeAttributor. Parameters are set by adding them as additional + calls after adding the node: + + \code + senf::console::root().add("taskStatus", &taskStatus) + .doc("Query the current task status") + .arg( name = "id", + description = "numeric id of task to check, -1 for the current task." + default_value = -1 ); + \endcode + + You may also add an additional \c std::ostream & Argument as first argument to the + callback. If this argument is present, the stream connected to the console which issued the + command will be passed there. This allows writing arbitrary messages to the console. + + Additionally, overloading is supported by registering multiple commands under the same + name. So, elaborating on above example: + \code + std::string taskStatus(int id); + std::string taskStatus(std::string const & name); + + senf::console::root() + .add("taskStatus", static_cast(&taskStatus)) + .doc("Query the current task status") + .overloadDoc("Query status by id") + .arg( name = "id", + description = "numeric id of task to check, -1 for the current task." + default_value = -1 ); + senf::console::root() + .add("taskStatus", static_cast(&taskStatus)) + .overloadDoc("Query status by name") + .arg( name = "name", + description = "name of task to check" ); + \endcode + + We can see here, that taking the address of an overloaded function requires a cast. If you + can give unique names to each of the C++ overloads (not the overloads in the console), you + should do so to make the unwieldy casts unnecessary. + + \section overload_parse Custom parameter parsers + + By default, parameters are parsed using \c boost::lexical_cast and therefore using \c + iostreams. This means, that any type which can be read from a stream can automatically be + used as argument type. + + However, argument parsing can be configured by specializing + senf::console::detail::ParameterTraits. See that class for more information. + + \section overload_format Custom return-value formatters + + By default, return values are streamed to an ostream. This automatically allows any + streamable type to be used as return value. To add new types or customize the formating, the + senf::console::detail::ReturnValueTraits template needs to be specialized for that type. See + that class for more information. + + \ingroup console_commands + */ class ParsedCommandOverloadBase : public CommandOverload { @@ -118,10 +197,10 @@ namespace console { private: }; - namespace tag { - BOOST_PARAMETER_KEYWORD(detail, name_); - BOOST_PARAMETER_KEYWORD(detail, description_); - BOOST_PARAMETER_KEYWORD(detail, default_value_); + namespace kw { + BOOST_PARAMETER_KEYWORD(type, name); + BOOST_PARAMETER_KEYWORD(type, description); + BOOST_PARAMETER_KEYWORD(type, default_value); } template @@ -155,9 +234,9 @@ namespace console { typedef ParsedAttributeAttributor return_type; typedef boost::parameter::parameters< - tag::detail::name_, - tag::detail::description_, - tag::detail::default_value_> arg_params; + kw::type::name, + kw::type::description, + kw::type::default_value> arg_params; next_type arg() const; @@ -171,16 +250,23 @@ namespace console { template next_type argInfo(ArgumentPack const & args) const; + template + void argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_) + const; template - next_type argInfo(ArgumentPack const & args, boost::mpl::true_) const; + void argInfo(boost::parameter::keyword const &, + ArgumentPack const & args, boost::mpl::false_) + const; template - next_type argInfo(ArgumentPack const & args, boost::mpl::false_) const; - - next_type argInfo(std::string const & name, std::string const & doc) const; - next_type argInfo(std::string const & name, std::string const & doc, - value_type const & value) const; + void argInfo(boost::parameter::keyword const &, + ArgumentPack const & args, boost::mpl::false_) + const; + template + void argInfo(boost::parameter::keyword const &, + ArgumentPack const & args, boost::mpl::false_) + const; - ParsedAttributeAttributor next() const; + next_type next() const; void defaultValue(value_type const & value) const; @@ -203,7 +289,8 @@ namespace console { template class ParsedAttributeAttributor - : public ParsedCommandAttributor< Overload > + : public ParsedAttributeAttributorBase< Overload, + ParsedAttributeAttributor > { public: typedef OverloadedCommandNode node_type;