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 One note: When taking the address of an overloaded function (member or non-member), the C++
362 language forces you to cast that address to one of the possible types so the compiler knows,
363 which overload is requested. So to add a function which is overloaded in C++, each overload
364 needs to be added explicitly, casting to the correct type:
369 senf::console::root()
370 .add("over", static_cast<void (*)(int)>(&over));
371 senf::console::root()
372 .add("over", static_cast<void (*)(int,int)>(&over));
376 \subsection console_attributes Attributes
378 As have seen so far, some documentation is automatically provided. We can add more info, by
379 setting additional attributes.
381 senf::console::root()
383 .doc("Echo text to the console")
384 .overloadDoc("Repeat {arg12} for {arg11} lines");
385 senf::console::root()
387 .overloadDoc("Echo the {arg21} argument")
390 This additional info is used to provide more documentation:
395 1- test5 arg11:int arg12:string
396 2- test5 arg21:string
398 Echo text to the console
401 Repeat {arg12} for {arg11} lines
404 Echo the {arg21} argument
410 \subsection console_argattributes Argument attributes
412 Additional attributes can be set for each parameter. They are all passed to the
413 senf::console::ParsedArgumentAttributor::arg() attribute.
416 namespace kw = senf::console::kw;
418 senf::console::root()
420 .doc("Echo text to the console")
421 .overloadDoc("Repeat {text} for {n} lines");
422 .arg( kw::name = "n", kw::description="Number of repetitions" )
423 .arg( kw::name = "text", kw::description="Text to output" );
424 senf::console::root()
426 .overloadDoc("Echo the {text} argument")
427 .arg( kw::name = "text" );
430 (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
431 Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
432 are set using keywords from the \ref senf::console::kw namespace. You will probably either use
433 this namespace via a namespace alias (as above) or via a <tt>using namespace
434 senf::console::kw</tt> declaration (but beware of name collisions).
436 You don't need to specify any information for an argument: To skip an argument, just call \c
437 arg() without attributes for this argument.
439 After adding this information, the online help is much more readable
444 1- test6 n:int text:string
448 n Number of repetitions
451 Echo text to the console
454 Repeat {text} for {n} lines
457 Echo the {text} argument
462 Since most of the time, we only need to set the name and possibly a description for arguments,
463 there is a shortcut: name and description can be specified as positional arguments in this
464 order. So the following will give the exactly same result as above:
466 namespace kw = senf::console::kw;
468 senf::console::root()
470 .doc("Echo text to the console")
471 .overloadDoc("Repeat <text> for <n> lines");
472 .arg("n", "Number of repetitions")
473 .arg("text", "Text to output");
474 senf::console::root()
476 .overloadDoc("Echo the <text> argument")
480 Keyword arguments should always be used if additional attributes are set. You can however mix
481 positional and keyword arguments.
484 \subsection console_defaults Default values
486 Another information which can not be automatically gathered from the type system is default
487 values. These have to be declared explicitly:
489 namespace kw = senf::console::kw;
491 senf::console::root()
493 .doc("Echo {text} to the console, repeating {text} for {n} lines")
494 .arg("n", "Number of repetitions", kw::default_value=1)
495 .arg("text", "Text to output");
498 Default values can be used together with overloading. Default (optional) value support is quite
499 flexible, it is not mandatory, for default values to be specified only for the trailing
500 arguments. For the exact definition, how parsed argument values are assigned to overload
501 arguments in the presence of default values, see \ref senf::console::kw::default_value.
514 test4 [n:unsigned] text:string
517 n Number of repetitions
521 Echo {text} to the console, repeating {text} for {n} lines
527 \subsection console_boostfn Non-function-pointer commands
529 It is possible to add other callable objects besides function (and member-function)
530 pointers. However, since it is not possible to automatically deduce the argument and return
531 types in this case, the callables have to be wrapped in a \c boost::function object:
534 senf::console::root()
536 boost::function<void (std::ostream &, std::string const &)>(
537 boost::bind(&fun3, _1, 4u, _2)));
540 This works with any callable object where argument types cannot be deduced automatically:
541 Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
558 \subsection console_attr_summary Attribute summary
560 Here a summary of the most common attributes
562 <table class="senf fixedwidth">
564 <tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
565 ( \e doc )</td><td>Set documentation for all overloads</td></tr>
567 <tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
568 .overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
570 <tr><td>\link senf::console::ParsedArgumentAttributor::arg() .arg\endlink ( \e argument \e
571 attributes )</td><td>Set argument attributes (see below)</td></tr>
575 The most important argument attributes (all defined in the senf::console::kw namespace) are:
577 <table class="senf fixed width">
579 <tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
582 <tr><td>\link senf::console::kw::description kw::description\endlink</td><td>One-line
583 description of the argument</td></tr>
585 <tr><td>\link senf::console::kw::default_value kw::default_value\endlink</td><td>Arguments
586 default value</td></tr>
591 href="classsenf_1_1console_1_1ParsedArgumentAttributor-members.html">senf::console::ParsedArgumentAttributor
592 / List of all members</a> for the complete attribute interface \n
593 \ref senf::console::kw for a list of all argument attribute keywords
596 \section console_memberfn Member functions
598 Member functions are supported like non-member functions. They must however be added through a
599 senf::console::ScopedDirectory instance to bind them to their instance.
604 senf::console::ScopedDirectory<Test1> dir;
606 Test1(std::string label) : dir(this), label_ (label)
607 { dir.add("test", &Test::test1);
608 dir.add("test", &Test::test2); }
610 std::string test1(std::string const & text)
611 { return label_ + ": " + text; }
613 void test2(std::ostream & os, unsigned n, std::string const & text)
614 { while (n-- > 0) os << label << ": " << text << std::endl; }
622 Test1 test1ob ("test");
623 senf::console::root().add("test1ob", test1ob.dir);
626 Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
627 from the tree when the object is destroyed.
630 \section console_variables Variables
632 \subsection console_varadd Adding
634 The console/config library supports the direct registration of variables as commands. A
635 variable command consists of two overloads, one to query the current value and one to change the
641 senf::console::ScopedDirectory<Test2> dir;
643 Test2() : dir(this), var_(0)
644 { dir.add("var", var_); }
651 senf::console::root().add("test2ob", test2ob.dir);
653 This shows the most common scenario: A member variable is added to a ScopedDirectory of the same
654 class. This ensures, that the variable command node is removed from the tree when the instance
655 (and thereby the variable) are destroyed. The variable can now be used like any other command:
658 server:/$ test2ob/var
660 server:/$ test2ob/var 10
661 server:/$ test2ob/var
663 server:/$ help test2ob
672 \subsection console_varro Read-only variables
674 The library also supports read-only variables. To make a variable read-only, just wrap it in \c
675 boost::cref() (where \c cref stands for \c const reference)
679 senf::console::root().add("var1", boost::cref(var));
681 A read-only variable only has a single overload:
694 \subsection console_varattr Attributes
696 The most important Variable command attributes are
698 <table class="senf fixedwidth">
700 <tr><td style="width:14em">\link senf::console::VariableAttributor::doc() .doc\endlink
701 ( \e doc )</td><td>Set variable documentation</td></tr>
703 <tr><td>\link senf::console::VariableAttributor::onChange() .onchange\endlink
704 ( \e handler )</td><td>Set change handler</td></tr>
708 \see senf::console::VariableAttributor for the complete attribute interface
710 \subsection console_varchange Change notification
712 A \e handler can be set to be called, whenever the variable is changed. It will be called with a
713 reference to the old value. The handler is called, after the value has been changed
718 // Since this is int, it would make sense to declare the argument pass-by-value (int old)
719 // but for more complex args, use a const & here
720 void varChanged(int const & old)
725 senf::console::root().add("var2",var)
726 .onChange(&varChanged);
729 After this setup, \c varChanged will be called, whenever the value has changed.
732 \see senf::console::VariableAttributor for the complete attribute interface
739 // comment-column: 40
740 // c-file-style: "senf"
741 // indent-tabs-mode: nil
742 // ispell-local-dictionary: "american"
743 // compile-command: "scons -u test"