Console: Implement autocomplete
[senf.git] / Console / Node.hh
index 9bf37ec..e443205 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 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.
@@ -306,7 +307,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 +317,7 @@ namespace console {
         /// Internal
         struct Creator {
             static result_type create(DirectoryNode & node, std::string const & name, 
-                                      Object const & ob);
+                                      Object & ob);
         };
     };
 
@@ -382,8 +383,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 +409,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
@@ -458,15 +465,18 @@ 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);
+        GenericNode & traverse(ForwardRange const & range, bool autocomplete=false);
                                         ///< Traverse node path starting at this node
                                         /**< The <tt>ForwardRange::value_type</tt> must be
                                              (convertible to) std::string. Each range element
@@ -475,7 +485,11 @@ namespace console {
                                              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. */
+                                             '..' and ignores further empty elements. 
+
+                                             If \a autocomplete is set to \c true, invalid path
+                                             components which can be uniquely completed will be
+                                             completed automatically while traversing the tree. */
 
         DirectoryNode & doc(std::string const & doc);
                                         ///< Set node documentation
@@ -506,11 +520,21 @@ namespace console {
     {};
 #endif
 
-    struct SyntaxErrorException : public senf::Exception
+    /**  \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 std::exception
     {
         explicit SyntaxErrorException(std::string const & msg = "");
+        virtual ~SyntaxErrorException() throw();
 
         virtual char const * what() const throw();
+        std::string const & message() const;
+
+    private:
+        std::string message_;
     };
 
     /** \brief Config/console tree command node
@@ -520,6 +544,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
@@ -573,9 +600,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,9 +652,10 @@ namespace console {
     };
 
 #ifndef DOXYGEN
-    template <class Function>
+
     SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name, 
-                                              Function const & fn, ...);
+                                              SimpleCommandNode::Function fn, int);
+
 #endif
 
     DirectoryNode & root();