4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 /** \mainpage The Configuration and Runtime Control Library
25 The Console library implements a runtime interactive (network) console which allows to
26 configure, control and manipulate a running application in any way. Additionally this library
27 provides support for configuration files and command line parsing which can be used with or
28 without the network console.
32 \section console_intro Introduction
34 There are three parts to the Config/console library:
36 \li The console/config library is based on a \link node_tree tree of console/config
38 \li Besides directories, the node contains command nodes. Commands are based on \link
39 console_commands variables or callbacks.\endlink
40 \li The console/config library is utilized by writing configuration files or interactive
41 commands in \link console_parser the console/config language.\endlink
43 The node tree works like a directory structure. Commands are entered into this directory
44 structure and can be called passing arbitrary arguments. Configuration parameters are just
45 commands which set their respective parameter, however the library allows commands to do much
48 \section console_example Example
50 The following example shows a \e very short summary on how to integrate the config/console
51 library. See above links for more:
54 // Define callback function.
55 void mycommand(std::ostream & os, int foo, int bar)
58 os << "!! Important message ...\n";
61 namespace kw = senf::console::kw;
65 // Provide global documentation
67 .doc("This is someServer server");
71 .add("mycommand", &mycommand)
72 .doc("If <bar> is given, flurgle the <foo>, otherwise burgle it")
74 .arg(kw::name = "bar", kw::default_value = 0);
76 // Start the interactive console server
77 senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
82 after this registration, the console can be accessed easily via telnet:
85 $ telnet localhost 23232
87 Connected to localhost.
88 Escape character is '^]'
89 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Registered new client 0xxxxxxx
92 someServer:/# mycommand
93 !! Important message ...
95 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Disposing client 0xxxxxxx
96 Connection closed by foreign host.
101 \section intro_nodes The node tree
103 The basic idea is, that the console/config library manages a directory structure of parameters
104 and auxiliary commands. Parameters are just commands which set a parameter value so everything
105 is either a directory entry (senf::console::DirectoryNode) or a command
106 (senf::console::CommandNode).
111 \section intro_commands Console/config commands
113 The console/config language does not define, how arguments are passed to the commands, it just
114 tokenizes the input and passes the tokens to the commands which then handle the
117 Since parsing the tokens into something usable is quite tedious and error prone, the library
118 implements automatic argument parsing where the argument tokens are automatically parsed
119 depending on argument types. This enables you to register a command taking an integer argument
120 which will be called with an already parsed integer value (or throw a
121 senf::console::SyntaxErrorException if the conversion fails). This will be the most often used
124 \see \ref console_commands
127 \section intro_language The console/config language
129 To call the commands and set parameters, a very simple language is defined. The language is
130 almost declarative (e.g. it does not have any control-flow statements) but is processed
131 imperatively from top to bottom. This is very simple and flexible.
133 Commands are referenced by their path in the node tree. To simplify working with deeply nested
134 directory structures, the current directory may be changed persistently or temporarily for some
139 /logger/targets/console {
140 accept senf::log::Debug IMPORTANT;
141 accept server::ServerLog CRITICAL;
145 \see \ref console_parser
148 /** \defgroup console_commands Supported command types
150 The Console/config library supports quite a number of different command types. All these types
151 of command are registered, by passing them to DirectoryNode::add()
155 \section console_cmdadd Adding commands and setting attributes
157 Basically, all commands are added using senf::console::DirectoryNode::add(). What exactly
158 happens depends on the type of object added.
160 dir.add("name", callback)
162 will add a command 'name' which will execute 'callback' when called, where 'callback' can be a
163 lot of things as documented in the following chapters.
165 The add call always returns (something which can be used as) a reference to the command node
168 senf::console::CommandNode & node ( dir.add( ... ) );
171 Depending on the object added, you can also bind to a more specific node type
172 (e.g. senf::console::SimpleCommand) if you know the type of node returned.
174 Depending on the type of object added, there are additional attributes which can be set. These
175 attributes are always set by calling them on the return value <b>before saving that value as a
176 node reference</b>. It is \e not guaranteed, you can call these members on the node
179 dir.add("name", callback)
180 .doc("The documentation");
182 sets the \e doc attribute (if that is available, otherwise this will fail to compile). The
183 attribute members return value is again (something which can be used as) a reference to the
186 senf::console::CommandNode & node (
187 dir.add("name", callback)
188 .doc("The documentation") );
192 \section console_manualparse Manually parsing command arguments
194 This is the most primitive type of command. It will be called with an output stream and with a
195 senf::console::ParseCommandInfo reference which holds information about the command parsed.
197 From this information the command callback gets a list of arguments or tokens which then can be
198 interpreted in an arbitrary way.
200 void fun1(std::ostream & os, senf::console::ParseCommandInfo const & command)
202 // We take exactly one argument
203 if (command.arguments().size() != 1)
204 raise senf::console::SyntaxErrorException("invalid number of arguments");
206 senf::console::ParseCommandInfo::TokenRange & argTokens (
207 command.arguments()[0]);
209 // The argument must have exactly one token
210 if (argTokens.size() != 1)
211 raise senf::console::SyntaxErrorException("argument syntax error");
213 // Retrieve the token value
214 std::string arg (argTokens[0].value());
216 // In this example, we just write the argument to the output stream
217 os << arg << std::endl;
221 Registering this callback is done by simply adding it. To provide online help, pass it to
224 senf::console::root()
229 "Echo 'arg' to the console");
232 The callback may now be called interactively on the console by it's registered name:
236 invalid number of arguments
237 server:/$ test1 stefan@j32.de
239 server:/$ test1 (echo me)
240 argument syntax error
245 Echo 'arg' to the console
250 As you can see above, the arguments and tokens are returned as <a
251 href="http://www.boost.org/doc/libs/1_33_1/libs/range/doc/utility_class.html#iter_range">
252 boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
253 \c end() and some other useful members.
255 The parser will have divided the argument tokens into arguments already. This simplifies further
256 parsing. If however you want to access the list of argument tokens as a single list, you can do
257 so using senf::console::ParseCommandInfo::tokens().
259 Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
260 can be delegated to the Console/config library. See the next section.
262 This type of command has only a single attribute, \e doc to set the commands documentation.
265 \section console_autoparse Automatic argument parsing
267 To greatly simplify parsing complex commands, we turn to automatic argument parsing.
269 \subsection console_autoadd Adding
271 Automatically parsed commands are registered by just adding a callback which has the correct
272 arguments and return-value defined:
274 std::string fun2(std::string const & arg)
280 This extremely simple callback may be registered by adding it to a senf::console::DirectoryNode.
282 senf::console::root()
283 .add("test2", &fun2);
285 The functionality is now identical to \c test1:
289 invalid number of arguments
290 server:/$ test2 stefan@j32.de
292 server:/$ test2 (echo me)
293 argument syntax error
302 \subsection command_ostream Accessing the console stream
304 Commands may have an optional first argument of type <tt>std::ostream &</tt>. This argument is
305 not considered part of the real interface. When the command is executed, the callback will be
306 passed the current console's output stream object in this argument. With this, the callback can
307 output arbitrary messages to the network console.
309 void fun3(std::ostream & os, unsigned n, std::string text)
311 while (n-- > 0) os << text << std::endl;
314 senf::console::root()
315 .add("test3", &fun3);
318 This simple command can now be used thus:
322 invalid number of arguments
323 server:/$ test3 stefan@j32.de
324 invalid number of arguments
330 test3 arg11:int arg12:string
335 \subsection command_overload Overloading
337 Automatically parsed commands can be overloaded: You can register multiple commands under the
338 same name. Each overload is tried in turn until no SyntaxErrorException is raised.
340 senf::console::root()
341 .add("test4", &fun3);
342 senf::console::root()
343 .add("test4", &fun2);
345 And now, we can call \c test4 with one or two args:
348 invalid number of arguments
349 server:/$ test4 stefan@j32.de
356 1- test4 arg11:int arg12:string
357 2- test4 arg21:string
361 \subsection console_attributes Attributes
363 As have seen so far, some documentation is automatically provided. We can add more info, by
364 setting additional attributes.
366 senf::console::root()
368 .doc("Echo text to the console")
369 .overloadDoc("Repeat {arg12} for {arg11} lines");
370 senf::console::root()
372 .overloadDoc("Echo the {arg21} argument")
375 This additional info is used to provide more documentation:
380 1- test5 arg11:int arg12:string
381 2- test5 arg21:string
383 Echo text to the console
386 Repeat {arg12} for {arg11} lines
389 Echo the {arg21} argument
395 \subsection console_argattributes Argument attributes
397 Additional attributes can be set for each parameter. They are all passed to the
398 senf::console::ParsedArgumentAttributor::arg() attribute.
401 namespace kw = senf::console::kw;
403 senf::console::root()
405 .doc("Echo text to the console")
406 .overloadDoc("Repeat {text} for {n} lines");
407 .arg( kw::name = "n", kw::description="Number of repetitions" )
408 .arg( kw::name = "text", kw::description="Text to output" );
409 senf::console::root()
411 .overloadDoc("Echo the {text} argument")
412 .arg( kw::name = "text" );
415 (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
416 Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
417 are set using keywords from the \ref senf::console::kw namespace. You will probably either use
418 this namespace via a namespace alias (as above) or via a <tt>using namespace
419 senf::console::kw</tt> declaration (but beware of name collisions).
421 You don't need to specify any information for an argument: To skip an argument, just call \c
422 arg() without attributes for this argument.
424 After adding this information, the online help is much more readable
429 1- test6 n:int text:string
433 n Number of repetitions
436 Echo text to the console
439 Repeat {text} for {n} lines
442 Echo the {text} argument
447 Since most of the time, we only need to set the name and possibly a description for arguments,
448 there is a shortcut: name and description can be specified as positional arguments in this
449 order. So the following will give the exactly same result as above:
451 namespace kw = senf::console::kw;
453 senf::console::root()
455 .doc("Echo text to the console")
456 .overloadDoc("Repeat <text> for <n> lines");
457 .arg("n", "Number of repetitions")
458 .arg("text", "Text to output");
459 senf::console::root()
461 .overloadDoc("Echo the <text> argument")
465 Keyword arguments should always be used if additional attributes are set. You can however mix
466 positional and keyword arguments.
469 \subsection console_defaults Default values
471 Another information which can not be automatically gathered from the type system is default
472 values. These have to be declared explicitly:
474 namespace kw = senf::console::kw;
476 senf::console::root()
478 .doc("Echo {text} to the console, repeating {text} for {n} lines")
479 .arg("n", "Number of repetitions", kw::default_value=1)
480 .arg("text", "Text to output");
483 Default values can be used together with overloading. Default (optional) value support is quite
484 flexible, it is not mandatory, for default values to be specified only for the trailing
485 arguments. For the exact definition, how parsed argument values are assigned to overload
486 arguments in the presence of default values, see \ref senf::console::kw::default_value.
499 test4 [n:unsigned] text:string
502 n Number of repetitions
506 Echo {text} to the console, repeating {text} for {n} lines
512 \subsection console_boostfn Non-function-pointer commands
514 It is possible to add other callable objects besides function (and member-function)
515 pointers. However, since it is not possible to automatically deduce the argument and return
516 types in this case, the callables have to be wrapped in a \c boost::function object:
519 senf::console::root()
521 boost::function<void (std::ostream &, std::string const &)>(
522 boost::bind(&fun3, _1, 4u, _2)));
525 This works with any callable object where argument types cannot be deduced automatically:
526 Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
543 \subsection console_attr_summary Attribute summary
545 Here a summary of the most common attributes
547 <table class="senf fixedwidth">
549 <tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
550 ( \e doc )</td><td>Set documentation for all overloads</td></tr>
552 <tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
553 .overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
555 <tr><td>\link senf::console::ParsedArgumentAttributor::arg() .arg\endlink ( \e argument \e
556 attributes )</td><td>Set argument attributes (see below)</td></tr>
560 The most important argument attributes (all defined in the senf::console::kw namespace) are:
562 <table class="senf fixed width">
564 <tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
567 <tr><td>\link senf::console::kw::description kw::description\endlink</td><td>One-line
568 description of the argument</td></tr>
570 <tr><td>\link senf::console::kw::default_value kw::default_value\endlink</td><td>Arguments
571 default value</td></tr>
576 href="classsenf_1_1console_1_1ParsedArgumentAttributor-members.html">senf::console::ParsedArgumentAttributor
577 / List of all members</a> for the complete attribute interface \n
578 \ref senf::console::kw for a list of all argument attribute keywords
581 \section console_memberfn Member functions
583 Member functions are supported like non-member functions. They must however be added through a
584 senf::console::ScopedDirectory instance to bind them to their instance.
589 senf::console::ScopedDirectory<Test> dir;
591 Test(std::string label) : dir(this), label_ (label)
593 dir.add("test4", &Test::test2);
594 dir.add("test4", &Test::test3);
597 std::string test2(std::string const & text)
598 { return label_ + ": " + text; }
600 void test3(std::ostream & os, unsigned n, std::string const & text)
601 { while (n-- > 0) os << label << ": " << text << std::endl; }
609 Test testOb ("test");
610 senf::console::root().add("testobj", testOb.dir);
613 Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
614 from the tree when the object is destroyed.
621 // comment-column: 40
622 // c-file-style: "senf"
623 // indent-tabs-mode: nil
624 // ispell-local-dictionary: "american"
625 // compile-command: "scons -u test"