Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / Utils / Console / Node.hh
index bfccb7a..4665716 100644 (file)
 
         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");
         // 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 <foo> [<bar>]\n\n"
-                 "If <bar> is given, flurgle the <foo>, otherwise burgle it");
+                 "If <bar> is given, flurgle the <foo>, otherwise burgle it"));
 
         // Create a SomeClass instance and add it's directory.
         SomeClass someClass;
     \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
     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.
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/utility.hpp>
 #include <boost/range/iterator_range.hpp>
-#include <boost/typeof/typeof.hpp>
-#include <boost/type_traits/remove_reference.hpp>
 #include <boost/any.hpp>
-#include "../../Utils/Exception.hh"
-#include "../../Utils/mpl.hh"
-#include "../../Utils/Logger/SenfLog.hh"
-#include "../../Utils/type_traits.hh"
-#include "Parse.hh"
+#include <senf/Utils/Exception.hh>
+#include <senf/Utils/Logger/SenfLog.hh>
 
 //#include "Node.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 
 namespace senf {
 namespace console {
@@ -223,6 +221,8 @@ namespace console {
     class DirectoryNode;
     class CommandNode;
 
+    namespace detail { struct NodeFactory {}; }
+
     /** \brief Get console root node */
     DirectoryNode & root();
 
@@ -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.
      */
@@ -258,14 +258,14 @@ namespace console {
     {
         SENF_LOG_CLASS_AREA();
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::shared_ptr<GenericNode> ptr;
         typedef boost::shared_ptr<GenericNode const> cptr;
         typedef boost::weak_ptr<GenericNode> weak_ptr;
 
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
 
         virtual ~GenericNode();
 
@@ -349,23 +349,23 @@ namespace console {
         : public GenericNode
     {
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::shared_ptr<LinkNode> ptr;
         typedef boost::shared_ptr<LinkNode const> cptr;
         typedef boost::weak_ptr<LinkNode> weak_ptr;
 
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
-        ///@{
+        //\{
 
         static ptr create(GenericNode & node); ///< Create new link node.
                                         /**< You should normally use DirectoryNode::link() to
                                              create a link node. */
 
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
 
         GenericNode & follow() const;   ///< Access the referenced node
 
@@ -382,38 +382,13 @@ namespace console {
 
     class SimpleCommandNode;
 
-    /** \brief Internal: Node creation helper traits
-
-        This class is used internally to find out the type of node to create for a specific argument
-        type.
-     */
-    template <class Object>
-    struct NodeCreateTraits
-    {
-        typedef BOOST_TYPEOF_TPL( senf_console_add_node(
-                                      * static_cast<DirectoryNode *>(0),
-                                      * static_cast<std::string const *>(0),
-                                      * static_cast<Object *>(0),
-                                      0) ) base_type;
-        typedef typename senf::remove_cvref<base_type>::type value_type;
-
-        typedef typename value_type::node_type NodeType;
-        typedef typename value_type::return_type result_type;
-
-        /// Internal
-        struct Creator {
-            static result_type create(DirectoryNode & node, std::string const & name,
-                                      Object & ob);
-        };
-    };
-
     /** \brief Config/console tree directory node
 
         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
@@ -433,7 +408,7 @@ namespace console {
         SENF_LOG_CLASS_AREA();
         typedef std::map<std::string, GenericNode::ptr> ChildMap;
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::shared_ptr<DirectoryNode> ptr;
@@ -446,19 +421,19 @@ namespace console {
         typedef DirectoryNode node_type;
         typedef DirectoryNode & return_type;
 
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
-        ///\{
+        //\{
 
         static ptr create();            ///< Create node object.
                                         /**< You should normally use either mkdir() or
                                              ScopedDirectory instead of create() */
         ~DirectoryNode();
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Children
-        ///\{
+        //\{
 
         template <class NodeType>
         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
@@ -469,38 +444,17 @@ namespace console {
                                              '-n' is added to the name until the name is unique. If
                                              \a name is empty, it is set to 'unnamed'. */
 
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object const & ob);
+        template <class NodeType>
+        NodeType & add(std::string const & name, NodeType & node,
+                       typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+
+        template <class Factory>
+        typename Factory::result_type add(std::string const & name, Factory const & factory,
+                                          typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type * = 0);
                                         ///< 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
-                                             the type of argument passed.
-
-                                             The node type is selected by the NodeCreateTraits
-                                             class. To allow adding a specific node type, you need
-                                             to provide an overload for
-                                             <tt>senf_console_add_node</tt> which must be visible at
-                                             when you register the new node.
-                                             \code
-                                             MyNodeType & senf_console_add_node(
-                                                 DirectoryNode & dir,
-                                                 std::string const & name,
-                                                 MySpecialObject const & ob,
-                                                 int)
-                                             {
-                                                 return dir.add(name, MyNodeType::create(ob));
-                                             }
-                                             \endcode
-                                             (Do not forget the last unnamed 'int' parameter which
-                                             is not used but serves to disambiguate the
-                                             overloads). */
-
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object & ob);
-                                        ///< Generic child node factory
-                                        /**< \see add() */
+                                             the type of argument passed. */
 
         GenericNode::ptr remove(std::string const & name);
                                         ///< Remove node \a name from the tree
@@ -553,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. */
 
@@ -565,12 +514,8 @@ 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. */
-
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
 
         DirectoryNode & doc(std::string const & doc); ///< Set node documentation
         DirectoryNode & shortdoc(std::string const & doc); ///< Set node short documentation
@@ -597,12 +542,6 @@ namespace console {
     struct UnknownNodeNameException : public senf::Exception
     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
 
-#ifndef DOXYGEN
-    template <class Type>
-    struct NodeCreateTraits< boost::shared_ptr<Type> >
-    {};
-#endif
-
     /** \brief Config/console tree command node
 
         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
@@ -619,14 +558,14 @@ namespace console {
     {
         SENF_LOG_CLASS_AREA();
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::shared_ptr<CommandNode> ptr;
         typedef boost::shared_ptr<CommandNode const> cptr;
         typedef boost::weak_ptr<CommandNode> weak_ptr;
 
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
 
         void execute(std::ostream & output, ParseCommandInfo const & command) const;
                                         ///< Execute the command
@@ -635,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
@@ -691,7 +630,7 @@ namespace console {
     {
         SENF_LOG_CLASS_AREA();
     public:
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         // Types
 
         typedef boost::shared_ptr<SimpleCommandNode> ptr;
@@ -703,14 +642,14 @@ namespace console {
         typedef SimpleCommandNode node_type;
         typedef SimpleCommandNode & return_type;
 
-        ///////////////////////////////////////////////////////////////////////////
+        //-////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
-        ///\{
+        //\{
 
         static ptr create(Function const & fn);
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        //\}
+        //-////////////////////////////////////////////////////////////////////////
 
         ptr thisptr();
         cptr thisptr() const;
@@ -733,31 +672,149 @@ namespace console {
         std::string shortdoc_;
     };
 
-#ifndef DOXYGEN
+    DirectoryNode & provideDirectory(DirectoryNode & dir, std::string const & name);
 
-    SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                              SimpleCommandNode::Function fn, int);
+/** \brief Console node factories
 
-    DirectoryNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                          DirectoryNode & dir, int);
+    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;
 
-#endif
+    senf::console::DirectoryNode & dir (node.add("dirname", fty::Directory()));
 
-}}
+    dir.add("name", fty::Command<void(bool)>(&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.
 
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+    \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.
 
-BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
-BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
+    \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
+    {
+    public:
+        typedef SimpleCommandNode node_type;
+        typedef SimpleCommandNode & result_type;
+
+        explicit SimpleCommand(SimpleCommandNode::Function fn);
+
+        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;
+    };
 
-///////////////////////////////hh.e////////////////////////////////////////
+    /** \brief DirectoryNode factory
+
+        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;
+    };
+
+}
+
+}}
+
+//-/////////////////////////////////////////////////////////////////////////////////////////////////
 #include "Node.cci"
 //#include "Node.ct"
 #include "Node.cti"
 #endif
 
-
+\f
 // Local Variables:
 // mode: c++
 // fill-column: 100