Console: More extensible keyword parameter dispatching in arg() attribute
[senf.git] / Console / Mainpage.dox
index 9c0ea9a..b63300e 100644 (file)
@@ -42,6 +42,7 @@
     To get started using the config/console library, see
     \li \ref node_tree
     \li \ref console_parser
+    \li \ref console_commands
 
     \section console_example Example
 
     </pre>
  */
 
+/** \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()
+
+    \autotoc
+
+    \section console_manualparse Manually parsing command arguments
+
+    This is the most primitive type of command. It will be called with an output stream and with a
+    senf::console::ParseCommandInfo reference which holds information about the command parsed.
+
+    From this information the command callback gets a list of arguments or tokens which then can be
+    interpreted in an arbitrary way.
+    \code
+    void test1(std::ostream & os, senf::console::ParseCommandInfo const & command)
+    {
+        // We take exactly one argument
+        if (command.arguments().size() != 1) 
+            raise senf::console::SyntaxErrorException("invalid number of arguments");
+
+        senf::console::ParseCommandInfo::TokenRange & argTokens (
+            command.arguments()[0]);
+
+        // The argument must have exactly one token
+        if (argTokens.size() != 1)
+            raise senf::console::SyntaxErrorException("argument syntax error");
+
+        // Retrieve the token value
+        std::string arg (argTokens[0].value());
+
+        // In this example, we just write the argument to the output stream
+        os << arg << std::endl;
+    }
+    \endcode
+    
+    Registering this callback is done by simply adding it. To provide online help, pass it to
+    'doc()':
+    \code
+    senf::console::root()
+        .add("test1", &test1)
+        .doc("Usage:\n"
+             "    test1 arg\n"
+             "\n"
+             "Echo 'arg' to the console");
+    \endcode
+
+    The callback may now be called interactively on the console by it's registered name:
+    \htmlonly
+    <pre>
+    server:/$ test1
+    invalid number of arguments
+    server:/$ test1 stefan@j32.de
+    stefan@j32.de
+    server:/$ test1 (echo me)
+    argument syntax error
+    server:/$ help test1
+    Usage:
+        test1 arg
+
+    Echo 'arg' to the console
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    As you can see above, the arguments and tokens are returned as <a
+    href="http://www.boost.org/doc/libs/1_33_1/libs/range/doc/utility_class.html#iter_range">
+    boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
+    \c end() and some other useful members.
+    
+    The parser will have divided the argument tokens into arguments already. This simplifies further
+    parsing. If however you want to access the list of argument tokens as a single list, you can do
+    so using senf::console::ParseCommandInfo::tokens().
+    
+    Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
+    can be delegated to the Console/config library. See the next section.
+
+
+    \section console_autoparse Automatic argument parsing
+    
+    To greatly simplify parsing complex commands, we turn to automatic argument parsing. This
+    feature allows to register (almost) arbitrary callbacks.
+
+    \code
+    std::string test2(std::string const & arg)
+    {
+        return arg;
+    }
+    \endcode
+
+    This extremely simple callback may be registered by adding it to a
+    senf::console::DirectoryNode.
+    \code
+    senf::console::root()
+        .add("test2", &test2);
+    \endcode
+    The functionality is now identical to \c test1:
+    \htmlonly
+    <pre>
+    server:/$ test2
+    invalid number of arguments
+    server:/$ test2 stefan@j32.de
+    stefan@j32.de
+    server:/$ test2 (echo me)
+    argument syntax error
+    server:/$ help test2
+    Usage:
+        test2 arg11:string
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    As we can see, some documentation is automatically provided. To add more info, we need to add
+    some additional attributes when registering the command:
+    \code
+    namespace kw = senf::console::kw;
+
+    senf::console::root()
+        .add("test2", &test2)
+        .doc("Echo 'arg' to the console")
+        .arg( kw::name = "arg",
+              kw::description = "Message to output" );
+    \endcode
+
+    (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
+    Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
+    are set using keywords from the \ref senf::console::kw namespace. You will probably wither use
+    this namespace via a namespace alias (as above) or via a <tt>using namespace
+    senf::console::kw</tt> declaration (as in all the following examples)
+
+    You don't need
+    to specify any information for an argument: To skip an argument, just call \c arg() without
+    attributes for this argument.
+
+    After adding this information, the online help is much more intelligible
+    \htmlonly
+    <pre>
+    server:/$ help test2
+    Usage:
+        test2 arg:string
+
+    With:
+        arg       Message to output
+
+    Echo 'arg' to the console
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    \subsection command_ostream Accessing the console stream
+
+    Commands may have an optional first argument of type <tt>std::ostream &</tt>. This argument is
+    not considered part of the real interface. When the command is executed, the callback will be
+    passed the current console's output stream object in this argument. With this, the callback can
+    output arbitrary messages to the network console. See the next section for an example.
+
+    \subsection command_overload Command overloading
+
+    Automatically parsed commands can be overloaded: You can register multiple commands under the
+    same name. If this happens, each command is tried in turn until no SyntaxErrorException is
+    raised.
+
+    \code
+    void test3(std::ostream & os, unsigned n, std::string text)
+    {
+        // It's perfectly valid to check additional constraints here and throw a
+        // SyntaxErrorException. In this case, the next overload will be tried. However, you must
+        // ensure, That no action takes place before this check !
+        if ( n==0 ) throw senf::console::SyntaxErrorException("invalid value for parameter 'n'");
+        while (n-- > 0) os << text << std::endl;
+    }
+
+    using namespace senf::console::kw;
+    
+    senf::console::root()
+        .add("test3", &test3)
+        .doc("Echo text to the console")
+        .overloadDoc("Repeat 'text' for 'n' lines")
+        .arg( name = "n", description = "Number of repetitions" )
+        .arg( name = "text", description = "Message to output" );
+    senf::console::root()
+        .add("test3", &test2)
+        .overloadDoc("Echo the 'text' argument")
+        .arg( name = "text", description = "Message to output" );
+    \endcode
+
+    We can now call \c test2 with one or two arguments:
+
+    \htmlonly
+    <pre>
+    server:/$ test3 "The sky is blue"
+    The sky is blue
+    server:/$ test3 4 ok
+    ok
+    ok
+    ok
+    ok
+    server:/$ help test3
+    Usage:
+        1- test3 n:unsigned text:string
+        2- test3 text:string
+    
+    With:
+        n         Numer of repetitions
+        text      Messsage to output
+
+    Echo text to the console
+
+    Variant 1:
+    Repeat 'text' for 'n' lines
+    
+    Variant 2:
+    Echo the 'text' argument
+    senf:/$    And 
+
+    </pre>
+    \endhtmlonly
+
+    \subsection console_defaults Default values
+    
+    Another information which can not be automatically gathered from the type system is default
+    values. These have to be explicitly declared:
+    \code
+    using namespace senf::console::kw;
+
+    senf::console::root()
+        .add("test4", &test2b)
+        .arg()
+        .arg( default_value = "ok" );
+    \endcode
+    (Default values must not necessarily be declared in the callback function too.) Of course,
+    default values can be used together with overloading. 
+
+    There must be no argument without default value after an argument with a default value
+    declared. This fill fail at compile time. 
+
+    \subsection console_auto_summary Attribute summary
+
+    Here a summary of all the attributes available for automatically parsed command nodes:
+    
+    <table class="senf fixedwidth">
+    
+    <tr><td style="width:12em">\c doc ( \e text )</td><td>Documentation for all overloads</td></tr>
+
+    <tr><td>\c overloadDoc ( \e text )</td><td>Documentation for a specific overliad</td></tr>
+
+    <tr><td>\c arg ( \e attributes )</td><td>Set parameter attributes. All attributes are
+    optional. The attribute keywords are defined in the \ref senf::console::kw namespace. Valid
+    Attributes are:
+    \li \e name: Parameter name
+    \li \e description: One-line description of the argument
+    \li \e default_value: Arguments default value</td></tr>
+
+    </table>
+    
+    \section console_memberfn Registering member functions
+    
+    Member functions are supported like non-member functions. They must however be added through a
+    senf::console::ScopedDirectory<> instance to bind them to their instance.
+    \code
+    class Test 
+    {
+    public:
+        ScopedDirectory<Test> dir;
+
+        Test(std::string label) : dir(this), label_ (label) {
+            dir.add("test4", &Test::test2);
+            dir.add("test4", &Test::test3);
+        }
+
+        std::string test2(std::string const & text) { return label_ + ": " + text; }
+        void test3(std::ostream & os, unsigned n, std::string const & text) {
+            while (n-- > 0) os << label << ": " << text << std::endl; }
+
+    private:
+        std::string label_;
+    };
+
+    // ...
+
+    Test testOb ("test");
+    senf::console::root().add("testobj", testOb.dir);
+    \endcode
+
+    Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
+    from the tree when an object is destroyed.
+ */
+
 \f
 // Local Variables:
 // mode: c++
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
 // compile-command: "scons -u test"
-// mode: flyspell
 // mode: auto-fill
 // End:
+