Packets: Restructure documentation
[senf.git] / Console / Node.hh
index 9bf37ec..e284998 100644 (file)
@@ -23,7 +23,7 @@
 /** \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
     
     \li senf::console::DirectoryNode provides internal nodes with an arbitrary number of children
     \li senf::console::CommandNode describes a command entry in the tree
+    \li senf::console::LinkNode is a link to another node. It works much like a symlink on POSIX
+        systems.
 
     senf::console::CommandNode is the base-class of all command nodes of which there are several,
     depending on the type of 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.
+    \li A senf::console::LinkNode is created by senf::console::DirectoryNode::link()
 
     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.
 namespace senf {
 namespace console {
 
+    class LinkNode;
     class DirectoryNode;
     class CommandNode;
 
+    DirectoryNode & root();
+
     /** \brief Config/console node tree base-class
 
         GenericNode is the base class of all node objects. There are two basic node types derived
@@ -258,6 +265,10 @@ namespace console {
         std::string path() const;       ///< Node path
                                         /**< The node path is built by joining the names of all
                                              parent nodes with '/' chars. */
+        std::string path(DirectoryNode const & root) const;       
+                                        ///< Node path up to \a root
+                                        /**< The node path is built by joining the names of all
+                                             parent nodes up to \a root with '/' chars. */
 
         ptr unlink();                   ///< Remove node from it's parent directory
                                         /**< You may either discard the return value and thereby
@@ -271,6 +282,20 @@ namespace console {
         ptr thisptr();                  ///< Get smart pointer to node
         cptr thisptr() const;           ///< Get smart pointer to node (const)
 
+        bool isChildOf(DirectoryNode & parent) const;
+                                        ///< \c true, if node is a child of \a parent
+                                        /**< Will also return \c true, if \a parent is the current
+                                             node. */
+
+        bool operator== (GenericNode & other) const;
+                                        /// \c true, if this and \a other are the same node
+        bool operator!= (GenericNode & other) const;
+                                        /// \c true, if this and \a other are different nodes
+
+        bool isDirectory() const;       ///< \c true, if this is a drectory node
+        bool isLink() const;            ///< \c true, if this is a link node
+        bool isCommand() const;         ///< \c true, if this is a command node
+
     protected:
         GenericNode();
 
@@ -293,6 +318,47 @@ namespace console {
         friend class DirectoryNode;
     };
 
+    /** \brief Config/console tree link node
+
+        A LinkNode references another node and provides an additional alias name for that node. A
+        LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a
+        UNIX symlink but references another node directly (not via it's path) like a UNIX
+        hardlink. Therefore, a LinkNode works across chroot().
+      */
+    class LinkNode
+        : 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
+
+    protected:
+
+    private:
+        explicit LinkNode(GenericNode & node);
+
+        virtual void v_help(std::ostream &) const;
+
+        GenericNode::ptr node_;
+    };
+
     class SimpleCommandNode;
 
     /** \brief Internal: Node creation helper traits
@@ -306,7 +372,7 @@ namespace console {
         typedef BOOST_TYPEOF_TPL( senf_console_add_node( 
                                       * static_cast<DirectoryNode *>(0),
                                       * static_cast<std::string const *>(0),
-                                      * static_cast<Object const *>(0),
+                                      * static_cast<Object *>(0),
                                       0) ) base_type;
         typedef typename senf::remove_cvref<base_type>::type value_type;
 
@@ -316,7 +382,7 @@ namespace console {
         /// Internal
         struct Creator {
             static result_type create(DirectoryNode & node, std::string const & name, 
-                                      Object const & ob);
+                                      Object & ob);
         };
     };
 
@@ -382,8 +448,8 @@ namespace console {
                                              \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);
+        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
@@ -408,6 +474,12 @@ namespace console {
                                              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() */
+
         GenericNode::ptr remove(std::string const & name);
                                         ///< Remove node \a name from the tree
                                         /**< The returned pointer may either be discarded, which
@@ -422,6 +494,10 @@ namespace console {
                                         ///< Get child node
                                         /**< \throws UnknownNodeNameException if a child \a name
                                                  does not exist */
+        GenericNode & getLink(std::string const & name) const;
+                                        ///< Get child node without dereferencing links
+                                        /**< \throws UnknownNodeNameException if a child \a name
+                                                 does not exist */
 
         DirectoryNode & getDirectory(std::string const & name) const;
                                         ///< Get directory child node
@@ -458,27 +534,19 @@ namespace console {
         DirectoryNode & mkdir(std::string const & name);
                                         ///< Create sub-directory node
         
-        ChildrenRange children() const;
-                                        ///< Return iterator range over all children.
+        ChildrenRange children() const; ///< Return iterator range over all children.
                                         /**< The returned range is sorted by child name. */
 
-        ///\}
-        ///////////////////////////////////////////////////////////////////////////
+        ChildrenRange completions(std::string const & s) const;
+                                        ///< Return iterator range of completions for \a s
+                                        /**< The returned range is sorted by child name. */
 
-        template <class ForwardRange>
-        GenericNode & traverse(ForwardRange const & range);
-                                        ///< Traverse node path starting at this node
-                                        /**< The <tt>ForwardRange::value_type</tt> must be
-                                             (convertible to) std::string. Each range element
-                                             constitutes a step along the node traversal.
+        void link(std::string const & name, GenericNode & target);
 
-                                             If the range starts with an empty element, the
-                                             traversal is started at the root() node, otherwise it
-                                             is started at \a this node. The traversal supports '.',
-                                             '..' and ignores further empty elements. */
+        ///\}
+        ///////////////////////////////////////////////////////////////////////////
 
-        DirectoryNode & doc(std::string const & doc);
-                                        ///< Set node documentation
+        DirectoryNode & doc(std::string const & doc); ///< Set node documentation
 
         ptr thisptr();
         cptr thisptr() const;
@@ -506,13 +574,6 @@ namespace console {
     {};
 #endif
 
-    struct SyntaxErrorException : public senf::Exception
-    {
-        explicit SyntaxErrorException(std::string const & msg = "");
-
-        virtual char const * what() const throw();
-    };
-
     /** \brief Config/console tree command node
 
         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
@@ -520,6 +581,9 @@ namespace console {
 
         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
       */
     class CommandNode : public GenericNode
@@ -541,7 +605,7 @@ namespace console {
                                              \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. */
+                                                 range of ranges of Token instances. */
 
         void operator()(std::ostream & output, ParseCommandInfo const & command) const;
                                         ///< Execute the command
@@ -549,7 +613,7 @@ namespace console {
                                              \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. */
+                                                 range of ranges of Token instances. */
 
         ptr thisptr();
         cptr thisptr() const;
@@ -565,7 +629,7 @@ namespace console {
                                         /**< \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. */
+                                                 range of ranges of Token instances. */
 
     private:
     };
@@ -573,9 +637,14 @@ namespace console {
     /** \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
     {
@@ -620,12 +689,11 @@ namespace console {
     };
 
 #ifndef DOXYGEN
-    template <class Function>
+
     SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name, 
-                                              Function const & fn, ...);
-#endif
+                                              SimpleCommandNode::Function fn, int);
 
-    DirectoryNode & root();
+#endif
 
 }}
 
@@ -637,7 +705,7 @@ BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "Node.cci"
-#include "Node.ct"
+//#include "Node.ct"
 #include "Node.cti"
 #endif