X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Console%2FMainpage.dox;h=6929f2537fba9c84879ff36f57e4af24a1bae86f;hb=8e708e9784c76461252c3bdf646d291c593a49be;hp=42187b72fa5b0e2b95ff879aa38a00cc4b2e08a6;hpb=61bbb1c1ec66b1a41951fc971d0325095e17e7a9;p=senf.git diff --git a/Console/Mainpage.dox b/Console/Mainpage.dox index 42187b7..6929f25 100644 --- a/Console/Mainpage.dox +++ b/Console/Mainpage.dox @@ -20,29 +20,30 @@ // Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -/** \mainpage The Configuration and Runtime Control Framework +/** \mainpage The Configuration and Runtime Control Library The Console library implements a runtime interactive (network) console which allows to configure, control and manipulate a running application in any way. Additionally this library provides support for configuration files and command line parsing which can be used with or without the network console. - \section console_intro Introduction + \autotoc - There are two components to the Config/console framework: + \section console_intro Introduction - \li Building the node tree by registering objects and callbacks - \li Utilizing the config/console framework by writing configuration files or using the - interactive console. + There are three parts to the Config/console library: - Basic data structure of the console and config framework is the config/console node tree. This - tree. This tree works like a file-system. Commands are added to this tree and can then be called - from configuration files or from the interactive console. + \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 - To get started using the config/console library, see - \li \ref node_tree - \li \ref console_parser - \li \ref console_commands + 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 @@ -51,12 +52,14 @@ \code // Define callback function. - void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command) + void mycommand(std::ostream & os, int foo, int bar) { // ... os << "!! Important message ...\n"; } + namespace kw = senf::console::kw; + int main(int, char**) { // Provide global documentation @@ -66,8 +69,9 @@ // Add a command senf::console::root() .add("mycommand", &mycommand) - .doc("mycommand []\n\n" - "If is given, flurgle the , otherwise burgle it"); + .doc("If is given, flurgle the , otherwise burgle it") + .arg("foo") + .arg(kw::name = "bar", kw::default_value = 0); // Start the interactive console server senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u)) @@ -92,6 +96,53 @@ Connection closed by foreign host. $ + + + \section intro_nodes The node tree + + The basic idea is, that the console/config library manages a directory structure of parameters + and auxiliary commands. Parameters are just commands which set a parameter value so everything + is either a directory entry (senf::console::DirectoryNode) or a command + (senf::console::CommandNode). + + \see \ref node_tree + + + \section intro_commands 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 + conversion. + + Since parsing the tokens into something usable is quite tedious and error prone, the library + implements automatic argument parsing where the argument tokens are automatically parsed + depending on argument types. This enables you to register a command taking an integer argument + which will be called with an already parsed integer value (or throw a + senf::console::SyntaxErrorException if the conversion fails). This will be the most often used + command. + + \see \ref console_commands + + + \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. + + 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 + commands. + \code + /server/port 1234; + + /logger/targets/console { + accept senf::log::Debug IMPORTANT; + accept server::ServerLog CRITICAL; + } + \endcode + + \see \ref console_parser */ /** \defgroup console_commands Supported command types @@ -101,6 +152,43 @@ \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. + \code + dir.add("name", 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. + + The add call always returns (something which can be used as) a reference to the command node + added: + \code + senf::console::CommandNode & node ( dir.add( ... ) ); + \endcode + + Depending on the object added, you can also bind to a more specific node type + (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 before saving that value as a + node reference. 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 + \code + senf::console::CommandNode & node ( + dir.add("name", callback) + .doc("The documentation") ); + \endcode + + \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 @@ -171,21 +259,25 @@ 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. + This type of command has only a single attribute, \e doc to set the commands documentation. + \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. + To greatly simplify parsing complex commands, we turn to automatic argument parsing. + \subsection console_autoadd Adding automatically parsed commands + + Automatically parsed commands are registered by just adding a callback which has the correct + arguments and return-value defined: \code - std::string fun(std::string const & arg) + std::string fun2(std::string const & arg) { return arg; } \endcode - This extremely simple callback may be registered by adding it to a - senf::console::DirectoryNode. + This extremely simple callback may be registered by adding it to a senf::console::DirectoryNode. \code senf::console::root() .add("test2", &fun2); @@ -206,172 +298,257 @@ \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: + + \subsection command_ostream Accessing the console stream + + Commands may have an optional first argument of type std::ostream &. 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. \code - namespace kw = senf::console::kw; + void fun3(std::ostream & os, unsigned n, std::string text) + { + while (n-- > 0) os << text << std::endl; + } senf::console::root() - .add("test2", &test2) - .doc("Echo 'arg' to the console") - .arg( kw::name = "arg", - kw::description = "Message to output" ); + .add("test3", &fun3); \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 using namespace - senf::console::kw declaration (as in all the following examples) + This simple command can now be used thus: + \htmlonly +
+    server:/$ test3
+    invalid number of arguments
+    server:/$ test3 stefan@j32.de
+    invalid number of arguments
+    server:/$ test3 2 ok
+    ok
+    ok
+    server:/$ help test3
+    Usage:
+        test3 arg11:int arg12:string
+    server:/$
+    
+ \endhtmlonly + + \subsection command_overload Command 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. + \code + senf::console::root() + .add("test4", &fun3); + senf::console::root() + .add("test4", &fun2); + \endcode + And now, we can call \c test4 with one or two args: +
+    server:/$ test4
+    invalid number of arguments
+    server:/$ test4 stefan@j32.de
+    stefan@j32.de
+    server:/$ test4 2 ok
+    ok
+    ok
+    server:/$ help test4
+    Usage:
+        1- test4 arg11:int arg12:string
+        2- test4 arg21:string
+    server:/$
+    
- You don't need - to specify any information for an argument: To skip an argument, just call \c arg() without - attributes for this argument. + \subsection console_attributes Attributes of automatically parsed commands - After adding this information, the online help is much more intelligible + 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) + .doc("Echo text to the console") + .overloadDoc("Repeat {arg12} for {arg11} lines"); + senf::console::root() + .add("test4", &fun2) + .overloadDoc("Echo the {arg21} argument") + \endcode + + This additional info is used to provide more documentation: \htmlonly
-    server:/$ help test2
+    server:/$ help test5
     Usage:
-        test2 arg:string
+        1- test5 arg11:int arg12:string
+        2- test5 arg21:string
 
-    With:
-        arg       Message to output
+    Echo text to the console
 
-    Echo 'arg' to the console
-    server:/$
+    Variant 1:
+    Repeat {arg12} for {arg11} lines
+    
+    Variant 2:
+    Echo the {arg21} argument
+    senf:/$
     
\endhtmlonly - \subsection command_ostream Accessing the console stream - - Commands may have an optional first argument of type std::ostream &. 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 + \subsection console_argattributes Argument attributes - 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. + Additional attributes can be set for each parameter. They are all passed to the + senf::console::ParsedArgumentAttributor::arg() attribute. \code - void fun3(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; - } + namespace kw = senf::console::kw; - using namespace senf::console::kw; - senf::console::root() - .add("test3", &fun3) + .add("test6", &fun3) .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" ); + .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("test3", &fun2) - .overloadDoc("Echo the 'text' argument") - .arg( name = "text" ); + .add("test6", &fun2) + .overloadDoc("Echo the {text} argument") + .arg( kw::name = "text" ); \endcode - We can now call \c test3 with one or two arguments: + (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 either use + this namespace via a namespace alias (as above) or via a using namespace + senf::console::kw declaration (but beware of name collisions). - \htmlonly + 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 readable + \htmlonly
-    server:/$ test3 "The sky is blue"
-    The sky is blue
-    server:/$ test3 4 ok
-    ok
-    ok
-    ok
-    ok
-    server:/$ help test3
+    server:/$ help test6
     Usage:
-        1- test3 n:unsigned text:string
-        2- test3 text:string
-    
+        1- test6 n:int text:string
+        2- test6 text:string
+
     With:
-        n         Numer of repetitions
-        text      Messsage to output
+        n         Number of repetitions
+        text      Text to output
 
     Echo text to the console
 
     Variant 1:
-    Repeat 'text' for 'n' lines
+    Repeat {text} for {n} lines
     
     Variant 2:
-    Echo the 'text' argument
-    senf:/$    And 
-
+    Echo the {text} argument
+    senf:/$
     
\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 + + \code + namespace kw = senf::console::kw; + + senf::console::root() + .add("test6", &fun3) + .doc("Echo text to the console") + .overloadDoc("Repeat for lines"); + .arg("n", "Number of repetitions") + .arg("text", "Text to output"); + senf::console::root() + .add("test6", &fun2) + .overloadDoc("Echo the argument") + .arg("text"); + \endcode + + Keyword arguments should always be used if additional attributes are set. You can however mix + positional and keyword arguments. + + \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: + values. These have to be declared explicitly: \code - using namespace senf::console::kw; + namespace kw = senf::console::kw; senf::console::root() - .add("test4", &fun3) - .arg( name = "n", description = "Number of repetitions", default_value = 1 ) - .arg( name = "text", description = "Message to output" ); + .add("test7", &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"); \endcode - (Default values must not necessarily be declared in the callback function too.) Of course, - default values can be used together with overloading. Default (optional) value support is quite + Default values can be used together with overloading. Default (optional) value support is quite flexible, it is not mandatory, for default values to be specified only for the trailing - arguments. + arguments. For the exact definition, how parsed argument values are assigned to overload + arguments in the presence of default values, see \ref senf::console::kw::default_value. \htmlonly
-    server:/$ test4 echo
+    server:/$ test7 echo
     echo
-    server:/$ test4 4 ok
+    server:/$ test7 4 ok
     ok
     ok
     ok
     ok
-    server:/$ help test4
+    server:/$ help test7
     Usage:
         test4 [n:unsigned] text:string
     
     With:
         n         Number of repetitions
-        text      Message to output
-            default value: ok
+            default: 1
+        text      Text to output
+
+    Echo {text} to the console, repeating {text} for {n} lines
     server:/$
     
\endhtmlonly - \subsection console_auto_summary Attribute summary + \subsection console_attr_summary Attribute summary + + Here a summary of the most common attributes - Here a summary of all the attributes available for automatically parsed command nodes: - - - - + + + - +
\c doc ( \e text )Documentation for all overloads
\c overloadDoc ( \e text )Documentation for a specific overliad
\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink ( \e doc )Set + documentation for all overloads
\link senf::console::ParsedArgumentAttributorBase::overloadDoc() + .overloadDoc\endlink ( \e doc )Set documentation for a specific overload
\c arg ( \e attributes )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
\link senf::console::ParsedArgumentAttributor::arg() .arg\endlink ( \e argument \e + attributes )Set argument attributes (see below)
- See senf::console::ParsedArgumentAttributor 'List of all members' + The most important argument attributes (all defined in the senf::console::kw namespace) are: + + + + + + + + +
\link senf::console::kw::name kw::name\endlinkParameter name
\link senf::console::kw::description kw::description\endlinkOne-line + description of the argument
\link senf::console::kw::default_value kw::default_value\endlinkArguments + default value
+ + \see senf::console::ParsedArgumentAttributor + / List of all members for the complete attribute interface \n + \ref senf::console::kw for a list of all argument attribute keywords + + \section console_memberfn Registering member functions Member functions are supported like non-member functions. They must however be added through a @@ -382,14 +559,17 @@ public: senf::console::ScopedDirectory dir; - Test(std::string label) : dir(this), label_ (label) { + 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; } + 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_;