Console: More extensible keyword parameter dispatching in arg() attribute
g0dil [Thu, 10 Apr 2008 15:35:57 +0000 (15:35 +0000)]
Console: Documentation

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@802 270642c3-0616-0410-b53a-bc976706d245

Console/Mainpage.dox
Console/Node.hh
Console/OverloadedCommand.cc
Console/OverloadedCommand.hh
Console/Parse.hh
Console/ParsedCommand.cti
Console/ParsedCommand.hh
Console/ParsedCommand.test.cc
HowTos/NewPacket/Mainpage.dox
senf.dict

index 9c0ea9a..b63300e 100644 (file)
@@ -42,6 +42,7 @@
     To get started using the config/console library, see
     \li \ref node_tree
     \li \ref console_parser
+    \li \ref console_commands
 
     \section console_example Example
 
     </pre>
  */
 
+/** \defgroup console_commands Supported command types
+
+    The Console/config library supports quite a number of different command types. All these types
+    of command are registered, by passing them to DirectoryNode::add()
+
+    \autotoc
+
+    \section console_manualparse Manually parsing command arguments
+
+    This is the most primitive type of command. It will be called with an output stream and with a
+    senf::console::ParseCommandInfo reference which holds information about the command parsed.
+
+    From this information the command callback gets a list of arguments or tokens which then can be
+    interpreted in an arbitrary way.
+    \code
+    void test1(std::ostream & os, senf::console::ParseCommandInfo const & command)
+    {
+        // We take exactly one argument
+        if (command.arguments().size() != 1) 
+            raise senf::console::SyntaxErrorException("invalid number of arguments");
+
+        senf::console::ParseCommandInfo::TokenRange & argTokens (
+            command.arguments()[0]);
+
+        // The argument must have exactly one token
+        if (argTokens.size() != 1)
+            raise senf::console::SyntaxErrorException("argument syntax error");
+
+        // Retrieve the token value
+        std::string arg (argTokens[0].value());
+
+        // In this example, we just write the argument to the output stream
+        os << arg << std::endl;
+    }
+    \endcode
+    
+    Registering this callback is done by simply adding it. To provide online help, pass it to
+    'doc()':
+    \code
+    senf::console::root()
+        .add("test1", &test1)
+        .doc("Usage:\n"
+             "    test1 arg\n"
+             "\n"
+             "Echo 'arg' to the console");
+    \endcode
+
+    The callback may now be called interactively on the console by it's registered name:
+    \htmlonly
+    <pre>
+    server:/$ test1
+    invalid number of arguments
+    server:/$ test1 stefan@j32.de
+    stefan@j32.de
+    server:/$ test1 (echo me)
+    argument syntax error
+    server:/$ help test1
+    Usage:
+        test1 arg
+
+    Echo 'arg' to the console
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    As you can see above, the arguments and tokens are returned as <a
+    href="http://www.boost.org/doc/libs/1_33_1/libs/range/doc/utility_class.html#iter_range">
+    boost::iterator_range</a> instances. These behave much like containers: They have \c begin() and
+    \c end() and some other useful members.
+    
+    The parser will have divided the argument tokens into arguments already. This simplifies further
+    parsing. If however you want to access the list of argument tokens as a single list, you can do
+    so using senf::console::ParseCommandInfo::tokens().
+    
+    Parsing arguments is quite simple but can get very tedious. To simplify this task, the parsing
+    can be delegated to the Console/config library. See the next section.
+
+
+    \section console_autoparse Automatic argument parsing
+    
+    To greatly simplify parsing complex commands, we turn to automatic argument parsing. This
+    feature allows to register (almost) arbitrary callbacks.
+
+    \code
+    std::string test2(std::string const & arg)
+    {
+        return arg;
+    }
+    \endcode
+
+    This extremely simple callback may be registered by adding it to a
+    senf::console::DirectoryNode.
+    \code
+    senf::console::root()
+        .add("test2", &test2);
+    \endcode
+    The functionality is now identical to \c test1:
+    \htmlonly
+    <pre>
+    server:/$ test2
+    invalid number of arguments
+    server:/$ test2 stefan@j32.de
+    stefan@j32.de
+    server:/$ test2 (echo me)
+    argument syntax error
+    server:/$ help test2
+    Usage:
+        test2 arg11:string
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    As we can see, some documentation is automatically provided. To add more info, we need to add
+    some additional attributes when registering the command:
+    \code
+    namespace kw = senf::console::kw;
+
+    senf::console::root()
+        .add("test2", &test2)
+        .doc("Echo 'arg' to the console")
+        .arg( kw::name = "arg",
+              kw::description = "Message to output" );
+    \endcode
+
+    (Sadly, there is no way to automatically find out the \e name of an argument, just it's type.)
+    Every callback argument corresponds with a call of the \c arg() attribute. Argument attributes
+    are set using keywords from the \ref senf::console::kw namespace. You will probably wither use
+    this namespace via a namespace alias (as above) or via a <tt>using namespace
+    senf::console::kw</tt> declaration (as in all the following examples)
+
+    You don't need
+    to specify any information for an argument: To skip an argument, just call \c arg() without
+    attributes for this argument.
+
+    After adding this information, the online help is much more intelligible
+    \htmlonly
+    <pre>
+    server:/$ help test2
+    Usage:
+        test2 arg:string
+
+    With:
+        arg       Message to output
+
+    Echo 'arg' to the console
+    server:/$
+    </pre>
+    \endhtmlonly
+
+    \subsection command_ostream Accessing the console stream
+
+    Commands may have an optional first argument of type <tt>std::ostream &</tt>. This argument is
+    not considered part of the real interface. When the command is executed, the callback will be
+    passed the current console's output stream object in this argument. With this, the callback can
+    output arbitrary messages to the network console. See the next section for an example.
+
+    \subsection command_overload Command overloading
+
+    Automatically parsed commands can be overloaded: You can register multiple commands under the
+    same name. If this happens, each command is tried in turn until no SyntaxErrorException is
+    raised.
+
+    \code
+    void test3(std::ostream & os, unsigned n, std::string text)
+    {
+        // It's perfectly valid to check additional constraints here and throw a
+        // SyntaxErrorException. In this case, the next overload will be tried. However, you must
+        // ensure, That no action takes place before this check !
+        if ( n==0 ) throw senf::console::SyntaxErrorException("invalid value for parameter 'n'");
+        while (n-- > 0) os << text << std::endl;
+    }
+
+    using namespace senf::console::kw;
+    
+    senf::console::root()
+        .add("test3", &test3)
+        .doc("Echo text to the console")
+        .overloadDoc("Repeat 'text' for 'n' lines")
+        .arg( name = "n", description = "Number of repetitions" )
+        .arg( name = "text", description = "Message to output" );
+    senf::console::root()
+        .add("test3", &test2)
+        .overloadDoc("Echo the 'text' argument")
+        .arg( name = "text", description = "Message to output" );
+    \endcode
+
+    We can now call \c test2 with one or two arguments:
+
+    \htmlonly
+    <pre>
+    server:/$ test3 "The sky is blue"
+    The sky is blue
+    server:/$ test3 4 ok
+    ok
+    ok
+    ok
+    ok
+    server:/$ help test3
+    Usage:
+        1- test3 n:unsigned text:string
+        2- test3 text:string
+    
+    With:
+        n         Numer of repetitions
+        text      Messsage to output
+
+    Echo text to the console
+
+    Variant 1:
+    Repeat 'text' for 'n' lines
+    
+    Variant 2:
+    Echo the 'text' argument
+    senf:/$    And 
+
+    </pre>
+    \endhtmlonly
+
+    \subsection console_defaults Default values
+    
+    Another information which can not be automatically gathered from the type system is default
+    values. These have to be explicitly declared:
+    \code
+    using namespace senf::console::kw;
+
+    senf::console::root()
+        .add("test4", &test2b)
+        .arg()
+        .arg( default_value = "ok" );
+    \endcode
+    (Default values must not necessarily be declared in the callback function too.) Of course,
+    default values can be used together with overloading. 
+
+    There must be no argument without default value after an argument with a default value
+    declared. This fill fail at compile time. 
+
+    \subsection console_auto_summary Attribute summary
+
+    Here a summary of all the attributes available for automatically parsed command nodes:
+    
+    <table class="senf fixedwidth">
+    
+    <tr><td style="width:12em">\c doc ( \e text )</td><td>Documentation for all overloads</td></tr>
+
+    <tr><td>\c overloadDoc ( \e text )</td><td>Documentation for a specific overliad</td></tr>
+
+    <tr><td>\c arg ( \e attributes )</td><td>Set parameter attributes. All attributes are
+    optional. The attribute keywords are defined in the \ref senf::console::kw namespace. Valid
+    Attributes are:
+    \li \e name: Parameter name
+    \li \e description: One-line description of the argument
+    \li \e default_value: Arguments default value</td></tr>
+
+    </table>
+    
+    \section console_memberfn Registering member functions
+    
+    Member functions are supported like non-member functions. They must however be added through a
+    senf::console::ScopedDirectory<> instance to bind them to their instance.
+    \code
+    class Test 
+    {
+    public:
+        ScopedDirectory<Test> dir;
+
+        Test(std::string label) : dir(this), label_ (label) {
+            dir.add("test4", &Test::test2);
+            dir.add("test4", &Test::test3);
+        }
+
+        std::string test2(std::string const & text) { return label_ + ": " + text; }
+        void test3(std::ostream & os, unsigned n, std::string const & text) {
+            while (n-- > 0) os << label << ": " << text << std::endl; }
+
+    private:
+        std::string label_;
+    };
+
+    // ...
+
+    Test testOb ("test");
+    senf::console::root().add("testobj", testOb.dir);
+    \endcode
+
+    Binding via senf::console::ScopedDirectory ensures, that the commands are automatically removed
+    from the tree when an object is destroyed.
+ */
+
 \f
 // Local Variables:
 // mode: c++
 // indent-tabs-mode: nil
 // ispell-local-dictionary: "american"
 // compile-command: "scons -u test"
-// mode: flyspell
 // mode: auto-fill
 // End:
+
index 9bf37ec..853cc1b 100644 (file)
@@ -23,7 +23,7 @@
 /** \file
     \brief Node public header */
 
-/** \defgroup node_tree The console/config file-system node tree
+/** \defgroup node_tree The node tree
     
     The console/config node tree is the central data-structure of the library. Into this tree, all
     commands and parameters are entered. The tree is then exposed using a file-system like
     \li An arbitrary node can be created and then (possibly later) added to the tree using the
         corresponding senf::console::DirectoryNode::add() overload.
     \li A senf::console::CommandNode is normally added to the tree by directly adding a callback
-        using one of the overloaded senf::console::DirectoryNode::add() members.
+        using one of the overloaded senf::console::DirectoryNode::add() members. See \ref
+        console_commands.
 
     When directly adding a node callback, the type of node added depends on the type of
     callback. The callback types which can be added are listed at \ref console_callbacks.
@@ -520,6 +521,9 @@ namespace console {
 
         To execute a command, CommandNode::operator()() or CommandNode::execute() is called.
 
+        Subclass instances of this node type are automatically created when adding commands to the
+        tree. See \ref console_commands.
+
         \ingroup node_tree
       */
     class CommandNode : public GenericNode
@@ -573,9 +577,14 @@ namespace console {
     /** \brief Most simple CommandNode implementation
 
         This CommandNode implementation simply forwards the \a output and \a arguments arguments to
-        an arbitrary callback.
+        an arbitrary callback. Thus, it allows to add callbacks with the signature
+        \code
+        void callback(std::ostream & os, senf::console::ParseCommandInfo const & command)
+        { ... }
+        \endcode
+        to the tree.
  
-        \ingroup node_tree
+        \ingroup console_commands
      */
     class SimpleCommandNode : public CommandNode
     {
index 47a08dc..921ce8f 100644 (file)
@@ -80,7 +80,9 @@ prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
         Overloads::const_iterator const i_end (overloads_.end());
         unsigned index (1);
         for (; i != i_end; ++i, ++index) {
-            os << "    " << index << "- " << name();
+            os << "    ";
+            if (overloads_.size() > 1) os << index << "- ";
+            os << name();
             for (unsigned j (0); j < (*i)->numArguments(); ++j) {
                 ArgumentDoc arg;
                 (*i)->argumentDoc(j, arg);
@@ -143,9 +145,12 @@ prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os)
         unsigned index (1);
         for (; i != i_end; ++i, ++index) {
             std::string overloadDoc ((*i)->doc());
-            if (! overloadDoc.empty())
-                os << "\n" << "Variant " << index << ":\n"
-                   << overloadDoc << "\n";
+            if (! overloadDoc.empty()) {
+                os << "\n";
+                if (overloads_.size() > 1)
+                    os << "Variant " << index << ":\n";
+                os << overloadDoc << "\n";
+            }
         }
     }
 }
index e7b5692..1363d52 100644 (file)
@@ -119,13 +119,13 @@ namespace console {
         cmd.add(senf::console::SimpleCommandOverload::create(&anotherCallback));
         \endcode
 
-        However, this facility is mostly used not directly but indirectly (and automatically) when
+        However, this facility is normally used not directly but indirectly (and automatically) when
         adding argument parsing callbacks.
 
         \warning For this to work, the commands <b>must</b> do all syntax checking before doing any
             operation
 
-        \ingroup node_tree
+        \ingroup console_commands
       */
     class OverloadedCommandNode
         : public CommandNode
index 1dc7498..91a1467 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef HH_Parse_
 #define HH_Parse_ 1
 
-/** \defgroup console_parser The console/config parser
+/** \defgroup console_parser The parser
 
     The console/config library defines a simple language used to interact with the console or to
     configure the application.  The parser is not concerned about interpreting commands or
index 72f372e..9abe00d 100644 (file)
@@ -118,63 +118,67 @@ ParsedAttributeAttributorBase(Overload & overload, unsigned index)
 // senf::console::ParsedAttributeAttributor<Overload,index,flag>
 
 template <class Overload, unsigned index, bool flag>
-template <class ArgumentPack>
 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::
-argInfo(ArgumentPack const & args)
+senf::console::ParsedAttributeAttributor<Overload,index,flag>::arg()
     const
 {
-    typedef typename boost::parameter::binding<
-        ArgumentPack, tag::detail::default_value_>::type default_value_t;
-    return argInfo( args, boost::is_same<default_value_t, void>() );
+    return next();
 }
 
 template <class Overload, unsigned index, bool flag>
 template <class ArgumentPack>
 prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
 senf::console::ParsedAttributeAttributor<Overload,index,flag>::
-argInfo(ArgumentPack const & args, boost::mpl::true_)
+argInfo(ArgumentPack const & args)
     const
 {
-    return argInfo( args[tag::name_ | ""], 
-                    args[tag::description_ | ""] );
+#   define HaveArg(tag) boost::is_same< \
+        typename boost::parameter::binding<ArgumentPack, tag>::type, void >()
+
+    argInfo( kw::name,          args, HaveArg(kw::type::name)          );
+    argInfo( kw::description,   args, HaveArg(kw::type::description)   );
+    argInfo( kw::default_value, args, HaveArg(kw::type::default_value) );
 
+    return next();
+
+#   undef HaveArg
 }
 
 template <class Overload, unsigned index, bool flag>
+template <class Kw, class ArgumentPack>
+prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_)
+    const
+{}
+
+template <class Overload, unsigned index, bool flag>
 template <class ArgumentPack>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::
-argInfo(ArgumentPack const & args, boost::mpl::false_)
+prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+argInfo(boost::parameter::keyword<kw::type::name> const &, ArgumentPack const & args,
+        boost::mpl::false_)
     const
 {
-    return argInfo( args[tag::name_ | ""], 
-                    args[tag::description_ | ""], 
-                    args[tag::default_value_ | value_type()] );
+    this->argName(args[kw::name]);
 }
 
 template <class Overload, unsigned index, bool flag>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::argInfo(std::string const & name,
-                                                                       std::string const & doc)
+template <class ArgumentPack>
+prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+argInfo(boost::parameter::keyword<kw::type::description> const &, ArgumentPack const & args,
+        boost::mpl::false_)
     const
 {
-    this->argName(name);
-    this->argDoc(doc);
-    return next();
+    this->argDoc(args[kw::description]);
 }
 
 template <class Overload, unsigned index, bool flag>
-prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
-senf::console::ParsedAttributeAttributor<Overload,index,flag>::argInfo(std::string const & name,
-                                                                       std::string const & doc,
-                                                                       value_type const & value)
+template <class ArgumentPack>
+prefix_ void senf::console::ParsedAttributeAttributor<Overload,index,flag>::
+argInfo(boost::parameter::keyword<kw::type::default_value> const &, ArgumentPack const & args,
+        boost::mpl::false_)
     const
 {
-    this->argName(name);
-    this->argDoc(doc);
-    defaultValue(value);
-    return next();
+    this->defaultValue(args[kw::default_value]);
 }
 
 template <class Overload, unsigned index, bool flag>
@@ -185,7 +189,7 @@ ParsedAttributeAttributor(Overload & overload)
 {}
 
 template <class Overload, unsigned index, bool flag>
-prefix_ senf::console::ParsedAttributeAttributor<Overload, index+1>
+prefix_ typename senf::console::ParsedAttributeAttributor<Overload,index,flag>::next_type
 senf::console::ParsedAttributeAttributor<Overload,index,flag>::next()
     const
 {
@@ -207,7 +211,8 @@ template <class Overload, unsigned index>
 prefix_
 senf::console::ParsedAttributeAttributor<Overload, index, false>::
 ParsedAttributeAttributor(Overload & overload)
-    : ParsedCommandAttributor<Overload> (overload, index)
+    : ParsedAttributeAttributorBase< Overload, 
+                                     ParsedAttributeAttributor<Overload, index, false> > (overload, index)
 {}
 
 ///////////////////////////////////////////////////////////////////////////
index 14d63a0..7df4366 100644 (file)
 namespace senf {
 namespace console {
 
+    /** \brief CommandOverload implementation with automatic argument parsing
+
+        ParsedCommandOverloadBase implements a CommandOverload implementation supporting automatic
+        parsing of arguments. This is \e not a node, it's a CommandOverload which is then added to
+        an OverloadedCommandNode instance.
+
+        Automatic argument parsing and return value processing consists of several components:
+        \li \ref overload_add Adding overload instances to the tree
+        \li (Advanced) \ref overload_parse
+        \li (Advanced) \ref overload_format
+
+        \section overload_add Adding argument parsing callbacks to the tree
+
+        Adding appropriate callbacks to the tree is very simple: just path a function pointer to
+        DirectoryNode::add() or a member function pointer to ScopedDirectory::add().
+        \code
+        std::string taskStatus(int id);
+
+        senf::console::root().add("taskStatus", &taskStatus);
+        \endcode
+
+        There are quite a number of additional parameters available to be set. These parameters are
+        documented in ParsedAttributeAttributor. Parameters are set by adding them as additional
+        calls after adding the node:
+
+        \code
+        senf::console::root().add("taskStatus", &taskStatus)
+            .doc("Query the current task status")
+            .arg( name = "id",
+                  description = "numeric id of task to check, -1 for the current task."
+                  default_value = -1 );
+        \endcode
+
+        You may also add an additional \c std::ostream & Argument as first argument to the
+        callback. If this argument is present, the stream connected to the console which issued the
+        command will be passed there. This allows writing arbitrary messages to the console.
+
+        Additionally, overloading is supported by registering multiple commands under the same
+        name. So, elaborating on above example:
+        \code
+        std::string taskStatus(int id);
+        std::string taskStatus(std::string const & name);
+
+        senf::console::root()
+            .add("taskStatus", static_cast<std::string (*)(int)>(&taskStatus))
+            .doc("Query the current task status")
+            .overloadDoc("Query status by id")
+            .arg( name = "id",
+                  description = "numeric id of task to check, -1 for the current task."
+                  default_value = -1 );
+        senf::console::root()
+            .add("taskStatus", static_cast<std::string (*)(std::string const &)>(&taskStatus))
+            .overloadDoc("Query status by name")
+            .arg( name = "name",
+                  description = "name of task to check" );
+        \endcode
+
+        We can see here, that taking the address of an overloaded function requires a cast. If you
+        can give unique names to each of the C++ overloads (not the overloads in the console), you
+        should do so to make the unwieldy casts unnecessary.
+
+        \section overload_parse Custom parameter parsers
+        
+        By default, parameters are parsed using \c boost::lexical_cast and therefore using \c
+        iostreams. This means, that any type which can be read from a stream can automatically be
+        used as argument type.
+
+        However, argument parsing can be configured by specializing
+        senf::console::detail::ParameterTraits. See that class for more information.
+
+        \section overload_format Custom return-value formatters
+
+        By default, return values are streamed to an ostream. This automatically allows any
+        streamable type to be used as return value. To add new types or customize the formating, the
+        senf::console::detail::ReturnValueTraits template needs to be specialized for that type. See
+        that class for more information.
+
+        \ingroup console_commands
+     */
     class ParsedCommandOverloadBase
         : public CommandOverload
     {
@@ -118,10 +197,10 @@ namespace console {
     private:
     };
     
-    namespace tag {
-        BOOST_PARAMETER_KEYWORD(detail, name_);
-        BOOST_PARAMETER_KEYWORD(detail, description_);
-        BOOST_PARAMETER_KEYWORD(detail, default_value_);
+    namespace kw {
+        BOOST_PARAMETER_KEYWORD(type, name);
+        BOOST_PARAMETER_KEYWORD(type, description);
+        BOOST_PARAMETER_KEYWORD(type, default_value);
     }
 
     template <class Overload, class Self>
@@ -155,9 +234,9 @@ namespace console {
         typedef ParsedAttributeAttributor return_type;
 
         typedef boost::parameter::parameters<
-            tag::detail::name_,
-            tag::detail::description_,
-            tag::detail::default_value_> arg_params;
+            kw::type::name,
+            kw::type::description,
+            kw::type::default_value> arg_params;
 
         next_type arg() const;
 
@@ -171,16 +250,23 @@ namespace console {
         template <class ArgumentPack>
         next_type argInfo(ArgumentPack const & args) const;
 
+        template <class Kw, class ArgumentPack>
+        void argInfo(Kw const &, ArgumentPack const &, boost::mpl::true_) 
+            const;
         template <class ArgumentPack>
-        next_type argInfo(ArgumentPack const & args, boost::mpl::true_) const;
+        void argInfo(boost::parameter::keyword<kw::type::name> const &, 
+                     ArgumentPack const & args, boost::mpl::false_) 
+            const;
         template <class ArgumentPack>
-        next_type argInfo(ArgumentPack const & args, boost::mpl::false_) const;
-
-        next_type argInfo(std::string const & name, std::string const & doc) const;
-        next_type argInfo(std::string const & name, std::string const & doc,
-                          value_type const & value) const;
+        void argInfo(boost::parameter::keyword<kw::type::description> const &, 
+                     ArgumentPack const & args, boost::mpl::false_) 
+            const;
+        template <class ArgumentPack>
+        void argInfo(boost::parameter::keyword<kw::type::default_value> const &, 
+                     ArgumentPack const & args, boost::mpl::false_) 
+            const;
 
-        ParsedAttributeAttributor<Overload, index+1> next() const;
+        next_type next() const;
 
         void defaultValue(value_type const & value) const;
 
@@ -203,7 +289,8 @@ namespace console {
 
     template <class Overload, unsigned index>
     class ParsedAttributeAttributor<Overload, index, false>
-        : public ParsedCommandAttributor< Overload >
+        : public ParsedAttributeAttributorBase< Overload, 
+                                                ParsedAttributeAttributor<Overload, index, false> >
     {
     public:
         typedef OverloadedCommandNode node_type;
index 94ab8fa..c850ca8 100644 (file)
@@ -118,7 +118,7 @@ BOOST_AUTO_UNIT_TEST(parsedCommand)
     {
         std::stringstream ss;
 
-        using namespace senf::console::tag;
+        using namespace senf::console::kw;
 
         dir.add("cb", &cb1)
             .doc(
@@ -133,11 +133,11 @@ BOOST_AUTO_UNIT_TEST(parsedCommand)
                 "Lo nam balnearius Opprimo Pennatus, no decentia sui, dicto esse se pulchritudo,\n"
                 "pupa Sive res indifferenter. Captivo pa." )
 
-            .arg( description_   = "Bar didelfrump di desgorb. Nu widsoflar brimeldrgf." )
+            .arg( description   = "Bar didelfrump di desgorb. Nu widsoflar brimeldrgf." )
 
-            .arg( name_          = "checkup", 
-                  description_   = "Florgel, dargel and durgel",
-                  default_value_ = 2.1 );
+            .arg( name          = "checkup", 
+                  description   = "Florgel, dargel and durgel",
+                  default_value = 2.1 );
 
         senf::console::OverloadedCommandNode & cbNode (
             dir.add("cb", &cb5)
index e519e91..aa400f9 100644 (file)
 
     \subsection howto_newpacket_parser_simple Simple field definitions
 
-    Packet parser fields are defined using special \ref packetpasermacros. We take the fields
+    Packet parser fields are defined using special \ref packetparsermacros. We take the fields
     directly from the packet definition (the GRE RFC in this case). This will give us to the
     following code fragment:
 
index 755321b..d853092 100644 (file)
--- a/senf.dict
+++ b/senf.dict
@@ -105,6 +105,7 @@ enableChecksum
 endcode
 endif
 endl
+endlink
 ENOFILE
 enum
 env
@@ -146,6 +147,7 @@ FileHandle
 FileTarget
 findNext
 findPrev
+fixedcolumn
 fixme
 fixvariant
 flurgle