Console: Complete 'Variable' command implementation
g0dil [Thu, 17 Apr 2008 10:19:37 +0000 (10:19 +0000)]
Console: Add support for read-only 'Variable' commands

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@817 270642c3-0616-0410-b53a-bc976706d245

14 files changed:
Console/Node.cci
Console/Node.cti
Console/Node.hh
Console/ParsedCommand.cti
Console/ParsedCommand.hh
Console/ParsedCommand.ih
Console/ParsedCommand.mpp
Console/ScopedDirectory.cti
Console/ScopedDirectory.hh
Console/Variables.cti
Console/Variables.hh
Console/Variables.ih
Console/Variables.test.cc
senfscons/CompileCheck.py

index 11d212e..6f24e9c 100644 (file)
@@ -235,6 +235,14 @@ prefix_ senf::console::SimpleCommandNode::cptr senf::console::SimpleCommandNode:
     return boost::static_pointer_cast<SimpleCommandNode const>(shared_from_this());
 }
 
+prefix_ senf::console::SimpleCommandNode &
+senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
+                                     SimpleCommandNode::Function fn, int)
+{
+    return node.add(name, SimpleCommandNode::create(fn));
+}
+
+
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
index 69baef1..a6e113f 100644 (file)
@@ -37,7 +37,7 @@ template <class Object>
 prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
 senf::console::NodeCreateTraits<Object>::Creator::create(DirectoryNode & node,
                                                          std::string const & name,
-                                                         Object const & ob)
+                                                         Object & ob)
 {
     return senf_console_add_node(node, name, ob, 0);
 }
@@ -59,17 +59,14 @@ template <class Object>
 prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
 senf::console::DirectoryNode::add(std::string const & name, Object const & ob)
 {
-    return NodeCreateTraits<Object>::Creator::create(*this, name, ob);
+    return NodeCreateTraits<Object const>::Creator::create(*this, name, ob);
 }
 
-///////////////////////////////////////////////////////////////////////////
-// senf::console::SimpleCommandNode
-
-template <class Function>
-prefix_ senf::console::SimpleCommandNode & senf::console::
-senf_console_add_node(DirectoryNode & node, std::string const & name, Function const & fn, ...)
+template <class Object>
+prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
+senf::console::DirectoryNode::add(std::string const & name, Object & ob)
 {
-    return node.add(name, SimpleCommandNode::create(fn));
+    return NodeCreateTraits<Object>::Creator::create(*this, name, ob);
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 71c66f7..6a2732c 100644 (file)
@@ -307,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;
 
@@ -317,7 +317,7 @@ namespace console {
         /// Internal
         struct Creator {
             static result_type create(DirectoryNode & node, std::string const & name, 
-                                      Object const & ob);
+                                      Object & ob);
         };
     };
 
@@ -383,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
@@ -409,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
@@ -634,9 +640,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();
index 1aa2020..64e8100 100644 (file)
@@ -67,14 +67,6 @@ prefix_ std::string senf::console::detail::ArgumentInfo<ParameterType>::defaultV
 // senf::console::ParsedCommandOverloadBase
 
 template <class Type>
-prefix_ senf::console::detail::ArgumentInfo<Type> &
-senf::console::ParsedCommandOverloadBase::arg(unsigned n)
-    const
-{
-    return dynamic_cast<detail::ArgumentInfo<Type> &>(arg(n));
-}
-
-template <class Type>
 prefix_ void senf::console::ParsedCommandOverloadBase::addParameter()
 {
     parameters_.push_back(detail::ArgumentInfo<Type>::create());
@@ -89,24 +81,6 @@ prefix_ void senf::console::ParsedCommandOverloadBase::addParameter()
 #include BOOST_PP_ITERATE()
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::ParsedCommandAttributorBase
-
-template <class Type>
-prefix_ void senf::console::ParsedCommandAttributorBase::defaultValue(Type const & value)
-    const
-{
-    overload().arg<Type>(index_).defaultValue = value;
-    overload().arg(index_).hasDefault = true;
-}
-
-template <class Type, class Fn>
-prefix_ void senf::console::ParsedCommandAttributorBase::parser(Fn fn)
-    const
-{
-    overload().arg<Type>(index_).parser = fn;
-}
-
-///////////////////////////////////////////////////////////////////////////
 // senf::console::ParsedCommandAttributor<Overload>
 
 template <class Overload>
@@ -306,7 +280,8 @@ prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 defaultValue(value_type const & value)
     const
 {
-    ParsedCommandAttributorBase::defaultValue<value_type>(value);
+    this->overload().arg<index>().defaultValue = value;
+    this->overload().arg(index).hasDefault = true;
 }
 
 template <class Overload, unsigned index, bool flag>
@@ -314,7 +289,7 @@ template <class Fn>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::parser(Fn fn)
     const
 {
-    ParsedCommandAttributorBase::parser<value_type>(fn);
+    this->overload().arg<index>().parser = fn;
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -324,8 +299,8 @@ template <class Overload, unsigned index>
 prefix_
 senf::console::ParsedArgumentAttributor<Overload, index, false>::
 ParsedArgumentAttributor(Overload & overload)
-    : ParsedArgumentAttributorBase< Overload, 
-                                     ParsedArgumentAttributor<Overload, index, false> > (overload, index)
+    : ParsedArgumentAttributorBase< 
+          Overload, ParsedArgumentAttributor<Overload, index, false> > (overload, index)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
index ba32137..af8dfe7 100644 (file)
@@ -137,15 +137,13 @@ namespace console {
         typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
 
         detail::ArgumentInfoBase & arg(unsigned n) const;
-        template <class Type> detail::ArgumentInfo<Type> & arg(unsigned n) const;
 
         void doc(std::string const & d);
 
     protected:
         ParsedCommandOverloadBase();
 
-        template <class Type>
-        void addParameter();
+        template <class Type> void addParameter();
 
     private:
         virtual unsigned v_numArguments() const;
@@ -212,14 +210,12 @@ namespace console {
 
         void argName(std::string const & name) const;
         void argDoc(std::string const & doc) const;
-        template <class Type> void defaultValue(Type const & value) const;
         void typeName(std::string const & doc) const;
         void defaultDoc(std::string const & doc) const;
 
         ParsedCommandOverloadBase & overload() const;
         void overloadDoc(std::string const & doc) const;
         void nodeDoc(std::string const & doc) const;
-        template <class Type, class Fn> void parser(Fn fn) const;
         
     private:
         ParsedCommandOverloadBase & overload_;
index c2d887b..d9c2610 100644 (file)
@@ -48,8 +48,12 @@ namespace console {
 
 namespace detail {
 
-#ifndef DOXYGEN
+    /** \brief Internal: Argument information structure
+        
+        This class is used to hold argument information for automatically parsed commands. 
 
+        \see ParsedCommandOverloadBase
+     */
     struct ArgumentInfoBase
         : public intrusive_refcount
     {
@@ -66,6 +70,12 @@ namespace detail {
         virtual std::string defaultValueStr() const = 0;
     };
     
+    /** \brief Internal: Argument information structure
+        
+        This class is used to hold argument information for automatically parsed commands. 
+
+        \see ParsedCommandOverloadBase
+     */
     template <class ParameterType>
     struct ArgumentInfo 
         : public ArgumentInfoBase
@@ -83,6 +93,8 @@ namespace detail {
         virtual std::string defaultValueStr() const;
     };
     
+#ifndef DOXYGEN
+
     // FirstArgType returns void, if the function has no arguments, otherwise it returns arg1_type
 
     template <class Traits, bool flag=(Traits::arity>0)>
index ede6974..a1c5e46 100644 (file)
@@ -38,6 +38,8 @@
 #include <boost/type_traits/remove_reference.hpp>
 #include <boost/type_traits/remove_const.hpp>
 #include <boost/bind.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/at.hpp>
 
 // ///////////////////////////mpp.p////////////////////////////////////////
 #elif BOOST_PP_IS_ITERATING // ////////////////////////////////////////////
 #define mpp_ArgTypeN(n) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(n)), _type)
 #define mpp_ArgN(n) BOOST_PP_CAT(arg, BOOST_PP_INC(n))
 
-#define mpp_ArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
-#define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
+#define mpp_TrailingArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
+#define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_TrailingArgTypes_, _ )
+
+#define mpp_ArgTypes_(z,n,d) mpp_ArgTypeN(n)
+#define mpp_ArgTypes() BOOST_PP_ENUM( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
 
 #define mpp_Args_(z,n,d) mpp_ArgN(n)
 #define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
@@ -80,10 +85,16 @@ public:
     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
 #   undef mpp_l
 
+    typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
+
     static ptr create(Function fn);
 
     void formatter(Formatter f);
 
+    using ParsedCommandOverloadBase::arg;
+    template <unsigned n>
+    detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
+
 protected:
 
 private:
@@ -112,8 +123,14 @@ public:
     BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
 #   undef mpp_l
 
+    typedef boost::mpl::vector< mpp_ArgTypes() > arg_types;
+
     static ptr create(Function fn);
 
+    using ParsedCommandOverloadBase::arg;
+    template <unsigned n>
+    detail::ArgumentInfo<typename boost::mpl::at_c<arg_types, n>::type> & arg() const;
+
 protected:
 
 private:
@@ -147,6 +164,20 @@ formatter(Formatter f)
 }
 
 template <class FunctionTraits, class ReturnValue>
+template <unsigned n>
+senf::console::detail::ArgumentInfo<
+    typename boost::mpl::at_c<
+        typename senf::console::ParsedCommandOverload<
+            FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::arg_types,
+        n>::type> &
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+arg() const
+{
+    return static_cast< detail::ArgumentInfo< 
+        typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
+}
+
+template <class FunctionTraits, class ReturnValue>
 prefix_
 senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
 ParsedCommandOverload(Function fn)
@@ -166,6 +197,20 @@ create(Function fn)
 }
 
 template <class FunctionTraits>
+template <unsigned n>
+senf::console::detail::ArgumentInfo<
+    typename boost::mpl::at_c<
+        typename senf::console::ParsedCommandOverload<
+            FunctionTraits, void, BOOST_PP_ITERATION()>::arg_types,
+        n>::type> &
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
+arg() const
+{
+    return static_cast< detail::ArgumentInfo< 
+        typename boost::mpl::at_c<arg_types, n>::type > & >(arg(n));
+}
+
+template <class FunctionTraits>
 prefix_
 senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
 ParsedCommandOverload(Function fn)
@@ -197,12 +242,12 @@ v_execute(std::ostream & os, ParseCommandInfo const & command)
     riterator const i_end (boost::rend(command.arguments()));
 
 #   define mpp_l(z,n,d)                                                                           \
-        mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue);                   \
+        mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
             if (i == i_end)                                                                       \
                 throw SyntaxErrorException("invalid number of arguments");                        \
-            if (arg< mpp_ArgTypeN(n) >(n).parser)                                                 \
-                arg< mpp_ArgTypeN(n) >(n).parser( *(i++), mpp_ArgN(n) );                          \
+            if (arg<n>().parser)                                                                  \
+                arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
             else                                                                                  \
                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
         }
@@ -233,12 +278,12 @@ v_execute(std::ostream & os, ParseCommandInfo const & command)
     riterator const i_end (boost::rend(command.arguments()));
 
 #   define mpp_l(z,n,d)                                                                           \
-        mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue);                   \
+        mpp_ArgTypeN(n) mpp_ArgN(n) (arg<n>().defaultValue);                                      \
         if (! arg(n).hasDefault || nDefaults-- <= 0) {                                            \
             if (i == i_end)                                                                       \
                 throw SyntaxErrorException("invalid number of arguments");                        \
-            if (arg< mpp_ArgTypeN(n) >(n).parser)                                                 \
-                arg< mpp_ArgTypeN(n) >(n).parser( *(i++), mpp_ArgN(n) );                          \
+            if (arg<n>().parser)                                                                  \
+                arg<n>().parser( *(i++), mpp_ArgN(n) );                                           \
             else                                                                                  \
                 ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );                  \
         }
index 2a3664f..d2ab881 100644 (file)
@@ -39,7 +39,7 @@ prefix_ typename senf::console::OwnerNodeCreateTraits<Owner,Object>::result_type
 senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNode & node,
                                                                     Owner & owner,
                                                                     std::string const & name,
-                                                                    Object const & ob)
+                                                                    Object & ob)
 {
     return senf_console_add_node(node, owner, name, ob, 0);
 }
@@ -59,6 +59,14 @@ template <class Object>
 prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::result_type
 senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object const & ob)
 {
+    return OwnerNodeCreateTraits<Owner, Object const>::Creator::create(node(), *owner_, name, ob);
+}
+
+template <class Owner>
+template <class Object>
+prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::result_type
+senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object & ob)
+{
     return OwnerNodeCreateTraits<Owner, Object>::Creator::create(node(), *owner_, name, ob);
 }
 
@@ -96,6 +104,13 @@ senf::console::ScopedDirectory<void>::add(std::string const & name, Object const
     return node().add(name, ob);
 }
 
+template <class Object>
+prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
+senf::console::ScopedDirectory<void>::add(std::string const & name, Object & ob)
+{
+    return node().add(name, ob);
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 91909b6..cd5b9b4 100644 (file)
@@ -49,7 +49,7 @@ namespace console {
                                       * static_cast<DirectoryNode *>(0),
                                       * static_cast<Owner *>(0),
                                       * static_cast<std::string const *>(0),
-                                      * static_cast<Object const *>(0),
+                                      * static_cast<Object *>(0),
                                       * static_cast<int *>(0)) ) base_type;
         typedef typename senf::remove_cvref<base_type>::type value_type;
 
@@ -59,7 +59,7 @@ namespace console {
         /// Internal
         struct Creator {
             static result_type create(DirectoryNode & node, Owner & owner, 
-                                     std::string const & name, Object const & ob);
+                                     std::string const & name, Object & ob);
         };
     };
     
@@ -157,6 +157,12 @@ namespace console {
                                              implementation just forwards the call to the proxied
                                              directory node. */
 
+        template <class Object>
+        typename OwnerNodeCreateTraits<Owner, Object>::result_type add(std::string const & name,
+                                                                       Object & ob);
+                                        ///< Create new child node
+                                        /**< \see add() */
+
     protected:
 
     private:
@@ -172,6 +178,10 @@ namespace console {
         template <class Object>
         typename NodeCreateTraits<Object>::result_type add(std::string const & name,
                                                            Object const & ob);
+
+        template <class Object>
+        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
+                                                           Object & ob);
     };
 
     template <class Owner, class Function>
index 2cdff1b..f074c5f 100644 (file)
@@ -73,32 +73,121 @@ prefix_ void senf::console::detail::SetVariable<Variable>::onChange(OnChangeHand
 }
 
 ///////////////////////////////////////////////////////////////////////////
+// senf::console::ConstVariableAttributor<Variable>
+
+template <class Variable>
+prefix_ senf::console::ConstVariableAttributor<Variable>
+senf::console::ConstVariableAttributor<Variable>::doc(std::string const & doc)
+{
+    queryOverload_.node().doc(doc);
+    return *this;
+}
+
+template <class Variable>
+prefix_ senf::console::ConstVariableAttributor<Variable>
+senf::console::ConstVariableAttributor<Variable>::formatter(Formatter formatter)
+{
+    queryOverload_.formatter(formatter);
+    return *this;
+}
+
+template <class Variable>
+prefix_ senf::console::ConstVariableAttributor<Variable>::
+ConstVariableAttributor(QueryOverload & queryOverload)
+    : queryOverload_ (queryOverload)
+{}
+
+///////////////////////////////////////////////////////////////////////////
 // senf::console::VariableAttributor<Variable>
 
 template <class Variable>
+prefix_ senf::console::VariableAttributor<Variable>
+senf::console::VariableAttributor<Variable>::parser(Parser parser)
+{
+    setOverload_.template arg<0>().parser = parser;
+    return *this;
+}
+
+template <class Variable>
+prefix_ senf::console::VariableAttributor<Variable>
+senf::console::VariableAttributor<Variable>::typeName(std::string const & name)
+{
+    setOverload_.arg(0).type = name;
+    return *this;
+}
+
+template <class Variable>
+prefix_ typename senf::console::VariableAttributor<Variable>
+senf::console::VariableAttributor<Variable>::doc(std::string const & doc)
+{
+    ConstVariableAttributor<Variable>::doc(doc);
+    return *this;
+}
+
+template <class Variable>
+prefix_ typename senf::console::VariableAttributor<Variable>
+senf::console::VariableAttributor<Variable>::formatter(Formatter formatter)
+{
+    ConstVariableAttributor<Variable>::formatter(formatter);
+    return *this;
+}
+
+template <class Variable>
 prefix_
 senf::console::VariableAttributor<Variable>::VariableAttributor(QueryOverload & queryOverload,
                                                                 SetOverload & setOverload)
-    : queryOverload_ (queryOverload), setOverload_ (setOverload)
+    : ConstVariableAttributor<Variable> (queryOverload), setOverload_ (setOverload)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
 
-template <class Variable>
+template <class Variable, bool isConst>
 prefix_ senf::console::VariableAttributor<Variable>
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     Variable * var, int)
+senf::console::detail::VariableNodeCreator<Variable,isConst>::add(DirectoryNode & node,
+                                                                  std::string const & name,
+                                                                  Variable & var)
 {
     typename VariableAttributor<Variable>::SetOverload & setOverload ( 
         node.add(name, typename detail::SetVariable<Variable>::Function(
-                     detail::SetVariable<Variable>(*var))).overload() );
+                     detail::SetVariable<Variable>(var)))
+            .arg("new_value")
+            .overload() );
     typename VariableAttributor<Variable>::QueryOverload & queryOverload ( 
         node.add(name, typename detail::QueryVariable<Variable>::Function(
-                     detail::QueryVariable<Variable>(*var))).overload() );
+                     detail::QueryVariable<Variable>(var))).overload() );
 
     return VariableAttributor<Variable>(queryOverload, setOverload);
 }
 
+template <class Variable>
+prefix_ senf::console::ConstVariableAttributor<Variable>
+senf::console::detail::VariableNodeCreator<Variable, true>::add(DirectoryNode & node,
+                                                                std::string const & name,
+                                                                Variable & var)
+{
+    typename VariableAttributor<Variable>::QueryOverload & queryOverload ( 
+        node.add(name, typename detail::QueryVariable<Variable>::Function(
+                     detail::QueryVariable<Variable>(var))).overload() );
+
+    return ConstVariableAttributor<Variable>(queryOverload);
+}
+
+template <class Variable>
+prefix_ senf::console::VariableAttributor<Variable> senf::console::
+senf_console_add_node(DirectoryNode & node, std::string const & name, Variable & var, int,
+                      typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type *)
+{
+    return detail::VariableNodeCreator<Variable>::add(node, name, var);
+}
+
+template <class Variable>
+prefix_ typename senf::console::detail::VariableNodeCreator<Variable>::result_type
+senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
+                                     boost::reference_wrapper<Variable> var, int)
+{
+    return detail::VariableNodeCreator<Variable>::add(node, name, var.get());
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 58924b2..5b1b728 100644 (file)
@@ -27,6 +27,9 @@
 #define HH_Variables_ 1
 
 // Custom includes
+#include <boost/utility.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/ref.hpp>
 #include "ParsedCommand.hh"
 
 #include "Variables.ih"
 namespace senf {
 namespace console {
 
+    class ScopedDirectoryBase;
+    template <class Variable> class VariableAttributor;
+
     template <class Variable>
-    class VariableAttributor
+    VariableAttributor<Variable> senf_console_add_node(
+        DirectoryNode & node, std::string const & name, Variable & var, int,
+        typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0);
+
+    template <class Variable>
+    typename detail::VariableNodeCreator<Variable>::result_type
+    senf_console_add_node(DirectoryNode & node, std::string const & name, 
+                          boost::reference_wrapper<Variable> var, int);
+
+    template <class Variable>
+    class ConstVariableAttributor
     {
     public:
-        typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
         typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
-
+        typedef typename QueryOverload::Formatter Formatter;
         typedef OverloadedCommandNode node_type;
-        typedef VariableAttributor return_type;
+        typedef ConstVariableAttributor return_type;
+
+        ConstVariableAttributor doc(std::string const & doc);
+        ConstVariableAttributor formatter(Formatter formatter);
 
     protected:
+        explicit ConstVariableAttributor(QueryOverload & queryOverload);
 
     private:
-        VariableAttributor(QueryOverload & queryOverload, SetOverload & setOverload);
-
         QueryOverload & queryOverload_;
-        SetOverload & setOverload_;
 
-#ifndef DOXYGEN
+        friend class detail::VariableNodeCreator<Variable const>;
+    };
+
+    template <class Variable>
+    class VariableAttributor
+        : public ConstVariableAttributor<Variable>
+    {
+    public:
+        typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
+        typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
+        typedef OverloadedCommandNode node_type;
+        typedef VariableAttributor return_type;
 
-        template <class V>
-        friend VariableAttributor<V> senf_console_add_node(DirectoryNode & node, 
-                                                           std::string const & name, 
-                                                           V * var, int);
+        typedef typename ConstVariableAttributor<Variable>::Formatter Formatter;
+        typedef typename ConstVariableAttributor<Variable>::QueryOverload QueryOverload;
 
-#endif
+        VariableAttributor parser(Parser parser);
+        VariableAttributor typeName(std::string const & name);
+        VariableAttributor doc(std::string const & doc);
+        VariableAttributor formatter(Formatter formatter);
+       
+    protected:
 
-    };
+    private:
+        VariableAttributor(QueryOverload & queryOverload, SetOverload & setOverload);
 
-    template <class Variable>
-    VariableAttributor<Variable> senf_console_add_node(DirectoryNode & node, 
-                                                       std::string const & name, 
-                                                       Variable * var, int);
+        SetOverload & setOverload_;
 
+        friend class detail::VariableNodeCreator<Variable>;
+    };
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////
index e1a2ce8..88b2207 100644 (file)
 
 // Custom includes
 #include <boost/function.hpp>
+#include <boost/type_traits/is_const.hpp>
 
 ///////////////////////////////ih.p////////////////////////////////////////
 
 namespace senf {
 namespace console {
+
+    template <class Variable> class ConstVariableAttributor;
+    template <class Variable> class VariableAttributor;
+
 namespace detail {
 
     template <class Variable>
@@ -66,6 +71,22 @@ namespace detail {
         OnChangeHandler handler_;
     };
 
+    template <class Variable, bool isConst=boost::is_const<Variable>::value>
+    struct VariableNodeCreator
+    {
+        typedef VariableAttributor<Variable> result_type;
+        static VariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
+                                                Variable & var);
+    };
+
+    template <class Variable>
+    struct VariableNodeCreator<Variable, true>
+    {
+        typedef ConstVariableAttributor<Variable> result_type;
+        static ConstVariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
+                                                     Variable & var);
+    };
+
 }}}
 
 ///////////////////////////////ih.e////////////////////////////////////////
index a190cea..6b1e315 100644 (file)
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+namespace {
+    void testParser(senf::console::ParseCommandInfo::TokensRange const &, int & value)
+    { value = 0; }
+
+    void testFormatter(int value, std::ostream & os)
+    { os << '[' << value << ']'; }
+}
+
 BOOST_AUTO_UNIT_TEST(variables)
 {
     senf::console::Executor executor;
@@ -50,12 +58,47 @@ BOOST_AUTO_UNIT_TEST(variables)
     int var (5);
 
     std::stringstream ss;
-    dir.add("var", &var);
+    dir.add("var", var)
+        .doc("Current blorg limit")
+        .formatter(&testFormatter)
+        .parser(&testParser)
+        .typeName("number");
     parser.parse("test/var; test/var 10; test/var",
                  boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
-    BOOST_CHECK_EQUAL( ss.str(), "5\n10\n" );
+    BOOST_CHECK_EQUAL( ss.str(), "[5]\n[0]\n" );
+
+    ss.str("");
+    dir("var").help(ss);
+    BOOST_CHECK_EQUAL(ss.str(), 
+                      "Usage:\n"
+                      "    1- var new_value:number\n"
+                      "    2- var\n"
+                      "\n"
+                      "Current blorg limit\n");
+
+    dir.add("refvar", boost::ref(var))
+        .doc("Current blorg limit")
+        .formatter(&testFormatter)
+        .parser(&testParser)
+        .typeName("number");
+
+    dir.add("crefvar", boost::cref(var))
+        .doc("Current blorg limit")
+        .formatter(&testFormatter);
 }
 
+#ifdef COMPILE_CHECK
+
+COMPILE_FAIL(constVariable)
+{
+    senf::console::ScopedDirectory<> dir;
+    int var;
+    dir.add("var", boost::cref(var))
+        .parser(&testParser);
+}
+
+#endif
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 81f38d3..34d3617 100644 (file)
@@ -64,7 +64,7 @@ def generate(env):
 
     builder = env.Builder(
         action = CompileCheck,
-        suffix = '.tsto',
+        suffix = '.checked',
         src_suffix = '.cc',
         source_scanner = SCons.Scanner.C.CScanner(),
         single_source=1