X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FNode.hh;h=e443205e4b41e9ee95811ca83ef536dd9759c72c;hb=ca70e274a556bf217f3f4c7b12e0fad2a7cd4853;hp=86c3e17ff146644f1e08f857937329e83b1f8e97;hpb=be33ff96c5b89738694da272d8610564cce48bfb;p=senf.git diff --git a/Console/Node.hh b/Console/Node.hh index 86c3e17..e443205 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -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 @@ -117,7 +117,8 @@ \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. @@ -205,13 +206,12 @@ #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 { @@ -307,15 +307,17 @@ namespace console { typedef BOOST_TYPEOF_TPL( senf_console_add_node( * static_cast(0), * static_cast(0), - * static_cast(0), - 0) ) result_type; + * static_cast(0), + 0) ) base_type; + typedef typename senf::remove_cvref::type value_type; - typedef typename boost::remove_reference::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 & ob); }; }; @@ -355,6 +357,9 @@ namespace console { typedef boost::iterator_range ChildrenRange; typedef ChildMap::const_iterator child_iterator; + typedef DirectoryNode node_type; + typedef DirectoryNode & return_type; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///\{ @@ -378,7 +383,7 @@ namespace console { \a name is empty, it is set to 'unnamed'. */ template - typename NodeCreateTraits::NodeType & add (std::string const & name, + typename NodeCreateTraits::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 @@ -404,6 +409,12 @@ namespace console { is not used but serves to disambiguate the overloads). */ + template + typename NodeCreateTraits::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 @@ -411,6 +422,9 @@ namespace console { 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 @@ -451,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 - GenericNode & traverse(ForwardRange const & range); + GenericNode & traverse(ForwardRange const & range, bool autocomplete=false); ///< Traverse node path starting at this node /**< The ForwardRange::value_type must be (convertible to) std::string. Each range element @@ -468,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 @@ -489,8 +510,6 @@ namespace console { friend DirectoryNode & root(); }; - BOOST_TYPEOF_REGISTER_TYPE(DirectoryNode); - /// Exception: Unknown node name struct UnknownNodeNameException : public senf::Exception { UnknownNodeNameException() : senf::Exception("Unknown node name") {}}; @@ -501,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 @@ -515,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 @@ -568,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 { @@ -585,6 +622,9 @@ namespace console { typedef boost::function Function; + typedef SimpleCommandNode node_type; + typedef SimpleCommandNode & return_type; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///\{ @@ -612,17 +652,22 @@ namespace console { }; #ifndef DOXYGEN - template + SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name, - Function const & fn, ...); -#endif + SimpleCommandNode::Function fn, int); - BOOST_TYPEOF_REGISTER_TYPE(SimpleCommandNode); +#endif 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"