4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
25 // Stefan Bund <g0dil@berlios.de>
28 /** \mainpage The Configuration and Runtime Control Library
30 The Console library implements a runtime interactive (network) console which allows to
31 configure, control and manipulate a running application in any way. Additionally this library
32 provides support for configuration files and command line parsing which can be used with or
33 without the network console.
38 \section console_intro Introduction
40 There are three parts to the Config/console library:
42 The Config/Console library is built around several components
44 \li The \link node_tree Node tree\endlink represents all configuration options and commands
45 organized in a filesystem like structure.
46 \li \link console_commands Actions\endlink are added to the node tree in the form of command
48 \li There exist several interfaces to \link console_access access\endlink entries in the node
49 tree: interactive console, reading configuration files etc.
51 The node tree works like a directory structure. Commands are entered into this directory
52 structure and can be called passing arbitrary arguments. Configuration parameters are just
53 commands which set their respective parameter, however the library allows commands to do much
57 \section console_example Example
59 The following example shows a \e very short summary on how to integrate the config/console
60 library. See above links for more:
63 #include <senf/Utils/Console.hh>
65 // Define callback function.
66 void mycommand(std::ostream & os, int foo, int bar)
69 os << "!! Important message ...\n";
72 namespace kw = senf::console::kw;
73 namespace fty = senf::console::factory;
75 int main(int argc, char** argv)
77 // Provide global documentation
79 .doc("This is someServer server");
82 senf::console::root().add("mycommand", fty::Command(&mycommand)
83 .doc("If <bar> is given, flurgle the <foo>, otherwise burgle it")
85 .arg(kw::name = "bar", kw::default_value = 0) );
87 // Parse command line parameters
88 senf::console::parseOptions(argc,argv);
90 // Start the interactive console server
91 senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
95 senf::scheduler::process();
99 after this registration, we can call the command from the command-line using
102 $ someServer --mycommand="1 2"
105 the console can be accessed easily via telnet:
108 $ telnet localhost 23232
110 Connected to localhost.
111 Escape character is '^]'
112 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Registered new client 0xxxxxxx
115 someServer:/# mycommand
116 !! Important message ...
118 xxxx-xx-xx xx:xx:xx.xxxxxx-0000 [NOTICE][senf::console::Server] Disposing client 0xxxxxxx
119 Connection closed by foreign host.
123 \see \ref console_testserver for a complete example application
126 \section intro_usage Using the Console: Configuration files, Network console
127 \seechapter \ref console_access
129 There are several ways to access the node tree:
130 \li By parsing configuration files
131 \li By parsing command line parameters
132 \li By providing interactive or non-interactive network console access
135 \section intro_nodes The node tree
136 \seechapter \ref node_tree
138 The basic idea is, that the console/config library manages a directory structure of parameters
139 and auxiliary commands. Parameters are just commands which set a parameter value so everything
140 is either a directory entry (senf::console::DirectoryNode) or a command
141 (senf::console::CommandNode).
144 \section intro_commands Implementing console/config commands
145 \seechapter \ref console_commands \n
146 \seechapter \ref senf::console::factory
148 The console/config language does not define, how arguments are passed to the commands, it just
149 tokenizes the input and passes the tokens to the commands which then handle the
152 Since parsing the tokens into something usable is quite tedious and error prone, the library
153 implements automatic argument parsing where the argument tokens are automatically parsed
154 depending on argument types. This enables you to register a command taking an integer argument
155 which will be called with an already parsed integer value (or throw a
156 senf::console::SyntaxErrorException if the conversion fails). This will be the most often used
160 /** \defgroup console_access Accessing the Console/Config tree
162 The Console/Config library provides several ways to use the node tree to configure and control
168 \section console_access_config Configuration support
170 The configuration support of the Console/Config library revolves around the ConfigSource
171 concept. Each ConfigSource will somehow provide commands which will then be executed against the
174 To simplify the usage, there will always be three interfaces to a specific config source:
175 \li A constructor to build a bare config source which is then added to a
176 senf::console::ConfigBundle (see \ref console_access_multiple)
177 \li A class parsing and executing a single config source. The visible interface of this class is
178 a combination of the constructor and the senf::console::ConfigBundle interfaces.
179 \li A helper function which will do the complete parsing of a single source with default
182 When parsing these configuration sources, it is always possible to optionally change the root
183 node used during parsing and it is also possible to restrict parsing to a command subset. See
184 \ref console_access_partial.
187 \subsection console_access_file Configuration files
189 <table class="senf fixedwidth">
190 <tr><td><b>Constructor</b></td> <td>senf::console::FileConfig()</td></tr>
191 <tr><td><b>Class</b></td> <td>senf::console::ConfigFile</td></tr>
192 <tr><td><b>Helper</b></td> <td>senf::console::parseFile()</td></tr>
195 In it's simplest form, parsing a configuration file consists of calling
196 senf::console::parseFile() with the name of the respective config file as argument.
199 senf::console::parseFile("some.conf");
202 To get more flexible, instantiate a senf::console::ConfigFile instance at use that to parse the
206 senf::console::ConfigFile cf ("some.conf");
207 // The following line is optional: Call to ignore mussing files
212 If the application supports other configuration sources besides a single configuration file
213 (like command line options) or if it supports multiple configuration files (e.g. a system-wide
214 and a user specific configuration file) see \ref console_access_multiple and add one (or more)
215 senf::console::FileConfig() source to a senf::console::ConfigBundle.
218 \subsubsection console_access_file_syntax Configuration file syntax
220 Configuration files are written in a simple configuration language. This language is almost
221 declarative (e.g. it does not have any control-flow statements) but is processed imperatively
222 from top to bottom. This is very simple and flexible.
224 Commands are referenced by their path in the node tree. To simplify working with deeply nested
225 directory structures, the current directory may be changed persistently or temporarily for some
230 /logger/targets/console {
231 accept senf::log::Debug IMPORTANT;
232 accept server::ServerLog CRITICAL;
236 \see \ref console_parser
239 \subsection console_access_options Command line options
241 <table class="senf fixedwidth">
242 <tr><td><b>Constructor</b></td> <td>senf::console::OptionsConfig()</td></tr>
243 <tr><td><b>Class</b></td> <td>senf::console::ProgramOptions</td></tr>
244 <tr><td><b>Helper</b></td> <td>senf::console::parseOptions()</td></tr>
247 Command line options can either be parsed by calling the senf::console::parseOptions() helper
250 senf::console::parseOptions(argc, argv)
253 or more flexibly by instantiating a senf::console::ProgramOptions class
256 std::vector<std::string> args;
257 senf::console::ProgramOptions opts (argc, argv);
260 .alias('c', "--mycommand",true)
261 .alias('C', "--mycommand=2 3");
265 This registeres two short options and accumulates all non-option arguments in \c args.
267 If the application supports other configuration sources besides the command line options (like
268 configuration files) see \ref console_access_multiple and add a senf::console::OptionsConfig()
269 source to a senf::console::ConfigBundle.
271 See \ref senf::console::ProgramOptions for the source specific additional parameters. These
272 apply to senf::console::ProgramOptions and to the senf::console::OptionsConfig() source.
275 \subsubsection console_access_options_syntax Options syntax
277 Command line options are primarily parsed as long-options. Long options start with '--'. Further
278 '-' characters serve as directory separators if required (that is, they are \e only interpreted
279 as directory separator is there is no entry in the current (sub-) directory matching more than a
280 single name component). This still allows using hyphens in node names.
282 Options can be abbreviated at each directory boundary: A command <tt>/foo/bar/do</tt> can be
283 called as <tt>--f-b-d</tt> as long as this name is unique.
285 Everything after the first '=' character is passed as arguments to the command. The exact
286 interpretation depends on the command:
287 \li If the command only takes a single token as argument (e.g. a single string or numeric
288 value), everything after the '=' sign is parsed into a single token (e.g. see rows 2 and 3
289 of the following table).
290 \li In all other cases, the string after the '=' sign is parsed into argument tokens using the
291 config/console parser. In this case, quoted strings need to be quoted twice, once for the
292 shell and once for the config/console parser (e.g. see rows 4 and 5 of the following table).
293 \li If the option has no '=' character, the list of argument tokens will be empty (e.g. see row
294 1 of the following table)
296 Without these rules, multi-word string arguments would \e always have to be quoted twice (for
297 the shell and the config/console parser).
299 <table style="font-size:80%" class="senf">
300 <tr><th>Command</th><th>File syntax</th><th>Option syntax</th></tr>
303 <td><tt>void doo()</tt></td>
304 <td><tt>/path/to/doo;</tt></td>
305 <td><tt>--path-to-doo</tt></td>
309 <td><tt>void doo(std::string const &)</tt></td>
310 <td><tt>/path/to/doo john.doe@everywhere.org;</tt></td>
311 <td><tt>--path-to-doo="john.doe@everywhere.org"</tt></td>
315 <td><tt>void doo(std::string const &)</tt></td>
316 <td><tt>/path/to/doo "some text";</tt></td>
317 <td><tt>--path-to-doo="some text"</tt></td>
321 <td><tt>void doo(std::string const &, int)</tt></td>
322 <td><tt>/path/to/doo take 1;</tt></td>
323 <td><tt>--path-to-doo="take 1"</tt></td>
327 <td><tt>void doo(std::string const &, int)</tt></td>
328 <td><tt>/path/to/doo "take two" 1;</tt></td>
329 <td><tt>--path-to-doo='"take two" 1'</tt></td>
333 Short options are registered as aliases for long options. They can be registered with or without
334 an implied parameter and can optionally take a parameter. so after
338 .alias('c', "--mycommand",true)
339 .alias('C', "--mycommand=2 3");
345 $ program -C -c "4 5"
352 $ program --mycommand="2 3" --mycommand="4 5"
355 (Beware, that the second argument to \c alias() must \e not be shell quoted).
358 \subsection console_access_root Changing the root node
360 When used in it's default state, parsing will always interpret all commands relative to the
361 senf::console::root() node and will parse a file completely.
363 The first possibility to control this is to change the root node. This is done by
364 \li passing that root node to the helper class or to the parse helper as an additional argument
365 (see the respective documentation).
366 \li passing it to the senf::console::ConfigBundle constructor when parsing multiple sources.
371 senf::console::parseFile("/etc/myserver.conf", senf::console::root()['config']);
374 This functionality is even more powerful by combining it with \c link nodes: This allows to
375 selectively choose commands from the node tree which are to be made accessible for
376 configuration. See \ref node_tree.
379 \subsection console_access_partial Partial / incremental configuration
381 Another feature provided by senf::console::ConfigBundle and all helper classes is partial
385 // Create a console/config aware object and place it (that is it's directory node) into the node
388 senf::console::root().add("foo", foo.dir);
390 // Open configuration file
391 senf::console::ConfigFile cf ("/etc/myserver.conf");
393 // Parse only commands in the configuration file which are in the foo.dir directory
398 // Anywhere later, parse the rest of the configuration file
402 This feature allows to parse parts of one or more configuration sources before the
403 console/config tree has been fully established. Partial parsing can be applied any number of
404 times to arbitrary nodes. Any command already parsed will be skipped automatically.
406 When combining partial parsing with \c chroot() and \c link's, it is important to realize, that
407 <em>partial parsing always applies to the \e real target and ignores links</em>. This is very
408 important: It allows a subsystem to parse it's configuration parameters irrespective of any
409 links pointing to nodes of that subsystem.
412 \subsection console_access_multiple Multiple sources
414 Most of the time, an application will utilize multiple configuration sources: A global
415 configuration file, maybe a user specific local configuration file, command line options ...
417 When parsing configuration commands, especially using partial / incremental parsing, all parse
418 commands should be applied to each configuration source in turn. This is the responsibility of
419 senf::console::ConfigBundle.
422 senf::console::ScopedDirectory<> config;
423 senf::console::root().add("config", config);
425 // Let's enable all logger commands for configuration
426 config.link("logger", senf::console::root()["logger"]);
428 // Create bundle and add sources
429 std::vector<std::string> args;
430 senf::console::ConfigBundle conf (senf::console::root()["config"]);
431 conf.add( senf::console::FileConfig("/etc/myserver.conf") );
432 conf.add( senf::console::FileConfig(".myserver.conf")->ignoreMissing() );
433 conf.add( senf::console::OptionsConfig(senf::Daemon::instance().argc(),
434 senf::Daemon::instance().argv()) )
436 .alias('c', "--mycommand",true)
437 .alias('C', "--mycommand=2 3");
439 // Parse the logger subsystem commands in '/logger'
440 conf.parse(senf::console::root()['logger']);
444 // Parse all other configuration commands. All necessary commands and links in '/config' must by
445 // now have been created.
449 This example parses three configuration sources: Two configuration files and additional
450 parameters specified on the command line. All the configuration commands are placed into the
451 <tt>/config</tt> directory (directly or via links). The configuration sources are parsed in the
452 order they are specified, so in this case, the command line options will override any options
453 specified in one of the configuration files.
456 \section console_access_console The network console
458 To make the network console accessible, it must be initialized when the program is started:
460 #include <senf/Console.hh>
462 int main(int argc, char * argv [])
464 // Configure console nodes, add commands ...
466 // Start console server
467 senf::console::start(senf::INet4SocketAddress(12345u))
470 // You need to enter the scheduler main-loop for the server to work
471 senf::scheduler::process();
473 // Alternatively enter the main-loop via the PPI
478 This will start the server on IPv4 port 12345. The servers name (as displayed in the interactive
479 console prompt) is set to 'myserver'.
481 After launching the application, the server can be accessed at the given port:
484 bash$ telnet localhost 12345
486 Connected to localhost.
487 Escape character is '^]'.
490 Connection closed by foreign host.
495 It is possible to start multiple server consoles by calling \c start() multiple times with
496 different ports/addresses. Each server can be configured separately (e.g. root node, mode ...).q
499 \subsection console_serverclient Server and Client objects
501 The senf::console::Server and senf::console::Client objects offer further API calls. To access
502 the server instance you need to store away the senf::console::Server reference returned when
503 starting the server so you can later refer to it:
505 int main(int, char**)
507 senf::console::Server & server ( senf::console::start( ... ) );
515 The client instance can be accessed via the \c std::ostream arg of any command callback
517 void someCallback(std::ostream & os, ... )
519 senf::console::Client & client (senf::console::Client::get(os));
521 // Use the client's log target
522 client.route<senf::log::Debug, senf::Log::IMPORTANT>();
527 senf::console::Server for the Server API \n
528 <a href="classsenf_1_1console_1_1Client-members.html">senf::console::Client / List of all
529 members</a> for the Client API
532 \subsection console_shell The interactive console shell
534 The interactive shell implements a fully function line editor on capable terminals. This support
535 is available when using a full featured telnet client on a fully supported terminal (like vt100
538 The shell supports auto-cd and auto-completion: If you enter the name of a directory at the
539 prompt, the console will change to that directory. With auto-completion, any unique beginning of
540 a path component will be completed automatically and transparently to the corresponding full
544 \subsection console_noninteractive Non-interactive network console
546 After a new connection is established, the console server waits a short time for data to arrive.
547 Only if nothing happens in the first 500ms, an interactive session is initialized.
549 By sending data immediately after opening the connection, the console is switched into
550 non-interactive mode. In this mode, no prompt is displayed. In this mode, commands are \e not
551 terminated automatically by end-of-line (CR). This allows, to easily cat an arbitrary
552 configuration file into the network console using netcat:
555 $ nc -q1 localhost 23232 < some.conf
558 The argument <tt>-q1</tt> makes netcat close the sending end of the connection on EOF and wait
559 up to 1 second for the console to terminate. Even better, use \c netcat6, which has full TCP
563 $ echo "ls" | nc6 --half-close localhost 23232 2>/dev/null
570 Commands are executed as soon as the terminating character (';', '{' or '}') is received or when
571 the sending end of the connection is closed.
573 \section console_udp Non-interactive UDP console
575 The UDP console allows to script the console tree via UDP packets. Every UDP packet must be a
576 complete command (or sequence of commands). The combined reply of all these commands will be
577 returned in a single UDP packet. This reply can be disabled or directed to a different address.
579 To start a UDP server, just create an instance of the senf::console::UDPServer class
581 senf::console::UDPServer server (senf::INet4SocketAddress("127.0.0.1:23232"));
583 (Remember to enter the scheduler main-loop for processing)
585 Commands may then be sent to this UDP console e.g. using netcat
587 $ echo "cd sys; ls" | nc -uq0 localhost 23232 2>/dev/null
590 \see senf::console::UDPServer
593 /** \defgroup console_commands Supported command types
595 The Console/config library supports quite a number of different command types. All these types
596 of command are registered by passing an appropriate factory instance to DirectoryNode::add()
601 \section console_cmdadd Adding commands and setting attributes
603 Basically, all commands are added using senf::console::DirectoryNode::add().
605 namespace fty = senf::console::factory;
606 dir.add("name", fty::Command(callback));
608 will add the command 'name' which will execute 'callback' when called.
610 The add call always returns (something which can be used as) a reference to the command node
613 senf::console::CommandNode & node ( dir.add( ... ) );
616 Depending on the object added, you can also bind to a more specific node type
617 (e.g. senf::console::SimpleCommand) if you know the type of node returned.
619 Nodes are always added using a factory from the senf::console::factory namespace. The factory
620 has additional (type specific) attributes. These attributes are set by calling member functions
621 called 'attributors' on the temporary factory instance. It is \e not guaranteed, you can call
622 these members on the node reference returned by the \c add() call.
624 namespace fty = senf::console::factory;
625 dir.add("name", fty::Command(callback) .doc("The documentation") );
627 sets the \e doc attribute (if that is available, otherwise this will fail to compile).
628 \see senf::console::factory for a list of all node factories.
631 \section console_manualparse Manually parsing command arguments
633 This is the most primitive type of command. It will be called with an output stream and with a
634 senf::console::ParseCommandInfo reference which holds information about the command parsed.
636 From this information the command callback gets a list of arguments or tokens which then can be
637 interpreted in an arbitrary way.
639 void fun1(std::ostream & os, senf::console::ParseCommandInfo const & command)
641 // Here we declare variables for the arguments
645 // We parse the arguments using the CheckedArgumentIteratorWrapper. This wrapper
646 // will throw a SyntaxErrorException if we access a nonexistent argument or if we
647 // do not parse all arguments.
648 senf::console::CheckedArgumentIteratorWrapper args (command.arguments());
650 // Extract the first argument. This is again a token range.
651 senf::console::ParseCommandInfo::TokensRange arg1Tokens ( *(args++) );
652 if (arg1Tokens.size() != 1)
653 raise senf::console::SyntaxErrorException("argument syntax error");
654 value = arg1Tokens[0].value();
657 os << value << std::endl;
661 Registering this callback is done by simply adding it. To provide online help, pass it to
664 namespace fty = senf::console::factory;
665 senf::console::root().add("test1", fty::Command(&fun1)
669 "Echo 'arg' to the console") );
672 The callback may now be called interactively on the console by it's registered name:
676 invalid number of arguments
677 server:/$ test1 stefan@j32.de
679 server:/$ test1 (echo me)
680 argument syntax error
685 Echo 'arg' to the console
690 As you can see above, the arguments and tokens are returned as <a
691 href="http://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/utilities/iterator_range.html">
692 boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
693 \c end() and some other useful members.
695 The parser will have divided the argument tokens into arguments already. This simplifies further
696 parsing. If however you want to access the list of argument tokens as a single list, you can do
697 so using senf::console::ParseCommandInfo::tokens().
699 Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
700 can be delegated to the Console/config library. See the next section.
702 This type of command has only a single attribute, \e doc to set the commands documentation.
705 \section console_autoparse Automatic argument parsing
707 To greatly simplify parsing complex commands, we turn to automatic argument parsing.
710 \subsection console_autoadd Adding
712 Automatically parsed commands are registered by just adding a callback which has the correct
713 arguments and return-value defined:
715 std::string fun2(std::string const & arg)
721 This extremely simple callback may be registered by adding it to a senf::console::DirectoryNode.
723 namespace fty = senf::console::factory;
724 senf::console::root().add("test2", fty::Command(&fun2));
726 The functionality is now identical to \c test1:
730 invalid number of arguments
731 server:/$ test2 stefan@j32.de
733 server:/$ test2 (echo me)
734 argument syntax error
743 \subsection command_ostream Accessing the console stream
745 Commands may have an optional first argument of type <tt>std::ostream &</tt>. This argument is
746 not considered part of the real interface. When the command is executed, the callback will be
747 passed the current consoles output stream object in this argument. With this, the callback can
748 output arbitrary messages to the network console.
750 namespace fty = senf::console::factory;
752 void fun3(std::ostream & os, unsigned n, std::string text)
754 while (n-- > 0) os << text << std::endl;
757 senf::console::root().add("test3", fty::Command(&fun3));
760 This simple command can now be used thus:
764 invalid number of arguments
765 server:/$ test3 stefan@j32.de
766 invalid number of arguments
772 test3 arg11:int arg12:string
778 \subsection command_overload Overloading
780 Automatically parsed commands can be overloaded: You can register multiple commands under the
781 same name. Each overload is tried in turn until no SyntaxErrorException is raised.
783 namespace fty = senf::console::factory;
785 senf::console::root().add("test4", fty::Command(&fun3));
786 senf::console::root().add("test4", fty::Command(&fun2));
788 And now, we can call \c test4 with one or two args:
791 invalid number of arguments
792 server:/$ test4 stefan@j32.de
799 1- test4 arg11:int arg12:string
800 2- test4 arg21:string
804 One note: When taking the address of an overloaded function (member or non-member), the C++
805 language forces you to cast that address to one of the possible types so the compiler knows,
806 which overload is requested. So to add a function which is overloaded in C++, each overload
807 needs to be added explicitly, casting to the correct type. There are some macros in
808 Utils/membind.hh to simplify this:
811 namespace fty = senf::console::factory;
816 senf::console::root().add("over", fty::Command(SENF_FNP(void, over, (int))));
817 senf::console::root().add("over", fty::Command(SENF_FNP(void, over, (int,int)));
820 senf::console::ScopedDirectory<SomeModule> dir;
822 unsigned int overlodedMethod() const {....};
823 void overlodedMethod(unsigned int) {....};
825 void addConsoleCommands() {
827 .add("overlodedMethod", fty::Command(
828 SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, () const)));
830 .add("overlodedMethod", fty::Command(
831 SENF_MEMBINDFNP(unsigned int, SomeModule, overlodedMethod, (unsigned int))));
837 \subsection console_attributes Attributes
839 As have seen so far, some documentation is automatically provided. We can add more info, by
840 setting additional attributes.
842 namespace fty = senf::console::factory;
844 senf::console::root().add("test5", fty::Command(&fun3)
845 .doc("Echo text to the console")
846 .overloadDoc("Repeat {arg12} for {arg11} lines") );
847 senf::console::root().add("test4", fty::Command(&fun2)
848 .overloadDoc("Echo the {arg21} argument") );
851 This additional info is used to provide more documentation:
856 1- test5 arg11:int arg12:string
857 2- test5 arg21:string
859 Echo text to the console
862 Repeat {arg12} for {arg11} lines
865 Echo the {arg21} argument
871 \subsection console_argattributes Argument attributes
873 Additional attributes can be set for each parameter. They are all passed to the
874 senf::console::ParsedArgumentAttributor::arg() attribute.
877 namespace kw = senf::console::kw;
878 namespace fty = senf::console::factory;
880 senf::console::root().add("test6", fty::Command(&fun3)
881 .doc("Echo text to the console")
882 .overloadDoc("Repeat {text} for {n} lines");
883 .arg( kw::name = "n", kw::description="Number of repetitions" )
884 .arg( kw::name = "text", kw::description="Text to output" ) );
885 senf::console::root().add("test6", fty::Command(&fun2)
886 .overloadDoc("Echo the {text} argument")
887 .arg( kw::name = "text" ) );
890 (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
891 Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
892 are set using keywords from the \ref senf::console::kw namespace. You will probably either use
893 this namespace via a namespace alias (as above) or via a <tt>using namespace
894 senf::console::kw</tt> declaration (but beware of name collisions).
896 You don't need to specify any information for an argument: To skip an argument, just call \c
897 arg() without attributes for this argument.
899 After adding this information, the online help is much more readable
904 1- test6 n:int text:string
908 n Number of repetitions
911 Echo text to the console
914 Repeat {text} for {n} lines
917 Echo the {text} argument
922 Since most of the time, we only need to set the name and possibly a description for arguments,
923 there is a shortcut: name and description can be specified as positional arguments in this
924 order. So the following will give the exactly same result as above:
926 namespace kw = senf::console::kw;
927 namespace fty = senf::console::factory;
929 senf::console::root().add("test6", fty::Command(&fun3)
930 .doc("Echo text to the console")
931 .overloadDoc("Repeat <text> for <n> lines");
932 .arg("n", "Number of repetitions")
933 .arg("text", "Text to output") );
934 senf::console::root().add("test6", fty::Command(&fun2)
935 .overloadDoc("Echo the <text> argument") );
939 Keyword arguments should always be used if additional attributes are set. You can however mix
940 positional and keyword arguments.
943 \subsection console_defaults Default values
945 Another information which can not be automatically gathered from the type system is default
946 values. These have to be declared explicitly:
948 namespace kw = senf::console::kw;
949 namespace fty = senf::console::factory;
951 senf::console::root().add("test7", fty::Command(&fun3)
952 .doc("Echo {text} to the console, repeating {text} for {n} lines")
953 .arg("n", "Number of repetitions", kw::default_value=1)
954 .arg("text", "Text to output") );
957 Default values can be used together with overloading. Default (optional) value support is quite
958 flexible, it is not mandatory, for default values to be specified only for the trailing
959 arguments. For the exact definition, how parsed argument values are assigned to overload
960 arguments in the presence of default values, see \ref senf::console::kw::default_value.
973 test4 [n:unsigned] text:string
976 n Number of repetitions
980 Echo {text} to the console, repeating {text} for {n} lines
986 \subsection console_boostfn Non-function-pointer commands
988 It is possible to add other callable objects besides function (and member-function)
989 pointers. However, since it is not possible to automatically deduce the argument and return
990 types in this case, the signature has to be specified explicitly:
992 namespace fty = senf::console::factory;
994 senf::console::root()
995 .add("test8",fty::Command<void (std::ostream &, std::string const &)>(
996 boost::bind(&fun3, _1, 4u, _2)));
999 This works with any callable object where argument types cannot be deduced automatically:
1000 Boost.Bind expressions, Boost.Lambda expressions, functors and so on.
1009 server:/$ help test8
1017 \subsection console_attr_summary Attribute summary
1019 Here a summary of the most common attributes
1021 <table class="senf fixedwidth">
1023 <tr><td style="width:14em">\link senf::console::ParsedArgumentAttributorBase::doc() .doc\endlink
1024 ( \e doc )</td><td>Set documentation for all overloads</td></tr>
1026 <tr><td>\link senf::console::ParsedArgumentAttributorBase::overloadDoc()
1027 .overloadDoc\endlink ( \e doc )</td><td>Set documentation for a specific overload</td></tr>
1029 <tr><td>\link senf::console::ParsedArgumentAttributor::arg() .arg\endlink ( \e argument \e
1030 attributes )</td><td>Set argument attributes (see below)</td></tr>
1034 The most important argument attributes (all defined in the senf::console::kw namespace) are:
1036 <table class="senf fixed width">
1038 <tr><td style="width:14em">\link senf::console::kw::name kw::name\endlink</td><td>Parameter
1041 <tr><td>\link senf::console::kw::description kw::description\endlink</td><td>One-line
1042 description of the argument</td></tr>
1044 <tr><td>\link senf::console::kw::default_value kw::default_value\endlink</td><td>Arguments
1045 default value</td></tr>
1050 href="classsenf_1_1console_1_1ParsedArgumentAttributor-members.html">senf::console::ParsedArgumentAttributor
1051 / List of all members</a> for the complete attribute interface \n
1052 \ref senf::console::kw for a list of all argument attribute keywords
1055 \section console_memberfn Member functions
1057 Non-static member functions are supported like non-member functions (static member functions are
1058 identical to non-members). They must however be added through a senf::console::ScopedDirectory
1059 instance to bind them to their instance.
1061 namespace fty = senf::console::factory;
1066 senf::console::ScopedDirectory<Test1> dir;
1068 Test1(std::string label) : dir(this), label_ (label)
1069 { dir.add("test", fty::Command(&Test::test1, this));
1070 dir.add("test", fty::Command(&Test::test2, this)); }
1072 std::string test1(std::string const & text)
1073 { return label_ + ": " + text; }
1075 void test2(std::ostream & os, unsigned n, std::string const & text)
1076 { while (n-- > 0) os << label << ": " << text << std::endl; }
1084 Test1 test1ob ("test");
1085 senf::console::root().add("test1ob", test1ob.dir);
1088 Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
1089 from the tree when the object is destroyed.
1092 \section console_variables Variables
1094 \subsection console_varadd Adding
1096 The console/config library supports the direct registration of variables as commands. A
1097 variable command consists of two overloads, one to query the current value and one to change the
1100 namespace fty = senf::console::factory;
1105 senf::console::ScopedDirectory<Test2> dir;
1107 Test2() : dir(this), var_(0)
1108 { dir.add("var", fty::Variable(var_) ); }
1115 senf::console::root().add("test2ob", test2ob.dir);
1117 This shows the most common scenario: A member variable is added to a ScopedDirectory of the same
1118 class. This ensures, that the variable command node is removed from the tree when the instance
1119 (and thereby the variable) are destroyed. The variable can now be used like any other command:
1122 server:/$ test2ob/var
1124 server:/$ test2ob/var 10
1125 server:/$ test2ob/var
1127 server:/$ help test2ob
1129 1- var new_value:int
1136 \subsection console_varro Read-only variables
1138 The library also supports read-only variables. To make a variable read-only, just wrap it in \c
1139 boost::cref() (where \c cref stands for \c const reference)
1141 namespace fty = senf::console::factory;
1145 senf::console::root().add("var1", fty::Variable(boost::cref(var)));
1147 A read-only variable only has a single overload:
1160 \subsection console_varattr Attributes
1162 The most important Variable command attributes are
1164 <table class="senf fixedwidth">
1166 <tr><td style="width:14em">\link senf::console::VariableAttributor::doc() .doc\endlink
1167 ( \e doc )</td><td>Set variable documentation</td></tr>
1169 <tr><td>\link senf::console::VariableAttributor::onChange() .onChange\endlink
1170 ( \e handler )</td><td>Set change handler</td></tr>
1174 \see senf::console::VariableAttributor for the complete attribute interface
1177 \subsection console_varchange Change notification
1179 A \e handler can be set to be called, whenever the variable is changed. It will be called with a
1180 reference to the old value. The handler is called, after the value has been changed
1183 namespace fty = senf::console::factory;
1187 // Since this is int, it would make sense to declare the argument pass-by-value (int old)
1188 // but for more complex args, use a const & here
1189 void varChanged(int const & old)
1194 senf::console::root().add("var2", fty::Variable(var)
1195 .onChange(&varChanged) );
1198 After this setup, \c varChanged will be called, whenever the value has changed.
1201 \section console_args Console library supported types
1203 By default, types which can be read and written using \c iostreams are automatically supported.
1204 This includes all the C++ built-in types as well as user defined streamable types.
1206 An exception is made for all \c char types: These types are by default parsed as \e numeric
1207 values not single-character data. To interpret \c char values as single-char strings, use \ref
1208 senf::console::CharAsString.
1210 \subsection console_args_stl STL container support
1212 The %console library contains support for the STL container types: \c std::vector, \c
1213 std::list, \c std::set, \c std::multiset, \c std::map and \c std::multimap.
1215 All container types are parsed as parenthesized list of elements. Each element is parsed as
1216 defined for the element type:
1218 \c vector, \c list or \c set of integers:
1223 \c vector, \c list or \c set of strings:
1225 ("String 1" "String 2" "String 3")
1228 \c vector, \c list or \c set of <tt>pair<int,string></tt>:
1230 ((1 "String 1") (2 "String 2") (3 "String 3"))
1238 Collection's with only one element may skip the parenthesis <em>if and only if</em> the element
1239 type does not need additional parenthesis
1241 A \c vector, \c list or \c set of integer with one element may be written with or without
1248 \e but a single element \c vector, \c list or \c set of <tt>pair<int,string></tt> may \e only be
1254 In mapping containers, the key and value are separated by \c =:
1256 (foo=1 bar=2 "foo bar"=3)
1260 \subsection console_args_bool Boolean arguments and return values
1262 The console library by default formats boolean values using the strings \c true and \c false for
1263 their representation. When parsing a boolean value, most sensible representations will be
1266 <table class="senf">
1267 <tr><td>\c true</td> <td>\c false</td> <td>\ref senf::console::formatTrueFalse</td></tr>
1268 <tr><td>\c on</td> <td>\c off</td> <td>\ref senf::console::formatOnOff</td></tr>
1269 <tr><td>\c enabled</td> <td>\c disabled</td> <td>\ref senf::console::formatEnabledDisabled</td></tr>
1270 <tr><td>\c yes</td> <td>\c no</td> <td>\ref senf::console::formatYesNo</td></tr>
1271 <tr><td><em>non-zero integer</em></td><td>\c 0</td><td>\ref senf::console::formatOneZero</td></tr>
1274 The boolean parser will accept these values in any (mixed) case and accepts any unique initial
1275 substring (e.g. \c Y / \c N).
1277 The last column lists explicit formatters which can be set to customize the return value
1278 formatting of a registered overload accordingly.
1281 \subsection console_args_enum Registering enum types
1283 Enum types are a special case, since it is not possible, to find a string representation for the
1284 enumerator values automatically. Therefore, enum types need to be registered manually.
1286 namespace fty = senf::console::factory;
1288 enum MyEnum { Sit, Run, Jump };
1289 SENF_CONSOLE_REGISTER_ENUM( MyEnum, (Sit)(Run)(Jump) );
1291 MyEnum fun4(MyEnum v) { return v }
1293 senf::console::root().add("test9", fty::Command(&fun4));
1296 After an enum type is registered, it can be used like any other type for arguments or
1303 server:/$ test9 Crawl
1304 argument syntax error: invalid enum value
1305 server:/$ help test9
1312 \ref SENF_CONSOLE_REGISTER_ENUM() can only be used, to register enums at namespace scope. To
1313 register enums defined within some class, use \ref SENF_CONSOLE_REGISTER_ENUM_MEMBER()
1316 namespace fty = senf::console::factory;
1321 enum Color { Red, Green, Blue };
1323 senf::console::ScopedDirectory<Test3> dir;
1327 Color mem3(Color c) { return c }
1329 SENF_CONSOLE_REGISTER_ENUM_MEMBER( Test3, Color, (Red)(Green)(Blue) );
1331 Test3::Test3() : dir(this)
1332 { dir.add("test", fty::Command(&Test3::mem3, this)); }
1335 senf::console::root().add("test3ob", test3ob.dir);
1338 Using this command/type is identical
1341 server:/$ test3ob/test Red
1343 server:/$ test3ob/test White
1344 argument syntax error: invalid enum value
1345 server:/$ help test3ob/test
1352 \subsection console_args_convert Handling argument types by conversion
1354 Sometimes an argument type is best handled by just pretending it to be of some other type. The
1355 basic idea is, to provide an explicit signature with different (but compatible) types to the
1359 namespace fty = senf::console::factory;
1366 senf::console::root()
1367 .add("test8", fty::Command<bool (bool)>(&fun4));
1370 Here, the type signature passed to fty::Command is different from the real type signature but it
1371 is compatible, the conversion is handled automatically. Since the console library now sees the
1372 argument and return value of type \c bool, the values will be parsed and formatted as boolean
1376 \subsection console_args_special Special Console types
1378 The %console library defines some special types to be used as arguments and/or return values.
1379 Some of these are wrappers around basic types which provide custom formatting. Those are used
1380 via argument type conversion (see previous section).
1382 \see \ref senf_console_utilities
1385 \subsection console_args_custom Extending the library to support additional types
1387 To support or customize parsing/formatting of other types, they need to be registered. In it's
1388 simplest case, this works, by just providing an appropriate overload for
1389 senf_console_parse_argument() and senf_console_format_value():
1393 Coordinate() : x(0), y(0) {}
1394 Coordinate(int x_, int y_) : x(x_), y(y_) {}
1399 void senf_console_parse_argument(senf::console::ParseCommandInfo::TokensRange const & tokens,
1402 senf::console::CheckedArgumentIteratorWrapper arg (tokens);
1403 senf::console::parse( *(arg++), out.x );
1404 senf::console::parse( *(arg++), out.y );
1407 void senf_console_format_value(Coordinate const & value, std::ostream & os)
1409 os << '(' << value.x << ' ' << value.y << ')';
1413 The parser will accept an argument with two tokens which are each forwarded to the integer
1414 parser. The senf::console::CheckedArgumentIteratorWrapper ensures two things: That all input
1415 tokens are parsed and no extra trailing tokens are left unparsed and it checks, that all
1416 referenced tokens really exist.
1418 The formatter writes out the value as a parenthesized pair.
1421 namespace fty = senf::console::factory;
1423 Coordinate fun5(Coordinate const & p) { return Coordinate(2*p.x, 2*p.y) }
1425 namespace kw = senf::console::kw;
1427 senf::console::root()
1428 .add("test10", fty::Command(&fun5))
1429 .arg("x","coordinate to double",
1430 kw::default_value = Coordinate())
1432 We can now call \c test10 with a coordinate argument:
1435 server:/$ test10 (2 7)
1437 server:/$ help test10
1439 test10 [x:Coordinate]
1442 x Coordinate to double
1448 If you want to customize the formatting of default values differently from the formating of
1449 return-values or if you want to change the displayed name of a type, you will need to specialize
1450 the senf::console::ArgumentTraits class instead of implementing
1451 senf_console_parse_argument(). See senf::console::ArgumentTraits and
1452 senf::console::ReturnValueTraits for more.
1459 // comment-column: 40
1460 // c-file-style: "senf"
1461 // indent-tabs-mode: nil
1462 // ispell-local-dictionary: "american"
1463 // compile-command: "scons -u test"