From: g0dil Date: Wed, 28 May 2008 15:14:58 +0000 (+0000) Subject: Console: Documentation of the configuration support X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=45df7138999be77ea7949c6249ca973305290f48;p=senf.git Console: Documentation of the configuration support git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@858 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Console/Config.hh b/Console/Config.hh index 81a94ef..f5804b7 100644 --- a/Console/Config.hh +++ b/Console/Config.hh @@ -38,34 +38,44 @@ namespace senf { namespace console { - /** \brief + /** \brief Combine multiple configuration sources + + A ConfigBundle combines several sources and parses them together, in the order they were + added. Parse restrictions are applied uniformly to all sources. + \code + // Add three configuration sources: A system configuration file, a user configuration file + // and command line options + senf::console::ConfigBundle conf; + conf.add( senf::console::FileConfig("/etc/some.conf") ); + conf.add( senf::console::FileConfig("local.conf") ); + conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(), + senf::Daemon::instance().argv()) ); + + conf.parse(); + \endcode + + This bundle may also be passed to other code which may use restricted parsing to parse + partial information from all configuration sources. + + \ingroup console_access */ class ConfigBundle { public: /////////////////////////////////////////////////////////////////////////// - // Types - - /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ ConfigBundle(); - ConfigBundle(DirectoryNode & root); - - // default default constructor - // default copy constructor - // default copy assignment - // default destructor - - // no conversion constructors + ConfigBundle(DirectoryNode & root); ///< Set custom root node ///@} /////////////////////////////////////////////////////////////////////////// template Source & add(boost::intrusive_ptr source); - + ///< Add configuration source + void parse(); ///< Parse config file /**< All nodes already parsed are skipped */ void parse(DirectoryNode & restrict); ///< Parse config file under \a restrict @@ -93,6 +103,12 @@ namespace console { namespace detail { // hrmpf ... Can't place this into Config.ih ... + /** \brief Internal: Provide ConfigBundle facade for a single-source config. + + The BundleMixin is used to define supplementary configuration objects for one specific + configuration source. A BundleMixin is \e not a ConfigBundle since it has no public \c add() + member. + */ class BundleMixin { public: diff --git a/Console/Config.ih b/Console/Config.ih index ceb081b..7ee336b 100644 --- a/Console/Config.ih +++ b/Console/Config.ih @@ -38,6 +38,11 @@ namespace senf { namespace console { namespace detail { + /** \brief Internal: Executor wrapper implementing restricted execution + + A RestrictedExecutor will only process commands which a re children of a given node. It does + \e not follow any links. + */ class RestrictedExecutor : boost::noncopyable { @@ -89,6 +94,11 @@ namespace detail { friend class RestrictGuard; }; + /** \brief Internal: Set restricted node of a RestrictedExecutor + + A RestrictGuard will set the node to which to restrict. It will automatically reset the node + in it's destructor. + */ class RestrictedExecutor::RestrictGuard { public: @@ -110,7 +120,10 @@ namespace detail { }; - /** \brief + /** \brief Internal: ConfigSource base class + + All configuration sources derive from ConfigSource. A ConigSource somehow reads + configuration commands and passes them to a RestrictedExecutor. */ class ConfigSource : public senf::intrusive_refcount diff --git a/Console/ConfigFile.cc b/Console/ConfigFile.cc index b20529d..d57a0a8 100644 --- a/Console/ConfigFile.cc +++ b/Console/ConfigFile.cc @@ -45,7 +45,7 @@ prefix_ void senf::console::detail::ConfigFileSource::v_parse(RestrictedExecutor /////////////////////////////////////////////////////////////////////////// -prefix_ void senf::console::readConfig(std::string const & filename, DirectoryNode & root) +prefix_ void senf::console::parseFile(std::string const & filename, DirectoryNode & root) { ConfigFile cfg (filename, root); cfg.parse(); diff --git a/Console/ConfigFile.hh b/Console/ConfigFile.hh index 3e08edf..8b5a291 100644 --- a/Console/ConfigFile.hh +++ b/Console/ConfigFile.hh @@ -52,6 +52,10 @@ namespace console { // Parse rest of the config file cf.parse(); \endcode + + If your application uses multiple configuration sources, use a ConfigBundle and FileConfig + + \ingroup console_access */ class ConfigFile : public detail::BundleMixin @@ -80,8 +84,15 @@ namespace console { \related ConfigFile */ - void readConfig(std::string const & filename, DirectoryNode & root = root()); + void parseFile(std::string const & filename, DirectoryNode & root = root()); + + /** \brief ConfigBundle source reading a configuration file + This constructor is used to create a config source parsing the given configuration file to + add to a ConfigBundle. + + \related ConfigFile + */ detail::ConfigFileSource::ptr FileConfig(std::string const & filename); }} diff --git a/Console/ConfigFile.ih b/Console/ConfigFile.ih index a02c467..59df5a9 100644 --- a/Console/ConfigFile.ih +++ b/Console/ConfigFile.ih @@ -34,6 +34,8 @@ namespace senf { namespace console { namespace detail { +#ifndef DOXYGEN + class ConfigFileSource : public ConfigSource { public: @@ -50,6 +52,8 @@ namespace detail { CommandParser parser_; }; +#endif + }}} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/Console/Mainpage.dox b/Console/Mainpage.dox index c143bc3..806f96f 100644 --- a/Console/Mainpage.dox +++ b/Console/Mainpage.dox @@ -33,13 +33,15 @@ 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 @@ -62,7 +64,7 @@ namespace kw = senf::console::kw; - int main(int, char**) + int main(int argc, char** argv) { // Provide global documentation senf::console::root() @@ -75,13 +77,25 @@ .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::instance().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 + +
+    $ someServer --mycommand="1 2"
+    
+ + the console can be accessed easily via telnet:
     $ telnet localhost 23232
@@ -101,44 +115,14 @@
 
     \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 
-
-    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
+    \section intro_usage Access
 
-    This will start the server on IPv4 port 12345. The servers name (as displayed in the interactive
-    console prompt) is set to 'myserver'.
+    There are several ways to access the node tree:
+    \li By parsing configuration files
+    \li By parsing command line parameters
+    \li By providing interactive console access
 
-    After launching the application, the server can be accessed at the given port:
-    \htmlonly
-    
-    bash$ telnet localhost 12345
-    Trying 127.0.0.1...
-    Connected to localhost.
-    Escape character is '^]'.
-
-    myserver:/$ exit
-    Connection closed by foreign host.
-    bash$
-    
- \endhtmlonly + \see console_access \section intro_nodes The node tree @@ -164,13 +148,66 @@ 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 + + + + + +
Constructor senf::console::FileConfig()
Class senf::console::ConfigFile
Helper senf::console::parseFile()
+ + 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 + \subsubsection console_access_file_syntax Configuration file syntax - 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. + 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 @@ -186,8 +223,242 @@ \see \ref console_parser + \subsection console_access_options Command line options + + + + + +
Constructor senf::console::OptionsConfig()
Class senf::console::ProgramOptions
Helper senf::console::parseOptions()
+ + 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 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 /foo/bar/do can be + called as --f-b-d 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. + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CommandFile syntaxOption syntax
void doo()/path/to/doo;--path-to-doo
void doo(std::string const &)/path/to/doo john.doe@everywhere.org;--path-to-doo="john.doe@everywhere.org"
void doo(std::string const &)/path/to/doo "some test";--path-to-doo='"some text"'
void doo(std::string const &, int)/path/to/doo take 1;--path-to-doo="take 1"
+ + 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 + +
+    $ program -C -c "4 5"
+    $ program -Cc"4 5"
+    
+ + which is the same as + +
+    $ program --mycommand="2 3" --mycommand="4 5"
+    
+ + (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: - \section console_misc Further features + \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::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 + partial parsing always applies to the \e real target and ignores links. 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 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 + /config 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 interactive console + + To make the console accessible, it must be initialized when the program is started: + \code + #include + + 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 +
+    bash$ telnet localhost 12345
+    Trying 127.0.0.1...
+    Connected to localhost.
+    Escape character is '^]'.
+
+    myserver:/$ exit
+    Connection closed by foreign host.
+    bash$
+    
+ \endhtmlonly \subsection console_serverclient Server and Client objects @@ -232,6 +503,7 @@ 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 diff --git a/Console/Parse.hh b/Console/Parse.hh index 142060d..c246ce1 100644 --- a/Console/Parse.hh +++ b/Console/Parse.hh @@ -251,8 +251,9 @@ namespace console { | HexString }; - Token(); - Token(TokenType type, std::string token); + Token(); ///< Create empty token + Token(TokenType type, std::string token); ///< Create token with given type and value + std::string const & value() const; ///< String value of token /**< This value is properly unquoted */ @@ -274,16 +275,48 @@ namespace console { std::ostream & operator<<(std::ostream & os, Token const & token); + /** \brief Create a \c None token + \related Token */ Token NoneToken(); + + /** \brief Create a \c PathSeparator ['/'] token + \related Token */ Token PathSeparatorToken(); + + /** \brief Create an \c ArgumentGroupOpen ['('] token + \related Token */ Token ArgumentGroupOpenToken(); + + /** \brief Create a \c ArgumentGroupClose [')'] token + \related Token */ Token ArgumentGroupCloseToken(); + + /** \brief Create a \c DirectoryGroupOpen ['{'] token + \related Token */ Token DirectoryGroupOpenToken(); + + /** \brief Create a \c DirectoryGroupClose ['}'] token + \related Token */ Token DirectoryGroupCloseToken(); + + /** \brief Create a \c CommandTerminator [';'] token + \related Token */ Token CommandTerminatorToken(); + + /** \brief Create a \c OtherPunctuation ['=', ','] token with the given \a value + \related Token */ Token OtherPunctuationToken(std::string const & value); + + /** \brief Create a \c BasicString token with the given \a value + \related Token */ Token BasicStringToken(std::string const & value); + + /** \brief Create a \c HexString token with the given \a value + \related Token */ Token HexStringToken(std::string const & value); + + /** \brief Create a \c Word token with the given \a value + \related Token */ Token WordToken(std::string const & value); /** \brief Single parsed console command @@ -343,12 +376,16 @@ namespace console { /**< The returned range contains \e all argument tokens in a single range not divided into separate arguments. */ - void clear(); + void clear(); ///< Clear all data members - void builtin(BuiltinCommand builtin); - void command(std::vector & commandPath); + void builtin(BuiltinCommand builtin); ///< Assign builtin command + void command(std::vector & commandPath); ///< Assign non-builtin command - void addToken(Token const & token); + void addToken(Token const & token); ///< Add argument token + /**< You \e must ensure, that the resulting argument tokens + are properly nested regarding '()' groups, otherwise + interpreting arguments using the arguments() call will + crash the program. */ protected: @@ -564,6 +601,11 @@ namespace console { read. */ bool parseArguments(std::string arguments, ParseCommandInfo & info); + ///< Parse \a argumtns + /**< parseArguments() parses the string \a arguments which + contains arbitrary command arguments (without the name + of the command). The argument tokens are written into + \a info. */ private: struct Impl; diff --git a/Console/ProgramOptions.hh b/Console/ProgramOptions.hh index 7fab5dc..25fbb2e 100644 --- a/Console/ProgramOptions.hh +++ b/Console/ProgramOptions.hh @@ -37,6 +37,33 @@ namespace senf { namespace console { + /** \brief Console node tree based command line option parser + + A ProgramOptions instance allows flexible parsing of command line options against the + console node tree. If you just want to parse all options, the senf::console::parseOptions() + function will do that. ProgramOptions however allows to incrementally parse only a + subset of the given command line options. + \code + std::vector args; + senf::console::ProgramOptions cf (argc, argv); + cf + .nonOptions(args) + .alias('n', "--foo-bar=x") + .alias('x', "--xxx", true); + + // Parse only options under the directory of some object. The object 'ob' + // must have been registered somewhere in the node tree + cf.parse(ob.dir); + + // Parse rest of the config file + cf.parse(); + \endcode + + If your application uses multiple configuration sources, use a ConfigBundle and + OptionsConfig. + + \ingroup console_access + */ class ProgramOptions : public detail::BundleMixin { @@ -46,20 +73,55 @@ namespace console { ///@{ ProgramOptions(int argc, char ** argv, DirectoryNode & root = root()); + ///< Create ProgramOptions parser for given options + /**< The given argc/argv values are those passed to main by + the operating system. Especially argv[0] is \e not an + option and is ignored. */ ///@} /////////////////////////////////////////////////////////////////////////// template ProgramOptions & nonOptions(Container & container); + ///< Set container to add non-option arguments to + /**< \a container must have a \c clear() and a \c + push_back(std::string) member. All non-options are + added to \a container. Before parsing the command-line, + \a clear() is called. */ ProgramOptions & alias(char letter, std::string const & longOpt, bool withArg=false); + ///< Set short option alias + /**< A short option is always an alias for a long option + with or without argument. if \a withArg is \c true, the + short option will expect an argument on the command + line. This argument will be appended (with an + additional '=') to \a longOpt. If \a withArg is \c + false (the default), \a longOpt may optional contain an + argument. + \param[in] letter option letter + \param[in] longOpt long option alias + \param[in] withArg \c true, if the option should take + an argument. */ private: detail::ProgramOptionsSource & config_; }; + /** \brief Parse command line options + + The command line otpions in \a argc / \a argv will be parsed, interpreting all node's + relative to \a root as root node. + + \related ProgramOptions + */ void parseOptions(int argc, char ** argv, DirectoryNode & root = root()); + /** \brief ConfigBundle source reading command line options + + This cosntructor is used to create aconfig source parsing the given command line options to + add to a ConfigBundle. + + \related ProgramOptions + */ detail::ProgramOptionsSource::ptr OptionsConfig(int argc, char ** argv); }} diff --git a/Console/ProgramOptions.ih b/Console/ProgramOptions.ih index 8fdf488..e02d174 100644 --- a/Console/ProgramOptions.ih +++ b/Console/ProgramOptions.ih @@ -36,6 +36,8 @@ namespace senf { namespace console { namespace detail { +#ifndef DOXYGEN + class ProgramOptionsSource : public ConfigSource { public: @@ -90,6 +92,8 @@ namespace detail { boost::scoped_ptr nonOptions_; }; +#endif + }}} ///////////////////////////////ih.e//////////////////////////////////////// diff --git a/Console/Readline.hh b/Console/Readline.hh index 48cfb71..00372d7 100644 --- a/Console/Readline.hh +++ b/Console/Readline.hh @@ -40,6 +40,8 @@ namespace senf { namespace console { namespace detail { +#ifndef DOXYGEN + /** \brief Internal: GNU readline based ClientReader implementation This implementation of the ClientReader interface uses GNU readline library to provide a @@ -107,6 +109,8 @@ namespace detail { boost::scoped_ptr reader_; }; +#endif + }}} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Console/Server.hh b/Console/Server.hh index b6e607f..0216840 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -66,6 +66,8 @@ namespace console { \implementation We do \e not provide an \c instance() member so we can easily later extend the server to allow registering more than one instance, e.g. with each instance on a differently firewalled port and with different security restrictions. + + \ingroup console_access */ class Server : boost::noncopyable @@ -115,6 +117,8 @@ namespace console { Whenever a new client connects, a new instance of this class is created. This class shows a command prompt, receives the commands, parses them and then passes (using a CommandParser) and passes the commands to an Executor instance. + + \ingroup console_access */ class Client : public senf::intrusive_refcount, @@ -166,10 +170,13 @@ namespace console { }; /** \brief Output Console Client instance as it's string representation - */ + \related Client + */ std::ostream & operator<<(std::ostream & os, Client const & client); + /** \brief Output Console Client instance as it's string representation - */ + \related Client + */ std::ostream & operator<<(std::ostream & os, Client * client); }} diff --git a/doclib/senf.css b/doclib/senf.css index d52ebef..61e0b3e 100644 --- a/doclib/senf.css +++ b/doclib/senf.css @@ -548,6 +548,11 @@ p.commalist { margin-left: 3em; } +h4 { + font-size: 100%; + margin-bottom: .4em; +} + table.memname { width: 100%; font-weight: normal;