Move debian and documentation specific parts of SConstruct into SConscript files
[senf.git] / Utils / Console / Traits.hh
index f7fa1e4..da5eb60 100644 (file)
@@ -29,6 +29,7 @@
 // Custom includes
 #include <iostream>
 #include <boost/intrusive_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
 #include "../../Utils/intrusive_refcount.hh"
 #include "Parse.hh"
 #include "Node.hh"
@@ -94,6 +95,12 @@ namespace console {
     {
         typedef Type type;
 
+        static bool const singleToken = 
+            boost::is_same< typeof(senf_console_parse_argument(
+                                       *static_cast<ParseCommandInfo::TokensRange const *>(0),
+                                       *static_cast<Type*>(0))),
+                            bool >::value;
+
         static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out);
                                         ///< Parse token range into value
                                         /**< This function needs to parse \a tokens and write the
@@ -121,7 +128,7 @@ namespace console {
         \related ArgumentTraits
      */
     template <class Type>
-    void senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out);
+    bool senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out);
 
     /** \brief Parse token range
 
@@ -143,6 +150,7 @@ namespace console {
     struct ArgumentTraits<bool>
     {
         typedef bool type;
+        static bool const singleToken = true;
 
         static void parse(ParseCommandInfo::TokensRange const & tokens, bool & out);
         static std::string description();
@@ -184,6 +192,10 @@ namespace console {
         This macro will register an enum type and it's enumerators defined at namespace scope. See
         \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER to register a member enum type.
 
+        \note All enumerator values must be unique ignoring case.
+
+        The enum parser will accept any unique initial substring ignoring case as valid enum value.
+
         \ingroup console_commands
      */
 #   define SENF_CONSOLE_REGISTER_ENUM(Type, Values) \
@@ -207,6 +219,73 @@ namespace console {
 #   define SENF_CONSOLE_REGISTER_ENUM_MEMBER(Class, Type, Values) \
         SENF_CONSOLE_REGISTER_ENUM_(Class::, Type, Values)
 
+    /** \brief Bit-mask flag argument type
+
+        senf::console::FlagCollection supplies a special argument type for use in registering
+        console commands. This argument type is used to represent a bit-mask of single flags. 
+
+        \code
+        // Function taking a flags argument
+        void func(unsigned flags);
+
+        // Enum containing all the possible flag values
+        enum MyFlags { Foo = 1,
+                     Bar = 2,
+                     Baz = 4,
+                     Doo = 8 };
+        SENF_CONSOLE_REGISTER_ENUM(MyFlags, (Foo)(Bar)(Baz)(Boo));
+        
+        // Register the function with a FlagCollection argument type
+        consoleDir.add("func", boost::function<void (FlagCollection<MyFlags>)>(&func));
+        \endcode
+
+        To use the FlagCollection class
+        \li you need a function which takes a bit-mask of flags as argument
+        \li you define and register an enum with all possible flag values
+        \li you register the function with a FlagCollection argument type using \c boost::function
+            for the conversion. This is also possible for return values.
+
+        The nice thing is, that \c boot::function supports compatible argument types and does
+        automatic type conversion. Since a FlagCollection is convertible to and from unsigned long,
+        this conversion will work. 
+
+        After registering this function, you can call it with a collection of flags as argument
+
+        <pre>
+        console:/$ help func
+        Usage:
+            func arg11:MyFlags
+        console:/$ func Foo
+        console:/$ func (Foo Boo)
+        </pre>
+     */
+    template <class Enum>
+    struct FlagCollection
+    {
+        operator unsigned long() const { return value; }
+        FlagCollection() : value (0) {}
+        FlagCollection(unsigned long value_) : value (value_) {}
+        FlagCollection(Enum value_) : value (value_) {}
+        unsigned long value;
+    };
+
+    template <class Enum>
+    struct ArgumentTraits< FlagCollection<Enum> >
+    {
+        typedef FlagCollection<Enum> type;
+        static bool const singleToken = false;
+        static void parse(ParseCommandInfo::TokensRange const & tokens, type & out);
+        static std::string description();
+        static std::string str(type const & value);
+    };
+
+    template <class Enum>
+    struct ReturnValueTraits< FlagCollection<Enum> >
+    {
+        typedef FlagCollection<Enum> type;
+        static void format(type const & value, std::ostream & os);
+    };
+
 }}
 
 ///////////////////////////////hh.e////////////////////////////////////////