// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
#include <vector>
#include <boost/type_traits/function_traits.hpp>
-#include <boost/type_traits/is_member_pointer.hpp>
+#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/mpl/if.hpp>
#include <boost/utility.hpp>
#include <boost/parameter/keyword.hpp>
\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().
+ To add overloads to the tree, use the senf::console::factory::Command factory:
\code
+ namespace fty = senf::console::factory;
+
std::string taskStatus(int id);
- senf::console::root().add("taskStatus", &taskStatus);
+ senf::console::root().add("taskStatus", fty::Command(&taskStatus));
\endcode
There are quite a number of additional parameters available to be set. These parameters are
calls after adding the node:
\code
- senf::console::root().add("taskStatus", &taskStatus)
+ senf::console::root().add("taskStatus", fty::Command(&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 );
+ default_value = -1 ) );
\endcode
You may also add an additional \c std::ostream & Argument as first argument to the
std::string taskStatus(std::string const & name);
senf::console::root()
- .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
+ .add("taskStatus", fty::Command(static_cast<std::string (*)(int)>(
+ &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 );
+ default_value = -1 ) );
senf::console::root()
- .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
+ .add("taskStatus", fty::Commande(static_cast<std::string (*)(std::string const &)>(
+ &taskStatus))
.overloadDoc("Query status by name")
.arg( name = "name",
- description = "name of task to check" );
+ description = "name of task to check" ) );
\endcode
We can see here, that taking the address of an overloaded function requires a cast. If 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.
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class is the base class for those attributors. It provides members which do not depend
in any way on the exact type of command added.
void argDoc(std::string const & doc);
void typeName(std::string const & doc);
void defaultDoc(std::string const & doc);
-
+
ParsedCommandOverloadBase & overload() const;
void overloadDoc(std::string const & doc);
void nodeDoc(std::string const & doc);
void shortDoc(std::string const & doc);
-
+
private:
ParsedCommandOverloadBase::ptr overload_;
unsigned index_;
boost::optional<std::string> shortdoc_;
};
- /** \brief Non argument dependent ParsedCommandBase attributes
-
+ /** \brief Non argument dependent ParsedCommandBase attributes
+
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
For the keyword tags, the standard C++ scoping rules apply
\code
+ namespace fty=senf::console::factory;
+
// Either qualify them with their complete namespace
- dir.add(...)
- .arg( senf::console::kw::name = "name" );
-
+ dir.add(..., fty::Command(...)
+ .arg( senf::console::kw::name = "name" ) );
+
// Or use a namespace alias
namespace kw = senf::console::kw;
- dir.add(...)
- .arg( kw::name = "name" );
+ dir.add(..., fty::Command(...)
+ .arg( kw::name = "name" ) );
// Or import the keywords into the current namespace (beware of name collisions)
using namespace senf::console::kw;
- dir.add(...)
- .arg( name = "name" );
+ dir.add(..., fty::Command(...)
+ .arg( name = "name" ) );
\endcode
The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
\code
void command(int);
- dir.add("command", &command)
+ dir.add("command", fty::Command(&command)
.arg( kw::name = "name",
kw::description = "description",
kw::default_value = 1,
kw::type_name = "type_name",
- kw::default_doc = "default_doc" );
+ kw::default_doc = "default_doc" ) );
\endcode
Will create the following documentation:
\htmlonly
<pre>
Usage:
command [name:type_name]
-
+
With:
name description
default: default_doc
token list returned by the console/config parser into
the appropriate value. If not set explicitly, this
conversion is supplied by the ArgumentTraits
- class.
+ class.
Setting the \a parser attribute allows to use a custom
parser. The parser is an arbitrary callable object with
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class adds all those members, which do not depend on any specific argument but which
need to return the correct attributor type.
Self doc(std::string const & doc); ///< Set documentation for all overloads
Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
- Self formatter(typename Overload::Formatter formatter);
+ Self formatter(typename Overload::Formatter formatter);
///< Set return value formatter
/**< This member is only available, if the \a ReturnType of
the installed callback is not \c void.
};
#endif
-
+
/** \brief Argument dependent ParsedCommandBase attributes
Attributes for parsed commands are not set directly on the node. They are set via a special
attributor temporary returned when adding a parsed command to the tree.
-
+
This class adds all those members, which depend on a specific argument. Each call to \c arg
will advance to the next argument.
*/
template <class Overload, unsigned index, bool flag>
class ParsedArgumentAttributor
- : public ParsedArgumentAttributorBase< Overload,
+ : public ParsedArgumentAttributorBase< Overload,
ParsedArgumentAttributor<Overload, index, flag> >
{
typedef boost::parameter::parameters<
kw::type::parser> arg_params;
public:
- typedef typename senf::function_traits_arg_type<
+ typedef typename senf::function_traits_arg_type<
typename Overload::traits, int(index) >::type arg_type;
typedef typename senf::remove_cvref< arg_type >::type value_type;
typedef ParsedArgumentAttributor<Overload, index+1> next_type;
argument. The attributes are passed to arg() as keyword
arguments using the <a
href="http://www.boost.org/doc/libs/1_33_1/libs/parameter/doc/html/index.html">Boost.Parameter</a>
- library.
+ library.
\code
...
- .arg( kw::name = "name",
+ .arg( kw::name = "name",
kw::default_value = 1 )
...
\endcode
The valid keywords are defined in the senf::console::kw
namespace.
-
+
Each call to arg() will increment the argument index
and advance to the next argument. This member is only
present, if there is an argument at the current
void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::name> const &,
+ void argInfo(boost::parameter::keyword<kw::type::name> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::description> const &,
+ void argInfo(boost::parameter::keyword<kw::type::description> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
+ void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
+ void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
+ void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
- void argInfo(boost::parameter::keyword<kw::type::parser> const &,
+ void argInfo(boost::parameter::keyword<kw::type::parser> const &,
ArgumentPack const & args, boost::mpl::true_);
next_type next() const;
template <class Overload, unsigned index>
class ParsedArgumentAttributor<Overload, index, false>
- : public ParsedArgumentAttributorBase< Overload,
+ : public ParsedArgumentAttributorBase< Overload,
ParsedArgumentAttributor<Overload, index, false> >
{
public:
namespace factory {
+ template <class Signature>
+ SimpleOverloadAttributor
+ Command(boost::function<Signature> fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Signature>::is_simple>::type * = 0);
+
+ template <class Function>
+ SimpleOverloadAttributor
+ Command(Function fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_simple>::type * = 0);
+
+ template <class Owner, class Member>
+ SimpleOverloadAttributor
+ Command(Member memfn, Owner * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
+
+ template <class Owner, class Member>
+ SimpleOverloadAttributor
+ Command(Member memfn, Owner const * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Member>::is_simple>::type * = 0);
+
template <class CastTo, class Signature>
typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
Command(boost::function<Signature> fn);
template <class CastTo, class Function>
typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
Command(Function fn,
- typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
+ typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
template <class Signature>
typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
template <class Function>
typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
Command(Function fn,
- typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0,
+ typename boost::disable_if<boost::is_member_function_pointer<Function> >::type * = 0);
template <class Owner, class Member>
typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
- BoundCommand(Owner * owner, Member memfn);
+ Command(Member memfn, Owner * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
template <class Owner, class Member>
typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
- BoundCommand(Owner const * owner, Member memfn);
+ Command(Member memfn, Owner const * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
template <class CastTo, class Owner, class Member>
typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
- BoundCommand(Owner * owner, Member memfn);
+ Command(Member memfn, Owner * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
template <class CastTo, class Owner, class Member>
typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
- BoundCommand(Owner const * owner, Member memfn);
+ Command(Member memfn, Owner const * owner,
+ typename boost::enable_if<boost::is_member_function_pointer<Member> >::type * = 0);
}}}