/** \file
\brief Node public header */
-/** \defgroup node_tree The console/config file-system node tree
+/** \defgroup node_tree The node tree
The console/config node tree is the central data-structure of the library. Into this tree, all
commands and parameters are entered. The tree is then exposed using a file-system like
\code
// Define callback function.
- void mycommand(std::ostream & os, senf::console::Arguments const & args)
+ void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// ...
os << "!! Important message ...\n";
.doc("Do the member operation");
}
- void member(std::ostream & os, senf::console::Arguments const & args)
+ void member(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// ...
}
\li An arbitrary node can be created and then (possibly later) added to the tree using the
corresponding senf::console::DirectoryNode::add() overload.
\li A senf::console::CommandNode is normally added to the tree by directly adding a callback
- using one of the overloaded senf::console::DirectoryNode::add() members.
+ using one of the overloaded senf::console::DirectoryNode::add() members. See \ref
+ console_commands.
When directly adding a node callback, the type of node added depends on the type of
callback. The callback types which can be added are listed at \ref console_callbacks.
\code
- void callback(std::ostream & os, senf::console::Arguments const & args) { ... }
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
// ...
myDirectory.add("foo",&callback);
\endcode
adding the node to the tree. If the name is empty or non-unique, a unique name will be
automatically provided.
- To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink()
- member. This call removes the node from it's parent and returns a (smart) node pointer.
+ To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink() or the
+ parents senf::console::DirectoryNode::remove() member. This call removes the node from it's
+ parent and returns a (smart) node pointer.
\li If you ignore the return value, the node (and it's children) will be deleted.
\li Alternatively, you may store away the node and re-attach it later.
\li To rename a node, unlink and re-add it with a different name.
\code
- myDirectory.add("bar", myDirectory("foo").unlink());
+ myDirectory.add("bar", myDirectory.remove("foo"));
\endcode
\subsection console_node_param Assigning additional node parameters
Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
'()' have been overloaded in senf::console::DirectoryNode.
\code
+ senf::console::root().getDirectory("myDirectory").getCommand("foo")
+ \\ or more concise but otherwise completely identical
senf::console::root()["myDirectory"]("foo")
\endcode
- The '[]' operator will return a senf::console::DirectoryNode whereas '()' will return a
- senf::console::CommandNode. If the node is not found or is not of the correct type, an exception
- will be raised.
+
+ getDirectory and the '[]' operator will return a senf::console::DirectoryNode whereas getCommand
+ and the '()' operator will return a senf::console::CommandNode. If the node is not found or is
+ not of the correct type, an exception will be raised.
\section console_object_dir Assigning a directory to an object instance
#include "../Utils/Exception.hh"
#include "../Utils/mpl.hh"
#include "../Utils/Logger/SenfLog.hh"
+#include "../Utils/type_traits.hh"
#include "Parse.hh"
//#include "Node.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
-
namespace senf {
namespace console {
* static_cast<DirectoryNode *>(0),
* static_cast<std::string const *>(0),
* static_cast<Object const *>(0),
- 0) ) result_type;
+ 0) ) base_type;
+ typedef typename senf::remove_cvref<base_type>::type value_type;
- typedef typename boost::remove_reference<result_type>::type NodeType;
+ typedef typename value_type::node_type NodeType;
+ typedef typename value_type::return_type result_type;
/// Internal
struct Creator {
- static NodeType & create(DirectoryNode & node, std::string const & name,
- Object const & ob);
+ static result_type create(DirectoryNode & node, std::string const & name,
+ Object const & ob);
};
};
typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
typedef ChildMap::const_iterator child_iterator;
+ typedef DirectoryNode node_type;
+ typedef DirectoryNode & return_type;
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///\{
\a name is empty, it is set to 'unnamed'. */
template <class Object>
- typename NodeCreateTraits<Object>::NodeType & add (std::string const & name,
- Object const & ob);
+ typename NodeCreateTraits<Object>::result_type add (std::string const & name,
+ Object const & ob);
///< Generic child node factory
/**< This member is used to create a new child node of the
current directory. The type of node created depends on
be saved and/or re-attached at some other place in the
tree. */
+ bool hasChild(std::string const & name) const;
+ ///< \c true, if there is a child with name \a name
+
+ GenericNode & get(std::string const & name) const;
+ ///< Get child node
+ /**< \throws UnknownNodeNameException if a child \a name
+ does not exist */
+
+ DirectoryNode & getDirectory(std::string const & name) const;
+ ///< Get directory child node
+ /**< Same as operator[]
+ \throws UnknownNodeNameException if a child \a name
+ does not exist.
+ \throws std::bad_cast if the child \a name is not a
+ directory node. */
+
DirectoryNode & operator[](std::string const & name) const;
///< Get directory child node
- /**< \throws UnknownNodeNameException if a child \a name
+ /**< Same as getDirectory
+ \throws UnknownNodeNameException if a child \a name
does not exist.
\throws std::bad_cast if the child \a name is not a
directory node. */
- CommandNode & operator()(std::string const & name) const;
+ CommandNode & getCommand(std::string const & name) const;
///< Get command child node
- /**< \throws UnknownNodeNameException if a child \a name
+ /**< Same as operator()
+ \throws UnknownNodeNameException if a child \a name
does not exist
\throws std::bad_cast if the child \a name is not a
command node. */
- GenericNode & get(std::string const & name) const;
- ///< Get child node
- /**< \throws UnknownNodeNameException if a child \a name
- does not exist */
+ CommandNode & operator()(std::string const & name) const;
+ ///< Get command child node
+ /**< Same as getCommand()
+ \throws UnknownNodeNameException if a child \a name
+ does not exist
+ \throws std::bad_cast if the child \a name is not a
+ command node. */
DirectoryNode & mkdir(std::string const & name);
///< Create sub-directory node
template <class ForwardRange>
GenericNode & traverse(ForwardRange const & range);
///< Traverse node path starting at this node
- /**< The <tt>FordwareRange::value_type</tt> must be
+ /**< The <tt>ForwardRange::value_type</tt> must be
(convertible to) std::string. Each range element
constitutes a step along the node traversal.
friend DirectoryNode & root();
};
- BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode);
-
/// Exception: Unknown node name
struct UnknownNodeNameException : public senf::Exception
{ UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
{};
#endif
+ /** \brief Syntax error parsing command arguments exception
+
+ All errors while parsing the arguments of a command must be signaled by throwing an instance
+ of SyntaxErrorException. This is important, so command overloading works.
+ */
struct SyntaxErrorException : public senf::Exception
{
explicit SyntaxErrorException(std::string const & msg = "");
The CommandNode is the base-class for the tree leaf nodes. Concrete command node
implementations are derived from this class.
- To execute a command, CommandNode::operator()() is called. This abstract virtual function
- must be implemented in a derived class.
+ To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
+
+ Subclass instances of this node type are automatically created when adding commands to the
+ tree. See \ref console_commands.
\ingroup node_tree
*/
typedef boost::shared_ptr<CommandNode const> cptr;
typedef boost::weak_ptr<CommandNode> weak_ptr;
- typedef ParseCommandInfo::ArgumentsRange Arguments;
-
///////////////////////////////////////////////////////////////////////////
- void operator()(std::ostream & output, Arguments const & arguments) const;
+ void execute(std::ostream & output, ParseCommandInfo const & command) const;
///< Execute the command
- /**< \param[in] output stream where result messages may be
+ /**< Same as operator()()
+ \param[in] output stream where result messages may be
+ written to
+ \param[in] arguments command arguments. This is a
+ range of ranges of ArgumentToken instances. */
+
+ void operator()(std::ostream & output, ParseCommandInfo const & command) const;
+ ///< Execute the command
+ /**< Same as execute()
+ \param[in] output stream where result messages may be
written to
\param[in] arguments command arguments. This is a
range of ranges of ArgumentToken instances. */
#ifndef DOXYGEN
private:
#endif
- virtual void v_execute(std::ostream & output, Arguments const & arguments) const = 0;
+ virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const = 0;
///< Called to execute the command
/**< \param[in] output stream where result messages may be
written to
private:
};
- typedef CommandNode::Arguments Arguments;
-
/** \brief Most simple CommandNode implementation
This CommandNode implementation simply forwards the \a output and \a arguments arguments to
- an arbitrary callback.
+ an arbitrary callback. Thus, it allows to add callbacks with the signature
+ \code
+ void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
+ { ... }
+ \endcode
+ to the tree.
- \ingroup node_tree
+ \ingroup console_commands
*/
class SimpleCommandNode : public CommandNode
{
typedef boost::shared_ptr<SimpleCommandNode const> cptr;
typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
- typedef boost::function<void (std::ostream &, Arguments const &)> Function;
+ typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
+
+ typedef SimpleCommandNode node_type;
+ typedef SimpleCommandNode & return_type;
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
private:
virtual void v_help(std::ostream & output) const;
- virtual void v_execute(std::ostream & output, Arguments const & arguments) const;
+ virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const;
Function fn_;
Function const & fn, ...);
#endif
- BOOST_TYPEOF_REGISTER_TYPE(SimpleCommandNode);
-
DirectoryNode & root();
}}
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+
+BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
+BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
+
+
///////////////////////////////hh.e////////////////////////////////////////
#include "Node.cci"
#include "Node.ct"