X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senf%2FUtils%2FConsole%2FNode.hh;h=a6d64c41f5d634db145589b981f50d05775153df;hb=6aae6e526573187ece558842e928578e5aa4cc4c;hp=0b854fb7ba66445856cfd2ee7e82c0e034ceebfa;hpb=f13780e9e4da7df981d6f6542fbdc714beb34765;p=senf.git diff --git a/senf/Utils/Console/Node.hh b/senf/Utils/Console/Node.hh index 0b854fb..a6d64c4 100644 --- a/senf/Utils/Console/Node.hh +++ b/senf/Utils/Console/Node.hh @@ -53,12 +53,13 @@ SomeClass() : dir(this) { + namespace fty = senf::console::factory; // You may document the directory here or later when adding it to the tree dir.doc("Manager for something"); // Add a member function (the pointer-to-member is automatically bound to this instance) - dir.add("member", &SomeClass::member) - .doc("Do the member operation"); + dir.add("member", fty::Command(&SomeClass::member, this) + .doc("Do the member operation")); } void member(std::ostream & os, senf::console::ParseCommandInfo const & command) @@ -69,6 +70,8 @@ int main(int, char**) { + namespace fty = senf::console::factory; + // Provide global documentation senf::console::root() .doc("This is someServer server"); @@ -76,13 +79,13 @@ // Add a new directory to the root and document it. All the mutators return the node object // itself so operations can be chained. senf::console::DirectoryNode & mydir ( senf::console::root() - .mkdir("myserver") - .doc("My server specific directory")); + .add("myserver", fty::Directory() + .doc("My server specific directory"))); // Add a command to that directory - mydir.add("mycommand", &mycommand) + mydir.add("mycommand", fty::Command(&mycommand) .doc("mycommand []\n\n" - "If is given, flurgle the , otherwise burgle it"); + "If is given, flurgle the , otherwise burgle it")); // Create a SomeClass instance and add it's directory. SomeClass someClass; @@ -129,7 +132,7 @@ \code void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... } // ... - myDirectory.add("foo",&callback); + myDirectory.add("foo",fty::Command(&callback)); \endcode Every node is identified among it's siblings by it's name. The name of the node is set when @@ -155,10 +158,10 @@ Depending on the node type added, additional node parameters may be set. For example, every node has a documentation parameter which is used by the online-help system. To assign these parameters, the node exposes corresponding member functions. Since - senf::console::DirectoryNode::add() returns the newly added node by reference, additional - parameters may just be added to the end of the add command: + senf::console::DirectoryNode::add() returns the newly added node by reference. Additional + parameters may be added after the factory call: \code - myDirectory.add("foo",&fooCallback).doc("The foo method"); + myDirectory.add("foo", fty::Command(&fooCallback).doc("The foo method") ); \endcode Since the parameter setters all return the node reference, additional parameters may just be added to the end of the command. @@ -206,10 +209,7 @@ #include #include #include -#include #include -#include -#include "Parse.hh" //#include "Node.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -230,7 +230,7 @@ namespace console { Recursively dumps the console directory structure starting at \a dir. By default, dumps the complete tree beginning at the root node. - + In contrast to the console 'lr' command, links are dumped by showing the \e absolute path to the target node. */ @@ -387,8 +387,8 @@ namespace console { This node type provides the internal and root nodes of the tree. It allows to add arbitrary children and supports directory traversal. - Nodes are normally not instantiated manually but are created by the DirectoryNode via - mkdir() or add(). Special add() members however allow externally allocated node objects. + Nodes are normally not instantiated manually but are created using factory calls. Special + add() members however allow externally allocated node objects. Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always managed dynamically, there is a special ScopedDirectory proxy template which provides a @@ -507,11 +507,6 @@ namespace console { \throws std::bad_cast if the child \a name is not a command node. */ - DirectoryNode & mkdir(std::string const & name); - ///< Create sub-directory node - DirectoryNode & provideDirectory(std::string const & name); - ///< Return subdirectory, possibly creating it - ChildrenRange children() const; ///< Return iterator range over all children. /**< The returned range is sorted by child name. */ @@ -519,10 +514,6 @@ namespace console { ///< Return iterator range of completions for \a s /**< The returned range is sorted by child name. */ - void link(std::string const & name, GenericNode & target); - ///< Create a child node which is a link to target. \a s - /**< The new link node will be a child of the node for which this member function is called. */ - ///\} /////////////////////////////////////////////////////////////////////////// @@ -583,7 +574,7 @@ namespace console { \param[in] command command arguments. This is a range of ranges of Token instances. */ - void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) + void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) const; ///< Execute the command /**< \param[out] rv command return value @@ -681,10 +672,51 @@ namespace console { std::string shortdoc_; }; -#ifndef DOXYGEN + DirectoryNode & provideDirectory(DirectoryNode & dir, std::string const & name); + +/** \brief Console node factories + + The senf::console::factory namespace (customarily aliased to \c fty in user code) contains + factories used to create new node types: + \code + namespace fty = senf::console::factory; + + senf::console::DirectoryNode & dir (node.add("dirname", fty::Directory())); + + dir.add("name", fty::Command(&fn) + .arg("flag") + .doc("documentation")); + \endcode + + The node is added by passing the factory instance to senf::console::DirectoryNode::add(). + + To further customize the node, you may call attributor members on the temporary factory class + instance. Since the attributor members always return a self-reference to the factory class + instance, attributor calls may be chained arbitrarily. + + \see + \ref console_commands for details on the command nodes \n + \ref node_tree for details on the structural nodes (directory, link) + + \note All factories are documented here as classes when in fact some are functions returning + internal classes. + + \implementation It is not true, that all attributor members return a self reference. Some + attributor members will return a new object of slightly different type. However, the + behavior is as documented above. + \ingroup console_commands + */ namespace factory { - + + /** \brief SimpleCommandNode factory + + This factory will create a SimpleCommandNode calling the given callback. A SimpleCommandNode + does not support overloading or automatic argument parsing. + + \attention This class is of interest mostly for testing and as a simple CommandNode + example. Use senf::console::factory::Command instead. + */ class SimpleCommand : public detail::NodeFactory { @@ -694,18 +726,85 @@ namespace factory { explicit SimpleCommand(SimpleCommandNode::Function fn); - SimpleCommandNode & create(DirectoryNode & dir, std::string const & name) const; - SimpleCommand const & doc(std::string const & doc) const; + ///< Set simple command documentation SimpleCommand const & shortdoc(std::string const & doc) const; + ///< Set simple command short documentation private: + SimpleCommandNode & create(DirectoryNode & dir, std::string const & name) const; + SimpleCommandNode::ptr node_; + + friend class senf::console::DirectoryNode; }; -} + /** \brief DirectoryNode factory -#endif + This factory will create new directory nodes. Use + + \code + namespace fty = senf::console::factory; + node.add("mydir", fty::Directory()) + \endcode + + To add a directory \a mydir to \a node. + + \see \ref node_tree + */ + class Directory + : public detail::NodeFactory + { + public: + typedef DirectoryNode node_type; + typedef DirectoryNode & result_type; + + Directory(); + + Directory const & doc(std::string const & doc) const; + ///< Set directory documentation + Directory const & shortdoc(std::string const & doc) const; + ///< Set directory short documentation + + private: + DirectoryNode & create(DirectoryNode & dir, std::string const & name) const; + + DirectoryNode::ptr node_; + + friend class senf::console::DirectoryNode; + }; + + /** \brief LinkNode factory + + This factory will create new link nodes. Use + + \code + namespace fty = senf::console::factory; + node.add("mylink", fty::Link(targetNode)) + \endcode + + To add a link \a mylink to \a node pointing to \a targetNode + + \see \ref node_tree + */ + class Link + : public detail::NodeFactory + { + public: + typedef LinkNode node_type; + typedef LinkNode & result_type; + + explicit Link(GenericNode & target); + + private: + LinkNode & create(DirectoryNode & dir, std::string const & name) const; + + LinkNode::ptr node_; + + friend class senf::console::DirectoryNode; + }; + +} }}