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 The Config/Console library is built around several components
38 \li The \link node_tree Node tree\endlink represents all configuration options and commands
39 organized in a filesystem like structure.
40 \li \link console_commands Actions\endlink are added to the node tree in the form of command
42 \li There exist several interfaces to \link console_access access\endlink entries in the node
43 tree: interactive console, reading configuration files etc.
45 The node tree works like a directory structure. Commands are entered into this directory
46 structure and can be called passing arbitrary arguments. Configuration parameters are just
47 commands which set their respective parameter, however the library allows commands to do much
50 \section console_example Example
52 The following example shows a \e very short summary on how to integrate the config/console
53 library. See above links for more:
56 #include <senf/Console.hh>
58 // Define callback function.
59 void mycommand(std::ostream & os, int foo, int bar)
62 os << "!! Important message ...\n";
65 namespace kw = senf::console::kw;
67 int main(int argc, char** argv)
69 // Provide global documentation
71 .doc("This is someServer server");
75 .add("mycommand", &mycommand)
76 .doc("If <bar> is given, flurgle the <foo>, otherwise burgle it")
78 .arg(kw::name = "bar", kw::default_value = 0);
80 // Parse command line parameters
81 senf::console::parseOptions(argc,argv);
83 // Start the interactive console server
84 senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
88 senf::Scheduler::instance().process();
92 after this registration, we can call the command from the command-line using
95 $ someServer --mycommand="1 2"
98 the console can be accessed easily via telnet:
101 $ telnet localhost 23232
103 Connected to localhost.
104 Escape character is '^]'
105 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Registered new client 0xxxxxxx
108 someServer:/# mycommand
109 !! Important message ...
111 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Disposing client 0xxxxxxx
112 Connection closed by foreign host.
116 \see \ref console_testserver for a complete example application
118 \section intro_usage Access
120 There are several ways to access the node tree:
121 \li By parsing configuration files
122 \li By parsing command line parameters
123 \li By providing interactive console access
127 \section intro_nodes The node tree
129 The basic idea is, that the console/config library manages a directory structure of parameters
130 and auxiliary commands. Parameters are just commands which set a parameter value so everything
131 is either a directory entry (senf::console::DirectoryNode) or a command
132 (senf::console::CommandNode).
137 \section intro_commands Registering console/config commands
139 The console/config language does not define, how arguments are passed to the commands, it just
140 tokenizes the input and passes the tokens to the commands which then handle the
143 Since parsing the tokens into something usable is quite tedious and error prone, the library
144 implements automatic argument parsing where the argument tokens are automatically parsed
145 depending on argument types. This enables you to register a command taking an integer argument
146 which will be called with an already parsed integer value (or throw a
147 senf::console::SyntaxErrorException if the conversion fails). This will be the most often used
150 \see \ref console_commands
153 /** \defgroup console_access Accessing the Console/Config tree
155 The Console/Config library provides several ways to use the node tree to configure and control
160 \section console_access_config Configuration support
162 The configuration support of the Console/Config library revolves around the ConfigSource
163 concept. Each ConfigSource will somehow provide commands which will then be executed against the
166 To simplify the usage, there will always be three interfaces to a specific config source:
167 \li A constructor to build a bare config source which is then added to a
168 senf::console::ConfigBundle (see \ref console_access_multiple)
169 \li A class parsing and executing a single config source. The visible interface of this class is
170 a combination of the constructor and the senf::console::ConfigBundle interfaces.
171 \li A helper function which will do the complete parsing of a single source with default
174 When parsing these configuration sources, it is always possible to optionally change the root
175 node used during parsing and it is also possible to restrict parsing to a command subset. See
176 \ref console_access_partial.
178 \subsection console_access_file Configuration files
180 <table class="senf fixedwidth">
181 <tr><td><b>Constructor</b></td> <td>senf::console::FileConfig()</td></tr>
182 <tr><td><b>Class</b></td> <td>senf::console::ConfigFile</td></tr>
183 <tr><td><b>Helper</b></td> <td>senf::console::parseFile()</td></tr>
186 In it's simplest form, parsing a configuration file consists of calling
187 senf::console::parseFile() with the name of the respective config file as argument.
190 senf::console::parseFile("some.conf");
193 To get more flexible, instantiate a senf::console::ConfigFile instance at use that to parse the
197 senf::console::ConfigFile cf ("some.conf");
201 If the application supports other configuration sources besides a single configuration file
202 (like command line options) or if it supports multiple configuration files (e.g. a system-wide
203 and a user specific configuration file) see \ref console_access_multiple and add one (or more)
204 senf::console::FileConfig() source to a senf::console::ConfigBundle.
206 \subsubsection console_access_file_syntax Configuration file syntax
208 Configuration files are written in a simple configuration language. This language is almost
209 declarative (e.g. it does not have any control-flow statements) but is processed imperatively
210 from top to bottom. This is very simple and flexible.
212 Commands are referenced by their path in the node tree. To simplify working with deeply nested
213 directory structures, the current directory may be changed persistently or temporarily for some
218 /logger/targets/console {
219 accept senf::log::Debug IMPORTANT;
220 accept server::ServerLog CRITICAL;
224 \see \ref console_parser
226 \subsection console_access_options Command line options
228 <table class="senf fixedwidth">
229 <tr><td><b>Constructor</b></td> <td>senf::console::OptionsConfig()</td></tr>
230 <tr><td><b>Class</b></td> <td>senf::console::ProgramOptions</td></tr>
231 <tr><td><b>Helper</b></td> <td>senf::console::parseOptions()</td></tr>
234 Command line options can either be parsed by calling the senf::console::parseOptions() helper
237 senf::console::parseOptions(argc, argv)
240 or more flexibly by instantiating a senf::console::ProgramOptions class
243 std::vector<std::string> args;
244 senf::console::ProgramOptions opts (argc, argv);
247 .alias('c', "--mycommand",true)
248 .alias('C', "--mycommand=2 3");
252 This registeres two short options and accumulates all non-option arguments in \c args.
254 If the application supports other configuration sources besides the command line options (like
255 configuration files) see \ref console_access_multiple and add a senf::console::OptionsConfig()
256 source to a senf::console::ConfigBundle.
258 See \ref senf::console::ProgramOptions for the source specific additional parameters. These
259 apply to senf::console::ProgramOptions and to the senf::console::OptionsConfig() source.
261 \subsubsection console_access_options_syntax Options syntax
263 Command line options are primarily parsed as long-options. Long options start with '--'. Further
264 '-' characters serve as directory separators if required (that is, they are \e only interpreted
265 as directory separator is there is no entry in the current (sub-) directory matching more than a
266 single name component). This still allows using hyphens in node names.
268 Options can be abbreviated at each directory boundary: A command <tt>/foo/bar/do</tt> can be
269 called as <tt>--f-b-d</tt> as long as this name is unique.
271 Everything after the first '=' character is parsed into argument tokens using the normal
272 config/console parser. If the option has no '=' character, the list of argument tokens will be
275 <table style="font-size:80%" class="senf">
276 <tr><th>Command</th><th>File syntax</th><th>Option syntax</th></tr>
279 <td><tt>void doo()</tt></td>
280 <td><tt>/path/to/doo;</tt></td>
281 <td><tt>--path-to-doo</tt></td>
285 <td><tt>void doo(std::string const &)</tt></td>
286 <td><tt>/path/to/doo john.doe@everywhere.org;</tt></td>
287 <td><tt>--path-to-doo="john.doe@everywhere.org"</tt></td>
291 <td><tt>void doo(std::string const &)</tt></td>
292 <td><tt>/path/to/doo "some test";</tt></td>
293 <td><tt>--path-to-doo='"some text"'</tt></td>
297 <td><tt>void doo(std::string const &, int)</tt></td>
298 <td><tt>/path/to/doo take 1;</tt></td>
299 <td><tt>--path-to-doo="take 1"</tt></td>
303 The last column is additionally quoted using standard \c sh quoting: quotes in arguments need to
304 be additionally quoted for the shell.
306 Short options are registered as aliases for long options. They can be registered with or without
307 an implied parameter and can optionally take a parameter. so after
311 .alias('c', "--mycommand",true)
312 .alias('C', "--mycommand=2 3");
318 $ program -C -c "4 5"
325 $ program --mycommand="2 3" --mycommand="4 5"
328 (Beware, that the second argument to \c alias() is \e not shell quoted).
330 \subsection console_access_root Changing the root node
332 When used in it's default state, parsing will always interpret all commands relative to the
333 senf::console::root() node and will parse a file completely.
335 The first possibility to control this is to change the root node. This is done by
336 \li passing that root node to the helper class or to the parse helper as an additional argument
337 (see the respective documentation).
338 \li passing it to the senf:;console::ConfigBundle constructor when parsing multiple sources.
343 senf::console::parseFile("/etc/myserver.conf", senf::console::root()['config']);
346 This functionality is even more powerful by combining it with \c link nodes: This allows to
347 selectively choose commands from the node tree which are to be made accessible for
348 configuration. See \ref node_tree.
350 \subsection console_access_partial Partial / incremental configuration
352 Another feature provided by senf::console::ConfigBundle and all helper classes is partial
356 // Create a console/config aware object and place it into the node tree
358 senf::console::add("foo", foo.dir);
360 // Open configuration file
361 senf::console::ConfigFile cf ("/etc/myserver.conf");
363 // Parse only commands in the configuration file which are in the foo.dir directory
368 // Anywhere later, parse the rest of the configuration file
372 This feature allows to parse parts of one or more configuration sources before the
373 console/config tree has been fully established. Partial parsing can be applied any number of
374 times to arbitrary nodes. Any command already parsed will be skipped automatically.
376 When combining partial parsing with \c chroot() and \c link's, it is important to realize, that
377 <em>partial parsing always applies to the \e real target and ignores links</em>. This is very
378 important: It allows a subsystem to parse it's configuration parameters irrespective of any
379 links pointing to nodes of that subsystem.
381 \subsection console_access_multiple Multiple sources
383 Most of the time, an application will utilize multiple configuration sources: A global
384 configuration file, maybe a user specific local configuration file, command line options ...
386 When parsing configuration commands, especially using partial / incremental parsing, all parse
387 commands should be applied to each configuration source in turn. This is the responsibility of
388 senf::console::ConfigBundle.
391 senf::console::ScopedDirectory<> config;
392 senf::console::root().add("config", config);
394 // Let's enable all logger commands for configuration
395 config.link("logger", senf::console::root()["logger"]);
397 // Create bundle and add sources
398 std::vector<std::string> args;
399 senf::console::ConfigBundle conf (senf::console::root()["config"]);
400 conf.add( senf::console::FileConfig("/etc/myserver.conf") );
401 conf.add( senf::console::FileConfig(".myserver.conf") );
402 conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(),
403 senf::Daemon::instance().argv()) )
405 .alias('c', "--mycommand",true)
406 .alias('C', "--mycommand=2 3");
408 // Parse the logger subsystem commands in '/logger'
409 conf.parse(senf::console::root()['logger']);
413 // Parse all other configuration commands. All necessary commands and links in '/config' must by
414 // now have been created.
418 This example parses three configuration sources: Two configuration files and additional
419 parameters specified on the command line. All the configuration commands are placed into the
420 <tt>/config</tt> directory (directly or via links). The configuration sources are parsed in the
421 order they are specified, so in this case, the command line options will override any options
422 specified in one of the configuration files.
424 \section console_access_console The interactive console
426 To make the console accessible, it must be initialized when the program is started:
428 #include <senf/Console.hh>
430 int main(int argc, char * argv [])
432 // Configure console nodes, add commands ...
434 // Start console server
435 senf::console::start(senf::INet4SocketAddress(12345u))
438 // You need to enter the scheduler main-loop for the server to work
439 senf::Scheduler::instance().process();
441 // Alternatively enter the main-loop via the PPI
446 This will start the server on IPv4 port 12345. The servers name (as displayed in the interactive
447 console prompt) is set to 'myserver'.
449 After launching the application, the server can be accessed at the given port:
452 bash$ telnet localhost 12345
454 Connected to localhost.
455 Escape character is '^]'.
458 Connection closed by foreign host.
463 \subsection console_serverclient Server and Client objects
465 The senf::console::Server and senf::console::Client objects offer further API calls. To access
466 the server instance you need to store away the senf::console::Server reference returned when
467 starting the server so you can later refer to it:
469 int main(int, char**)
471 senf::console::Server & server ( senf::console::start( ... ) );
479 The client instance can be accessed via the \c std::ostream arg of any command callback
481 void someCallback(std::ostream & os, ... )
483 senf::console::Client & client (senf::console::Client::get(os));
485 // Use the client's log target
486 client.route<senf::log::Debug, senf::Log::IMPORTANT>();
491 senf::console::Server for the Server API \n
492 <a href="classsenf_1_1console_1_1Client-members.html">senf::console::Client / List of all
493 members</a> for the Client API
496 \subsection console_shell Features of the interactive console shell
498 The interactive shell will use the GNU readline library for the first connected
499 instance. Further users will not have access to this functionality since GNU readline is
500 completely non-reentrant.
502 The shell supports auto-cd and auto-completion: If you enter the name of a directory at the
503 prompt, the console will change to that directory. With auto-completion, any unique beginning of
504 a path component will be completed automatically and transparently to th corresponding full
509 /** \defgroup console_commands Supported command types
511 The Console/config library supports quite a number of different command types. All these types
512 of command are registered, by passing them to DirectoryNode::add()
516 \section console_cmdadd Adding commands and setting attributes
518 Basically, all commands are added using senf::console::DirectoryNode::add(). What exactly
519 happens depends on the type of object added.
521 dir.add("name", callback)
523 will add a command 'name' which will execute 'callback' when called, where 'callback' can be a
524 lot of things as documented in the following chapters.
526 The add call always returns (something which can be used as) a reference to the command node
529 senf::console::CommandNode & node ( dir.add( ... ) );
532 Depending on the object added, you can also bind to a more specific node type
533 (e.g. senf::console::SimpleCommand) if you know the type of node returned.
535 Depending on the type of object added, there are additional attributes which can be set. These
536 attributes are always set by calling them on the return value <b>before saving that value as a
537 node reference</b>. It is \e not guaranteed, you can call these members on the node
540 dir.add("name", callback)
541 .doc("The documentation");
543 sets the \e doc attribute (if that is available, otherwise this will fail to compile). The
544 attribute members return value is again (something which can be used as) a reference to the
547 senf::console::CommandNode & node (
548 dir.add("name", callback)
549 .doc("The documentation") );
553 \section console_manualparse Manually parsing command arguments
555 This is the most primitive type of command. It will be called with an output stream and with a
556 senf::console::ParseCommandInfo reference which holds information about the command parsed.
558 From this information the command callback gets a list of arguments or tokens which then can be
559 interpreted in an arbitrary way.
561 void fun1(std::ostream & os, senf::console::ParseCommandInfo const & command)
563 // Here we declare variables for the arguments
567 // We parse the arguments using the CheckedArgumentIteratorWrapper. This wrapper
568 // will throw a SyntaxErrorException if we access a nonexistent argument or if we
569 // do not parse all arguments.
570 senf::console::CheckedArgumentIteratorWrapper args (command.arguments());
572 senf::console::ParseCommandInfo::TokensRange argTokens ( *(args++) );
573 if (arg1Tokens.size() != 1)
574 raise senf::console::SyntaxErrorException("argument syntax error");
575 value = arg1Tokens[0];
578 os << value << std::endl;
582 Registering this callback is done by simply adding it. To provide online help, pass it to
585 senf::console::root()
590 "Echo 'arg' to the console");
593 The callback may now be called interactively on the console by it's registered name:
597 invalid number of arguments
598 server:/$ test1 stefan@j32.de
600 server:/$ test1 (echo me)
601 argument syntax error
606 Echo 'arg' to the console
611 As you can see above, the arguments and tokens are returned as <a
612 href="http://www.boost.org/doc/libs/1_33_1/libs/range/doc/utility_class.html#iter_range">
613 boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
614 \c end() and some other useful members.
616 The parser will have divided the argument tokens into arguments already. This simplifies further
617 parsing. If however you want to access the list of argument tokens as a single list, you can do
618 so using senf::console::ParseCommandInfo::tokens().
620 Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
621 can be delegated to the Console/config library. See the next section.
623 This type of command has only a single attribute, \e doc to set the commands documentation.
626 \section console_autoparse Automatic argument parsing
628 To greatly simplify parsing complex commands, we turn to automatic argument parsing.
630 \subsection console_autoadd Adding
632 Automatically parsed commands are registered by just adding a callback which has the correct
633 arguments and return-value defined:
635 std::string fun2(std::string const & arg)
641 This extremely simple callback may be registered by adding it to a senf::console::DirectoryNode.
643 senf::console::root()
644 .add("test2", &fun2);
646 The functionality is now identical to \c test1:
650 invalid number of arguments
651 server:/$ test2 stefan@j32.de
653 server:/$ test2 (echo me)
654 argument syntax error
663 \subsection command_ostream Accessing the console stream
665 Commands may have an optional first argument of type <tt>std::ostream &</tt>. This argument is
666 not considered part of the real interface. When the command is executed, the callback will be
667 passed the current consoles output stream object in this argument. With this, the callback can
668 output arbitrary messages to the network console.
670 void fun3(std::ostream & os, unsigned n, std::string text)
672 while (n-- > 0) os << text << std::endl;
675 senf::console::root()
676 .add("test3", &fun3);
679 This simple command can now be used thus:
683 invalid number of arguments
684 server:/$ test3 stefan@j32.de
685 invalid number of arguments
691 test3 arg11:int arg12:string
696 \subsection command_overload Overloading
698 Automatically parsed commands can be overloaded: You can register multiple commands under the
699 same name. Each overload is tried in turn until no SyntaxErrorException is raised.
701 senf::console::root()
702 .add("test4", &fun3);
703 senf::console::root()
704 .add("test4", &fun2);
706 And now, we can call \c test4 with one or two args:
709 invalid number of arguments
710 server:/$ test4 stefan@j32.de
717 1- test4 arg11:int arg12:string
718 2- test4 arg21:string
722 One note: When taking the address of an overloaded function (member or non-member), the C++
723 language forces you to cast that address to one of the possible types so the compiler knows,
724 which overload is requested. So to add a function which is overloaded in C++, each overload
725 needs to be added explicitly, casting to the correct type:
730 senf::console::root()
731 .add("over", static_cast<void (*)(int)>(&over));
732 senf::console::root()
733 .add("over", static_cast<void (*)(int,int)>(&over));
737 \subsection console_attributes Attributes
739 As have seen so far, some documentation is automatically provided. We can add more info, by
740 setting additional attributes.
742 senf::console::root()
744 .doc("Echo text to the console")
745 .overloadDoc("Repeat {arg12} for {arg11} lines");
746 senf::console::root()
748 .overloadDoc("Echo the {arg21} argument")
751 This additional info is used to provide more documentation:
756 1- test5 arg11:int arg12:string
757 2- test5 arg21:string
759 Echo text to the console
762 Repeat {arg12} for {arg11} lines
765 Echo the {arg21} argument
771 \subsection console_argattributes Argument attributes
773 Additional attributes can be set for each parameter. They are all passed to the
774 senf::console::ParsedArgumentAttributor::arg() attribute.
777 namespace kw = senf::console::kw;
779 senf::console::root()
781 .doc("Echo text to the console")
782 .overloadDoc("Repeat {text} for {n} lines");
783 .arg( kw::name = "n", kw::description="Number of repetitions" )
784 .arg( kw::name = "text", kw::description="Text to output" );
785 senf::console::root()
787 .overloadDoc("Echo the {text} argument")
788 .arg( kw::name = "text" );
791 (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
792 Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
793 are set using keywords from the \ref senf::console::kw namespace. You will probably either use
794 this namespace via a namespace alias (as above) or via a <tt>using namespace
795 senf::console::kw</tt> declaration (but beware of name collisions).
797 You don't need to specify any information for an argument: To skip an argument, just call \c
798 arg() without attributes for this argument.
800 After adding this information, the online help is much more readable
805 1- test6 n:int text:string
809 n Number of repetitions
812 Echo text to the console
815 Repeat {text} for {n} lines
818 Echo the {text} argument
823 Since most of the time, we only need to set the name and possibly a description for arguments,
824 there is a shortcut: name and description can be specified as positional arguments in this
825 order. So the following will give the exactly same result as above:
827 namespace kw = senf::console::kw;
829 senf::console::root()
831 .doc("Echo text to the console")
832 .overloadDoc("Repeat <text> for <n> lines");
833 .arg("n", "Number of repetitions")
834 .arg("text", "Text to output");
835 senf::console::root()
837 .overloadDoc("Echo the <text> argument")
841 Keyword arguments should always be used if additional attributes are set. You can however mix
842 positional and keyword arguments.
845 \subsection console_defaults Default values
847 Another information which can not be automatically gathered from the type system is default
848 values. These have to be declared explicitly:
850 namespace kw = senf::console::kw;
852 senf::console::root()
854 .doc("Echo {text} to the console, repeating {text} for {n} lines")
855 .arg("n", "Number of repetitions", kw::default_value=1)
856 .arg("text", "Text to output");
859 Default values can be used together with overloading. Default (optional) value support is quite
860 flexible, it is not mandatory, for default values to be specified only for the trailing
861 arguments. For the exact definition, how parsed argument values are assigned to overload
862 arguments in the presence of default values, see \ref senf::console::kw::default_value.
875 test4 [n:unsigned] text:string
878 n Number of repetitions
882 Echo {text} to the console, repeating {text} for {n} lines
888 \subsection console_boostfn Non-function-pointer commands
890 It is possible to add other callable objects besides function (and member-function)
891 pointers. However, since it is not possible to automatically deduce the argument and return
892 types in this case, the callables have to be wrapped in a \c boost::function object:
895 senf::console::root()
897 boost::function<void (std::ostream &, std::string const &)>(
898 boost::bind(&fun3, _1, 4u, _2)));
901 This works with any callable object where argument types cannot be deduced automatically:
902 Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
919 \subsection console_attr_summary Attribute summary
921 Here a summary of the most common attributes
923 <table class="senf fixedwidth">
925 <tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
926 ( \e doc )</td><td>Set documentation for all overloads</td></tr>
928 <tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
929 .overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
931 <tr><td>\link senf::console::ParsedArgumentAttributor::arg() .arg\endlink ( \e argument \e
932 attributes )</td><td>Set argument attributes (see below)</td></tr>
936 The most important argument attributes (all defined in the senf::console::kw namespace) are:
938 <table class="senf fixed width">
940 <tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
943 <tr><td>\link senf::console::kw::description kw::description\endlink</td><td>One-line
944 description of the argument</td></tr>
946 <tr><td>\link senf::console::kw::default_value kw::default_value\endlink</td><td>Arguments
947 default value</td></tr>
952 href="classsenf_1_1console_1_1ParsedArgumentAttributor-members.html">senf::console::ParsedArgumentAttributor
953 / List of all members</a> for the complete attribute interface \n
954 \ref senf::console::kw for a list of all argument attribute keywords
957 \section console_memberfn Member functions
959 Non-static member functions are supported like non-member functions (static member functions are
960 identical to non-members). They must however be added through a senf::console::ScopedDirectory
961 instance to bind them to their instance.
966 senf::console::ScopedDirectory<Test1> dir;
968 Test1(std::string label) : dir(this), label_ (label)
969 { dir.add("test", &Test::test1);
970 dir.add("test", &Test::test2); }
972 std::string test1(std::string const & text)
973 { return label_ + ": " + text; }
975 void test2(std::ostream & os, unsigned n, std::string const & text)
976 { while (n-- > 0) os << label << ": " << text << std::endl; }
984 Test1 test1ob ("test");
985 senf::console::root().add("test1ob", test1ob.dir);
988 Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
989 from the tree when the object is destroyed.
992 \section console_variables Variables
994 \subsection console_varadd Adding
996 The console/config library supports the direct registration of variables as commands. A
997 variable command consists of two overloads, one to query the current value and one to change the
1003 senf::console::ScopedDirectory<Test2> dir;
1005 Test2() : dir(this), var_(0)
1006 { dir.add("var", var_); }
1013 senf::console::root().add("test2ob", test2ob.dir);
1015 This shows the most common scenario: A member variable is added to a ScopedDirectory of the same
1016 class. This ensures, that the variable command node is removed from the tree when the instance
1017 (and thereby the variable) are destroyed. The variable can now be used like any other command:
1020 server:/$ test2ob/var
1022 server:/$ test2ob/var 10
1023 server:/$ test2ob/var
1025 server:/$ help test2ob
1027 1- var new_value:int
1034 \subsection console_varro Read-only variables
1036 The library also supports read-only variables. To make a variable read-only, just wrap it in \c
1037 boost::cref() (where \c cref stands for \c const reference)
1041 senf::console::root().add("var1", boost::cref(var));
1043 A read-only variable only has a single overload:
1056 \subsection console_varattr Attributes
1058 The most important Variable command attributes are
1060 <table class="senf fixedwidth">
1062 <tr><td style="width:14em">\link senf::console::VariableAttributor::doc() .doc\endlink
1063 ( \e doc )</td><td>Set variable documentation</td></tr>
1065 <tr><td>\link senf::console::VariableAttributor::onChange() .onChange\endlink
1066 ( \e handler )</td><td>Set change handler</td></tr>
1070 \see senf::console::VariableAttributor for the complete attribute interface
1072 \subsection console_varchange Change notification
1074 A \e handler can be set to be called, whenever the variable is changed. It will be called with a
1075 reference to the old value. The handler is called, after the value has been changed
1080 // Since this is int, it would make sense to declare the argument pass-by-value (int old)
1081 // but for more complex args, use a const & here
1082 void varChanged(int const & old)
1087 senf::console::root().add("var2",var)
1088 .onChange(&varChanged);
1091 After this setup, \c varChanged will be called, whenever the value has changed.
1094 \section console_args Registering special argument types
1096 By default, argument types which can be read and written using \c iostreams are automatically
1097 supported. Other types need to be registered explicitly
1100 \subsection console_args_enum Registering enum types
1102 Enum types are a special case, since it is not possible, to find a string representation for the
1103 enumerator values automatically. Therefore, enum types need to be registered manually.
1105 enum MyEnum { Sit, Run, Jump };
1106 SENF_CONSOLE_REGISTER_ENUM( MyEnum, (Sit)(Run)(Jump) );
1108 MyEnum fun4(MyEnum v) { return v }
1110 senf::console::root()
1111 .add("test9", &fun4);
1114 After an enum type is registered, it can be used like any other type for arguments or
1121 server:/$ test9 Crawl
1122 argument syntax error: invalid enum value
1123 server:/$ help test9
1130 \ref SENF_CONSOLE_REGISTER_ENUM() can only be used, to register enums at namespace scope. To
1131 register enums defined within some class, use \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER()
1137 enum Color { Red, Green, Blue };
1139 senf::console::ScopedDirectory<MyClass> dir;
1143 Color mem3(Color c) { return c }
1145 SENF_CONSOLE_REGISTER_ENUM_MEMBER( Test3, Color, (Red)(Green)(Blue) );
1147 Test3::Test3() : dir(this)
1148 { dir.add("test", &MyClass::mem3); }
1151 senf::console::root().add("test3ob", test3ob.dir);
1154 Using this command/type is identical
1157 server:/$ test3ob/test Red
1159 server:/$ test3ob/test White
1160 argument syntax error: invalid enum value
1161 server:/$ help test3ob/test
1168 \subsection console_args_custom Customizing argument and return value parsing/formatting
1170 To support or customize parsing/formatting of other types, they need to be registered. In it's
1171 simplest case, this works, by just providing an appropriate overload for
1172 senf_console_parse_argument() and senf_console_format_value():
1176 Coordinate() : x(0), y(0) {}
1177 Coordinate(int x_, int y_) : x(x_), y(y_) {}
1182 void senf_console_parse_argument(senf::console::ParseCommandInfo::TokensRange const & tokens,
1185 senf::console::CheckedArgumentIteratorWrapper arg (tokens);
1186 senf::console::parse( *(arg++), out.x );
1187 senf::console::parse( *(arg++), out.y );
1190 void senf_console_format_value(Coordinate const & value, std::ostream & os)
1192 os << '(' << value.x << ' ' << value.y << ')';
1196 The parser will accept an argument with two tokens which are each forwarded to the integer
1197 parser. The senf::console::CheckedArgumentIteratorWrapper ensures two things: That all input
1198 tokens are parsed and no extra trailing tokens are left unparsed and it checks, that all
1199 referenced tokens really exist.
1201 The formatter writes out the value as a parenthesized pair.
1204 Coordinate fun5(Coordinate const & p) { return Coordinate(2*p.x, 2*p.y) }
1206 namespace kw = senf::console::kw;
1208 senf::console::root()
1209 .add("test10", &fun5)
1210 .arg("x","coordinate to double",
1211 kw::default_value = Coordinate())
1213 We can now call \c test10 with a coordinate argument:
1216 server:/$ test10 (2 7)
1218 server:/$ help test10
1220 test10 [x:Coordinate]
1223 x Coordinate to double
1229 If you want to customize the formatting of default values differently from the formating of
1230 return-values or if you want to change the displayed name of a type, you will need to specialize
1231 the senf::console::ArgumentTraits class instead of implementing
1232 senf_console_parse_argument(). See senf::console::ArgumentTraits and
1233 senf::console::ReturnValueTraits for more.
1240 // comment-column: 40
1241 // c-file-style: "senf"
1242 // indent-tabs-mode: nil
1243 // ispell-local-dictionary: "american"
1244 // compile-command: "scons -u test"