Console: Implement keyword arguments for 'arg'
[senf.git] / Console / ParsedCommand.hh
index b2fca48..14d63a0 100644 (file)
@@ -33,6 +33,8 @@
 #include <boost/type_traits/is_same.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/utility.hpp>
+#include <boost/parameter/keyword.hpp>
+#include <boost/parameter/parameters.hpp>
 #include "../config.hh"
 #include "OverloadedCommand.hh"
 #include "ParseParameter.hh"
@@ -51,20 +53,25 @@ namespace console {
     public:
         typedef boost::intrusive_ptr<ParsedCommandOverloadBase> ptr;
 
-    protected:
-        ParsedCommandOverloadBase();
-
         detail::ParameterInfoBase & arg(unsigned n) const;
         template <class Type> detail::ParameterInfo<Type> & arg(unsigned n) const;
 
+        void doc(std::string const & d);
+
+    protected:
+        ParsedCommandOverloadBase();
+
         template <class Type>
         void addParameter();
 
     private:
-        virtual void v_help(std::ostream & os) const;
+        virtual unsigned v_numArguments() const;
+        virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const;
+        virtual std::string v_doc() const;
 
         typedef std::vector<detail::ParameterInfoBase::ptr> Parameters;
         Parameters parameters_;
+        std::string doc_;
     };
 
     template <class FunctionTraits, unsigned arity=FunctionTraits::arity>
@@ -75,17 +82,167 @@ namespace console {
                                             1))
 #   include BOOST_PP_ITERATE()
 
+    class ParsedCommandAttributorBase
+    {
+    public:
+        OverloadedCommandNode & node() const;
+        operator OverloadedCommandNode & () const;
+
+    protected:
+        ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
+
+        void argName(std::string const & name) const;
+        void argDoc(std::string const & doc) const;
+        template <class Type> void defaultValue(Type const & value) const;
+
+        ParsedCommandOverloadBase & overload() const;
+        void overloadDoc(std::string const & doc) const;
+
+        void nodeDoc(std::string const & doc) const;
+        
+    private:
+        ParsedCommandOverloadBase & overload_;
+        unsigned index_;
+    };
+
+    template <class Overload>
+    class ParsedCommandAttributor
+        : public ParsedCommandAttributorBase
+    {
+    public:
+        Overload & overload() const;
+
+    protected:
+        ParsedCommandAttributor(Overload & overload, unsigned index);
+
+    private:
+    };
+    
+    namespace tag {
+        BOOST_PARAMETER_KEYWORD(detail, name_);
+        BOOST_PARAMETER_KEYWORD(detail, description_);
+        BOOST_PARAMETER_KEYWORD(detail, default_value_);
+    }
+
+    template <class Overload, class Self>
+    class ParsedAttributeAttributorBase
+        : public ParsedCommandAttributor<Overload>
+    {
+    public:
+        Self doc(std::string const & doc) const;
+        Self overloadDoc(std::string const & doc) const;
+
+    protected:
+        ParsedAttributeAttributorBase(Overload & overload, unsigned index);
+
+    private:
+    };
+
+    template < class Overload, 
+               unsigned index=0, 
+               bool flag=(index < unsigned(Overload::traits::arity)) >
+    class ParsedAttributeAttributor
+        : public ParsedAttributeAttributorBase< Overload, 
+                                                ParsedAttributeAttributor<Overload, index, flag> >
+    {
+    public:
+        typedef typename senf::function_traits_arg_type< 
+            typename Overload::traits, int(index) >::type arg_type;
+        typedef typename senf::remove_cvref< arg_type >::type value_type;
+        typedef ParsedAttributeAttributor<Overload, index+1> next_type;
+
+        typedef OverloadedCommandNode node_type;
+        typedef ParsedAttributeAttributor return_type;
+
+        typedef boost::parameter::parameters<
+            tag::detail::name_,
+            tag::detail::description_,
+            tag::detail::default_value_> arg_params;
+
+        next_type arg() const;
+
+#       define BOOST_PP_ITERATION_PARAMS_1 \
+            (4, (1, 3, SENF_ABSOLUTE_INCLUDE_PATH(Console/ParsedCommand.mpp), 5))
+#       include BOOST_PP_ITERATE()
+
+    private:
+        explicit ParsedAttributeAttributor(Overload & overload);
+
+        template <class ArgumentPack>
+        next_type argInfo(ArgumentPack const & args) const;
+
+        template <class ArgumentPack>
+        next_type argInfo(ArgumentPack const & args, boost::mpl::true_) const;
+        template <class ArgumentPack>
+        next_type argInfo(ArgumentPack const & args, boost::mpl::false_) const;
+
+        next_type argInfo(std::string const & name, std::string const & doc) const;
+        next_type argInfo(std::string const & name, std::string const & doc,
+                          value_type const & value) const;
+
+        ParsedAttributeAttributor<Overload, index+1> next() const;
+
+        void defaultValue(value_type const & value) const;
+
+        template <class O, unsigned i, bool f>
+        friend class ParsedAttributeAttributor;
+        
+        template <class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
+        
+        template <class Owner, class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
+                              Function fn, int,
+                              typename boost::enable_if_c<
+                                  detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+    };
+
+    template <class Overload, unsigned index>
+    class ParsedAttributeAttributor<Overload, index, false>
+        : public ParsedCommandAttributor< Overload >
+    {
+    public:
+        typedef OverloadedCommandNode node_type;
+        typedef ParsedAttributeAttributor return_type;
+
+    private:
+        explicit ParsedAttributeAttributor(Overload & overload);
+
+        template <class O, unsigned i, bool f>
+        friend class ParsedAttributeAttributor;
+        
+        template <class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
+        
+        template <class Owner, class Function>
+        friend ParsedAttributeAttributor<
+            ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
+        senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
+                              Function fn, int,
+                              typename boost::enable_if_c<
+                                  detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+    };
+
 #ifndef DOXYGEN
 
     template <class Function>
-    ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> &
+    ParsedAttributeAttributor<
+        ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
     senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int);
 
     template <class Owner, class Function>
-    ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> &
+    ParsedAttributeAttributor<
+        ParsedCommandOverload<typename detail::ParsedCommandTraits<Function>::traits> >
     senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
                           Function fn, int,
-                          typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+                          typename boost::enable_if_c<
+                              detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
 
 #endif
 
@@ -94,6 +251,7 @@ namespace console {
 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
 
 BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
+BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedAttributeAttributor, (class, unsigned, bool))
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
 
 ///////////////////////////////hh.e////////////////////////////////////////