Utils/Logger: Remove dependency on libboost_datetime
[senf.git] / Console / Mainpage.dox
index 6929f25..c143bc3 100644 (file)
@@ -51,6 +51,8 @@
     library. See above links for more:
 
     \code
+    #include <senf/Console.hh>
+
     // Define callback function.
     void mycommand(std::ostream & os, int foo, int bar)
     {
     $
     </pre>
 
+    \see \ref console_testserver for a complete example application
+
+    \section intro_init Initialization
+
+    To make the 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::instance().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
 
     \section intro_nodes The node tree
 
     \see \ref node_tree
 
 
-    \section intro_commands Console/config commands
+    \section intro_commands Registering 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
     \endcode
 
     \see \ref console_parser
+
+
+    \section console_misc Further features
+
+    \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 Features of 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.
+
+    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 th corresponding full
+    name.
  */
 
 /** \defgroup console_commands Supported command types
     \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");
+        // Here we declare variables for the arguments
+        std::string value;
 
-        // Retrieve the token value
-        std::string arg (argTokens[0].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];
+        }
 
-        // In this example, we just write the argument to the output stream
-        os << arg << std::endl;
+        os << value << std::endl;
     }
     \endcode
     
     
     To greatly simplify parsing complex commands, we turn to automatic argument parsing. 
 
-    \subsection console_autoadd Adding automatically parsed commands
+    \subsection console_autoadd Adding
 
     Automatically parsed commands are registered by just adding a callback which has the correct
     arguments and return-value defined:
 
     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 Command overloading
+    \subsection command_overload Overloading
 
     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.
     server:/$
     </pre>
 
-    \subsection console_attributes Attributes of automatically parsed commands
+    One note: When taking the address of an overloaded function (member or non-member), the C++
+    language forces you to cast that address to one of the possible types so the compiler knows,
+    which overload is requested. So to add a function which is overloaded in C++, each overload
+    needs to be added explicitly, casting to the correct type:
+    \code
+    void over(int);
+    void over(int,int);
+
+    senf::console::root()
+        .add("over", static_cast<void (*)(int)>(&over));
+    senf::console::root()
+        .add("over", static_cast<void (*)(int,int)>(&over));
+    \endcode
+
+
+    \subsection console_attributes Attributes
 
     As have seen so far, some documentation is automatically provided. We can add more info, by
     setting additional attributes. 
     </pre>
     \endhtmlonly
 
-
-    \subsection console_argattribpos Passing argument attributes as positional arguments
-
     Since most of the time, we only need to set the name and possibly a description for arguments,
     there is a shortcut: name and description can be specified as positional arguments in this
-    order. So the following will give the exactly same result as the example in the previous section
-
+    order. So the following will give the exactly same result as above:
     \code
     namespace kw = senf::console::kw;
 
     </pre>
     \endhtmlonly
 
+
+    \subsection console_boostfn Non-function-pointer commands
+
+    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:
+
+    \code
+    senf::console::root()
+        .add("test8", 
+             boost::function<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:
+    Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
+    
+    \htmlonly
+    <pre>
+    server:/$ test8 ok
+    ok
+    ok
+    ok
+    ok
+    server:/$ help test8
+    Usage:
+        test8 arg11:string
+    server:/$
+    </pre>
+    \endhtmlonly
+
+
     \subsection console_attr_summary Attribute summary
 
     Here a summary of the most common attributes
 
     <table class="senf fixedwidth">
 
-    <tr><td>\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink ( \e doc )</td><td>Set
-    documentation for all overloads</td></tr>
+    <tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
+    ( \e doc )</td><td>Set documentation for all overloads</td></tr>
     
     <tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
     .overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
     
     <table class="senf fixed width">
 
-    <tr><td>\link senf::console::kw::name kw::name\endlink</td><td>Parameter name</td></tr>
+    <tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
+    name</td></tr>
 
     <tr><td>\link senf::console::kw::description kw::description\endlink</td><td>One-line
     description of the argument</td></tr>
         \ref senf::console::kw for a list of all argument attribute keywords
 
         
-    \section console_memberfn Registering member functions
+    \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 Test 
+    class Test1
     {
     public:
-        senf::console::ScopedDirectory<Test> dir;
-
-        Test(std::string label) : dir(this), label_ (label) 
-        {
-            dir.add("test4", &Test::test2);
-            dir.add("test4", &Test::test3);
-        }
+        senf::console::ScopedDirectory<Test1> dir;
 
-        std::string test2(std::string const & text)
+        Test1(std::string label) : dir(this), label_ (label) 
+            { dir.add("test", &Test::test1);
+              dir.add("test", &Test::test2); }
+    
+        std::string test1(std::string const & text)
             { return label_ + ": " + text; }
 
-        void test3(std::ostream & os, unsigned n, std::string const & text) 
+        void test2(std::ostream & os, unsigned n, std::string const & text) 
             { while (n-- > 0) os << label << ": " << text << std::endl; }
 
     private:
 
     // ...
 
-    Test testOb ("test");
-    senf::console::root().add("testobj", testOb.dir);
+    Test1 test1ob ("test");
+    senf::console::root().add("test1ob", test1ob.dir);
     \endcode
 
     Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
     from the tree when the object is destroyed.
+
+
+    \section console_variables Variables
+    
+    \subsection console_varadd Adding
+
+    The console/config library supports the direct registration of variables as commands. A
+    variable command consists of two overloads, one to query the current value and one to change the
+    value. 
+    \code
+    class Test2
+    {
+    public:
+        senf::console::ScopedDirectory<Test2> dir;
+
+        Test2() : dir(this), var_(0)
+            { dir.add("var", var_); }
+
+    private:
+        int var_;
+    };
+
+    Test2 test2ob;
+    senf::console::root().add("test2ob", test2ob.dir);
+    \endcode
+    This shows the most common scenario: A member variable is added to a ScopedDirectory of the same
+    class. This ensures, that the variable command node is removed from the tree when the instance
+    (and thereby the variable) are destroyed. The variable can now be used like any other command:
+    \htmlonly
+    <pre>
+    server:/$ test2ob/var
+    0
+    server:/$ test2ob/var 10
+    server:/$ test2ob/var
+    10
+    server:/$ help test2ob
+    Usage:
+        1- var new_value:int
+        2- var
+    server:/$
+    </pre>
+    \endhtmlonly
+
+
+    \subsection console_varro Read-only variables
+    
+    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
+    int var (0);
+
+    senf::console::root().add("var1", boost::cref(var));
+    \endcode
+    A read-only variable only has a single overload:
+    \htmlonly
+    <pre>
+    server:/$ var1
+    0
+    server:/$ help var1
+    Usage:
+        var1
+    server:/$ 
+    </pre>
+    \endhtmlonly
+
+
+    \subsection console_varattr Attributes
+
+    The most important Variable command attributes are
+
+    <table class="senf fixedwidth">
+
+    <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
+    ( \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
+    reference to the old value. The handler is called, after the value has been changed
+
+    \code
+    int var (0);
+
+    // Since this is int, it would make sense to declare the argument pass-by-value (int old)
+    // but for more complex args, use a const & here
+    void varChanged(int const & old)
+    {
+        // ...
+    }
+
+    senf::console::root().add("var2",var)
+        .onChange(&varChanged);
+    \endcode
+    
+    After this setup, \c varChanged will be called, whenever the value has changed.
+
+
+    \section console_args Registering 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_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 Customizing argument and return value parsing/formatting
+
+    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