Scheduler: Remove obsolete 'Scheduler' class
[senf.git] / Console / Mainpage.dox
index 2466616..b1636e3 100644 (file)
 
     \autotoc
 
+
     \section console_intro Introduction
 
     There are three parts to the Config/console library:
 
-    \li The console/config library is based on a \link node_tree tree of console/config
-        nodes. \endlink
-    \li Besides directories, the node contains command nodes. Commands are based on \link
-        console_commands variables or callbacks.\endlink
-    \li The console/config library is utilized by writing configuration files or interactive
-        commands in \link console_parser the console/config language.\endlink
+    The Config/Console library is built around several components
 
+    \li The \link node_tree Node tree\endlink represents all configuration options and commands
+        organized in a filesystem like structure.
+    \li \link console_commands Actions\endlink are added to the node tree in the form of command
+        nodes.
+    \li There exist several interfaces to \link console_access access\endlink entries in the node
+        tree: interactive console, reading configuration files etc.
+    
     The node tree works like a directory structure. Commands are entered into this directory
     structure and can be called passing arbitrary arguments. Configuration parameters are just
     commands which set their respective parameter, however the library allows commands to do much
     more than just that.
 
+
     \section console_example Example
 
     The following example shows a \e very short summary on how to integrate the config/console
     library. See above links for more:
 
     \code
+    #include <senf/Console.hh>
+
     // Define callback function.
     void mycommand(std::ostream & os, int foo, int bar)
     {
@@ -60,7 +66,7 @@
 
     namespace kw = senf::console::kw;
 
-    int main(int, char**)
+    int main(int argc, char** argv)
     {
         // Provide global documentation
         senf::console::root()
             .arg("foo")
             .arg(kw::name = "bar", kw::default_value = 0);
 
+       // Parse command line parameters
+       senf::console::parseOptions(argc,argv);
+
         // Start the interactive console server
         senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
             .name("someServer");
+
+        // Run the scheduler
+       senf::scheduler::process();
     }
     \endcode
 
-    after this registration, the console can be accessed easily via telnet:
+    after this registration, we can call the command from the command-line using
+
+    <pre>
+    $ someServer --mycommand="1 2"
+    </pre>
+
+    the console can be accessed easily via telnet:
     
     <pre>
     $ telnet localhost 23232
     $
     </pre>
 
+    \see \ref console_testserver for a complete example application
+
+
+    \section intro_usage Using the Console: Configuration files, Network console, ...
+
+    There are several ways to access the node tree:
+    \li By parsing configuration files
+    \li By parsing command line parameters
+    \li By providing interactive or non-interactive network console access
+
+    \see console_access
+
 
     \section intro_nodes The node tree
 
     \see \ref node_tree
 
 
-    \section intro_commands Console/config commands
+    \section intro_commands Implementing console/config commands
 
     The console/config language does not define, how arguments are passed to the commands, it just
     tokenizes the input and passes the tokens to the commands which then handle the
     command.
 
     \see \ref console_commands
+ */
+
+/** \defgroup console_access Accessing the Console/Config tree
+
+    The Console/Config library provides several ways to use the node tree to configure and control
+    an application.
+
+    \autotoc
+
+
+    \section console_access_config Configuration support
+
+    The configuration support of the Console/Config library revolves around the ConfigSource
+    concept. Each ConfigSource will somehow provide commands which will then be executed against the
+    node tree.
+
+    To simplify the usage, there will always be three interfaces to a specific config source:
+    \li A constructor to build a bare config source which is then added to a
+        senf::console::ConfigBundle (see \ref console_access_multiple)
+    \li A class parsing and executing a single config source. The visible interface of this class is
+        a combination of the constructor and the senf::console::ConfigBundle interfaces.
+    \li A helper function which will do the complete parsing of a single source with default
+        parameters.
+
+    When parsing these configuration sources, it is always possible to optionally change the root
+    node used during parsing and it is also possible to restrict parsing to a command subset. See
+    \ref console_access_partial.
+
+
+    \subsection console_access_file Configuration files
+
+    <table class="senf fixedwidth">
+    <tr><td><b>Constructor</b></td> <td>senf::console::FileConfig()</td></tr>
+    <tr><td><b>Class</b></td>       <td>senf::console::ConfigFile</td></tr>
+    <tr><td><b>Helper</b></td>      <td>senf::console::parseFile()</td></tr>
+    </table>
+
+    In it's simplest form, parsing a configuration file consists of calling
+    senf::console::parseFile() with the name of the respective config file as argument.
+
+    \code
+    senf::console::parseFile("some.conf");
+    \endcode
+
+    To get more flexible, instantiate a senf::console::ConfigFile instance at use that to parse the
+    file
     
+    \code
+    senf::console::ConfigFile cf ("some.conf");
+    cf.parse();
+    \endcode
+
+    If the application supports other configuration sources besides a single configuration file
+    (like command line options) or if it supports multiple configuration files (e.g. a system-wide
+    and a user specific configuration file) see \ref console_access_multiple and add one (or more)
+    senf::console::FileConfig() source to a senf::console::ConfigBundle.
 
-    \section intro_language The console/config language
 
-    To call the commands and set parameters, a very simple language is defined. The language is
-    almost declarative (e.g. it does not have any control-flow statements) but is processed
-    imperatively from top to bottom. This is very simple and flexible.
+    \subsubsection console_access_file_syntax Configuration file syntax
+
+    Configuration files are written in a simple configuration language. This language is almost
+    declarative (e.g. it does not have any control-flow statements) but is processed imperatively
+    from top to bottom. This is very simple and flexible.
 
     Commands are referenced by their path in the node tree. To simplify working with deeply nested
     directory structures, the current directory may be changed persistently or temporarily for some
     \endcode
 
     \see \ref console_parser
+
+
+    \subsection console_access_options Command line options
+
+    <table class="senf fixedwidth">
+    <tr><td><b>Constructor</b></td> <td>senf::console::OptionsConfig()</td></tr>
+    <tr><td><b>Class</b></td>       <td>senf::console::ProgramOptions</td></tr>
+    <tr><td><b>Helper</b></td>      <td>senf::console::parseOptions()</td></tr>
+    </table>
+
+    Command line options can either be parsed by calling the senf::console::parseOptions() helper
+
+    \code
+    senf::console::parseOptions(argc, argv)
+    \endcode
+
+    or more flexibly by instantiating a senf::console::ProgramOptions class
+
+    \code
+    std::vector<std::string> args;
+    senf::console::ProgramOptions opts (argc, argv);
+    opts
+        .nonOptions(args)
+        .alias('c', "--mycommand",true)
+        .alias('C', "--mycommand=2 3");
+    opts.parse();
+    \endcode
+
+    This registeres two short options and accumulates all non-option arguments in \c args.
+    
+    If the application supports other configuration sources besides the command line options (like
+    configuration files) see \ref console_access_multiple and add a senf::console::OptionsConfig()
+    source to a senf::console::ConfigBundle.
+
+    See \ref senf::console::ProgramOptions for the source specific additional parameters. These
+    apply to senf::console::ProgramOptions and to the senf::console::OptionsConfig() source.
+
+
+    \subsubsection console_access_options_syntax Options syntax
+
+    Command line options are primarily parsed as long-options. Long options start with '--'. Further
+    '-' characters serve as directory separators if required (that is, they are \e only interpreted
+    as directory separator is there is no entry in the current (sub-) directory matching more than a
+    single name component). This still allows using hyphens in node names.
+
+    Options can be abbreviated at each directory boundary: A command <tt>/foo/bar/do</tt> can be
+    called as <tt>--f-b-d</tt> as long as this name is unique.
+
+    Everything after the first '=' character is parsed into argument tokens using the normal
+    config/console parser. If the option has no '=' character, the list of argument tokens will be
+    empty.
+    
+    <table style="font-size:80%" class="senf">
+    <tr><th>Command</th><th>File syntax</th><th>Option syntax</th></tr>
+
+    <tr>
+      <td><tt>void doo()</tt></td>
+      <td><tt>/path/to/doo;</tt></td>
+      <td><tt>--path-to-doo</tt></td>
+    </tr>
+
+    <tr>
+      <td><tt>void doo(std::string const &)</tt></td>
+      <td><tt>/path/to/doo john.doe@everywhere.org;</tt></td>
+      <td><tt>--path-to-doo="john.doe@everywhere.org"</tt></td>
+    </tr>
+    
+    <tr>
+      <td><tt>void doo(std::string const &)</tt></td>
+      <td><tt>/path/to/doo "some test";</tt></td>
+      <td><tt>--path-to-doo='"some text"'</tt></td>
+    </tr>
+
+    <tr>
+      <td><tt>void doo(std::string const &, int)</tt></td>
+      <td><tt>/path/to/doo take 1;</tt></td>
+      <td><tt>--path-to-doo="take 1"</tt></td>
+    </tr>
+    </table>
+
+    The last column is additionally quoted using standard \c sh quoting: quotes in arguments need to
+    be additionally quoted for the shell.
+
+    Short options are registered as aliases for long options. They can be registered with or without
+    an implied parameter and can optionally take a parameter. so after
+
+    \code
+    opts
+        .alias('c', "--mycommand",true)
+        .alias('C', "--mycommand=2 3");
+    \endcode
+
+    we can call
+
+    <pre>
+    $ program -C -c "4 5"
+    $ program -Cc"4 5"
+    </pre>
+
+    which is the same as
+    
+    <pre>
+    $ program --mycommand="2 3" --mycommand="4 5"
+    </pre>
+
+    (Beware, that the second argument to \c alias() is \e not shell quoted). 
+
+
+    \subsection console_access_root Changing the root node
+
+    When used in it's default state, parsing will always interpret all commands relative to the
+    senf::console::root() node and will parse a file completely.
+
+    The first possibility to control this is to change the root node. This is done by 
+    \li passing that root node to the helper class or to the parse helper as an additional argument
+        (see the respective documentation).
+    \li passing it to the senf:;console::ConfigBundle constructor when parsing multiple sources.
+    
+    for example:
+
+    \code
+    senf::console::parseFile("/etc/myserver.conf", senf::console::root()['config']);
+    \endcode
+
+    This functionality is even more powerful by combining it with \c link nodes: This allows to
+    selectively choose commands from the node tree which are to be made accessible for
+    configuration. See \ref node_tree.
+
+
+    \subsection console_access_partial Partial / incremental configuration
+
+    Another feature provided by senf::console::ConfigBundle and all helper classes is partial
+    parsing.
+
+    \code
+    // Create a console/config aware object and place it into the node tree
+    FooObject foo;
+    senf::console::root().add("foo", foo.dir);
+
+    // Open configuration file
+    senf::console::ConfigFile cf ("/etc/myserver.conf");
+    
+    // Parse only commands in the configuration file which are in the foo.dir directory
+    cf.parse(foo.dir);
+
+    ...
+
+    // Anywhere later, parse the rest of the configuration file
+    cf.parse();
+    \endcode
+
+    This feature allows to parse parts of one or more configuration sources before the
+    console/config tree has been fully established. Partial parsing can be applied any number of
+    times to arbitrary nodes. Any command already parsed will be skipped automatically.
+
+    When combining partial parsing with \c chroot() and \c link's, it is important to realize, that
+    <em>partial parsing always applies to the \e real target and ignores links</em>. This is very
+    important: It allows a subsystem to parse it's configuration parameters irrespective of any
+    links pointing to nodes of that subsystem.
+
+
+    \subsection console_access_multiple Multiple sources
+
+    Most of the time, an application will utilize multiple configuration sources: A global
+    configuration file, maybe a user specific local configuration file, command line options ...
+
+    When parsing configuration commands, especially using partial / incremental parsing, all parse
+    commands should be applied to each configuration source in turn. This is the responsibility of
+    senf::console::ConfigBundle.
+
+    \code
+    senf::console::ScopedDirectory<> config;
+    senf::console::root().add("config", config);
+
+    // Let's enable all logger commands for configuration
+    config.link("logger", senf::console::root()["logger"]);
+
+    // Create bundle and add sources
+    std::vector<std::string> args;
+    senf::console::ConfigBundle conf (senf::console::root()["config"]);
+    conf.add( senf::console::FileConfig("/etc/myserver.conf") );
+    conf.add( senf::console::FileConfig(".myserver.conf") );
+    conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(), 
+                                           senf::Daemon::instance().argv()) )
+        .nonOptions(args)
+        .alias('c', "--mycommand",true)
+        .alias('C', "--mycommand=2 3");
+
+    // Parse the logger subsystem commands in '/logger'
+    conf.parse(senf::console::root()['logger']);
+    
+    ...
+
+    // Parse all other configuration commands. All necessary commands and links in '/config' must by
+    // now have been created.  
+    conf.parse();
+    \endcode
+
+    This example parses three configuration sources: Two configuration files and additional
+    parameters specified on the command line. All the configuration commands are placed into the
+    <tt>/config</tt> directory (directly or via links). The configuration sources are parsed in the
+    order they are specified, so in this case, the command line options will override any options
+    specified in one of the configuration files.
+
+
+    \section console_access_console The network console
+
+    To make the network console accessible, it must be initialized when the program is started:
+    \code
+    #include <senf/Console.hh>
+
+    int main(int argc, char * argv [])
+    {
+        // Configure console nodes, add commands ...
+
+        // Start console server
+        senf::console::start(senf::INet4SocketAddress(12345u))
+           .name("myserver");
+
+        // You need to enter the scheduler main-loop for the server to work
+        senf::scheduler::process();
+       
+        // Alternatively enter the main-loop via the PPI
+        // senf::ppi::run();
+    }
+    \endcode
+
+    This will start the server on IPv4 port 12345. The servers name (as displayed in the interactive
+    console prompt) is set to 'myserver'.
+
+    After launching the application, the server can be accessed at the given port:
+    \htmlonly
+    <pre>
+    bash$ telnet localhost 12345
+    Trying 127.0.0.1...
+    Connected to localhost.
+    Escape character is '^]'.
+
+    myserver:/$ exit
+    Connection closed by foreign host.
+    bash$
+    </pre>
+    \endhtmlonly
+
+    It is possible to start multiple server consoles by calling \c start() multiple times with
+    different ports/addresses. Each server can be configured separately (e.g. root node, mode ...).q
+
+
+    \subsection console_serverclient Server and Client objects
+
+    The senf::console::Server and senf::console::Client objects offer further API calls. To access
+    the server instance you need to store away the senf::console::Server reference returned when
+    starting the server so you can later refer to it:
+    \code
+    int main(int, char**)
+    {
+        senf::console::Server & server ( senf::console::start( ... ) );
+    
+        // Do something ...
+
+        server.stop()
+    }
+    \endcode
+
+    The client instance can be accessed via the \c std::ostream arg of any command callback
+    \code
+    void someCallback(std::ostream & os, ... )
+    {
+        senf::console::Client & client (senf::console::Client::get(os));
+    
+        // Use the client's log target
+        client.route<senf::log::Debug, senf::Log::IMPORTANT>();
+    }
+    \endcode
+
+    \see 
+        senf::console::Server for the Server API \n
+        <a href="classsenf_1_1console_1_1Client-members.html">senf::console::Client / List of all
+        members</a> for the Client API
+
+
+    \subsection console_shell The interactive console shell
+
+    The interactive shell will use the GNU readline library for the first connected
+    instance. Further users will not have access to this functionality since GNU readline is
+    completely non-reentrant. GNU readline supports history and some command keys (like C-d for \c
+    exit or C-c to clear and restart the input).
+
+    The shell supports auto-cd and auto-completion: If you enter the name of a directory at the
+    prompt, the console will change to that directory. With auto-completion, any unique beginning of
+    a path component will be completed automatically and transparently to the corresponding full
+    name.
+
+
+    \subsection console_noninteractive Non-interactive network console
+
+    After a new connection is established, the console server waits a short time for data to arrive.
+    arrive. Only if nothing happens in the first 500ms, readline is initialized (if available) and
+    the interactive prompt is displayed.
+
+    By sending data immediately after opening the connection, the console is switched into
+    non-interactive mode. In this mode, no prompt is displayed. In this mode, commands are \e not
+    terminated automatically by end-of-line (CR). This allows, to easily cat an arbitrary
+    configuration file into the network console using netcat:
+    
+    <pre>
+    $ nc -q1 localhost 23232 < some.conf
+    </pre>
+
+    The argument <tt>-q1</tt> makes netcat close the sending end of the connection on EOF and wait
+    up to 1 second for the console to terminate. Even better, use \c netcat6, which has full TCP
+    half-close support.
+
+    <pre>
+    $ echo "ls" | nc6 --half-close localhost 23232 2>/dev/null
+    console/
+    server/
+    test/
+    $
+    </pre>
+
+    Commands are executed as soon as the terminating character (';', '{' or '}') is received or when
+    the sending end of the connection is closed.    
  */
 
 /** \defgroup console_commands Supported command types
 
     \autotoc
 
+
     \section console_cmdadd Adding commands and setting attributes
 
     Basically, all commands are added using senf::console::DirectoryNode::add(). What exactly
     \code
     void fun1(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;
+        // Here we declare variables for the arguments
+        std::string value;
+
+        {
+            // We parse the arguments using the CheckedArgumentIteratorWrapper. This wrapper
+            // will throw a SyntaxErrorException if we access a nonexistent argument or if we
+            // do not parse all arguments.
+            senf::console::CheckedArgumentIteratorWrapper args (command.arguments());
+
+            senf::console::ParseCommandInfo::TokensRange argTokens ( *(args++) );
+            if (arg1Tokens.size() != 1)
+                raise senf::console::SyntaxErrorException("argument syntax error");
+            value = arg1Tokens[0];
+        }
+
+        os << value << std::endl;
     }
     \endcode
     
     
     To greatly simplify parsing complex commands, we turn to automatic argument parsing. 
 
+
     \subsection console_autoadd Adding
 
     Automatically parsed commands are registered by just adding a callback which has the correct
 
     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
+    passed the current consoles output stream object in this argument. With this, the callback can
     output arbitrary messages to the network console.
     \code
     void fun3(std::ostream & os, unsigned n, std::string text)
     </pre>
     \endhtmlonly
 
+
     \subsection command_overload Overloading
 
     Automatically parsed commands can be overloaded: You can register multiple commands under the
         
     \section console_memberfn 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.
+    Non-static member functions are supported like non-member functions (static member functions are
+    identical to non-members). They must however be added through a senf::console::ScopedDirectory
+    instance to bind them to their instance.
     \code
     class Test1
     {
     <tr><td style="width:14em">\link senf::console::VariableAttributor::doc() .doc\endlink
     ( \e doc )</td><td>Set variable documentation</td></tr>
     
-    <tr><td>\link senf::console::VariableAttributor::onChange() .onchange\endlink
+    <tr><td>\link senf::console::VariableAttributor::onChange() .onChange\endlink
     ( \e handler )</td><td>Set change handler</td></tr>
     
     </table>
 
     \see senf::console::VariableAttributor for the complete attribute interface
 
+
     \subsection console_varchange Change notification
 
     A \e handler can be set to be called, whenever the variable is changed. It will be called with a
     After this setup, \c varChanged will be called, whenever the value has changed.
 
 
-    \see senf::console::VariableAttributor for the complete attribute interface
+    \section console_args Special argument types
+
+    By default, argument types which can be read and written using \c iostreams are automatically
+    supported. Other types need to be registered explicitly
+
+
+    \subsection console_args_bool Boolean arguments and return values
+
+    The console library by default formats boolean values using the strings \c true and \c false for
+    their representation. When parsing a boolean value, most sensible representations will be
+    accepted:
+    
+    <table class="senf">
+    <tr><td>\c true</td>    <td>\c false</td>    <td>\ref senf::console::formatTrueFalse</td></tr>
+    <tr><td>\c on</td>      <td>\c off</td>      <td>\ref senf::console::formatOnOff</td></tr>
+    <tr><td>\c enabled</td> <td>\c disabled</td> <td>\ref senf::console::formatEnabledDisabled</td></tr>
+    <tr><td>\c yes</td>     <td>\c no</td>       <td>\ref senf::console::formatYesNo</td></tr>
+    <tr><td><em>non-zero integer</em></td><td>\c 0</td><td>\ref senf::console::formatOneZero</td></tr>
+    </table>
+
+    The boolean parser will accept these values in any (mixed) case and accepts any unique initial
+    substring (e.g. \c Y / \c N).
+
+    The last column lists explicit formatters which can be set to customize the return value
+    formatting of a registered overload accordingly.
+
+    
+    \subsection console_args_enum Registering enum types
+
+    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
+    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);
+    \endcode
+
+    After an enum type is registered, it can be used like any other type for arguments or
+    return-values:
+
+    \htmlonly
+    <pre>
+    server:/$ test9 Sit
+    Sit
+    server:/$ test9 Crawl
+    argument syntax error: invalid enum value
+    server:/$ help test9
+    Usage:
+        test9 arg11:MyEnum
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    \ref SENF_CONSOLE_REGISTER_ENUM() can only be used, to register enums at namespace scope. To
+    register enums defined within some class, use \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER()
+
+    \code
+    class Test3
+    {
+    public:
+        enum Color { Red, Green, Blue };
+    
+        senf::console::ScopedDirectory<MyClass> dir;
+
+        Test3();
+
+        Color mem3(Color c) { return c }
+    };
+    SENF_CONSOLE_REGISTER_ENUM_MEMBER( Test3, Color, (Red)(Green)(Blue) );
+
+    Test3::Test3() : dir(this)
+        { dir.add("test", &MyClass::mem3); }
+    
+    Test3 test3ob;
+    senf::console::root().add("test3ob", test3ob.dir);
+    \endcode
+
+    Using this command/type is identical
+    \htmlonly
+    <pre>
+    server:/$ test3ob/test Red
+    Red
+    server:/$ test3ob/test White
+    argument syntax error: invalid enum value
+    server:/$ help test3ob/test
+    Usage:
+        test arg11:Color
+    </pre>
+    \endhtmlonly
+
+
+    \subsection console_args_custom Extending the library to support additional types
+
+    To support or customize parsing/formatting of other types, they need to be registered. In it's
+    simplest case, this works, by just providing an appropriate overload for
+    senf_console_parse_argument() and senf_console_format_value():
+    \code
+    struct Coordinate
+    {
+        Coordinate() : x(0), y(0) {}
+        Coordinate(int x_, int y_) : x(x_), y(y_) {}
+
+        int x, y;
+    }
+
+    void senf_console_parse_argument(senf::console::ParseCommandInfo::TokensRange const & tokens,
+                                     Coordinate & out)
+    {
+        senf::console::CheckedArgumentIteratorWrapper arg (tokens);
+        senf::console::parse( *(arg++), out.x );
+        senf::console::parse( *(arg++), out.y );
+    }
+
+    void senf_console_format_value(Coordinate const & value, std::ostream & os)
+    {
+        os << '(' << value.x << ' ' << value.y << ')';
+    }
+    \endcode 
+
+    The parser will accept an argument with two tokens which are each forwarded to the integer
+    parser. The senf::console::CheckedArgumentIteratorWrapper ensures two things: That all input
+    tokens are parsed and no extra trailing tokens are left unparsed and it checks, that all
+    referenced tokens really exist.
+
+    The formatter writes out the value as a parenthesized pair.
+
+    \code
+    Coordinate fun5(Coordinate const & p) { return Coordinate(2*p.x, 2*p.y) }
+    
+    namespace kw = senf::console::kw;
+
+    senf::console::root()
+        .add("test10", &fun5)
+        .arg("x","coordinate to double",
+             kw::default_value = Coordinate())
+    \endcode
+    We can now call \c test10 with a coordinate argument:
+    \htmlonly
+    <pre>
+    server:/$ test10 (2 7)
+    (4 14)
+    server:/$ help test10
+    Usage:
+        test10 [x:Coordinate]
+
+    With:
+        x         Coordinate to double
+            default: (0 0)
+    server:/$
+    </pre>
+    \endhtmlonly
+    
+    If you want to customize the formatting of default values differently from the formating of
+    return-values or if you want to change the displayed name of a type, you will need to specialize
+    the senf::console::ArgumentTraits class instead of implementing
+    senf_console_parse_argument(). See senf::console::ArgumentTraits and
+    senf::console::ReturnValueTraits for more.
  */
 
 \f