Fix SCons 1.2.0 build failure
[senf.git] / Utils / Console / Node.hh
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
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.
12 //
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.
17 //
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.
22
23 /** \file
24     \brief Node public header */
25
26 /** \defgroup node_tree The node tree
27
28     The console/config node tree is the central data-structure of the library. Into this tree, all
29     commands and parameters are entered. The tree is then exposed using a file-system like
30     interface.
31
32     \autotoc
33
34     \section console_tree The tree
35
36     We will start by giving a more complete example. This example contains most of the stuff needed
37     for using the console/config library.
38
39     \code
40     // Define callback function.
41     void mycommand(std::ostream & os, senf::console::ParseCommandInfo const & command)
42     {
43         // ...
44         os << "!! Important message ...\n";
45     }
46
47     class SomeClass
48     {
49     public:
50         // Declare a directory node (proxy) for use by this class. This must be public so we can add
51         // it to the node tree later.
52         senf::console::ScopedDirectory<SomeClass> dir;
53
54         SomeClass() : dir(this)
55         {
56             // You may document the directory here or later when adding it to the tree
57             dir.doc("Manager for something");
58
59             // Add a member function (the pointer-to-member is automatically bound to this instance)
60             dir.add("member", &SomeClass::member)
61                 .doc("Do the member operation");
62         }
63
64         void member(std::ostream & os, senf::console::ParseCommandInfo const & command)
65         {
66             // ...
67         }
68     };
69
70     int main(int, char**)
71     {
72         // Provide global documentation
73         senf::console::root()
74             .doc("This is someServer server");
75
76         // Add a new directory to the root and document it. All the mutators return the node object
77         // itself so operations can be chained.
78         senf::console::DirectoryNode & mydir ( senf::console::root()
79                 .mkdir("myserver")
80                 .doc("My server specific directory"));
81
82         // Add a command to that directory
83         mydir.add("mycommand", &mycommand)
84             .doc("mycommand <foo> [<bar>]\n\n"
85                  "If <bar> is given, flurgle the <foo>, otherwise burgle it");
86
87         // Create a SomeClass instance and add it's directory.
88         SomeClass someClass;
89         mydir.add("someClass", someClass.dir);
90
91         // Start the interactive console server
92         senf::console::Server::start(senf::INet4SocketAddress(senf::INet4Address::None, 23232u))
93             .name("someServer");
94     }
95     \endcode
96
97     \subsection console_nodes Node types
98
99     The console/config library tree consists of two basic node types:
100
101     \li senf::console::DirectoryNode provides internal nodes with an arbitrary number of children
102     \li senf::console::CommandNode describes a command entry in the tree
103     \li senf::console::LinkNode is a link to another node. It works much like a symlink on POSIX
104         systems.
105
106     senf::console::CommandNode is the base-class of all command nodes of which there are several,
107     depending on the type of command.
108
109     There is a single root node, the senf::console::DirectoryNode called senf::console::root(). From
110     this node, the tree is traversed.
111
112     All nodes are allocated on the heap and are managed using a smart pointer.
113
114     \subsection console_manipulate Manipulating the node tree
115
116     There are several ways to add nodes to the tree:
117
118     \li A senf::console::DirectoryNode can be added using senf::console::DirectoryNode::mkdir().
119     \li An arbitrary node can be created and then (possibly later) added to the tree using the
120         corresponding senf::console::DirectoryNode::add() overload.
121     \li A senf::console::CommandNode is normally added to the tree by directly adding a callback
122         using one of the overloaded senf::console::DirectoryNode::add() members. See \ref
123         console_commands.
124     \li A senf::console::LinkNode is created by senf::console::DirectoryNode::link()
125
126     When directly adding a node callback, the type of node added depends on the type of
127     callback. The callback types which can be added are listed at \ref console_callbacks.
128
129     \code
130     void callback(std::ostream & os, senf::console::ParseCommandInfo const & command) { ... }
131     // ...
132     myDirectory.add("foo",&callback);
133     \endcode
134
135     Every node is identified among it's siblings by it's name. The name of the node is set when
136     adding the node to the tree. If the name is empty or non-unique, a unique name will be
137     automatically provided.
138
139     To remove a node from the tree, just use the nodes senf::console::GenericNode::unlink() or the
140     parents senf::console::DirectoryNode::remove() member. This call removes the node from it's
141     parent and returns a (smart) node pointer.
142
143     \li If you ignore the return value, the node (and it's children) will be deleted.
144     \li Alternatively, you may store away the node and re-attach it later.
145     \li An node (or subtree) can be moved to a different place by unlinking the node at it's old
146         place and re-adding it at it's new location.
147     \li To rename a node, unlink and re-add it with a different name.
148
149     \code
150     myDirectory.add("bar", myDirectory.remove("foo"));
151     \endcode
152
153     \subsection console_node_param Assigning additional node parameters
154
155     Depending on the node type added, additional node parameters may be set. For example, every node
156     has a documentation parameter which is used by the online-help system. To assign these
157     parameters, the node exposes corresponding member functions. Since
158     senf::console::DirectoryNode::add() returns the newly added node by reference, additional
159     parameters may just be added to the end of the add command:
160     \code
161     myDirectory.add("foo",&fooCallback).doc("The foo method");
162     \endcode
163     Since the parameter setters all return the node reference, additional parameters may just be
164     added to the end of the command.
165
166     \subsection console_tree_traverse Traversing the tree
167
168     The simplest way to access tree elements is to save the return value of the
169     senf::console::DirectoryNode::add() members. However, saving the reference will not ensure, that
170     the node is not removed. If the node might be removed from the tree, you should use a smart
171     pointer (either <tt>ptr</tt> or <tt>weak_ptr</tt>) to hold the node.
172
173     Another possibility is to traverse the tree explicitly. For this purpose, the operators '[]' and
174     '()' have been overloaded in senf::console::DirectoryNode.
175     \code
176     senf::console::root().getDirectory("myDirectory").getCommand("foo")
177     \\ or more concise but otherwise completely identical
178     senf::console::root()["myDirectory"]("foo")
179     \endcode
180
181     getDirectory and the '[]' operator will return a senf::console::DirectoryNode whereas getCommand
182     and the '()' operator will return a senf::console::CommandNode. If the node is not found or is
183     not of the correct type, an exception will be raised.
184
185     \section console_object_dir Assigning a directory to an object instance
186
187     Most objects will register several commands. So it makes sense for these objects to manage their
188     own directory. Since directories are however allocated on the heap, they cannot be directly
189     added to a class. To facilitate this usage, the senf::console::ScopedDirectory is used. This
190     class provides a senf::console::DirectoryNode facade. Internally, it automatically creates a
191     senf::console::DirectoryNode to which all calls are forwarded.
192
193     The senf::console::ScopedDirectory member should be declared public. This allows the user of the
194     class to add the node to the tree.
195  */
196
197 #ifndef HH_SENF_Scheduler_Console_Node_
198 #define HH_SENF_Scheduler_Console_Node_ 1
199
200 // Custom includes
201 #include <map>
202 #include <boost/shared_ptr.hpp>
203 #include <boost/weak_ptr.hpp>
204 #include <boost/enable_shared_from_this.hpp>
205 #include <boost/utility.hpp>
206 #include <boost/range/iterator_range.hpp>
207 #include <boost/typeof/typeof.hpp>
208 #include <boost/type_traits/remove_reference.hpp>
209 #include <boost/any.hpp>
210 #include "../../Utils/Exception.hh"
211 #include "../../Utils/mpl.hh"
212 #include "../../Utils/Logger/SenfLog.hh"
213 #include "../../Utils/type_traits.hh"
214 #include "Parse.hh"
215
216 //#include "Node.mpp"
217 ///////////////////////////////hh.p////////////////////////////////////////
218
219 namespace senf {
220 namespace console {
221
222     class LinkNode;
223     class DirectoryNode;
224     class CommandNode;
225
226     /** \brief Get console root node */
227     DirectoryNode & root();
228
229     /** \brief Dump console directory structure
230
231         Recursively dumps the console directory structure starting at \a dir. By default, dumps the
232         complete tree beginning at the root node.
233         
234         In contrast to the console 'lr' command, links are dumped by showing the \e absolute path
235         to the target node.
236      */
237     void dump(std::ostream & os, DirectoryNode & dir=root());
238
239     /** \brief Config/console node tree base-class
240
241         GenericNode is the base class of all node objects. There are two basic node types derived
242         from GenericNode:  DirectoryNode and CommandNode.
243
244         All nodes are dynamically allocated and automatically managed using reference counting.
245
246         All nodes are normally linked into a single tree which root node is
247         senf::console::root(). Nodes may however be orphaned (not linked to the tree) either
248         directly (the node has no parent) or indirectly (the node has a parent but is part of an
249         orphaned subtree which is not linked to the root node).
250
251         Every active (non-orphaned) node (except the root() node) has a non-empty node name. This
252         name is assigned to the node when adding the node to the tree.
253
254         \ingroup node_tree
255       */
256     class GenericNode
257         : public boost::enable_shared_from_this<GenericNode>
258     {
259         SENF_LOG_CLASS_AREA();
260     public:
261         ///////////////////////////////////////////////////////////////////////////
262         // Types
263
264         typedef boost::shared_ptr<GenericNode> ptr;
265         typedef boost::shared_ptr<GenericNode const> cptr;
266         typedef boost::weak_ptr<GenericNode> weak_ptr;
267
268         ///////////////////////////////////////////////////////////////////////////
269
270         virtual ~GenericNode();
271
272         std::string const & name() const; ///< Node name
273         boost::shared_ptr<DirectoryNode> parent() const; ///< Parent node
274                                         /**< May be null, if the node is the root node or if it is
275                                              not linked to the tree */
276
277         std::string path() const;       ///< Node path
278                                         /**< The node path is built by joining the names of all
279                                              parent nodes with '/' chars. */
280         std::string path(DirectoryNode const & root) const;
281                                         ///< Node path up to \a root
282                                         /**< The node path is built by joining the names of all
283                                              parent nodes up to \a root with '/' chars. */
284
285         ptr unlink();                   ///< Remove node from it's parent directory
286                                         /**< You may either discard the return value and thereby
287                                              dispose the node or may re-attach the node at some
288                                              other place using DirectoryNode::add(). */
289
290         bool active() const;            ///< \c true, if node is attached to the root() node
291
292         void help(std::ostream & output) const; ///< Write help info to \a output
293         std::string shorthelp() const;  ///< Get short (one-line) documentation
294
295         ptr thisptr();                  ///< Get smart pointer to node
296         cptr thisptr() const;           ///< Get smart pointer to node (const)
297
298         bool isChildOf(DirectoryNode & parent) const;
299                                         ///< \c true, if node is a child of \a parent
300                                         /**< Will also return \c true, if \a parent is the current
301                                              node. */
302
303         bool operator== (GenericNode & other) const;
304                                         ///< \c true, if this and \a other are the same node
305         bool operator!= (GenericNode & other) const;
306                                         ///< \c true, if this and \a other are different nodes
307
308         bool isDirectory() const;       ///< \c true, if this is a directory node
309         bool isLink() const;            ///< \c true, if this is a link node
310         bool isCommand() const;         ///< \c true, if this is a command node
311
312         GenericNode const & followLink() const; ///< Follow link if \c this node is a link node
313         GenericNode & followLink();     ///< Follow link if \c this node is a link node
314
315     protected:
316         GenericNode();
317
318         void name(std::string const & name);
319
320 #ifndef DOXYGEN
321     private:
322 #else
323     public:
324 #endif
325         virtual void v_help(std::ostream & output) const = 0;
326                                         ///< Provide help information
327                                         /**< This member must be implemented in derived classes to
328                                              provide node specific help information. */
329         virtual std::string v_shorthelp() const = 0;
330                                         ///< Provide short documentation
331                                         /**< This member must be implemented in derived classes to
332                                              provide node specific documentation. */
333
334     private:
335         std::string name_;
336         DirectoryNode * parent_;
337
338         friend class DirectoryNode;
339     };
340
341     /** \brief Config/console tree link node
342
343         A LinkNode references another node and provides an additional alias name for that node. A
344         LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a
345         UNIX symlink but references another node directly (not via it's path) like a UNIX
346         hardlink. Therefore, a LinkNode works across chroot().
347       */
348     class LinkNode
349         : public GenericNode
350     {
351     public:
352         ///////////////////////////////////////////////////////////////////////////
353         // Types
354
355         typedef boost::shared_ptr<LinkNode> ptr;
356         typedef boost::shared_ptr<LinkNode const> cptr;
357         typedef boost::weak_ptr<LinkNode> weak_ptr;
358
359         ///////////////////////////////////////////////////////////////////////////
360         ///\name Structors and default members
361         ///@{
362
363         static ptr create(GenericNode & node); ///< Create new link node.
364                                         /**< You should normally use DirectoryNode::link() to
365                                              create a link node. */
366
367         ///@}
368         ///////////////////////////////////////////////////////////////////////////
369
370         GenericNode & follow() const;   ///< Access the referenced node
371
372     protected:
373
374     private:
375         explicit LinkNode(GenericNode & node);
376
377         virtual void v_help(std::ostream &) const;
378         virtual std::string v_shorthelp() const;
379
380         GenericNode::ptr node_;
381     };
382
383     class SimpleCommandNode;
384
385     /** \brief Internal: Node creation helper traits
386
387         This class is used internally to find out the type of node to create for a specific argument
388         type.
389      */
390     template <class Object>
391     struct NodeCreateTraits
392     {
393         typedef BOOST_TYPEOF_TPL( senf_console_add_node(
394                                       * static_cast<DirectoryNode *>(0),
395                                       * static_cast<std::string const *>(0),
396                                       * static_cast<Object *>(0),
397                                       0) ) base_type;
398         typedef typename senf::remove_cvref<base_type>::type value_type;
399
400         typedef typename value_type::node_type NodeType;
401         typedef typename value_type::return_type result_type;
402
403         /// Internal
404         struct Creator {
405             static result_type create(DirectoryNode & node, std::string const & name,
406                                       Object & ob);
407         };
408     };
409
410     /** \brief Config/console tree directory node
411
412         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
413         children and supports directory traversal.
414
415         Nodes are normally not instantiated manually but are created by the DirectoryNode via
416         mkdir() or add(). Special add() members however allow externally allocated node objects.
417
418         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
419         managed dynamically, there is a special ScopedDirectory proxy template which provides a
420         DirectoryNode facade. ScopedDirectory is used if a class wants to manage it's own directory
421         as a data member.
422
423         Every node is assigned a (new) name when it is added to a directory. If the directory
424         already has an entry of that name, the name is made unique by appending a suffix of the form
425         '-n' where n is a number starting at 1. If the name is empty, int is set to 'unnamed' and
426         then uniquified as above. Automatically providing unique names simplifies adding
427         configuration/console support to generic components.
428
429         \ingroup node_tree
430       */
431     class DirectoryNode : public GenericNode
432     {
433         SENF_LOG_CLASS_AREA();
434         typedef std::map<std::string, GenericNode::ptr> ChildMap;
435     public:
436         ///////////////////////////////////////////////////////////////////////////
437         // Types
438
439         typedef boost::shared_ptr<DirectoryNode> ptr;
440         typedef boost::shared_ptr<DirectoryNode const> cptr;
441         typedef boost::weak_ptr<DirectoryNode> weak_ptr;
442
443         typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
444         typedef ChildMap::const_iterator child_iterator;
445
446         typedef DirectoryNode node_type;
447         typedef DirectoryNode & return_type;
448
449         ///////////////////////////////////////////////////////////////////////////
450         ///\name Structors and default members
451         ///\{
452
453         static ptr create();            ///< Create node object.
454                                         /**< You should normally use either mkdir() or
455                                              ScopedDirectory instead of create() */
456         ~DirectoryNode();
457
458         ///\}
459         ///////////////////////////////////////////////////////////////////////////
460         ///\name Children
461         ///\{
462
463         template <class NodeType>
464         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
465                                         ///< Add node to tree
466                                         /**< Adds the \a node to the tree as a child of \a this
467                                              node. The node is given the name \a name. If a node of
468                                              that name already exists, a numeric suffix of the form
469                                              '-n' is added to the name until the name is unique. If
470                                              \a name is empty, it is set to 'unnamed'. */
471
472         template <class Object>
473         typename NodeCreateTraits<Object>::result_type add(std::string const & name,
474                                                            Object const & ob);
475                                         ///< Generic child node factory
476                                         /**< This member is used to create a new child node of the
477                                              current directory. The type of node created depends on
478                                              the type of argument passed.
479
480                                              The node type is selected by the NodeCreateTraits
481                                              class. To allow adding a specific node type, you need
482                                              to provide an overload for
483                                              <tt>senf_console_add_node</tt> which must be visible at
484                                              when you register the new node.
485                                              \code
486                                              MyNodeType & senf_console_add_node(
487                                                  DirectoryNode & dir,
488                                                  std::string const & name,
489                                                  MySpecialObject const & ob,
490                                                  int)
491                                              {
492                                                  return dir.add(name, MyNodeType::create(ob));
493                                              }
494                                              \endcode
495                                              (Do not forget the last unnamed 'int' parameter which
496                                              is not used but serves to disambiguate the
497                                              overloads). */
498
499         template <class Object>
500         typename NodeCreateTraits<Object>::result_type add(std::string const & name,
501                                                            Object & ob);
502                                         ///< Generic child node factory
503                                         /**< \see add() */
504
505         GenericNode::ptr remove(std::string const & name);
506                                         ///< Remove node \a name from the tree
507                                         /**< The returned pointer may either be discarded, which
508                                              will automatically dispose the removed node, or it may
509                                              be saved and/or re-attached at some other place in the
510                                              tree. */
511
512         bool hasChild(std::string const & name) const;
513                                         ///< \c true, if there is a child with name \a name
514
515         GenericNode & get(std::string const & name) const;
516                                         ///< Get child node automatically dereferencing links
517                                         /**< \throws UnknownNodeNameException if a child \a name
518                                                  does not exist */
519         GenericNode & getLink(std::string const & name) const;
520                                         ///< Get child node without dereferencing links
521                                         /**< \throws UnknownNodeNameException if a child \a name
522                                                  does not exist */
523
524         DirectoryNode & getDirectory(std::string const & name) const;
525                                         ///< Get directory child node (dereferencing links)
526                                         /**< Same as operator[]
527                                              \throws UnknownNodeNameException if a child \a name
528                                                  does not exist.
529                                              \throws std::bad_cast if the child \a name is not a
530                                                  directory node. */
531
532         DirectoryNode & operator[](std::string const & name) const;
533                                         ///< Get directory child node (dereferencing links)
534                                         /**< Same as getDirectory
535                                              \throws UnknownNodeNameException if a child \a name
536                                                  does not exist.
537                                              \throws std::bad_cast if the child \a name is not a
538                                                  directory node. */
539
540         CommandNode & getCommand(std::string const & name) const;
541                                         ///< Get command child node (dereferencing links)
542                                         /**< Same as operator()
543                                              \throws UnknownNodeNameException if a child \a name
544                                                  does not exist
545                                              \throws std::bad_cast if the child \a name is not a
546                                                  command node. */
547
548         CommandNode & operator()(std::string const & name) const;
549                                         ///< Get command child node (dereferencing links)
550                                         /**< Same as getCommand()
551                                              \throws UnknownNodeNameException if a child \a name
552                                                  does not exist
553                                              \throws std::bad_cast if the child \a name is not a
554                                                  command node. */
555
556         DirectoryNode & mkdir(std::string const & name);
557                                         ///< Create sub-directory node
558         DirectoryNode & provideDirectory(std::string const & name);
559                                         ///< Return subdirectory, possibly creating it
560
561         ChildrenRange children() const; ///< Return iterator range over all children.
562                                         /**< The returned range is sorted by child name. */
563
564         ChildrenRange completions(std::string const & s) const;
565                                         ///< Return iterator range of completions for \a s
566                                         /**< The returned range is sorted by child name. */
567
568         void link(std::string const & name, GenericNode & target);
569                                         ///< Create a child node which is a link to target. \a s
570                                         /**< The new link node will be a child of the node for which this member function is called. */
571
572         ///\}
573         ///////////////////////////////////////////////////////////////////////////
574
575         DirectoryNode & doc(std::string const & doc); ///< Set node documentation
576         DirectoryNode & shortdoc(std::string const & doc); ///< Set node short documentation
577
578         ptr thisptr();
579         cptr thisptr() const;
580
581     protected:
582         DirectoryNode();
583
584     private:
585         void add(GenericNode::ptr node);
586         virtual void v_help(std::ostream & output) const;
587         virtual std::string v_shorthelp() const;
588
589         ChildMap children_;
590         std::string doc_;
591         std::string shortdoc_;
592
593         friend DirectoryNode & root();
594     };
595
596     /// Exception: Unknown node name
597     struct UnknownNodeNameException : public senf::Exception
598     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
599
600 #ifndef DOXYGEN
601     template <class Type>
602     struct NodeCreateTraits< boost::shared_ptr<Type> >
603     {};
604 #endif
605
606     /** \brief Config/console tree command node
607
608         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
609         implementations are derived from this class.
610
611         To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
612
613         Subclass instances of this node type are automatically created when adding commands to the
614         tree. See \ref console_commands.
615
616         \ingroup node_tree
617       */
618     class CommandNode : public GenericNode
619     {
620         SENF_LOG_CLASS_AREA();
621     public:
622         ///////////////////////////////////////////////////////////////////////////
623         // Types
624
625         typedef boost::shared_ptr<CommandNode> ptr;
626         typedef boost::shared_ptr<CommandNode const> cptr;
627         typedef boost::weak_ptr<CommandNode> weak_ptr;
628
629         ///////////////////////////////////////////////////////////////////////////
630
631         void execute(std::ostream & output, ParseCommandInfo const & command) const;
632                                         ///< Execute the command
633                                         /**< \param[in] output stream where result messages may be
634                                                  written to
635                                              \param[in] command command arguments. This is a
636                                                  range of ranges of Token instances. */
637
638         void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) 
639             const;
640                                         ///< Execute the command
641                                         /**< \param[out] rv command return value
642                                              \param[in] output stream where result messages may be
643                                                  written to
644                                              \param[in] command command arguments. This is a
645                                                  range of ranges of Token instances. */
646
647         void operator()(std::ostream & output, ParseCommandInfo const & command) const;
648                                         ///< Execute the command
649                                         /**< Same as execute()
650                                              \param[in] output stream where result messages may be
651                                                  written to
652                                              \param[in] command command arguments. This is a
653                                                  range of ranges of Token instances. */
654         void operator()(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
655             const;
656
657         ptr thisptr();
658         cptr thisptr() const;
659
660     protected:
661         CommandNode();
662
663 #ifndef DOXYGEN
664     private:
665 #endif
666         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
667             const = 0;
668                                         ///< Called to execute the command
669                                         /**< \param[out] rv return value holder
670                                               \param[in] os stream where result messages may be
671                                                  written to
672                                              \param[in] command command arguments. This is a
673                                                  range of ranges of Token instances. */
674
675     private:
676     };
677
678     /** \brief Most simple CommandNode implementation
679
680         This CommandNode implementation simply forwards the \a output and \a arguments arguments to
681         an arbitrary callback. Thus, it allows to add callbacks with the signature
682         \code
683         void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
684         { ... }
685         \endcode
686         to the tree.
687
688         \ingroup console_commands
689      */
690     class SimpleCommandNode : public CommandNode
691     {
692         SENF_LOG_CLASS_AREA();
693     public:
694         ///////////////////////////////////////////////////////////////////////////
695         // Types
696
697         typedef boost::shared_ptr<SimpleCommandNode> ptr;
698         typedef boost::shared_ptr<SimpleCommandNode const> cptr;
699         typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
700
701         typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
702
703         typedef SimpleCommandNode node_type;
704         typedef SimpleCommandNode & return_type;
705
706         ///////////////////////////////////////////////////////////////////////////
707         ///\name Structors and default members
708         ///\{
709
710         static ptr create(Function const & fn);
711
712         ///\}
713         ///////////////////////////////////////////////////////////////////////////
714
715         ptr thisptr();
716         cptr thisptr() const;
717
718         SimpleCommandNode & doc(std::string const & doc);
719         SimpleCommandNode & shortdoc(std::string const & doc);
720
721     protected:
722         SimpleCommandNode(Function const & fn);
723
724     private:
725         virtual void v_help(std::ostream & output) const;
726         virtual std::string v_shorthelp() const;
727         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
728             const;
729
730
731         Function fn_;
732         std::string doc_;
733         std::string shortdoc_;
734     };
735
736 #ifndef DOXYGEN
737
738     SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
739                                               SimpleCommandNode::Function fn, int);
740
741     DirectoryNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
742                                           DirectoryNode & dir, int);
743
744 #endif
745
746 }}
747
748 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
749
750 BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
751 BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
752
753
754 ///////////////////////////////hh.e////////////////////////////////////////
755 #include "Node.cci"
756 //#include "Node.ct"
757 #include "Node.cti"
758 #endif
759
760
761 // Local Variables:
762 // mode: c++
763 // fill-column: 100
764 // comment-column: 40
765 // c-file-style: "senf"
766 // indent-tabs-mode: nil
767 // ispell-local-dictionary: "american"
768 // compile-command: "scons -u test"
769 // End: