Utils/Console: Add basic short-help info
[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 (
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     DirectoryNode & root();
227
228     /** \brief Config/console node tree base-class
229
230         GenericNode is the base class of all node objects. There are two basic node types derived
231         from GenericNode:  DirectoryNode and CommandNode.
232
233         All nodes are dynamically allocated and automatically managed using reference counting.
234
235         All nodes are normally linked into a single tree which root node is
236         senf::console::root(). Nodes may however be orphaned (not linked to the tree) either
237         directly (the node has no parent) or indirectly (the node has a parent but is part of an
238         orphaned subtree which is not linked to the root node).
239
240         Every active (non-orphaned) node (except the root() node) has a non-empty node name. This
241         name is assigned to the node when adding the node to the tree.
242
243         \ingroup node_tree
244       */
245     class GenericNode
246         : public boost::enable_shared_from_this<GenericNode>
247     {
248         SENF_LOG_CLASS_AREA();
249     public:
250         ///////////////////////////////////////////////////////////////////////////
251         // Types
252
253         typedef boost::shared_ptr<GenericNode> ptr;
254         typedef boost::shared_ptr<GenericNode const> cptr;
255         typedef boost::weak_ptr<GenericNode> weak_ptr;
256
257         ///////////////////////////////////////////////////////////////////////////
258
259         virtual ~GenericNode();
260
261         std::string const & name() const; ///< Node name
262         boost::shared_ptr<DirectoryNode> parent() const; ///< Parent node
263                                         /**< May be null, if the node is the root node or if it is
264                                              not linked to the tree */
265
266         std::string path() const;       ///< Node path
267                                         /**< The node path is built by joining the names of all
268                                              parent nodes with '/' chars. */
269         std::string path(DirectoryNode const & root) const;
270                                         ///< Node path up to \a root
271                                         /**< The node path is built by joining the names of all
272                                              parent nodes up to \a root with '/' chars. */
273
274         ptr unlink();                   ///< Remove node from it's parent directory
275                                         /**< You may either discard the return value and thereby
276                                              dispose the node or may re-attach the node at some
277                                              other place using DirectoryNode::add(). */
278
279         bool active() const;            ///< \c true, if node is attached to the root() node
280
281         void help(std::ostream & output) const; ///< Write help info to \a output
282         std::string shorthelp() const;  ///< Get short (one-line) documentation
283
284         ptr thisptr();                  ///< Get smart pointer to node
285         cptr thisptr() const;           ///< Get smart pointer to node (const)
286
287         bool isChildOf(DirectoryNode & parent) const;
288                                         ///< \c true, if node is a child of \a parent
289                                         /**< Will also return \c true, if \a parent is the current
290                                              node. */
291
292         bool operator== (GenericNode & other) const;
293                                         ///< \c true, if this and \a other are the same node
294         bool operator!= (GenericNode & other) const;
295                                         ///< \c true, if this and \a other are different nodes
296
297         bool isDirectory() const;       ///< \c true, if this is a directory node
298         bool isLink() const;            ///< \c true, if this is a link node
299         bool isCommand() const;         ///< \c true, if this is a command node
300
301         GenericNode const & followLink() const; ///< Follow link if \c this node is a link node
302         GenericNode & followLink();     ///< Follow link if \c this node is a link node
303
304     protected:
305         GenericNode();
306
307         void name(std::string const & name);
308
309 #ifndef DOXYGEN
310     private:
311 #else
312     public:
313 #endif
314         virtual void v_help(std::ostream & output) const = 0;
315                                         ///< Provide help information
316                                         /**< This member must be implemented in derived classes to
317                                              provide node specific help information. */
318         virtual std::string v_shorthelp() const = 0;
319                                         ///< Provide short documentation
320                                         /**< This member must be implemented in derived classes to
321                                              provide node specific documentation. */
322
323     private:
324         std::string name_;
325         DirectoryNode * parent_;
326
327         friend class DirectoryNode;
328     };
329
330     /** \brief Config/console tree link node
331
332         A LinkNode references another node and provides an additional alias name for that node. A
333         LinkNode works like a mixture of UNIX symlinks and hardlinks: It is an explicit link like a
334         UNIX symlink but references another node directly (not via it's path) like a UNIX
335         hardlink. Therefore, a LinkNode works across chroot().
336       */
337     class LinkNode
338         : public GenericNode
339     {
340     public:
341         ///////////////////////////////////////////////////////////////////////////
342         // Types
343
344         typedef boost::shared_ptr<LinkNode> ptr;
345         typedef boost::shared_ptr<LinkNode const> cptr;
346         typedef boost::weak_ptr<LinkNode> weak_ptr;
347
348         ///////////////////////////////////////////////////////////////////////////
349         ///\name Structors and default members
350         ///@{
351
352         static ptr create(GenericNode & node); ///< Create new link node.
353                                         /**< You should normally use DirectoryNode::link() to
354                                              create a link node. */
355
356         ///@}
357         ///////////////////////////////////////////////////////////////////////////
358
359         GenericNode & follow() const;   ///< Access the referenced node
360
361     protected:
362
363     private:
364         explicit LinkNode(GenericNode & node);
365
366         virtual void v_help(std::ostream &) const;
367         virtual std::string v_shorthelp() const;
368
369         GenericNode::ptr node_;
370     };
371
372     class SimpleCommandNode;
373
374     /** \brief Internal: Node creation helper traits
375
376         This class is used internally to find out the type of node to create for a specific argument
377         type.
378      */
379     template <class Object>
380     struct NodeCreateTraits
381     {
382         typedef BOOST_TYPEOF_TPL( senf_console_add_node(
383                                       * static_cast<DirectoryNode *>(0),
384                                       * static_cast<std::string const *>(0),
385                                       * static_cast<Object *>(0),
386                                       0) ) base_type;
387         typedef typename senf::remove_cvref<base_type>::type value_type;
388
389         typedef typename value_type::node_type NodeType;
390         typedef typename value_type::return_type result_type;
391
392         /// Internal
393         struct Creator {
394             static result_type create(DirectoryNode & node, std::string const & name,
395                                       Object & ob);
396         };
397     };
398
399     /** \brief Config/console tree directory node
400
401         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
402         children and supports directory traversal.
403
404         Nodes are normally not instantiated manually but are created by the DirectoryNode via
405         mkdir() or add(). Special add() members however allow externally allocated node objects.
406
407         Nodes may be added to the tree only once, otherwise chaos will ensue. Since nodes are always
408         managed dynamically, there is a special ScopedDirectory proxy template which provides a
409         DirectoryNode facade. ScopedDirectory is used if a class wants to manage it's own directory
410         as a data member.
411
412         Every node is assigned a (new) name when it is added to a directory. If the directory
413         already has an entry of that name, the name is made unique by appending a suffix of the form
414         '-n' where n is a number starting at 1. If the name is empty, int is set to 'unnamed' and
415         then uniquified as above. Automatically providing unique names simplifies adding
416         configuration/console support to generic components.
417
418         \ingroup node_tree
419       */
420     class DirectoryNode : public GenericNode
421     {
422         SENF_LOG_CLASS_AREA();
423         typedef std::map<std::string, GenericNode::ptr> ChildMap;
424     public:
425         ///////////////////////////////////////////////////////////////////////////
426         // Types
427
428         typedef boost::shared_ptr<DirectoryNode> ptr;
429         typedef boost::shared_ptr<DirectoryNode const> cptr;
430         typedef boost::weak_ptr<DirectoryNode> weak_ptr;
431
432         typedef boost::iterator_range<ChildMap::const_iterator> ChildrenRange;
433         typedef ChildMap::const_iterator child_iterator;
434
435         typedef DirectoryNode node_type;
436         typedef DirectoryNode & return_type;
437
438         ///////////////////////////////////////////////////////////////////////////
439         ///\name Structors and default members
440         ///\{
441
442         static ptr create();            ///< Create node object.
443                                         /**< You should normally use either mkdir() or
444                                              ScopedDirectory instead of create() */
445         ~DirectoryNode();
446
447         ///\}
448         ///////////////////////////////////////////////////////////////////////////
449         ///\name Children
450         ///\{
451
452         template <class NodeType>
453         NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
454                                         ///< Add node to tree
455                                         /**< Adds the \a node to the tree as a child of \a this
456                                              node. The node is given the name \a name. If a node of
457                                              that name already exists, a numeric suffix of the form
458                                              '-n' is added to the name until the name is unique. If
459                                              \a name is empty, it is set to 'unnamed'. */
460
461         template <class Object>
462         typename NodeCreateTraits<Object>::result_type add(std::string const & name,
463                                                            Object const & ob);
464                                         ///< Generic child node factory
465                                         /**< This member is used to create a new child node of the
466                                              current directory. The type of node created depends on
467                                              the type of argument passed.
468
469                                              The node type is selected by the NodeCreateTraits
470                                              class. To allow adding a specific node type, you need
471                                              to provide an overload for
472                                              <tt>senf_console_add_node</tt> which must be visible at
473                                              when you register the new node.
474                                              \code
475                                              MyNodeType & senf_console_add_node(
476                                                  DirectoryNode & dir,
477                                                  std::string const & name,
478                                                  MySpecialObject const & ob,
479                                                  int)
480                                              {
481                                                  return dir.add(name, MyNodeType::create(ob));
482                                              }
483                                              \endcode
484                                              (Do not forget the last unnamed 'int' parameter which
485                                              is not used but serves to disambiguate the
486                                              overloads). */
487
488         template <class Object>
489         typename NodeCreateTraits<Object>::result_type add(std::string const & name,
490                                                            Object & ob);
491                                         ///< Generic child node factory
492                                         /**< \see add() */
493
494         GenericNode::ptr remove(std::string const & name);
495                                         ///< Remove node \a name from the tree
496                                         /**< The returned pointer may either be discarded, which
497                                              will automatically dispose the removed node, or it may
498                                              be saved and/or re-attached at some other place in the
499                                              tree. */
500
501         bool hasChild(std::string const & name) const;
502                                         ///< \c true, if there is a child with name \a name
503
504         GenericNode & get(std::string const & name) const;
505                                         ///< Get child node automatically dereferencing links
506                                         /**< \throws UnknownNodeNameException if a child \a name
507                                                  does not exist */
508         GenericNode & getLink(std::string const & name) const;
509                                         ///< Get child node without dereferencing links
510                                         /**< \throws UnknownNodeNameException if a child \a name
511                                                  does not exist */
512
513         DirectoryNode & getDirectory(std::string const & name) const;
514                                         ///< Get directory child node (dereferencing links)
515                                         /**< Same as operator[]
516                                              \throws UnknownNodeNameException if a child \a name
517                                                  does not exist.
518                                              \throws std::bad_cast if the child \a name is not a
519                                                  directory node. */
520
521         DirectoryNode & operator[](std::string const & name) const;
522                                         ///< Get directory child node (dereferencing links)
523                                         /**< Same as getDirectory
524                                              \throws UnknownNodeNameException if a child \a name
525                                                  does not exist.
526                                              \throws std::bad_cast if the child \a name is not a
527                                                  directory node. */
528
529         CommandNode & getCommand(std::string const & name) const;
530                                         ///< Get command child node (dereferencing links)
531                                         /**< Same as operator()
532                                              \throws UnknownNodeNameException if a child \a name
533                                                  does not exist
534                                              \throws std::bad_cast if the child \a name is not a
535                                                  command node. */
536
537         CommandNode & operator()(std::string const & name) const;
538                                         ///< Get command child node (dereferencing links)
539                                         /**< Same as getCommand()
540                                              \throws UnknownNodeNameException if a child \a name
541                                                  does not exist
542                                              \throws std::bad_cast if the child \a name is not a
543                                                  command node. */
544
545         DirectoryNode & mkdir(std::string const & name);
546                                         ///< Create sub-directory node
547         DirectoryNode & provideDirectory(std::string const & name);
548                                         ///< Return subdirectory, possibly creating it
549
550         ChildrenRange children() const; ///< Return iterator range over all children.
551                                         /**< The returned range is sorted by child name. */
552
553         ChildrenRange completions(std::string const & s) const;
554                                         ///< Return iterator range of completions for \a s
555                                         /**< The returned range is sorted by child name. */
556
557         void link(std::string const & name, GenericNode & target);
558                                         ///< Create a child node which is a link to target. \a s
559                                         /**< The new link node will be a child of the node for which this member function is called. */
560
561         ///\}
562         ///////////////////////////////////////////////////////////////////////////
563
564         DirectoryNode & doc(std::string const & doc); ///< Set node documentation
565         DirectoryNode & shortdoc(std::string const & doc); ///< Set node short documentation
566
567         ptr thisptr();
568         cptr thisptr() const;
569
570     protected:
571         DirectoryNode();
572
573     private:
574         void add(GenericNode::ptr node);
575         virtual void v_help(std::ostream & output) const;
576         virtual std::string v_shorthelp() const;
577
578         ChildMap children_;
579         std::string doc_;
580         std::string shortdoc_;
581
582         friend DirectoryNode & root();
583     };
584
585     /// Exception: Unknown node name
586     struct UnknownNodeNameException : public senf::Exception
587     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
588
589 #ifndef DOXYGEN
590     template <class Type>
591     struct NodeCreateTraits< boost::shared_ptr<Type> >
592     {};
593 #endif
594
595     /** \brief Config/console tree command node
596
597         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
598         implementations are derived from this class.
599
600         To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
601
602         Subclass instances of this node type are automatically created when adding commands to the
603         tree. See \ref console_commands.
604
605         \ingroup node_tree
606       */
607     class CommandNode : public GenericNode
608     {
609         SENF_LOG_CLASS_AREA();
610     public:
611         ///////////////////////////////////////////////////////////////////////////
612         // Types
613
614         typedef boost::shared_ptr<CommandNode> ptr;
615         typedef boost::shared_ptr<CommandNode const> cptr;
616         typedef boost::weak_ptr<CommandNode> weak_ptr;
617
618         ///////////////////////////////////////////////////////////////////////////
619
620         void execute(std::ostream & output, ParseCommandInfo const & command) const;
621                                         ///< Execute the command
622                                         /**< \param[in] output stream where result messages may be
623                                                  written to
624                                              \param[in] arguments command arguments. This is a
625                                                  range of ranges of Token instances. */
626
627         void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) 
628             const;
629                                         ///< Execute the command
630                                         /**< \param[out] rv command return value
631                                              \param[in] output stream where result messages may be
632                                                  written to
633                                              \param[in] arguments command arguments. This is a
634                                                  range of ranges of Token instances. */
635
636         void operator()(std::ostream & output, ParseCommandInfo const & command) const;
637                                         ///< Execute the command
638                                         /**< Same as execute()
639                                              \param[in] output stream where result messages may be
640                                                  written to
641                                              \param[in] arguments command arguments. This is a
642                                                  range of ranges of Token instances. */
643         void operator()(boost::any & rv, std::ostream & output, ParseCommandInfo const & command)
644             const;
645
646         ptr thisptr();
647         cptr thisptr() const;
648
649     protected:
650         CommandNode();
651
652 #ifndef DOXYGEN
653     private:
654 #endif
655         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
656             const = 0;
657                                         ///< Called to execute the command
658                                         /**< \param[out] rv return value holder
659                                              \param[in] arguments command arguments. This is a
660                                                  range of ranges of Token instances. */
661
662     private:
663     };
664
665     /** \brief Most simple CommandNode implementation
666
667         This CommandNode implementation simply forwards the \a output and \a arguments arguments to
668         an arbitrary callback. Thus, it allows to add callbacks with the signature
669         \code
670         void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
671         { ... }
672         \endcode
673         to the tree.
674
675         \ingroup console_commands
676      */
677     class SimpleCommandNode : public CommandNode
678     {
679         SENF_LOG_CLASS_AREA();
680     public:
681         ///////////////////////////////////////////////////////////////////////////
682         // Types
683
684         typedef boost::shared_ptr<SimpleCommandNode> ptr;
685         typedef boost::shared_ptr<SimpleCommandNode const> cptr;
686         typedef boost::weak_ptr<SimpleCommandNode> weak_ptr;
687
688         typedef boost::function<void (std::ostream &, ParseCommandInfo const &)> Function;
689
690         typedef SimpleCommandNode node_type;
691         typedef SimpleCommandNode & return_type;
692
693         ///////////////////////////////////////////////////////////////////////////
694         ///\name Structors and default members
695         ///\{
696
697         static ptr create(Function const & fn);
698
699         ///\}
700         ///////////////////////////////////////////////////////////////////////////
701
702         ptr thisptr();
703         cptr thisptr() const;
704
705         SimpleCommandNode & doc(std::string const & doc);
706         SimpleCommandNode & shortdoc(std::string const & doc);
707
708     protected:
709         SimpleCommandNode(Function const & fn);
710
711     private:
712         virtual void v_help(std::ostream & output) const;
713         virtual std::string v_shorthelp() const;
714         virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command)
715             const;
716
717
718         Function fn_;
719         std::string doc_;
720         std::string shortdoc_;
721     };
722
723 #ifndef DOXYGEN
724
725     SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
726                                               SimpleCommandNode::Function fn, int);
727
728     DirectoryNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
729                                           DirectoryNode & dir, int);
730
731 #endif
732
733 }}
734
735 #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
736
737 BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
738 BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
739
740
741 ///////////////////////////////hh.e////////////////////////////////////////
742 #include "Node.cci"
743 //#include "Node.ct"
744 #include "Node.cti"
745 #endif
746
747
748 // Local Variables:
749 // mode: c++
750 // fill-column: 100
751 // comment-column: 40
752 // c-file-style: "senf"
753 // indent-tabs-mode: nil
754 // ispell-local-dictionary: "american"
755 // compile-command: "scons -u test"
756 // End: