Utils/Console: New add() API documentation updates
g0dil [Mon, 3 May 2010 15:33:42 +0000 (15:33 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1615 270642c3-0616-0410-b53a-bc976706d245

senf/Utils/Console/Mainpage.dox
senf/Utils/Console/Node.hh
senf/Utils/Console/ParsedCommand.hh
senf/Utils/Console/ScopedDirectory.hh
senf/Utils/Console/Utility.hh
senf/Utils/Console/Variables.hh
tools/doxygrep [new file with mode: 0755]

index 4177e2f..9b25f2e 100644 (file)
@@ -65,6 +65,7 @@
     }
 
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
     int main(int argc, char** argv)
     {
             .doc("This is someServer server");
 
         // Add a command
-        senf::console::root()
-            .add("mycommand", &mycommand)
+        senf::console::root().add("mycommand", fty::Command(&mycommand)
             .doc("If <bar> is given, flurgle the <foo>, otherwise burgle it")
             .arg("foo")
-            .arg(kw::name = "bar", kw::default_value = 0);
+            .arg(kw::name = "bar", kw::default_value = 0) );
 
        // Parse command line parameters
        senf::console::parseOptions(argc,argv);
     parsing.
 
     \code
-    // Create a console/config aware object and place it into the node tree
+    // Create a console/config aware object and place it (that is it's directory node) into the node
+    // tree
     FooObject foo;
     senf::console::root().add("foo", foo.dir);
 
 /** \defgroup console_commands Supported command types
 
     The Console/config library supports quite a number of different command types. All these types
-    of command are registered, by passing them to DirectoryNode::add()
+    of command are registered by passing an appropriate factory instance to DirectoryNode::add()
 
     \autotoc
 
 
     \section console_cmdadd Adding commands and setting attributes
 
-    Basically, all commands are added using senf::console::DirectoryNode::add(). What exactly
-    happens depends on the type of object added.
+    Basically, all commands are added using senf::console::DirectoryNode::add().
     \code
-    dir.add("name", callback)
+    namespace fty = senf::console::factory;
+    dir.add("name", fty::Command(callback));
     \endcode
-    will add a command 'name' which will execute 'callback' when called, where 'callback' can be a
-    lot of things as documented in the following chapters.
+    will add the command 'name' which will execute 'callback' when called.
 
     The add call always returns (something which can be used as) a reference to the command node
     added:
     (e.g. senf::console::SimpleCommand) if you know the type of node returned.
 
     Depending on the type of object added, there are additional attributes which can be set. These
-    attributes are always set by calling them on the return value <b>before saving that value as a
-    node reference</b>. It is \e not guaranteed, you can call these members on the node
-    reference.
-    \code
-    dir.add("name", callback)
-        .doc("The documentation");
-    \endcode
-    sets the \e doc attribute (if that is available, otherwise this will fail to compile). The
-    attribute members return value is again (something which can be used as) a reference to the
-    command node
+    attributes are always set by calling them on the factory return value. It is \e not guaranteed,
+    you can call these members on the node reference returned by the \c add() call.
     \code
-    senf::console::CommandNode & node (
-        dir.add("name", callback)
-            .doc("The documentation") );
+    namespace fty = senf::console::factory;
+    dir.add("name", fty::Command(callback)
+        .doc("The documentation") );
     \endcode
+    sets the \e doc attribute (if that is available, otherwise this will fail to compile).
 
 
     \section console_manualparse Manually parsing command arguments
     Registering this callback is done by simply adding it. To provide online help, pass it to
     'doc()':
     \code
-    senf::console::root()
-        .add("test1", &fun1)
+    namespace fty = senf::console::factory;
+    senf::console::root().add("test1", fty::Command(&fun1)
         .doc("Usage:\n"
              "    test1 arg\n"
              "\n"
-             "Echo 'arg' to the console");
+             "Echo 'arg' to the console") );
     \endcode
 
     The callback may now be called interactively on the console by it's registered name:
 
     This extremely simple callback may be registered by adding it to a senf::console::DirectoryNode.
     \code
-    senf::console::root()
-        .add("test2", &fun2);
+    namespace fty = senf::console::factory;
+    senf::console::root().add("test2", fty::Command(&fun2));
     \endcode
     The functionality is now identical to \c test1:
     \htmlonly
     passed the current consoles output stream object in this argument. With this, the callback can
     output arbitrary messages to the network console.
     \code
+    namespace fty = senf::console::factory;
+
     void fun3(std::ostream & os, unsigned n, std::string text)
     {
         while (n-- > 0) os << text << std::endl;
     }
 
-    senf::console::root()
-        .add("test3", &fun3);
+    senf::console::root().add("test3", fty::Command(&fun3));
     \endcode
 
     This simple command can now be used thus:
     Automatically parsed commands can be overloaded: You can register multiple commands under the
     same name. Each overload is tried in turn until no SyntaxErrorException is raised.
     \code
-    senf::console::root()
-        .add("test4", &fun3);
-    senf::console::root()
-        .add("test4", &fun2);
+    namespace fty = senf::console::factory;
+
+    senf::console::root().add("test4", fty::Command(&fun3));
+    senf::console::root().add("test4", fty::Command(&fun2));
     \endcode
     And now, we can call \c test4 with one or two args:
     <pre>
     Utils/membind.hh to simplify this:
 
     \code
+    namespace fty = senf::console::factory;
+
     void over(int);
     void over(int,int);
 
-    senf::console::root()
-        .add("over", SENF_FNP(void, over, (int)));
-    senf::console::root()
-        .add("over", SENF_FNP(void, over, (int,int));
+    senf::console::root().add("over", fty::Command(SENF_FNP(void, over, (int))));
+    senf::console::root().add("over", fty::Command(SENF_FNP(void, over, (int,int)));
 
     class SomeModule {
       senf::console::ScopedDirectory<SomeModule> dir;
       void overlodedMethod(unsigned int)   {....};
 
       void addConsoleCommands() {
-        dir.node().add("overlodedMethod",
-                       SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, () const));
-        dir.node().add("overlodedMethod",
-                       SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, (unsigned int));
+        dir.node()
+            .add("overlodedMethod", fty::Command(
+                     SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, () const)));
+        dir.node()
+            .add("overlodedMethod", fty::Command(
+                     SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, (unsigned int))));
       }
     }
     \endcode
     As have seen so far, some documentation is automatically provided. We can add more info, by
     setting additional attributes.
     \code
-    senf::console::root()
-        .add("test5", &fun3)
+    namespace fty = senf::console::factory;
+
+    senf::console::root().add("test5", fty::Command(&fun3)
         .doc("Echo text to the console")
-        .overloadDoc("Repeat {arg12} for {arg11} lines");
-    senf::console::root()
-        .add("test4", &fun2)
-        .overloadDoc("Echo the {arg21} argument")
+        .overloadDoc("Repeat {arg12} for {arg11} lines") );
+    senf::console::root().add("test4", fty::Command(&fun2)
+        .overloadDoc("Echo the {arg21} argument") );
     \endcode
 
     This additional info is used to provide more documentation:
 
     \code
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    senf::console::root()
-        .add("test6", &fun3)
+    senf::console::root().add("test6", fty::Command(&fun3)
         .doc("Echo text to the console")
         .overloadDoc("Repeat {text} for {n} lines");
         .arg( kw::name = "n", kw::description="Number of repetitions" )
-        .arg( kw::name = "text", kw::description="Text to output" );
-    senf::console::root()
-        .add("test6", &fun2)
+        .arg( kw::name = "text", kw::description="Text to output" ) );
+    senf::console::root().add("test6", fty::Command(&fun2)
         .overloadDoc("Echo the {text} argument")
-        .arg( kw::name = "text" );
+        .arg( kw::name = "text" ) );
     \endcode
 
     (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
     order. So the following will give the exactly same result as above:
     \code
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    senf::console::root()
-        .add("test6", &fun3)
+    senf::console::root().add("test6", fty::Command(&fun3)
         .doc("Echo text to the console")
         .overloadDoc("Repeat <text> for <n> lines");
         .arg("n",    "Number of repetitions")
-        .arg("text", "Text to output");
-    senf::console::root()
-        .add("test6", &fun2)
-        .overloadDoc("Echo the <text> argument")
+        .arg("text", "Text to output") );
+    senf::console::root().add("test6", fty::Command(&fun2)
+        .overloadDoc("Echo the <text> argument") );
         .arg("text");
     \endcode
 
     values. These have to be declared explicitly:
     \code
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    senf::console::root()
-        .add("test7", &fun3)
+    senf::console::root().add("test7", fty::Command(&fun3)
         .doc("Echo {text} to the console, repeating {text} for {n} lines")
         .arg("n",    "Number of repetitions", kw::default_value=1)
-        .arg("text", "Text to output");
+        .arg("text", "Text to output") );
     \endcode
 
     Default values can be used together with overloading. Default (optional) value support is quite
 
     It is possible to add other callable objects besides function (and member-function)
     pointers. However, since it is not possible to automatically deduce the argument and return
-    types in this case, the callables have to be wrapped in a \c boost::function object:
-
+    types in this case, the signature has to be specified explicitly:
     \code
+    namespace fty = senf::console::factory;
+
     senf::console::root()
-        .add("test8",
-             boost::function<void (std::ostream &, std::string const &)>(
-                 boost::bind(&fun3, _1, 4u, _2)));
+        .add("test8",fty::Command<void (std::ostream &, std::string const &)>(
+                         boost::bind(&fun3, _1, 4u, _2)));
     \endcode
 
     This works with any callable object where argument types cannot be deduced automatically:
     identical to non-members). They must however be added through a senf::console::ScopedDirectory
     instance to bind them to their instance.
     \code
+    namespace fty = senf::console::factory;
+
     class Test1
     {
     public:
         senf::console::ScopedDirectory<Test1> dir;
 
         Test1(std::string label) : dir(this), label_ (label)
-            { dir.add("test", &Test::test1);
-              dir.add("test", &Test::test2); }
+            { dir.add("test", fty::Command(&Test::test1, this));
+              dir.add("test", fty::Command(&Test::test2, this)); }
 
         std::string test1(std::string const & text)
             { return label_ + ": " + text; }
     variable command consists of two overloads, one to query the current value and one to change the
     value.
     \code
+    namespace fty = senf::console::factory;
+
     class Test2
     {
     public:
         senf::console::ScopedDirectory<Test2> dir;
 
         Test2() : dir(this), var_(0)
-            { dir.add("var", var_); }
+            { dir.add("var", fty::Variabl(var_) ); }
 
     private:
         int var_;
     The library also supports read-only variables. To make a variable read-only, just wrap it in \c
     boost::cref() (where \c cref stands for \c const reference)
     \code
+    namespace fty = senf::console::factory;
+
     int var (0);
 
-    senf::console::root().add("var1", boost::cref(var));
+    senf::console::root().add("var1", fty::Variable(boost::cref(var)));
     \endcode
     A read-only variable only has a single overload:
     \htmlonly
     reference to the old value. The handler is called, after the value has been changed
 
     \code
+    namespace fty = senf::console::factory;
+
     int var (0);
 
     // Since this is int, it would make sense to declare the argument pass-by-value (int old)
         // ...
     }
 
-    senf::console::root().add("var2",var)
-        .onChange(&varChanged);
+    senf::console::root().add("var2", fty::Variable(var)
+        .onChange(&varChanged) );
     \endcode
 
     After this setup, \c varChanged will be called, whenever the value has changed.
     Enum types are a special case, since it is not possible, to find a string representation for the
     enumerator values automatically. Therefore, enum types need to be registered manually.
     \code
+    namespace fty = senf::console::factory;
+
     enum MyEnum { Sit, Run, Jump };
     SENF_CONSOLE_REGISTER_ENUM( MyEnum, (Sit)(Run)(Jump) );
 
     MyEnum fun4(MyEnum v) { return v }
 
-    senf::console::root()
-        .add("test9", &fun4);
+    senf::console::root().add("test9", fty::Command(&fun4));
     \endcode
 
     After an enum type is registered, it can be used like any other type for arguments or
     register enums defined within some class, use \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER()
 
     \code
+    namespace fty = senf::console::factory;
+
     class Test3
     {
     public:
     SENF_CONSOLE_REGISTER_ENUM_MEMBER( Test3, Color, (Red)(Green)(Blue) );
 
     Test3::Test3() : dir(this)
-        { dir.add("test", &Test3::mem3); }
+        { dir.add("test", fty::Command(&Test3::mem3, this)); }
 
     Test3 test3ob;
     senf::console::root().add("test3ob", test3ob.dir);
     \subsection console_args_convert Handling argument types by conversion
 
     Sometimes an argument type is best handled by just pretending it to be of some other type. The
-    basic idea is, to us \c boost::function to convert the real argument type to some different type
+    basic idea is, to provide an explicit signature with different (but compatible) types to the
+    factory:
 
     \code
+    namespace fty = senf::console::factory;
+
     int fun4(int value)
     {
         return value;
     }
 
     senf::console::root()
-        .add("test8", boost::function<bool (bool)>(&fun4));
+        .add("test8", fty::Command<bool (bool)>(&fun4));
     \endcode
 
-    Here, the type signature specified via \c boost::function is different from the real type
-    signature but is compatible. \c boost::function automatically handles the conversion
-    process. Since the console library now sees the argument and return value of type \c bool,
-    the values will be parsed and formatted as boolean values.
+    Here, the type signature passed to fty::Command is different from the real type signature but it
+    is compatible, the conversion is handled automatically. Since the console library now sees the
+    argument and return value of type \c bool, the values will be parsed and formatted as boolean
+    values.
 
 
     \subsection console_args_special Special Console types
     The formatter writes out the value as a parenthesized pair.
 
     \code
+    namespace fty = senf::console::factory;
+
     Coordinate fun5(Coordinate const & p) { return Coordinate(2*p.x, 2*p.y) }
 
     namespace kw = senf::console::kw;
 
     senf::console::root()
-        .add("test10", &fun5)
+        .add("test10", fty::Command(&fun5))
         .arg("x","coordinate to double",
              kw::default_value = Coordinate())
     \endcode
index 5765dd6..286f516 100644 (file)
@@ -58,7 +58,7 @@
             dir.doc("Manager for something");
 
             // Add a member function (the pointer-to-member is automatically bound to this instance)
-            dir.add("member", fty::Command(this, &SomeClass::member)
+            dir.add("member", fty::Command(&SomeClass::member, this)
                 .doc("Do the member operation"));
         }
 
     \code
     void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
     // ...
-    myDirectory.add("foo",&callback);
+    myDirectory.add("foo",fty::Command(&callback));
     \endcode
 
     Every node is identified among it's siblings by it's name. The name of the node is set when
     Depending on the node type added, additional node parameters may be set. For example, every node
     has a documentation parameter which is used by the online-help system. To assign these
     parameters, the node exposes corresponding member functions. Since
-    senf::console::DirectoryNode::add() returns the newly added node by reference, additional
-    parameters may just be added to the end of the add command:
+    senf::console::DirectoryNode::add() returns the newly added node by reference. Additional
+    parameters may be added after the factory call:
     \code
-    myDirectory.add("foo",&fooCallback).doc("The foo method");
+    myDirectory.add("foo", fty::Command(&fooCallback).doc("The foo method") );
     \endcode
     Since the parameter setters all return the node reference, additional parameters may just be
     added to the end of the command.
@@ -387,8 +387,8 @@ namespace console {
         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
         children and supports directory traversal.
 
-        Nodes are normally not instantiated manually but are created by the DirectoryNode via
-        mkdir() or add(). Special add() members however allow externally allocated node objects.
+        Nodes are normally not instantiated manually but are created using factory calls. Special
+        add() members however allow externally allocated node objects.
 
         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
         managed dynamically, there is a special ScopedDirectory proxy template which provides a
index 753bd83..6c443ba 100644 (file)
@@ -64,12 +64,13 @@ namespace console {
 
         \section overload_add Adding argument parsing callbacks to the tree
 
-        Adding appropriate callbacks to the tree is very simple: just path a function pointer to
-        DirectoryNode::add() or a member function pointer to ScopedDirectory::add().
+        To add overloads to the tree, use the senf::console::factory::Command factory:
         \code
+        namespace fty = senf::console::factory;
+
         std::string taskStatus(int id);
 
-        senf::console::root().add("taskStatus", &taskStatus);
+        senf::console::root().add("taskStatus", fty::Command(&taskStatus));
         \endcode
 
         There are quite a number of additional parameters available to be set. These parameters are
@@ -77,11 +78,11 @@ namespace console {
         calls after adding the node:
 
         \code
-        senf::console::root().add("taskStatus", &taskStatus)
+        senf::console::root().add("taskStatus", fty::Command(&taskStatus)
             .doc("Query the current task status")
             .arg( name = "id",
                   description = "numeric id of task to check, -1 for the current task."
-                  default_value = -1 );
+                  default_value = -1 ) );
         \endcode
 
         You may also add an additional \c std::ostream & Argument as first argument to the
@@ -95,17 +96,19 @@ namespace console {
         std::string taskStatus(std::string const & name);
 
         senf::console::root()
-            .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
+            .add("taskStatus", fty::Command(static_cast<std::string (*)(int)>(
+                                                &taskStatus))
             .doc("Query the current task status")
             .overloadDoc("Query status by id")
             .arg( name = "id",
                   description = "numeric id of task to check, -1 for the current task."
-                  default_value = -1 );
+                  default_value = -1 ) );
         senf::console::root()
-            .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
+            .add("taskStatus", fty::Commande(static_cast<std::string (*)(std::string const &)>(
+                                                 &taskStatus))
             .overloadDoc("Query status by name")
             .arg( name = "name",
-                  description = "name of task to check" );
+                  description = "name of task to check" ) );
         \endcode
 
         We can see here, that taking the address of an overloaded function requires a cast. If you
@@ -262,19 +265,21 @@ namespace console {
 
         For the keyword tags, the standard C++ scoping rules apply
         \code
+        namespace fty=senf::console::factory;
+
         // Either qualify them with their complete namespace
-        dir.add(...)
-            .arg( senf::console::kw::name = "name" );
+        dir.add(..., fty::Command(...)
+            .arg( senf::console::kw::name = "name" ) );
 
         // Or use a namespace alias
         namespace kw = senf::console::kw;
-        dir.add(...)
-            .arg( kw::name = "name" );
+        dir.add(..., fty::Command(...)
+            .arg( kw::name = "name" ) );
 
         // Or import the keywords into the current namespace (beware of name collisions)
         using namespace senf::console::kw;
-        dir.add(...)
-            .arg( name = "name" );
+        dir.add(..., fty::Command(...)
+            .arg( name = "name" ) );
         \endcode
 
         The second alternative is preferred, the <tt>using namespace</tt> directive may be used as
@@ -288,12 +293,12 @@ namespace console {
         \code
         void command(int);
 
-        dir.add("command", &command)
+        dir.add("command", fty::Command(&command)
             .arg( kw::name          = "name",
                   kw::description   = "description",
                   kw::default_value = 1,
                   kw::type_name     = "type_name",
-                  kw::default_doc   = "default_doc" );
+                  kw::default_doc   = "default_doc" ) );
         \endcode
         Will create the following documentation:
         \htmlonly
index 2b298f9..e5f1248 100644 (file)
@@ -96,7 +96,7 @@ namespace console {
 
             MyClass() : configDir(this)
             {
-                configDIr.add(...);
+                configDir.add(...);
             }
         };
         \endcode
index 6cf2433..e13c248 100644 (file)
@@ -53,7 +53,7 @@ namespace console {
         char foo(char v) { return v; }
 
         senf::console::root().add(
-            "foo", boost::function< CharAsString<char> (CharAsString<char>) >(&foo));
+            "foo", fty::Command< CharAsString<char> (CharAsString<char>) >(&foo));
         \endcode
 
         \tparam CharT character type, one of \c char, \c signed \c char or \c unsigned \c char
@@ -146,7 +146,7 @@ namespace console {
         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));
+        consoleDir.add("func", fty::Command<void (FlagCollection<MyFlags>)>(&func));
         \endcode
 
         To use the FlagCollection class
index de9da46..a732b41 100644 (file)
@@ -82,7 +82,7 @@ namespace factory {
             int var;
             ScopedDirectory<> dir;
 
-        dir.add("var", var);
+        dir.add("var", fty::Variable(var));
         \endcode
 
         Variables should be registered only with a ScopedDirectory declared in the same scope
@@ -97,7 +97,7 @@ namespace factory {
         boost::cref(). Such a variable cannot be changed only queried. Therefore, it does not have
         the parser() and typeName() attributes.
         \code
-            dir.add("const_var", boost::cref(var))
+            dir.add("const_var", fty::Variable(boost::cref(var)));
         \endcode
 
         \ingroup console_commands
diff --git a/tools/doxygrep b/tools/doxygrep
new file mode 100755 (executable)
index 0000000..9928bfc
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/perl -0777n
+
+BEGIN { 
+    $re = shift;
+    if (! $re) {
+       print STDERR 
+           "Usage: doxygrep <re> [<file>...]\n".
+           "\n".
+           "Greps for <re> only within doxygen comments in [files] or stdin\n";
+       exit(1);
+    }
+}
+
+while(m{/\*\*<?(.*?)\*/|///<?(.*?)$}smg) {
+    $t=$1||$2;
+    $pre=$`;
+    $post=$'; #';
+    while ($t=~/$re/mg) {
+       $ppre=$pre.$`;
+       $ppost=$'.$post; #';
+       ($tt = $&.$ppost)=~s/\n.*$//s;
+       $n = ($ppre =~ tr{\n}{\n})+1;
+       $ppre =~ s/^.*\n//s;
+       $m = length($ppre);
+       print "$ARGV:$n:$m:$ppre$tt\n";
+    }
+}