Utils/Console: Fix DirectoryNode::add(...) API
g0dil [Mon, 1 Feb 2010 14:44:21 +0000 (14:44 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1558 270642c3-0616-0410-b53a-bc976706d245

41 files changed:
senf/PPI/Connectors.cc
senf/PPI/ModuleManager.cc
senf/Scheduler/EventManager.cc
senf/Socket/Protocols/DVB/DVBProtocolWrapper.cc
senf/Socket/Protocols/DVB/DVBSocketController.cc
senf/Utils/Console/Config.test.cc
senf/Utils/Console/ConfigFile.test.cc
senf/Utils/Console/Executor.test.cc
senf/Utils/Console/Node.cci
senf/Utils/Console/Node.cti
senf/Utils/Console/Node.hh
senf/Utils/Console/Node.test.cc
senf/Utils/Console/OverloadedCommand.cc
senf/Utils/Console/OverloadedCommand.cci
senf/Utils/Console/OverloadedCommand.hh
senf/Utils/Console/ParsedCommand.cci
senf/Utils/Console/ParsedCommand.cti
senf/Utils/Console/ParsedCommand.hh
senf/Utils/Console/ParsedCommand.ih
senf/Utils/Console/ParsedCommand.mpp
senf/Utils/Console/ParsedCommand.test.cc
senf/Utils/Console/ProgramOptions.test.cc
senf/Utils/Console/STLSupport.test.cc
senf/Utils/Console/ScopedDirectory.cti
senf/Utils/Console/ScopedDirectory.hh
senf/Utils/Console/ScopedDirectory.test.cc
senf/Utils/Console/Server.cc
senf/Utils/Console/Traits.test.cc
senf/Utils/Console/Utility.test.cc
senf/Utils/Console/Variables.cti
senf/Utils/Console/Variables.hh
senf/Utils/Console/Variables.ih
senf/Utils/Console/Variables.test.cc
senf/Utils/Logger/FileTarget.cc
senf/Utils/Logger/LogFormat.cc
senf/Utils/Logger/SyslogTarget.cc
senf/Utils/Logger/SyslogUDPTarget.cc
senf/Utils/Logger/Target.cc
senf/Utils/Statistics.cc
senf/Utils/Statistics.cci
senf/Utils/StatisticsTargets.cc

index 065d36f..04ce2bd 100644 (file)
@@ -120,40 +120,44 @@ namespace {
     ConsoleRegister::ConsoleRegister()
     {
         senf::ppi::ModuleManager::instance().consoleDir()
-            .add("tracing", SENF_FNP(senf::ppi::connector::Connector::TraceState,
-                                     senf::ppi::connector::Connector::tracing, ()))
-            .doc("Log every packet sent or received by any module.\n"
-                 "There are three different tracing levels:\n"
-                 "\n"
-                 "    NO_TRACING      don't output any tracing information\n"
-                 "    TRACE_IDS       trace packet id's but do not show packet contents\n"
-                 "    TRACE_CONTENTS  trace complete packet contents\n"
-                 "\n"
-                 "A log message is generated whenever the packet traverses a connector. The\n"
-                 "TRACE_IDS log message has the following format:\n"
-                 "\n"
-                 "    PPI packet trace: <direction> <packet-id> <packet-type>\n"
-                 "                      on <module-id> <module-type> connector <connector-id>\n"
-                 "    PPI throttling trace: <direction> <throttle-msg>\n"
-                 "                      on <module-id> <module-type> connector <connector-id>\n"
-                 "\n"
-                 "The fields are:\n"
-                 "\n"
-                 "    direction       'IN' for packets/throttle notifications entering the module,\n"
-                 "                    'OUT' for packets/throttle notifications leaving it\n"
-                 "    packet-id       Numeric unique packet id. This value is unique for packets\n"
-                 "                    alive at the same time, packets at different times may (and\n"
-                 "                    will) share id's\n"
-                 "    packet-type     The type of the packet header\n"
-                 "    module-id       Unique module id\n"
-                 "    module-type     Type of the module the packet is sent to/from\n"
-                 "    connector-id    Unique connector id\n"
-                 "    throttle-msg    Type of throttling event\n");
+            .add("tracing", senf::console::factory::Command(
+                     SENF_FNP(senf::ppi::connector::Connector::TraceState,
+                              senf::ppi::connector::Connector::tracing, ()))
+                 .doc("Log every packet sent or received by any module.\n"
+                      "There are three different tracing levels:\n"
+                      "\n"
+                      "    NO_TRACING      don't output any tracing information\n"
+                      "    TRACE_IDS       trace packet id's but do not show packet contents\n"
+                      "    TRACE_CONTENTS  trace complete packet contents\n"
+                      "\n"
+                      "A log message is generated whenever the packet traverses a connector. The\n"
+                      "TRACE_IDS log message has the following format:\n"
+                      "\n"
+                      "    PPI packet trace: <direction> <packet-id> <packet-type>\n"
+                      "                      on <module-id> <module-type> connector <connector-id>\n"
+                      "    PPI throttling trace: <direction> <throttle-msg>\n"
+                      "                      on <module-id> <module-type> connector <connector-id>\n"
+                      "\n"
+                      "The fields are:\n"
+                      "\n"
+                      "    direction       'IN' for packets/throttle notifications entering the module,\n"
+                      "                    'OUT' for packets/throttle notifications leaving it\n"
+                      "    packet-id       Numeric unique packet id. This value is unique for packets\n"
+                      "                    alive at the same time, packets at different times may (and\n"
+                      "                    will) share id's\n"
+                      "    packet-type     The type of the packet header\n"
+                      "    module-id       Unique module id\n"
+                      "    module-type     Type of the module the packet is sent to/from\n"
+                      "    connector-id    Unique connector id\n"
+                      "    throttle-msg    Type of throttling event\n")
+                );
 
         senf::ppi::ModuleManager::instance().consoleDir()
-            .add("tracing", SENF_FNP(void, senf::ppi::connector::Connector::tracing,
-                                     (senf::ppi::connector::Connector::TraceState)))
-            .arg("state", "new tracing state");
+            .add("tracing", senf::console::factory::Command(
+                     SENF_FNP(void, senf::ppi::connector::Connector::tracing,
+                              (senf::ppi::connector::Connector::TraceState)))
+                 .arg("state", "new tracing state")
+                );
     }
 
     ConsoleRegister consoleRegister;
index 3d2b3d5..66190d4 100644 (file)
@@ -77,16 +77,18 @@ prefix_ senf::ppi::ModuleManager::ModuleManager()
     senf::console::sysdir().add("ppi", consoleDir_);
 
     consoleDir_
-        .add("dump", senf::membind(&ModuleManager::dumpModules, this))
-        .doc("Dump complete PPI structure\n"
-             "The dump will contain one paragraph for each module. The first line gives module\n"
-             "information, additional lines list all connectors and their peers (if connected).\n"
-             "\n"
-             "This information can be processed by 'PPI/drawmodules.py' and 'dot' (from the\n"
-             "graphviz package) to generate a graphic representation of the module structure:\n"
-             "\n"
-             "    $ echo /sys/ppi/dump | nc -q1 <host> <port> \\\n"
-             "          | python PPI/drawmodules.py | dot -Tpng /dev/fd/0 >modules.png\n");
+        .add("dump", senf::console::factory::Command(
+                 senf::membind(&ModuleManager::dumpModules, this))
+             .doc("Dump complete PPI structure\n"
+                  "The dump will contain one paragraph for each module. The first line gives module\n"
+                  "information, additional lines list all connectors and their peers (if connected).\n"
+                  "\n"
+                  "This information can be processed by 'PPI/drawmodules.py' and 'dot' (from the\n"
+                  "graphviz package) to generate a graphic representation of the module structure:\n"
+                  "\n"
+                  "    $ echo /sys/ppi/dump | nc -q1 <host> <port> \\\n"
+                  "          | python PPI/drawmodules.py | dot -Tpng /dev/fd/0 >modules.png\n")
+            );
 }
 
 prefix_ void senf::ppi::ModuleManager::dumpModules(std::ostream & os)
index ec4d1be..4dd2064 100644 (file)
@@ -39,7 +39,8 @@
 prefix_ senf::scheduler::detail::EventManager::EventManager()
 {
 #ifndef SENF_DISABLE_CONSOLE
-    consoleDir_().add("events", senf::membind(&EventManager::listEvents, this))
+    consoleDir_().add("events", senf::console::factory::Command(
+                          senf::membind(&EventManager::listEvents, this))
         .doc("List all scheduler events sorted by priority\n"
              "\n"
              "Columns:\n"
@@ -55,7 +56,8 @@ prefix_ senf::scheduler::detail::EventManager::EventManager()
              "              R  runnable\n"
              "              W  waiting\n"
              "              -  event disabled\n"
-             "    INFO    further event specific information");
+             "    INFO    further event specific information")
+        );
 
     senf::console::sysdir().add("scheduler", consoleDir_());
 #endif
index 0d615ca..42dd6b5 100644 (file)
@@ -34,27 +34,46 @@ prefix_ senf::DVBSectionProtocolWrapper::DVBSectionProtocolWrapper(senf::DVBDemu
     : protocol(sh.protocol()), dir(this)
 {
     namespace kw = senf::console::kw;
-    dir.add("buffersize", &DVBSectionProtocolWrapper::setBufferSize)
-       .doc("Set the size of the circular buffer used for filtered data.")
-       .arg("size", "in byte");
+    namespace fty = senf::console::factory;
 
-    dir.add("start", &DVBSectionProtocolWrapper::startFiltering)
-       .doc("Starts filtering");
+    dir.add("buffersize", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+           .doc("Set the size of the circular buffer used for filtered data.")
+           .arg("size", "in byte") );
 
-    dir.add("stop", &DVBSectionProtocolWrapper::setBufferSize)
-       .doc("Stops filtering");
+    dir.add("start", fty::BoundCommand(this,&DVBSectionProtocolWrapper::startFiltering)
+           .doc("Starts filtering") );
 
-    dir.node().add("filter", boost::function<void (unsigned short int, unsigned, senf::console::FlagCollection<Flags>, unsigned, unsigned, unsigned)>(senf::membind(&DVBSectionProtocolWrapper::setSectionFilter, this)))
-       .arg("pid", "pid to filter")
-       .arg("filter", "filter", kw::default_value = 62, kw::default_doc = "0x3e")
-       .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT", kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC, kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
-       .arg("mask", "mask", kw::default_value = 0xff, kw::default_doc = "0xff")
-       .arg("mode", "mode", kw::default_value = 0, kw::default_doc = "0x00")
-       .arg("timeout", "timeout", kw::default_value = 0, kw::default_doc = "0x00")
-       .doc("Sets parameters for section filter.");
+    dir.add("stop", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+           .doc("Stops filtering") );
 
-    dir.add("stop", &DVBSectionProtocolWrapper::setBufferSize)
-       .doc("Stops filtering");
+    dir.add("filter", 
+           fty::BoundCommand<void (unsigned short int, 
+                                   unsigned, 
+                                   senf::console::FlagCollection<Flags>, 
+                                   unsigned, 
+                                   unsigned, 
+                                   unsigned)
+           >(this, &DVBSectionProtocolWrapper::setSectionFilter)
+           .arg("pid", "pid to filter")
+           .arg("filter", "filter", 
+                kw::default_value = 62, 
+                kw::default_doc = "0x3e")
+           .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
+                kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+                kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+           .arg("mask", "mask", 
+                kw::default_value = 0xff, 
+                kw::default_doc = "0xff")
+           .arg("mode", "mode", 
+                kw::default_value = 0, 
+                kw::default_doc = "0x00")
+           .arg("timeout", "timeout", 
+                kw::default_value = 0, 
+                kw::default_doc = "0x00")
+           .doc("Sets parameters for section filter.") );
+
+    dir.add("stop", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+           .doc("Stops filtering") );
 }
 
 
@@ -62,20 +81,31 @@ prefix_ senf::DVBPESProtocolWrapper::DVBPESProtocolWrapper(senf::DVBDemuxPESHand
     : protocol(sh.protocol()), dir(this) 
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    dir.node().add("filter", boost::function<void ( unsigned short int, dmx_input_t, dmx_output_t, dmx_pes_type_t, senf::console::FlagCollection<Flags>)>(senf::membind(&DVBPESProtocolWrapper::setPESFilter, this)))
-       .arg("pid", "pid to filter")
-       .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
-       .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
-       .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], DMX_PES_OTHER")
-       .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT", kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC, kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
-       .doc("Sets parameters for PES filter.");
-
-    dir.add("start", &DVBPESProtocolWrapper::startFiltering)
-       .doc("Starts filtering");
+    dir.add("filter", 
+           fty::BoundCommand<void (unsigned short int, 
+                                   dmx_input_t, 
+                                   dmx_output_t, 
+                                   dmx_pes_type_t, 
+                                   senf::console::FlagCollection<Flags>)
+           >(this,&DVBPESProtocolWrapper::setPESFilter)
+           .arg("pid", "pid to filter")
+           .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
+           .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
+           .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] "
+                           "DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], "
+                           "DMX_PES_OTHER")
+           .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT", 
+                kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC, 
+                kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+           .doc("Sets parameters for PES filter.") );
+    
+    dir.add("start", fty::BoundCommand(this, &DVBPESProtocolWrapper::startFiltering)
+           .doc("Starts filtering") );
 
-    dir.add("stop", &DVBPESProtocolWrapper::stopFiltering)
-       .doc("Stops filtering");
+    dir.add("stop", fty::BoundCommand(this, &DVBPESProtocolWrapper::stopFiltering)
+           .doc("Stops filtering") );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index a24d566..c72ba15 100644 (file)
@@ -425,30 +425,31 @@ prefix_ void senf::DVBSocketController::readEvent(int event)
 
 prefix_ void senf::DVBSocketController::initConsole()
 {
-    // binding functions to console
+    namespace fty = senf::console::factory;
     namespace kw = senf::console::kw;
+
     dir.doc("DVB Controller " + controllerNr);
     ++controllerNr;
 
-    dir.add("type", &DVBSocketController::getTypeString)
-    .doc("Shows actual type of card DVB-{T, S, C}");
-
-    dir.add("info", &DVBSocketController::getTuneInfo)
-    .doc("Returns a string which shows actual tuning status.\n\
-            \"S\" prints signal strength (in hex)\n\
-            \"s\" prints singal to noise ration (in hex)\n\
-            \"b\" prints bit error rate (in hex)\n\
-            \"u\" prints uncorrected blocks (in hex)\n\
-            \"f\" prints readable overal status e.g. \"Has Lock\"\n\n\
-            These characters can be used to form the output. Be aware, some\n\
-            features may not be supported be your current driver implementation\n\
-            and could end in throwing an exception!")
-    .arg("conf", "Ssbuf", kw::default_value = "Ssbuf");
-
-    dir.add("tune", &DVBSocketController::tuneToCMD)
-        .doc("tunes to channel listet in the configfile.")
-        .arg("channel", "channel to tune")
-        .arg("mode", "mode \"sync\" or \"async\"", kw::default_value = "async");
+    dir.add("type", fty::BoundCommand(this, &DVBSocketController::getTypeString)
+           .doc("Shows actual type of card DVB-{T, S, C}") );
+
+    dir.add("info", fty::BoundCommand(this, &DVBSocketController::getTuneInfo)
+           .doc("Returns a string which shows actual tuning status.\n"
+                "'S' prints signal strength (in hex)\n"
+                "'s' prints singal to noise ration (in hex)\n"
+                "'b' prints bit error rate (in hex)\n"
+                "'u' prints uncorrected blocks (in hex)\n"
+                "'f' prints readable overal status e.g. 'Has Lock'\n\n"
+                "These characters can be used to form the output. Be aware, some\n"
+                "features may not be supported be your current driver implementation\n"
+                "and could end in throwing an exception!")
+           .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
+
+    dir.add("tune", fty::BoundCommand(this,&DVBSocketController::tuneToCMD)
+           .doc("tunes to channel listet in the configfile.")
+           .arg("channel", "channel to tune")
+           .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index d319966..a952491 100644 (file)
@@ -60,20 +60,23 @@ namespace {
         std::string name_;
         std::ofstream file_;
     };
+   
 }
 
 SENF_AUTO_UNIT_TEST(configBundle)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::ScopedDirectory<> root;
     senf::console::root().add("root", root);
 
     senf::console::ScopedDirectory<> chroot;
     senf::console::root().add("chroot", chroot);
 
-    root.mkdir("dir1").add("fun1", &fun1);
-    root.add("fun2", &fun2);
-    chroot.mkdir("dir1").add("fun1", &fun1);
-    chroot.add("fun2", &fun2);
+    root.mkdir("dir1").add("fun1", fty::Command(&fun1));
+    root.add("fun2", fty::Command(&fun2));
+    chroot.mkdir("dir1").add("fun1", fty::Command(&fun1));
+    chroot.add("fun2", fty::Command(&fun2));
 
     TempFile cfg ("test.cfg");
     cfg << "dir1/fun1 foo; fun2;" << TempFile::close;
index ddb9067..5d424c0 100644 (file)
@@ -64,13 +64,15 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(configFile)
 {
+    namespace fty = senf::console::factory;
+
     TempFile cfgf ("test.cfg");
     cfgf << "dir1/fun1 10;\n" 
          << TempFile::close;
     
     senf::console::ScopedDirectory<> dir1;
     senf::console::root().add("dir1", dir1);
-    dir1.add("fun1",&fun1);
+    dir1.add("fun1",fty::Command(&fun1));
 
     {
         senf::console::ConfigFile cfg (cfgf.name());
@@ -98,6 +100,8 @@ SENF_AUTO_UNIT_TEST(configFile)
 
 SENF_AUTO_UNIT_TEST(configFileRestrict)
 {
+    namespace fty = senf::console::factory;
+
     TempFile cfgf ("test.cfg");
     cfgf << "dir1/fun1 10;\n"
          << "dir2/fun2;\n"
@@ -105,7 +109,7 @@ SENF_AUTO_UNIT_TEST(configFileRestrict)
     
     senf::console::ScopedDirectory<> dir1;
     senf::console::root().add("dir1", dir1);
-    dir1.add("fun1",&fun1);
+    dir1.add("fun1",fty::Command(&fun1));
     
     {
         var1 = 0;
@@ -119,7 +123,7 @@ SENF_AUTO_UNIT_TEST(configFileRestrict)
 
         senf::console::ScopedDirectory<> dir2;
         senf::console::root().add("dir2", dir2);
-        dir2.add("fun2",&fun2);
+        dir2.add("fun2",fty::Command(&fun2));
 
         var1 = 0;
         var2 = false;
@@ -132,6 +136,8 @@ SENF_AUTO_UNIT_TEST(configFileRestrict)
 
 SENF_AUTO_UNIT_TEST(configFileSkipGroup)
 {
+    namespace fty = senf::console::factory;
+
     TempFile cfgf ("test.cfg");
     cfgf << "dir1/fun1 10;\n"
          << "dir2 { dir3 { fun2; } fun1 5; }"
@@ -139,13 +145,13 @@ SENF_AUTO_UNIT_TEST(configFileSkipGroup)
     
     senf::console::ScopedDirectory<> dir1;
     senf::console::root().add("dir1", dir1);
-    dir1.add("fun1",&fun1);
+    dir1.add("fun1",fty::Command(&fun1));
     
     senf::console::ScopedDirectory<> dir2;
     senf::console::root().add("dir2", dir2);
     
-    dir2.mkdir("dir3").add("fun2", &fun2);
-    dir2.add("fun1", &fun1);
+    dir2.mkdir("dir3").add("fun2", fty::Command(&fun2));
+    dir2.add("fun1", fty::Command(&fun1));
 
     {
         var1 = 0;
@@ -173,6 +179,8 @@ SENF_AUTO_UNIT_TEST(configFileSkipGroup)
 
 SENF_AUTO_UNIT_TEST(configRestrictAndLink)
 {
+    namespace fty = senf::console::factory;
+
     TempFile cfgf ("test.cfg");
     cfgf << "dir1/fun1 10;\n"
          << "link1 { dir3 { fun2; } fun1 5; }"
@@ -180,13 +188,13 @@ SENF_AUTO_UNIT_TEST(configRestrictAndLink)
     
     senf::console::ScopedDirectory<> dir1;
     senf::console::root().add("dir1", dir1);
-    dir1.add("fun1",&fun1);
+    dir1.add("fun1",fty::Command(&fun1));
     
     senf::console::ScopedDirectory<> dir2;
     dir1.add("dir2", dir2);
     
-    dir2.mkdir("dir3").add("fun2", &fun2);
-    dir2.add("fun1", &fun1);
+    dir2.mkdir("dir3").add("fun2", fty::Command(&fun2));
+    dir2.add("fun1", fty::Command(&fun1));
 
     senf::console::ScopedDirectory<> dir4;
     senf::console::root().add("dir4", dir4);
index 0826459..551c0ab 100644 (file)
@@ -49,8 +49,10 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(executor)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::root().mkdir("dir1").mkdir("dir3");
-    senf::console::root().mkdir("dir2").doc("Helptext").add("test",&testCommand);
+    senf::console::root().mkdir("dir2").doc("Helptext").add("test",fty::Command(&testCommand));
 
     senf::console::Executor executor;
     senf::console::CommandParser parser;
@@ -182,8 +184,10 @@ SENF_AUTO_UNIT_TEST(executor)
 
 SENF_AUTO_UNIT_TEST(executorChroot)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::root().mkdir("dir1").mkdir("dir3");
-    senf::console::root().mkdir("dir2").doc("Helptext").add("test",&testCommand);
+    senf::console::root().mkdir("dir2").doc("Helptext").add("test", fty::Command(&testCommand));
 
     senf::console::Executor executor;
     senf::console::CommandParser parser;
@@ -216,8 +220,10 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(executorPolicy)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::root().mkdir("dir1").mkdir("dir3");
-    senf::console::root().mkdir("dir2").doc("Helptext").add("test",&testCommand);
+    senf::console::root().mkdir("dir2").doc("Helptext").add("test",fty::Command(&testCommand));
 
     senf::console::Executor executor;
     senf::console::CommandParser parser;
@@ -247,8 +253,10 @@ SENF_AUTO_UNIT_TEST(executorPolicy)
 
 SENF_AUTO_UNIT_TEST(executorAuto)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::root().mkdir("tdir1").mkdir("dir3");
-    senf::console::root().mkdir("dir2").doc("Helptext").add("test",&testCommand);
+    senf::console::root().mkdir("dir2").doc("Helptext").add("test",fty::Command(&testCommand));
 
     senf::console::Executor executor;
     executor
index c7107f1..61c3646 100644 (file)
@@ -280,6 +280,7 @@ prefix_ senf::console::detail::NodeTraverser::NodeTraverser(DirectoryNode & root
                                                             bool autocomplete)
     : root_ (root), dir_ (dir.thisptr()), autocomplete_ (autocomplete), init_ (false)
 {}
+
 #endif
 
 ///////////////////////////////////////////////////////////////////////////
@@ -367,23 +368,35 @@ prefix_ senf::console::SimpleCommandNode::cptr senf::console::SimpleCommandNode:
     return boost::static_pointer_cast<SimpleCommandNode const>(shared_from_this());
 }
 
-#ifndef DOXYGEN
+///////////////////////////////////////////////////////////////////////////
+// senf::console::factory::SimpleCommand
+
+prefix_ senf::console::factory::SimpleCommand::SimpleCommand(SimpleCommandNode::Function fn)
+    : node_ (SimpleCommandNode::create(fn))
+{}
 
 prefix_ senf::console::SimpleCommandNode &
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     SimpleCommandNode::Function fn, int)
+senf::console::factory::SimpleCommand::create(DirectoryNode & dir, std::string const & name)
+    const
 {
-    return node.add(name, SimpleCommandNode::create(fn));
+    return dir.add(name, node_);
 }
 
-prefix_ senf::console::DirectoryNode &
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     DirectoryNode & dir, int)
+prefix_ senf::console::factory::SimpleCommand const &
+senf::console::factory::SimpleCommand::doc(std::string const & doc)
+    const
 {
-    return node.add(name, dir.thisptr());
+    node_->doc(doc);
+    return *this;
 }
 
-#endif
+prefix_ senf::console::factory::SimpleCommand const &
+senf::console::factory::SimpleCommand::shortdoc(std::string const & doc)
+    const
+{
+    node_->shortdoc(doc);
+    return *this;
+}
 
 ///////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
index b7f118b..260c9a3 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::NodeCreateTraits<Object>::Creator
-
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::NodeCreateTraits<Object>::Creator::create(DirectoryNode & node,
-                                                         std::string const & name,
-                                                         Object & ob)
-{
-    return senf_console_add_node(node, name, ob, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////
 // senf::console::DirectoryNode
 
 template <class NodeType>
@@ -55,18 +43,22 @@ prefix_ NodeType & senf::console::DirectoryNode::add(std::string const & name,
     return *node;
 }
 
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::DirectoryNode::add(std::string const & name, Object const & ob)
+template <class NodeType>
+prefix_ NodeType & senf::console::DirectoryNode::
+add(std::string const & name, NodeType & node,
+    typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
 {
-    return NodeCreateTraits<Object const>::Creator::create(*this, name, ob);
+    // This makes objects with implicit conversion operators work (hi, ScopedDirectory ..)
+    add(name, static_cast<GenericNode &>(node).thisptr());
+    return node;
 }
 
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::DirectoryNode::add(std::string const & name, Object & ob)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::DirectoryNode::
+add(std::string const & name, Factory const & factory,
+    typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type *)
 {
-    return NodeCreateTraits<Object>::Creator::create(*this, name, ob);
+    return factory.create(*this, name);
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 3158023..0b854fb 100644 (file)
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/utility.hpp>
 #include <boost/range/iterator_range.hpp>
-#include <boost/typeof/typeof.hpp>
-#include <boost/type_traits/remove_reference.hpp>
 #include <boost/any.hpp>
 #include <senf/Utils/Exception.hh>
 #include <senf/Utils/mpl.hh>
@@ -223,6 +221,8 @@ namespace console {
     class DirectoryNode;
     class CommandNode;
 
+    namespace detail { struct NodeFactory {}; }
+
     /** \brief Get console root node */
     DirectoryNode & root();
 
@@ -382,31 +382,6 @@ namespace console {
 
     class SimpleCommandNode;
 
-    /** \brief Internal: Node creation helper traits
-
-        This class is used internally to find out the type of node to create for a specific argument
-        type.
-     */
-    template <class Object>
-    struct NodeCreateTraits
-    {
-        typedef BOOST_TYPEOF_TPL( senf_console_add_node(
-                                      * static_cast<DirectoryNode *>(0),
-                                      * static_cast<std::string const *>(0),
-                                      * static_cast<Object *>(0),
-                                      0) ) base_type;
-        typedef typename senf::remove_cvref<base_type>::type value_type;
-
-        typedef typename value_type::node_type NodeType;
-        typedef typename value_type::return_type result_type;
-
-        /// Internal
-        struct Creator {
-            static result_type create(DirectoryNode & node, std::string const & name,
-                                      Object & ob);
-        };
-    };
-
     /** \brief Config/console tree directory node
 
         This node type provides the internal and root nodes of the tree. It allows to add arbitrary
@@ -469,38 +444,17 @@ namespace console {
                                              '-n' is added to the name until the name is unique. If
                                              \a name is empty, it is set to 'unnamed'. */
 
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object const & ob);
+        template <class NodeType>
+        NodeType & add(std::string const & name, NodeType & node,
+                       typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+
+        template <class Factory>
+        typename Factory::result_type add(std::string const & name, Factory const & factory,
+                                          typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type * = 0);
                                         ///< Generic child node factory
                                         /**< This member is used to create a new child node of the
                                              current directory. The type of node created depends on
-                                             the type of argument passed.
-
-                                             The node type is selected by the NodeCreateTraits
-                                             class. To allow adding a specific node type, you need
-                                             to provide an overload for
-                                             <tt>senf_console_add_node</tt> which must be visible at
-                                             when you register the new node.
-                                             \code
-                                             MyNodeType & senf_console_add_node(
-                                                 DirectoryNode & dir,
-                                                 std::string const & name,
-                                                 MySpecialObject const & ob,
-                                                 int)
-                                             {
-                                                 return dir.add(name, MyNodeType::create(ob));
-                                             }
-                                             \endcode
-                                             (Do not forget the last unnamed 'int' parameter which
-                                             is not used but serves to disambiguate the
-                                             overloads). */
-
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object & ob);
-                                        ///< Generic child node factory
-                                        /**< \see add() */
+                                             the type of argument passed. */
 
         GenericNode::ptr remove(std::string const & name);
                                         ///< Remove node \a name from the tree
@@ -597,12 +551,6 @@ namespace console {
     struct UnknownNodeNameException : public senf::Exception
     { UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
 
-#ifndef DOXYGEN
-    template <class Type>
-    struct NodeCreateTraits< boost::shared_ptr<Type> >
-    {};
-#endif
-
     /** \brief Config/console tree command node
 
         The CommandNode is the base-class for the tree leaf nodes. Concrete command node
@@ -735,21 +683,31 @@ namespace console {
 
 #ifndef DOXYGEN
 
-    SimpleCommandNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                              SimpleCommandNode::Function fn, int);
+namespace factory {
+    
+    class SimpleCommand
+        : public detail::NodeFactory
+    {
+    public:
+        typedef SimpleCommandNode node_type;
+        typedef SimpleCommandNode & result_type;
 
-    DirectoryNode & senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                          DirectoryNode & dir, int);
+        explicit SimpleCommand(SimpleCommandNode::Function fn);
 
-#endif
+        SimpleCommandNode & create(DirectoryNode & dir, std::string const & name) const;
 
-}}
+        SimpleCommand const & doc(std::string const & doc) const;
+        SimpleCommand const & shortdoc(std::string const & doc) const;
 
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+    private:
+        SimpleCommandNode::ptr node_;
+    };
 
-BOOST_TYPEOF_REGISTER_TYPE(senf::console::DirectoryNode)
-BOOST_TYPEOF_REGISTER_TYPE(senf::console::SimpleCommandNode)
+}
 
+#endif
+
+}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "Node.cci"
index e837142..be5964c 100644 (file)
@@ -155,10 +155,11 @@ namespace {
     };
 }
 
-SENF_AUTO_UNIT_TEST(senfConsoleAddNode)
+SENF_AUTO_UNIT_TEST(factory)
 {
-    senf::console::root().add("fn1", &callback);
-    senf::console::root().add("fn2", boost::function<void(std::ostream&,senf::console::ParseCommandInfo const &)>(Functor()));
+    namespace fty = senf::console::factory;
+    senf::console::root().add("fn1", fty::SimpleCommand(&callback));
+    senf::console::root().add("fn2", fty::SimpleCommand(Functor()));
     
     senf::console::ParseCommandInfo info;
 
index c9e7529..8205ec5 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::OverloadedCommandNode
 
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::OverloadedCommandNode::insertOverload(DirectoryNode & dir,
+                                                     std::string const & name,
+                                                     CommandOverload::ptr overload)
+{
+    OverloadedCommandNode & node (
+        dir.hasChild(name)
+        ? dynamic_cast<OverloadedCommandNode &>(dir(name))
+        : dir.add(name, OverloadedCommandNode::create()));
+    node.add(overload);
+    return node;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // So soll die doku aussehen:
 //
index c891fda..8a5c382 100644 (file)
@@ -153,7 +153,57 @@ prefix_ senf::console::SimpleCommandOverload::SimpleCommandOverload(Function fn)
     : fn_ (fn)
 {}
 
-///////////////////////////////cci.e///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SimpleOverloadAttributor
+
+prefix_ senf::console::SimpleOverloadAttributor::
+SimpleOverloadAttributor(SimpleCommandOverload::Function fn)
+    : overload_ (SimpleCommandOverload::create(fn))
+{}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::doc(std::string const & doc)
+    const
+{
+    doc_ = doc;
+    return *this;
+}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::shortdoc(std::string const & doc)
+    const
+{
+    shortdoc_ = doc;
+    return *this;
+}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::overloadDoc(std::string const & doc)
+    const
+{
+    overload_->doc(doc);
+    return *this;
+}
+
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::SimpleOverloadAttributor::create(DirectoryNode & dir, std::string const & name)
+    const
+{
+    OverloadedCommandNode & node (OverloadedCommandNode::insertOverload(dir, name, overload_));
+    if (doc_) node.doc(*doc_);
+    if (shortdoc_) node.shortdoc(*shortdoc_);
+    return node;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ senf::console::SimpleOverloadAttributor
+senf::console::factory::Command(SimpleCommandOverload::Function fn)
+{
+    return SimpleOverloadAttributor(fn);
+}
+
+/////////////////////////////cci.e///////////////////////////////////////
 #undef prefix_
 
 \f
index 349159c..ab339f3 100644 (file)
@@ -31,6 +31,7 @@
 #include <boost/intrusive_ptr.hpp>
 #include <boost/range/iterator_range.hpp>
 #include <senf/Utils/intrusive_refcount.hh>
+#include <boost/optional.hpp>
 
 //#include "OverloadedCommand.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -203,6 +204,9 @@ namespace console {
         ptr thisptr();
         cptr thisptr() const;
 
+        static OverloadedCommandNode & insertOverload(DirectoryNode & dir, std::string const & name,
+                                                      CommandOverload::ptr overload);
+
     private:
         OverloadedCommandNode();
 
@@ -259,7 +263,32 @@ namespace console {
         std::string doc_;
     };
 
-}}
+    class SimpleOverloadAttributor
+        : public detail::NodeFactory
+    {
+    public:
+        typedef OverloadedCommandNode node_type;
+        typedef OverloadedCommandNode & result_type;
+
+        explicit SimpleOverloadAttributor(SimpleCommandOverload::Function fn);
+
+        SimpleOverloadAttributor const & doc(std::string const & doc) const;
+        SimpleOverloadAttributor const & shortdoc(std::string const & doc) const;
+        SimpleOverloadAttributor const & overloadDoc(std::string const & doc) const;
+
+        OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+        
+    private:
+        SimpleCommandOverload::ptr overload_;
+        mutable boost::optional<std::string> doc_;
+        mutable boost::optional<std::string> shortdoc_;
+    };
+
+namespace factory {
+
+    SimpleOverloadAttributor Command(SimpleCommandOverload::Function fn);
+
+}}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "OverloadedCommand.cci"
index 5d168ec..5c71e65 100644 (file)
@@ -61,70 +61,66 @@ prefix_ void senf::console::ParsedCommandOverloadBase::doc(std::string const & d
 // senf::console::ParsedCommandAttributorBase
 
 prefix_ senf::console::OverloadedCommandNode &
-senf::console::ParsedCommandAttributorBase::node()
+senf::console::ParsedCommandAttributorBase::create(DirectoryNode & dir,
+                                                   std::string const & name)
     const
 {
-    return overload_.node();
+    OverloadedCommandNode & node (OverloadedCommandNode::insertOverload(dir, name, overload_));
+    if (doc_) node.doc(*doc_);
+    if (shortdoc_) node.shortdoc(*shortdoc_);
+    return node;
 }
 
-prefix_ senf::console::ParsedCommandAttributorBase::operator OverloadedCommandNode &()
-    const
-{
-    return node();
-}
+prefix_ senf::console::ParsedCommandAttributorBase::
+ParsedCommandAttributorBase(ParsedCommandOverloadBase::ptr overload, unsigned index)
+  : overload_ (overload), index_ (index)
+{}
 
 prefix_ senf::console::ParsedCommandAttributorBase::
-ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index)
-    : overload_ (overload), index_ (index)
+ParsedCommandAttributorBase(ParsedCommandAttributorBase const & other, unsigned index)
+    : overload_ (other.overload_), index_ (index), doc_ (other.doc_), shortdoc_ (other.shortdoc_)
 {}
 
 prefix_ senf::console::ParsedCommandOverloadBase &
 senf::console::ParsedCommandAttributorBase::overload()
     const
 {
-    return overload_;
+    return *overload_;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::argName(std::string const & name)
-    const
 {
     overload().arg(index_).name = name;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::argDoc(std::string const & doc)
-    const
 {
     overload().arg(index_).doc = doc;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::typeName(std::string const & doc)
-    const
 {
     overload().arg(index_).type = doc;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::defaultDoc(std::string const & doc)
-    const
 {
     overload().arg(index_).defaultDoc = doc;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::overloadDoc(std::string const & doc)
-    const
 {
     overload().doc(doc);
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::nodeDoc(std::string const & doc)
-    const
 {
-    node().doc(doc);
+    doc_ = doc;
 }
 
 prefix_ void senf::console::ParsedCommandAttributorBase::shortDoc(std::string const & doc)
-    const
 {
-    node().shortdoc(doc);
+    shortdoc_ = doc;
 }
 
 ///////////////////////////////cci.e///////////////////////////////////////
index 2ef3adc..43a2cff 100644 (file)
@@ -85,19 +85,23 @@ prefix_ Overload & senf::console::ParsedCommandAttributor<Overload>::overload()
 }
 
 template <class Overload>
-prefix_
-senf::console::ParsedCommandAttributor<Overload>::ParsedCommandAttributor(Overload & overload,
-                                                                          unsigned index)
+prefix_ senf::console::ParsedCommandAttributor<Overload>::
+ParsedCommandAttributor(typename Overload::ptr overload, unsigned index)
     : ParsedCommandAttributorBase (overload, index)
 {}
 
+template <class Overload>
+prefix_ senf::console::ParsedCommandAttributor<Overload>::
+ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index)
+    : ParsedCommandAttributorBase (other, index)
+{}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::ParsedArgumentAttributorBase<Overload,Self>
 
 template <class Overload, class Self, class ReturnType>
 prefix_ Self
 senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::doc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::nodeDoc(doc);
     return static_cast<Self const &>(*this);
@@ -106,7 +110,6 @@ senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::doc(std::
 template <class Overload, class Self, class ReturnType>
 prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
 shortdoc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::shortDoc(doc);
     return static_cast<Self const &>(*this);
@@ -115,7 +118,6 @@ shortdoc(std::string const & doc)
 template <class Overload, class Self, class ReturnType>
 prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
 overloadDoc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::overloadDoc(doc);
     return static_cast<Self const &>(*this);
@@ -124,7 +126,6 @@ overloadDoc(std::string const & doc)
 template <class Overload, class Self, class ReturnType>
 prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
 formatter(typename Overload::Formatter f)
-    const
 {
     this->overload().formatter(f);
     return static_cast<Self const &>(*this);
@@ -133,14 +134,20 @@ formatter(typename Overload::Formatter f)
 template <class Overload, class Self, class ReturnType>
 prefix_
 senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
-ParsedArgumentAttributorBase(Overload & overload, unsigned index)
+ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index)
     : ParsedCommandAttributor<Overload> (overload, index)
 {}
 
+template <class Overload, class Self, class ReturnType>
+prefix_
+senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
+ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index)
+    : ParsedCommandAttributor<Overload> (other, index)
+{}
+
 template <class Overload, class Self>
 prefix_ Self
 senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::doc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::nodeDoc(doc);
     return static_cast<Self const &>(*this);
@@ -149,7 +156,6 @@ senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::doc(std::string
 template <class Overload, class Self>
 prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
 shortdoc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::shortDoc(doc);
     return static_cast<Self const &>(*this);
@@ -158,7 +164,6 @@ shortdoc(std::string const & doc)
 template <class Overload, class Self>
 prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
 overloadDoc(std::string const & doc)
-    const
 {
     this->ParsedCommandAttributorBase::overloadDoc(doc);
     return static_cast<Self const &>(*this);
@@ -166,11 +171,18 @@ overloadDoc(std::string const & doc)
 
 template <class Overload, class Self>
 prefix_
-senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
-ParsedArgumentAttributorBase(Overload & overload, unsigned index)
+senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
+ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index)
     : ParsedCommandAttributor<Overload> (overload, index)
 {}
 
+template <class Overload, class Self>
+prefix_
+senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
+ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index)
+    : ParsedCommandAttributor<Overload> (other, index)
+{}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::ParsedArgumentAttributor<Overload,index,flag>
 
@@ -187,7 +199,6 @@ template <class ArgumentPack>
 prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::next_type
 senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(ArgumentPack const & args)
-    const
 {
 #   define ProcessArg(tag) \
         argInfo( kw:: tag, args, senf::has_parameter< ArgumentPack, kw::type:: tag >() )
@@ -208,7 +219,6 @@ template <class Overload, unsigned index, bool flag>
 template <class Kw, class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_)
-    const
 {}
 
 template <class Overload, unsigned index, bool flag>
@@ -216,7 +226,6 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::name> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     this->argName(args[kw::name]);
 }
@@ -226,7 +235,6 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::description> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     this->argDoc(args[kw::description]);
 }
@@ -236,7 +244,6 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::default_value> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     this->defaultValue(args[kw::default_value]);
 }
@@ -246,7 +253,6 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::type_name> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     this->typeName(args[kw::type_name]);
 }
@@ -256,7 +262,6 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::default_doc> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     BOOST_STATIC_ASSERT(( senf::has_parameter<ArgumentPack, kw::type::default_value>::value ));
     this->defaultDoc(args[kw::default_doc]);
@@ -267,16 +272,20 @@ template <class ArgumentPack>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 argInfo(boost::parameter::keyword<kw::type::parser> const &, ArgumentPack const & args,
         boost::mpl::true_)
-    const
 {
     this->parser(args[kw::parser]);
 }
 
 template <class Overload, unsigned index, bool flag>
-prefix_
-senf::console::ParsedArgumentAttributor<Overload,index,flag>::
-ParsedArgumentAttributor(Overload & overload)
-    : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (overload, index)
+prefix_ senf::console::ParsedArgumentAttributor<Overload,index,flag>::
+ParsedArgumentAttributor(typename Overload::ptr overload)
+: ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (overload, index)
+{}
+
+template <class Overload, unsigned index, bool flag>
+prefix_ senf::console::ParsedArgumentAttributor<Overload,index,flag>::
+ParsedArgumentAttributor(ParsedCommandAttributorBase const & other)
+    : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (other, index)
 {}
 
 template <class Overload, unsigned index, bool flag>
@@ -284,13 +293,12 @@ prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::n
 senf::console::ParsedArgumentAttributor<Overload,index,flag>::next()
     const
 {
-    return ParsedArgumentAttributor<Overload, index+1>(this->overload());
+    return ParsedArgumentAttributor<Overload, index+1>(*this);
 }
 
 template <class Overload, unsigned index, bool flag>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
 defaultValue(value_type const & value)
-    const
 {
     this->overload().arg<index>().defaultValue = value;
     this->overload().arg(index).hasDefault = true;
@@ -299,7 +307,6 @@ defaultValue(value_type const & value)
 template <class Overload, unsigned index, bool flag>
 template <class Fn>
 prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::parser(Fn fn)
-    const
 {
     this->overload().arg<index>().parser = fn;
 }
@@ -310,11 +317,18 @@ prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::parse
 template <class Overload, unsigned index>
 prefix_
 senf::console::ParsedArgumentAttributor<Overload, index, false>::
-ParsedArgumentAttributor(Overload & overload)
+ParsedArgumentAttributor(typename Overload::ptr overload)
     : ParsedArgumentAttributorBase< 
           Overload, ParsedArgumentAttributor<Overload, index, false> > (overload, index)
 {}
 
+template <class Overload, unsigned index>
+prefix_
+senf::console::ParsedArgumentAttributor<Overload, index, false>::
+ParsedArgumentAttributor(ParsedCommandAttributorBase const & other)
+    : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (other, index)
+{}
+
 ///////////////////////////////////////////////////////////////////////////
 // namespace members
 
@@ -326,97 +340,86 @@ namespace detail {
 
     struct ParsedCommandAddNodeAccess
     {
-        template <class Attributor, class Node>
-        static Attributor attributor(Node & node)
-            { return Attributor(node); }
-    };
-
-    // What is THIS about ??
-
-    // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
-    // this argument is given, then the function will be called with the console output stream as
-    // it's first argument.
-    //
-    // This is implemented in the following way: ParsedCommandOverload (the class responsible for
-    // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
-    // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
-    // function will be directly passed to ParsedCommandOverload.
-    //
-    // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
-    // the create member will use boost::bind to DROP the first argument.
-    
-    template <class Traits, 
-              bool ignoreOneArg=! Traits::has_ostream_arg, 
-              unsigned arity=Traits::traits::arity>
-    struct CreateParsedCommandOverload
-    {};
-
-    template <class Traits, unsigned arity>
-    struct CreateParsedCommandOverload<Traits, false, arity>
-    {
-        typedef typename Traits::traits traits;
-        
-        template <class Function>
-        static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn) 
-            { return senf::console::ParsedCommandOverload<traits>::create(fn); };
+        template <class Attributor, class NodePtr>
+        static Attributor attributor(NodePtr ptr)
+            { return Attributor(ptr); }
     };
 
-#   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
-                                            SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
-                                            4))
-#   include BOOST_PP_ITERATE()
-
     template <class Signature, class Fn>
     typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
-    addOverloadedCommandNode(senf::console::DirectoryNode & node,  std::string const & name, Fn fn)
+    addOverloadedCommandNode(Fn fn)
     {
-        senf::console::OverloadedCommandNode & cmdNode (
-            node.hasChild(name) 
-            ? dynamic_cast<senf::console::OverloadedCommandNode &>(node(name))
-            : node.add(name, senf::console::OverloadedCommandNode::create()) );
-
         typedef senf::console::detail::ParsedCommandTraits<Signature> CmdTraits;
         typedef senf::console::ParsedCommandOverload<typename CmdTraits::traits> Overload;
         typedef senf::console::ParsedArgumentAttributor<Overload> Attributor;
 
-        return senf::console::detail::ParsedCommandAddNodeAccess::attributor<Attributor>(
-            cmdNode.add( CreateParsedCommandOverload<CmdTraits>::create(fn) ) );
+        return detail::ParsedCommandAddNodeAccess::attributor<Attributor>(
+            CreateParsedCommandOverload<CmdTraits>::create(fn));
     }
 
 #endif
 
 }}}
 
-#ifndef DOXYGEN
+template <class CastTo, class Signature>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::Command(boost::function<Signature> fn)
+{
+    return detail::addOverloadedCommandNode<CastTo>(fn);
+}
 
-template <class Function>
-typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     Function fn, int,
-                                     typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
+template <class CastTo, class Function>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::
+Command(Function fn,
+        typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
 {
-    return senf::console::detail::addOverloadedCommandNode<Function>(node, name, fn);
+    return detail::addOverloadedCommandNode<CastTo>(fn);
 }
 
 template <class Signature>
-typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     boost::function<Signature> fn, int)
+prefix_ typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
+senf::console::factory::Command(boost::function<Signature> fn)
 {
-    return senf::console::detail::addOverloadedCommandNode<Signature>(node, name, fn);
+    return detail::addOverloadedCommandNode<Signature>(fn);
 }
 
-template <class Owner, class Function>
-typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
-                                     Function fn, int,
-                                     typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type *)
+template <class Function>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
+senf::console::factory::
+Command(Function fn,
+        typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
 {
-    return senf::console::detail::addOverloadedCommandNode<Function>(
-        node, name, senf::membind(fn,&owner));
+    return detail::addOverloadedCommandNode<Function>(fn);
 }
 
-#endif
+template <class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+senf::console::factory::BoundCommand(Owner * owner, Member memfn)
+{
+    return detail::addOverloadedCommandNode<Member>(senf::membind(memfn,owner));
+}
+
+template <class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+senf::console::factory::BoundCommand(Owner const * owner, Member memfn)
+{
+    return detail::addOverloadedCommandNode<Member>(senf::membind(memfn,owner));
+}
+
+template <class CastTo, class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::BoundCommand(Owner * owner, Member memfn)
+{
+    return detail::addOverloadedCommandNode<CastTo>(senf::membind(memfn,owner));
+}
+
+template <class CastTo, class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::BoundCommand(Owner const * owner, Member memfn)
+{
+    return detail::addOverloadedCommandNode<CastTo>(senf::membind(memfn,owner));
+}
 
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
index 0fdccd7..ce9cad5 100644 (file)
@@ -182,14 +182,15 @@ namespace console {
 
 #ifndef DOXYGEN
 
-#   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
-                                            SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
-                                            1))
+#   define BOOST_PP_ITERATION_PARAMS_1                                  \
+        (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                         \
+             SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
+             1))
 #   include BOOST_PP_ITERATE()
 
 #endif
 
-    /** \brief Generic ParsedCommandOverladBase attributes
+    /** \brief Generic ParsedCommandOverloadBase attributes
 
         Attributes for parsed commands are not set directly on the node. They are set via a special
         attributor temporary returned when adding a parsed command to the tree.
@@ -200,27 +201,33 @@ namespace console {
         \see \ref console_autoparse
      */
     class ParsedCommandAttributorBase
+        : public detail::NodeFactory
     {
     public:
-        OverloadedCommandNode & node() const; ///< Return the node object
-        operator OverloadedCommandNode & () const; ///< Automatically convert to node object
+        typedef OverloadedCommandNode node_type;
+        typedef OverloadedCommandNode & result_type;
 
-    protected:
-        ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
+        OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
 
-        void argName(std::string const & name) const;
-        void argDoc(std::string const & doc) const;
-        void typeName(std::string const & doc) const;
-        void defaultDoc(std::string const & doc) const;
+    protected:
+        ParsedCommandAttributorBase(ParsedCommandOverloadBase::ptr overload, unsigned index);
+        ParsedCommandAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
 
+        void argName(std::string const & name);
+        void argDoc(std::string const & doc);
+        void typeName(std::string const & doc);
+        void defaultDoc(std::string const & doc);
+        
         ParsedCommandOverloadBase & overload() const;
-        void overloadDoc(std::string const & doc) const;
-        void nodeDoc(std::string const & doc) const;
-        void shortDoc(std::string const & doc) const;
+        void overloadDoc(std::string const & doc);
+        void nodeDoc(std::string const & doc);
+        void shortDoc(std::string const & doc);
         
     private:
-        ParsedCommandOverloadBase & overload_;
+        ParsedCommandOverloadBase::ptr overload_;
         unsigned index_;
+        boost::optional<std::string> doc_;
+        boost::optional<std::string> shortdoc_;
     };
 
     /** \brief Non argument dependent ParsedCommandBase attributes 
@@ -241,7 +248,8 @@ namespace console {
         Overload & overload() const;    ///< Get the command overload
 
     protected:
-        ParsedCommandAttributor(Overload & overload, unsigned index);
+        ParsedCommandAttributor(typename Overload::ptr overload, unsigned index);
+        ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index);
 
     private:
     };
@@ -398,10 +406,10 @@ namespace console {
         : public ParsedCommandAttributor<Overload>
     {
     public:
-        Self doc(std::string const & doc) const; ///< Set documentation for all overloads
-        Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
-        Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
-        Self formatter(typename Overload::Formatter formatter) const; 
+        Self doc(std::string const & doc); ///< Set documentation for all overloads
+        Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
+        Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
+        Self formatter(typename Overload::Formatter formatter); 
                                         ///< Set return value formatter
                                         /**< This member is only available, if the \a ReturnType of
                                              the installed callback is not \c void.
@@ -415,7 +423,8 @@ namespace console {
                                              value and writes it properly formated to \a os. */
 
     protected:
-        ParsedArgumentAttributorBase(Overload & overload, unsigned index);
+        ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
+        ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
 
     private:
     };
@@ -427,12 +436,13 @@ namespace console {
         : public ParsedCommandAttributor<Overload>
     {
     public:
-        Self doc(std::string const & doc) const; ///< Set documentation for all overloads
-        Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
-        Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
+        Self doc(std::string const & doc); ///< Set documentation for all overloads
+        Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
+        Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
 
     protected:
-        ParsedArgumentAttributorBase(Overload & overload, unsigned index);
+        ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
+        ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
 
     private:
     };
@@ -449,7 +459,7 @@ namespace console {
 
         \see \ref console_autoparse
      */
-    template < class Overload, unsigned index, bool flag>
+    template <class Overload, unsigned index, bool flag>
     class ParsedArgumentAttributor
         : public ParsedArgumentAttributorBase< Overload, 
                                                 ParsedArgumentAttributor<Overload, index, flag> >
@@ -463,9 +473,6 @@ namespace console {
             kw::type::parser> arg_params;
 
     public:
-        typedef OverloadedCommandNode node_type;
-        typedef ParsedArgumentAttributor return_type;
-
         typedef typename senf::function_traits_arg_type< 
             typename Overload::traits, int(index) >::type arg_type;
         typedef typename senf::remove_cvref< arg_type >::type value_type;
@@ -502,43 +509,37 @@ namespace console {
 #endif
 
     private:
-        explicit ParsedArgumentAttributor(Overload & overload);
+        explicit ParsedArgumentAttributor(typename Overload::ptr overload);
+        explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
 
         template <class ArgumentPack>
-        next_type argInfo(ArgumentPack const & args) const;
+        next_type argInfo(ArgumentPack const & args);
         template <class Kw, class ArgumentPack>
-        void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_) 
-            const;
+        void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
 
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::name> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::description> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::default_value> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::type_name> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::default_doc> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
         template <class ArgumentPack>
         void argInfo(boost::parameter::keyword<kw::type::parser> const &, 
-                     ArgumentPack const & args, boost::mpl::true_) 
-            const;
+                     ArgumentPack const & args, boost::mpl::true_);
 
         next_type next() const;
 
-        void defaultValue(value_type const & value) const;
-        template <class Fn> void parser(Fn fn) const;
+        void defaultValue(value_type const & value);
+        template <class Fn> void parser(Fn fn);
 
         template <class O, unsigned i, bool f>
         friend class ParsedArgumentAttributor;
@@ -558,7 +559,8 @@ namespace console {
         typedef ParsedArgumentAttributor return_type;
 
     private:
-        explicit ParsedArgumentAttributor(Overload & overload);
+        explicit ParsedArgumentAttributor(typename Overload::ptr overload);
+        explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
 
         template <class O, unsigned i, bool f>
         friend class ParsedArgumentAttributor;
@@ -566,33 +568,46 @@ namespace console {
         friend class detail::ParsedCommandAddNodeAccess;
     };
 
-    template <class Function>
-    typename detail::ParsedCommandTraits<Function>::Attributor
-    senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int,
-                          typename boost::enable_if_c<
-                              detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
+#endif
+
+namespace factory {
+
+    template <class CastTo, class Signature>
+    typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+    Command(boost::function<Signature> fn);
+
+    template <class CastTo, class Function>
+    typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+    Command(Function fn,
+            typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
 
     template <class Signature>
-    typename detail::ParsedCommandTraits<Signature>::Attributor
-    senf_console_add_node(DirectoryNode & node, std::string const & name, 
-                          boost::function<Signature> fn, int);
+    typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
+    Command(boost::function<Signature> fn);
 
-    template <class Owner, class Function>
-    typename detail::ParsedCommandTraits<Function>::Attributor
-    senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
-                          Function fn, int,
-                          typename boost::enable_if_c<
-                              detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+    template <class Function>
+    typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
+    Command(Function fn,
+            typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
 
-#endif
+    template <class Owner, class Member>
+    typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+    BoundCommand(Owner * owner, Member memfn);
+
+    template <class Owner, class Member>
+    typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+    BoundCommand(Owner const * owner, Member memfn);
+
+    template <class CastTo, class Owner, class Member>
+    typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+    BoundCommand(Owner * owner, Member memfn);
 
-}}
+    template <class CastTo, class Owner, class Member>
+    typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+    BoundCommand(Owner const * owner, Member memfn);
 
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
 
-BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
-BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedArgumentAttributor, (class, unsigned, bool))
-BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
+}}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "ParsedCommand.cci"
index 0dbe33b..5ee1a84 100644 (file)
@@ -158,6 +158,41 @@ namespace detail {
 
     struct ParsedCommandAddNodeAccess;
 
+    // What is THIS about ??
+
+    // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
+    // this argument is given, then the function will be called with the console output stream as
+    // it's first argument.
+    //
+    // This is implemented in the following way: ParsedCommandOverload (the class responsible for
+    // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
+    // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
+    // function will be directly passed to ParsedCommandOverload.
+    //
+    // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
+    // the create member will use boost::bind to DROP the first argument.
+    
+    template <class Traits, 
+              bool ignoreOneArg=! Traits::has_ostream_arg, 
+              unsigned arity=Traits::traits::arity>
+    struct CreateParsedCommandOverload
+    {};
+
+    template <class Traits, unsigned arity>
+    struct CreateParsedCommandOverload<Traits, false, arity>
+    {
+        typedef typename Traits::traits traits;
+        
+        template <class Function>
+        static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn) 
+            { return senf::console::ParsedCommandOverload<traits>::create(fn); };
+    };
+
+#   define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY,                     \
+                                            SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
+                                            4))
+#   include BOOST_PP_ITERATE()
+
 #endif
 
 }}}
index 340e073..ab3caa6 100644 (file)
@@ -356,7 +356,7 @@ struct CreateParsedCommandOverload<Traits, true, BOOST_PP_ITERATION()>
 template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) > 
 next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
                 typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
-                    kw = arg_params()) const {
+                    kw = arg_params()) {
     return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
 }
 
index 7e03013..13402dd 100644 (file)
@@ -58,6 +58,8 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(parsedCommand)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
@@ -65,7 +67,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
     {
         std::stringstream ss;
-        dir.add("cb1", &cb1);
+        dir.add("cb1", fty::Command(&cb1));
         parser.parse("test/cb1 2 3.2", 
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "5\n" );
@@ -73,7 +75,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
     {
         std::stringstream ss;
-        dir.add("cb2", &cb2);
+        dir.add("cb2", fty::Command(&cb2));
         parser.parse("test/cb2",
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "1.2\n" );
@@ -81,7 +83,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
     {
         std::stringstream ss;
-        dir.add("cb3", &cb3);
+        dir.add("cb3", fty::Command(&cb3));
         parser.parse("test/cb3 234",
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "" );
@@ -89,7 +91,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
     {
         std::stringstream ss;
-        dir.add("cb4", &cb4);
+        dir.add("cb4", fty::Command(&cb4));
         parser.parse("test/cb4",
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "text\n" "value\n" );
@@ -97,7 +99,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
     {
         std::stringstream ss;
-        dir.add("cb5", &cb5);
+        dir.add("cb5", fty::Command(&cb5));
         parser.parse("test/cb5 1234",
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
         BOOST_CHECK_EQUAL( ss.str(), "Value: 1234\n" );
@@ -127,8 +129,10 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
         std::stringstream ss;
 
         // Just for the fun of it, use a functor and not a function pointer as parser ...
-        dir.add("cb6", &cb5)
-            .arg( kw::parser = TestParser() );
+        dir.add("cb6", 
+                fty::Command(&cb5)
+                    .arg( kw::parser = TestParser() )
+            );
         SENF_CHECK_NO_THROW(
             parser.parse("test/cb6 false",
                          boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
@@ -140,8 +144,10 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
         // This tests adding boost::function objects and at the same time validates, that 
         // compatible types also work
-        dir.add("cb7", boost::function<float()>(&cb2))
-            .formatter( &testFormatter );
+        dir.add("cb7", 
+                fty::Command(boost::function<float()>(&cb2))
+                    .formatter( &testFormatter )
+            );
         SENF_CHECK_NO_THROW(
             parser.parse("test/cb7",
                          boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
@@ -153,7 +159,7 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 
         using namespace senf::console::kw;
 
-        dir.add("cb", &cb1)
+        dir.add("cb", fty::Command(&cb1)
             .doc(
                 "Ops fortunate, ops me ut orgia vociferatio contumax per, rudo re loco emitto\n"
                 "intolerabiliter ita iugo. Subcribo gravo. Devenio luna fonticulus Castanea\n"
@@ -175,15 +181,17 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
                   type_name     = "number",
                   description   = "Florgel, dargel and durgel",
                   default_value = 2.1,
-                  default_doc   = "(double) 2.1" );
+                  default_doc   = "(double) 2.1" )
+            );
 
         senf::console::OverloadedCommandNode & cbNode (
-            dir.add("cb", &cb5)
+            dir.add("cb", fty::Command(&cb5)
                 .overloadDoc(
                     "Uus Primordia fundo falsidicus corium, diurnitas humo pro leto. Sui Ueraciter\n"
                     "hio eruca lenis qua Agalmate ut fors penitentia. Iugum obdormio anxio nuncupo\n"
                     "iam, in vos nam Custodi." ) 
-                .arg( "text", default_value = "" ) );
+                .arg( "text", default_value = "" ) )
+            );
 
         (void) cbNode;
 
@@ -240,14 +248,14 @@ SENF_AUTO_UNIT_TEST(parsedCommand)
 }
 
 namespace {
-
     struct Test 
     {
         senf::console::ScopedDirectory<Test> dir;
         std::string name_;
 
         Test(std::string const & name) : dir(this), name_ (name) {
-            dir.add("name", &Test::name);
+            dir.add("name", senf::console::factory::Command(
+                        SENF_MEMBINDFNP(std::string, Test, name, (std::string const &))));
         }
 
         std::string name(std::string const & suffix) {
@@ -279,9 +287,11 @@ namespace {
 
     senf::console::DirectoryNode::ptr dircb() 
     {
+        namespace fty = senf::console::factory;
+
         senf::console::DirectoryNode & dir (
             senf::console::root()["test"].mkdir("dircb"));
-        dir.add("cb1", &cb1);
+        dir.add("cb1", fty::Command(&cb1));
         return dir.thisptr();
     }
 
@@ -289,11 +299,13 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(directoryReturn)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
-    dir.add("test", &dircb);
+    dir.add("test", fty::Command(&dircb));
 
     {
         std::stringstream ss;
index a186106..fd8bfd0 100644 (file)
@@ -48,12 +48,14 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(programOptions)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::ScopedDirectory<> root;
     senf::console::root().add("root", root);
 
-    root.mkdir("dir1").add("fun1", &fun1);
-    root.add("fun2", &fun2);
-    root.mkdir("name-with-dashes").add("fun-2", &fun2);
+    root.mkdir("dir1").add("fun1", fty::Command(&fun1));
+    root.add("fun2", fty::Command(&fun2));
+    root.mkdir("name-with-dashes").add("fun-2", fty::Command(&fun2));
 
     {
         char const * argv[] = { "", "--dir1-fun1=foo","--fun2" };
index 0b86895..9ce13ad 100644 (file)
@@ -67,14 +67,17 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(vectorSupport)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
 
     std::vector<int> defv (boost::assign::list_of(7)(2).to_container(defv));
-    dir.add("test", &Summer<std::vector<int> >::test)
-        .arg("data", "test data", senf::console::kw::default_value = defv);
+    dir.add("test", fty::Command(&Summer<std::vector<int> >::test)
+        .arg("data", "test data", senf::console::kw::default_value = defv)
+        );
     std::stringstream ss;
 
     SENF_CHECK_NO_THROW(
@@ -98,14 +101,17 @@ SENF_AUTO_UNIT_TEST(vectorSupport)
 
 SENF_AUTO_UNIT_TEST(listSupport)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
 
     std::list<int> defv (boost::assign::list_of(7)(2).to_container(defv));
-    dir.add("test", &Summer<std::list<int> >::test)
-        .arg("data", "test data", senf::console::kw::default_value = defv);
+    dir.add("test", fty::Command(&Summer<std::list<int> >::test)
+        .arg("data", "test data", senf::console::kw::default_value = defv)
+        );
     std::stringstream ss;
 
     SENF_CHECK_NO_THROW(
@@ -129,14 +135,17 @@ SENF_AUTO_UNIT_TEST(listSupport)
 
 SENF_AUTO_UNIT_TEST(setSupport)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
 
     std::set<int> defv (boost::assign::list_of(7)(2).to_container(defv));
-    dir.add("test", &Summer<std::set<int> >::test)
-        .arg("data", "test data", senf::console::kw::default_value = defv);
+    dir.add("test", fty::Command(&Summer<std::set<int> >::test)
+        .arg("data", "test data", senf::console::kw::default_value = defv)
+        );
     std::stringstream ss;
 
     SENF_CHECK_NO_THROW(
@@ -160,6 +169,8 @@ SENF_AUTO_UNIT_TEST(setSupport)
 
 SENF_AUTO_UNIT_TEST(mapSupport)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
@@ -167,8 +178,9 @@ SENF_AUTO_UNIT_TEST(mapSupport)
 
     std::map<std::string, int> defv (
         boost::assign::map_list_of("foo bar",7)("bar",2).to_container(defv));
-    dir.add("test", &mapTest)
-        .arg("data", "test data", senf::console::kw::default_value = defv);
+    dir.add("test", fty::Command(&mapTest)
+        .arg("data", "test data", senf::console::kw::default_value = defv)
+        );
     std::stringstream ss;
 
     SENF_CHECK_NO_THROW(
index f379c4e..8b18ff0 100644 (file)
 ///////////////////////////////cti.p///////////////////////////////////////
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator
-
-template <class Owner, class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner,Object>::result_type
-senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNode & node,
-                                                                    Owner & owner,
-                                                                    std::string const & name,
-                                                                    Object & ob)
-{
-    return senf_console_add_node(node, owner, name, ob, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////
 // senf::console::ScopedDirectory<Owner>
 
 template <class Owner>
@@ -55,73 +42,66 @@ prefix_ senf::console::ScopedDirectory<Owner>::ScopedDirectory(Owner * owner)
 }
 
 template <class Owner>
-template <class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object const>::result_type
-senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object const & ob)
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<Owner>::add(std::string const & name,
+                                                              boost::shared_ptr<NodeType> othernode)
 {
-    return OwnerNodeCreateTraits<Owner, Object const>::Creator::create(node(), *owner_, name, ob);
+    return node().add(name, othernode);
 }
 
 template <class Owner>
-template <class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::result_type
-senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object & ob)
-{
-    return OwnerNodeCreateTraits<Owner, Object>::Creator::create(node(), *owner_, name, ob);
-}
-
-#ifndef DOXYGEN
-
-template <class Owner, class Function>
-prefix_ senf::console::SimpleCommandNode & senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name,
-                      SimpleCommandNode::Function fn, int)
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, NodeType & othernode,
+    typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
 {
-    return node.add(name,fn);
+    return node().add(name,othernode);
 }
 
 template <class Owner>
-prefix_ senf::console::SimpleCommandNode & senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
-                      void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, Factory const & factory,
+    typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type *)
 {
-    return node.add(name, boost::function<void (std::ostream&,ParseCommandInfo const &)>(
-                        boost::bind(fn,boost::ref(owner),_1,_2)));
+    return factory.create(*owner_, name, node());
 }
 
 template <class Owner>
-prefix_ senf::console::DirectoryNode &
-senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner,
-                                     std::string const & name, DirectoryNode & dir, int)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, Factory const & factory,
+    typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type *,
+    typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type *)
 {
-    return node.add(name, dir.thisptr());
+    return node().add(name, factory);
 }
 
-template <class Node>
-prefix_ senf::console::DirectoryNode & senf::console::
-senf_console_add_node(DirectoryNode & dir, std::string const & name, Node const & node, int,
-                      typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type *)
-{
-    return dir.add(name, node.node().thisptr());
-}
-
-#endif
-
 ///////////////////////////////////////////////////////////////////////////
 // senf::console::ScopedDirectory<void>
 
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::ScopedDirectory<void>::add(std::string const & name, Object const & ob)
+
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<void>::add(std::string const & name,
+                                                             boost::shared_ptr<NodeType> othernode)
+{
+    return node().add(name,othernode);
+}
+
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<void>::
+add(std::string const & name, NodeType & othernode,
+    typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
 {
-    return node().add(name, ob);
+    return node().add(name,othernode);
 }
 
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::ScopedDirectory<void>::add(std::string const & name, Object & ob)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<void>::
+add(std::string const & name, Factory const & factory,
+    typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type *)
 {
-    return node().add(name, ob);
+    return node().add(name,factory);
 }
 
 ///////////////////////////////cti.e///////////////////////////////////////
index 0613d10..ddbf292 100644 (file)
 namespace senf {
 namespace console {
 
-    /** \brief Internal: Node creation helper traits (ScopedDirectory proxy)
-        
-        This class is used like NodeCreateTraits to customize the child node creation. This trait
-        class is used however by the ScopedDirectory proxy.
-     */
-    template <class Owner, class Object>
-    struct OwnerNodeCreateTraits
-    {
-        typedef BOOST_TYPEOF_TPL( senf_console_add_node( 
-                                      * static_cast<DirectoryNode *>(0),
-                                      * static_cast<Owner *>(0),
-                                      * static_cast<std::string const *>(0),
-                                      * static_cast<Object *>(0),
-                                      * static_cast<int *>(0)) ) base_type;
-        typedef typename senf::remove_cvref<base_type>::type value_type;
-
-        typedef typename value_type::node_type NodeType;
-        typedef typename value_type::return_type result_type;
-
-        /// Internal
-        struct Creator {
-            static result_type create(DirectoryNode & node, Owner & owner, 
-                                     std::string const & name, Object & ob);
-        };
-    };
-    
+    namespace detail { struct OwnedNodeFactory {}; }
+
     /** \brief Internal: Marker base class for all ScopedDirectory proxies
      */
     class ScopedDirectoryBase
@@ -150,21 +126,18 @@ namespace console {
         ///@}
         ///////////////////////////////////////////////////////////////////////////
 
-        template <class Object>
-        typename OwnerNodeCreateTraits<Owner, Object const>::result_type add(
-            std::string const & name, Object const & ob);
-                                        ///< Create new child node
-                                        /**< Adds a new child node to the (proxied)
-                                             DirectoryNode. How the node is added is configured
-                                             using the OwnerNodeCreateTraits template. The default
-                                             implementation just forwards the call to the proxied
-                                             directory node. */
-
-        template <class Object>
-        typename OwnerNodeCreateTraits<Owner, Object>::result_type add(
-            std::string const & name, Object & ob);
-                                        ///< Create new child node
-                                        /**< \see add() */
+        template <class NodeType>
+        NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
+        template <class NodeType>
+        NodeType & add(std::string const & name, NodeType & node,
+                       typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+        template <class Factory>
+        typename Factory::result_type add(std::string const & name, Factory const & factory,
+                                          typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
+        template <class Factory>
+        typename Factory::result_type add(std::string const & name, Factory const & factory,
+                                          typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0,
+                                          typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
 
     protected:
 
@@ -178,33 +151,16 @@ namespace console {
     class ScopedDirectory<void> : public ScopedDirectoryBase
     {
     public:
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object const & ob);
-
-        template <class Object>
-        typename NodeCreateTraits<Object>::result_type add(std::string const & name,
-                                                           Object & ob);
+        template <class NodeType>
+        NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
+        template <class NodeType>
+        NodeType & add(std::string const & name, NodeType & node,
+                       typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+        template <class Factory>
+        typename Factory::result_type add(std::string const & name, Factory const & factory,
+                                          typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0);
     };
 
-    template <class Owner, class Function>
-    SimpleCommandNode & senf_console_add_node(
-        DirectoryNode & node, Owner & owner, std::string const & name,
-        SimpleCommandNode::Function fn, int);
-
-    template <class Owner>
-    SimpleCommandNode & senf_console_add_node(
-        DirectoryNode & node, Owner & owner, std::string const & name,
-        void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int);
-
-    template <class Owner>
-    DirectoryNode & senf_console_add_node(DirectoryNode & node, Owner & owner, 
-                                          std::string const & name, DirectoryNode & dir, int);
-
-    template <class Node>
-    DirectoryNode & senf_console_add_node(
-        DirectoryNode & dir, std::string const & name, Node const & node, int, 
-        typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type * = 0);
 #endif
 
 }}
index 8cf9c6c..92e30aa 100644 (file)
@@ -43,7 +43,7 @@ namespace {
 
         senf::console::ScopedDirectory<Self> dir;
         TestObject() : dir(this) {
-            dir.add("member", &Self::member);
+            dir.add("member", senf::console::factory::Command(senf::membind(&Self::member,this)));
         }
 
         void member(std::ostream & os, senf::console::ParseCommandInfo const &) {
@@ -73,10 +73,12 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(scopedDirectoryVoid)
 {
+    namespace fty = senf::console::factory;
+
     {
         senf::console::ScopedDirectory<> dir;
         senf::console::root().add("dir", dir);
-        dir.add("cb", &callback);
+        dir.add("cb", fty::Command(&callback));
         std::stringstream ss;
         senf::console::ParseCommandInfo info;
         senf::console::root()["dir"]("cb")(ss, info);
@@ -96,11 +98,13 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(scopedDirectoryBase)
 {
+    namespace fty = senf::console::factory;
+
     {
         senf::console::ScopedDirectory<> dir;
         senf::console::root().add("dir", dir);
         dir.mkdir("foo");
-        dir.add("cb", &callback);
+        dir.add("cb", fty::Command(&callback));
         BOOST_CHECK( &dir["foo"] == &dir.get("foo") );
         BOOST_CHECK( &dir("cb") == &dir.get("cb") );
         
index 6ed4b3b..b46cd6e 100644 (file)
@@ -354,8 +354,10 @@ prefix_ unsigned senf::console::Client::getWidth(std::ostream & os, unsigned def
 
 prefix_ senf::console::Client::SysBacktrace::SysBacktrace()
 {
-    sysdir().node().add("backtrace", &SysBacktrace::backtrace)
-        .doc("Display the backtrace of the last error / exception in this console");
+    namespace fty = senf::console::factory;
+
+    sysdir().add("backtrace", fty::Command(&SysBacktrace::backtrace)
+                 .doc("Display the backtrace of the last error / exception in this console") );
 }
 
 prefix_ void senf::console::Client::SysBacktrace::backtrace(std::ostream & os)
index 59f848a..cc5697f 100644 (file)
@@ -56,15 +56,17 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(charTraits)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
     std::stringstream ss;
 
-    dir.add("test",&charTest);
-    dir.add("stest",&scharTest);
-    dir.add("utest",&ucharTest);
+    dir.add("test",fty::Command(&charTest));
+    dir.add("stest",fty::Command(&scharTest));
+    dir.add("utest",fty::Command(&ucharTest));
 
     SENF_CHECK_NO_THROW(
         parser.parse("test/test 10; test/test 20",
@@ -87,12 +89,14 @@ SENF_AUTO_UNIT_TEST(charTraits)
 
 SENF_AUTO_UNIT_TEST(boolTraits)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
 
-    dir.add("test", &boolTest);
+    dir.add("test", fty::Command(&boolTest));
 
     std::stringstream ss;
     SENF_CHECK_NO_THROW(
@@ -118,7 +122,7 @@ SENF_AUTO_UNIT_TEST(boolTraits)
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
     BOOST_CHECK_EQUAL( ss.str(), "true\n" "true\n" );
 
-    dir.add("test2", &boolTest).formatter( senf::console::formatEnabledDisabled );
+    dir.add("test2", fty::Command(&boolTest).formatter( senf::console::formatEnabledDisabled ));
     ss.str("");
     SENF_CHECK_NO_THROW(
         parser.parse("test/test2 0; test/test2 -1",
@@ -135,12 +139,14 @@ SENF_AUTO_UNIT_TEST(stringTraits)
 
 SENF_AUTO_UNIT_TEST(enumSupport)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
 
-    dir.add("test",&test);
+    dir.add("test",fty::Command(&test));
     
     std::stringstream ss;
     SENF_CHECK_NO_THROW(
@@ -164,7 +170,7 @@ SENF_AUTO_UNIT_TEST(enumSupport)
                      boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
         senf::console::SyntaxErrorException );
 
-    dir.add("member", &TestClass::test);
+    dir.add("member", fty::Command(&TestClass::test));
 
     ss.str("");
     SENF_CHECK_NO_THROW(
index 2496f3b..3333cd5 100644 (file)
@@ -49,14 +49,17 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(charAsString)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
     std::stringstream ss;
 
-    dir.add("test", boost::function<
-            senf::console::CharAsString<char> (senf::console::CharAsString<char>)>(&charTest));
+    dir.add("test", 
+            fty::Command<senf::console::CharAsString<char> (senf::console::CharAsString<char>)>(
+                &charTest));
 
     ss.str("");
     SENF_CHECK_NO_THROW(
@@ -67,13 +70,15 @@ SENF_AUTO_UNIT_TEST(charAsString)
 
 SENF_AUTO_UNIT_TEST(flagCollection)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
     senf::console::root().add("test", dir);
     std::stringstream ss;
 
-    dir.add("test",&collectionTest);
+    dir.add("test",fty::Command(&collectionTest));
     
     ss.str("");
     SENF_CHECK_NO_THROW(
index e5a311c..80d5d73 100644 (file)
@@ -39,6 +39,13 @@ prefix_ senf::console::detail::QueryVariable<Variable>::QueryVariable(Variable c
 {}
 
 template <class Variable>
+prefix_ typename senf::console::detail::QueryVariable<Variable>::Traits::Overload::ptr
+senf::console::detail::QueryVariable<Variable>::create(Variable const & var)
+{
+    return CreateOverload::create(Function(QueryVariable(var)));
+}
+
+template <class Variable>
 prefix_ Variable const & senf::console::detail::QueryVariable<Variable>::operator()()
     const
 {
@@ -55,6 +62,15 @@ prefix_ senf::console::detail::SetVariable<Variable>::SetVariable(Variable & var
 {}
 
 template <class Variable>
+prefix_ typename senf::console::detail::SetVariable<Variable>::Traits::Overload::ptr
+senf::console::detail::SetVariable<Variable>::create(Variable & var)
+{
+    typename Traits::Overload::ptr overload (CreateOverload::create(Function(SetVariable(var))));
+    overload->arg(0).name = "new_value";
+    return overload;
+}
+
+template <class Variable>
 prefix_ void senf::console::detail::SetVariable<Variable>::operator()(Variable const & value)
     const
 {
@@ -68,189 +84,150 @@ prefix_ void senf::console::detail::SetVariable<Variable>::operator()(Variable c
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::ConstVariableAttributor<Variable>
+// senf::console::ConstVariableFactory<Variable>
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::doc(std::string const & doc)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::doc(std::string const & doc)
 {
-    queryOverload_.node().doc(doc);
+    doc_ = doc;
     return *this;
 }
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::shortdoc(std::string const & doc)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::shortdoc(std::string const & doc)
 {
-    queryOverload_.node().shortdoc(doc);
+    shortdoc_ = doc;
     return *this;
 }
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::formatter(Formatter formatter)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::formatter(Formatter formatter)
 {
-    queryOverload_.formatter(formatter);
+    queryOverload_->formatter(formatter);
     return *this;
 }
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>::
-ConstVariableAttributor(QueryOverload & queryOverload)
-    : queryOverload_ (queryOverload)
-{}
-
-template <class Variable>
 prefix_ senf::console::OverloadedCommandNode &
-senf::console::ConstVariableAttributor<Variable>::node()
+senf::console::factory::ConstVariableFactory<Variable>::create(DirectoryNode & dir,
+                                                               std::string const & name)
     const
 {
-    return queryOverload_.node();
+    OverloadedCommandNode & node (OverloadedCommandNode::insertOverload(dir, name, queryOverload_));
+    if (doc_) node.doc(*doc_);
+    if (shortdoc_) node.shortdoc(*shortdoc_);
+    return node;
 }
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>::
-operator senf::console::OverloadedCommandNode &()
-    const
-{
-    return node();
-}
+prefix_ senf::console::factory::ConstVariableFactory<Variable>::
+ConstVariableFactory(Variable const & var)
+    : queryOverload_ (detail::QueryVariable<Variable>::create(var))
+{}
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::console::VariableAttributor<Variable>
+// senf::console::VariableFactory<Variable>
 
 template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::parser(Parser parser)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::parser(Parser parser)
 {
-    setOverload_.template arg<0>().parser = parser;
+    setOverload_->template arg<0>().parser = parser;
     return *this;
 }
 
 template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::typeName(std::string const & name)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::typeName(std::string const & name)
 {
-    setOverload_.arg(0).type = name;
+    setOverload_->arg(0).type = name;
     return *this;
 }
 
 template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::onChange(OnChangeHandler handler)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::onChange(OnChangeHandler handler)
 {
-    setOverload_.function( 
+    setOverload_->function( 
         boost::bind(detail::SetVariable<Variable>(var_, handler),_2));
     return *this;
 }
 
 template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::doc(std::string const & doc)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::doc(std::string const & doc)
 {
-    ConstVariableAttributor<Variable>::doc(doc);
+    ConstVariableFactory<Variable>::doc(doc);
     return *this;
 }
 
 template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::shortdoc(std::string const & doc)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::shortdoc(std::string const & doc)
 {
-    ConstVariableAttributor<Variable>::shortdoc(doc);
+    ConstVariableFactory<Variable>::shortdoc(doc);
     return *this;
 }
 
 template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::formatter(Formatter formatter)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::formatter(Formatter formatter)
 {
-    ConstVariableAttributor<Variable>::formatter(formatter);
+    ConstVariableFactory<Variable>::formatter(formatter);
     return *this;
 }
 
 template <class Variable>
-prefix_
-senf::console::VariableAttributor<Variable>::VariableAttributor(QueryOverload & queryOverload,
-                                                                SetOverload & setOverload,
-                                                                Variable & var)
-    : ConstVariableAttributor<Variable> (queryOverload), setOverload_ (setOverload), var_ (var)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-
-template <class Variable, bool isConst>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::detail::VariableNodeCreator<Variable,isConst>::add(DirectoryNode & node,
-                                                                  std::string const & name,
-                                                                  Variable & var)
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::factory::VariableFactory<Variable>::create(DirectoryNode & dir,
+                                                          std::string const & name)
+    const
 {
-    typename VariableAttributor<Variable>::SetOverload & setOverload ( 
-        node.add(name, typename detail::SetVariable<Variable>::Function(
-                     detail::SetVariable<Variable>(var)))
-            .arg("new_value")
-            .overload() );
-    typename VariableAttributor<Variable>::QueryOverload & queryOverload ( 
-        node.add(name, typename detail::QueryVariable<Variable>::Function(
-                     detail::QueryVariable<Variable>(var))).overload() );
-
-    return VariableAttributor<Variable>(queryOverload, setOverload, var);
+    OverloadedCommandNode & node (ConstVariableFactory<Variable>::create(dir,name));
+    node.add(setOverload_);
+    return node;
 }
 
 template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::detail::VariableNodeCreator<Variable, true>::add(DirectoryNode & node,
-                                                                std::string const & name,
-                                                                Variable & var)
-{
-    typename VariableAttributor<Variable>::QueryOverload & queryOverload ( 
-        node.add(name, typename detail::QueryVariable<Variable>::Function(
-                     detail::QueryVariable<Variable>(var))).overload() );
-
-    return ConstVariableAttributor<Variable>(queryOverload);
-}
+prefix_ senf::console::factory::VariableFactory<Variable>::VariableFactory(Variable & var)
+    : ConstVariableFactory<Variable> (var), 
+      setOverload_ (detail::SetVariable<Variable>::create(var)),
+      var_ (var)
+{}
 
-#ifndef DOXYGEN
+///////////////////////////////////////////////////////////////////////////
 
-template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable> senf::console::
-senf_console_add_node(DirectoryNode & node, std::string const & name, Variable & var, int,
-                      typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type *,
-                      typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type *, 
-                      typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type *)
+template <class Var>
+prefix_ senf::console::factory::VariableFactory<Var>
+senf::console::factory::Variable(Var & var)
 {
-    return detail::VariableNodeCreator<Variable>::add(node, name, var);
+    return VariableFactory<Var>(var);
 }
 
-template <class Variable>
-prefix_ typename senf::console::detail::VariableNodeCreator<Variable>::result_type
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
-                                     boost::reference_wrapper<Variable> var, int)
+template <class Var>
+prefix_ senf::console::factory::VariableFactory<Var>
+senf::console::factory::Variable(boost::reference_wrapper<Var> var)
 {
-    return detail::VariableNodeCreator<Variable>::add(node, name, var.get());
+    return VariableFactory<Var>(var);
 }
 
-template <class Variable, class Owner>
-prefix_ senf::console::VariableAttributor<Variable> senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
-                      Variable & var, int,
-                      typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type *, 
-                      typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type *, 
-                      typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type *)
+template <class Var>
+prefix_ senf::console::factory::ConstVariableFactory<Var>
+senf::console::factory::Variable(Var const & var)
 {
-    return detail::VariableNodeCreator<Variable>::add(node, name, var);
+    return ConstVariableFactory<Var>(var);
 }
 
-template <class Variable, class Owner>
-prefix_ typename senf::console::detail::VariableNodeCreator<Variable>::result_type
-senf::console::senf_console_add_node(DirectoryNode & node, Owner &,
-                                     std::string const & name,
-                                     boost::reference_wrapper<Variable> var, int)
+template <class Var>
+prefix_ senf::console::factory::ConstVariableFactory<Var>
+senf::console::factory::Variable(boost::reference_wrapper<Var const> var)
 {
-    return detail::VariableNodeCreator<Variable>::add(node, name, var.get());
+    return ConstVariableFactory<Var>(var);
 }
 
-#endif
-
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 4f93a93..92df05d 100644 (file)
@@ -42,63 +42,34 @@ namespace console {
     class ScopedDirectoryBase;
     template <class Variable> class VariableAttributor;
 
-    
-
-#ifndef DOXYGEN
-
-    template <class Variable>
-    VariableAttributor<Variable> senf_console_add_node(
-        DirectoryNode & node, std::string const & name, Variable & var, int,
-        typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
-        typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type * = 0,
-        typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
-
-    template <class Variable>
-    typename detail::VariableNodeCreator<Variable>::result_type
-    senf_console_add_node(DirectoryNode & node, std::string const & name, 
-                          boost::reference_wrapper<Variable> var, int);
-
-    template <class Variable, class Owner>
-    VariableAttributor<Variable> senf_console_add_node(
-        DirectoryNode & node, Owner & owner, std::string const & name, Variable & var, int,
-        typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
-        typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type * = 0,
-        typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
-
-    template <class Variable, class Owner>
-    typename detail::VariableNodeCreator<Variable>::result_type
-    senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, 
-                          boost::reference_wrapper<Variable> var, int);
-
-#endif
+namespace factory {
 
     /** \brief Variable command attributes (const)
         
-        \see VariableAttributor
+        \see VariableFactory
      */
     template <class Variable>
-    class ConstVariableAttributor
+    class ConstVariableFactory
+        : public detail::NodeFactory
     {
     public:
         typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
         typedef typename QueryOverload::Formatter Formatter;
         typedef OverloadedCommandNode node_type;
-        typedef ConstVariableAttributor return_type;
-
-        ConstVariableAttributor doc(std::string const & doc);
-        ConstVariableAttributor shortdoc(std::string const & doc);
-        ConstVariableAttributor formatter(Formatter formatter);
+        typedef OverloadedCommandNode & result_type;
 
-        OverloadedCommandNode & node() const; ///< Return the node object
-        operator OverloadedCommandNode & () const; ///< Automatically convert to node object
+        ConstVariableFactory doc(std::string const & doc);
+        ConstVariableFactory shortdoc(std::string const & doc);
+        ConstVariableFactory formatter(Formatter formatter);
 
-    protected:
-        explicit ConstVariableAttributor(QueryOverload & queryOverload);
+        OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+        
+        explicit ConstVariableFactory(Variable const & var);
 
     private:
-        QueryOverload & queryOverload_;
-
-        friend class detail::VariableNodeCreator<Variable const>;
+        typename QueryOverload::ptr queryOverload_;
+        boost::optional<std::string> doc_;
+        boost::optional<std::string> shortdoc_;
     };
  
     /** \brief Variable command attributes
@@ -132,65 +103,74 @@ namespace console {
         \ingroup console_commands
      */
     template <class Variable>
-    class VariableAttributor
-        : public ConstVariableAttributor<Variable>
+    class VariableFactory
+        : public ConstVariableFactory<Variable>
     {
     public:
         typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
         typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
         typedef typename detail::SetVariable<Variable>::OnChangeHandler OnChangeHandler;
-        typedef OverloadedCommandNode node_type;
-        typedef VariableAttributor return_type;
-
-        typedef typename ConstVariableAttributor<Variable>::Formatter Formatter;
-        typedef typename ConstVariableAttributor<Variable>::QueryOverload QueryOverload;
-
-        VariableAttributor doc(std::string const & doc); ///< Set documentation of the variable
-        VariableAttributor shortdoc(std::string const & doc); ///< Set short documentation
-        VariableAttributor formatter(Formatter formatter); ///< Set formatter
-        /**< The \a formatter must be a callable with a signature
-             compatible with
-             \code
-                 void formatter(Variable const & value, std::ostream & os);
-             \endcode
-                 The \a formatter takes the return value of the call \a
-                 value and writes it properly formated to \a os. */
-       
-        VariableAttributor parser(Parser parser); ///< Set argument parser
-        /**< The parser is an arbitrary callable object with
-             the signature
-             \code
-                 void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
-             \endcode
-
-             where \c value_type is the type of the overload
-             parameter. The parser must read and parse the complete
-             \a tokens range and return the parsed value in \a
-             out. If the parser fails, it must raise a
-             senf::console::SyntaxErrorException. */
-        VariableAttributor typeName(std::string const & name); ///< Set name of the variable type
-        VariableAttributor onChange(OnChangeHandler handler); ///< Set change callback
-        /**< The \a handler callback is called, whenever the value
-             of the variable is changed. The new value has already
-             been set, when the callback is called, the old value is
-             passed to the callback. The callback must have a
-             signature compatible to
-             \code
-                 void handler(Variable const & oldValue);
-             \endcode */
+
+        typedef typename ConstVariableFactory<Variable>::Formatter Formatter;
+        typedef typename ConstVariableFactory<Variable>::QueryOverload QueryOverload;
+
+        VariableFactory doc(std::string const & doc); ///< Set documentation of the variable
+        VariableFactory shortdoc(std::string const & doc); ///< Set short documentation
+        VariableFactory formatter(Formatter formatter); ///< Set formatter
+                                        /**< The \a formatter must be a callable with a signature
+                                             compatible with
+                                             \code
+                                                 void formatter(Variable const & value, std::ostream & os);
+                                             \endcode
+                                                 The \a formatter takes the return value of the call \a
+                                                 value and writes it properly formated to \a os. */
+        VariableFactory parser(Parser parser); ///< Set argument parser
+                                        /**< The parser is an arbitrary callable object with
+                                             the signature
+                                             \code
+                                                 void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
+                                             \endcode
+                                             
+                                             where \c value_type is the type of the overload
+                                             parameter. The parser must read and parse the complete
+                                             \a tokens range and return the parsed value in \a
+                                             out. If the parser fails, it must raise a
+                                             senf::console::SyntaxErrorException. */
+        VariableFactory typeName(std::string const & name); ///< Set name of the variable type
+        VariableFactory onChange(OnChangeHandler handler); ///< Set change callback
+                                        /**< The \a handler callback is called, whenever the value
+                                             of the variable is changed. The new value has already
+                                             been set, when the callback is called, the old value is
+                                             passed to the callback. The callback must have a
+                                             signature compatible to
+                                             \code
+                                                 void handler(Variable const & oldValue);
+                                             \endcode */
+
+        OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+
+        explicit VariableFactory(Variable & var);
+
     protected:
 
     private:
-        VariableAttributor(QueryOverload & queryOverload, SetOverload & setOverload, 
-                           Variable & var);
-
-        SetOverload & setOverload_;
+        typename SetOverload::ptr setOverload_;
         Variable & var_;
-
-        friend class detail::VariableNodeCreator<Variable>;
     };
-}}
+
+    template <class Var>
+    VariableFactory<Var> Variable(Var & var);
+
+    template <class Var>
+    VariableFactory<Var> Variable(boost::reference_wrapper<Var> var);
+
+    template <class Var>
+    ConstVariableFactory<Var> Variable(Var const & var);
+
+    template <class Var>
+    ConstVariableFactory<Var> Variable(boost::reference_wrapper<Var const> var);
+
+}}}
 
 ///////////////////////////////hh.e////////////////////////////////////////
 //#include "Variables.cci"
index 0f703aa..3e3f2f5 100644 (file)
@@ -48,10 +48,13 @@ namespace detail {
         typedef Variable const & Signature ();
         typedef boost::function<Signature> Function;
         typedef detail::ParsedCommandTraits<Signature> Traits;
+        typedef detail::CreateParsedCommandOverload<Traits> CreateOverload;
         typedef Variable const & result_type;
 
         QueryVariable(Variable const & var);
 
+        static typename Traits::Overload::ptr create(Variable const & var);
+
         Variable const & operator()()  const;
 
         Variable const & var_;
@@ -63,10 +66,13 @@ namespace detail {
         typedef void Signature (Variable &);
         typedef boost::function<Signature> Function;
         typedef detail::ParsedCommandTraits<Signature> Traits;
+        typedef detail::CreateParsedCommandOverload<Traits> CreateOverload;
         typedef boost::function<void (Variable const &)> OnChangeHandler;
         typedef void result_type;
         
         SetVariable(Variable & var, OnChangeHandler handler = OnChangeHandler());
+
+        static typename Traits::Overload::ptr create(Variable & var);
         
         void operator()(Variable const & value) const;
 
@@ -74,22 +80,6 @@ namespace detail {
         OnChangeHandler handler_;
     };
 
-    template <class Variable, bool isConst=boost::is_const<Variable>::value>
-    struct VariableNodeCreator
-    {
-        typedef VariableAttributor<Variable> result_type;
-        static VariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
-                                                Variable & var);
-    };
-
-    template <class Variable>
-    struct VariableNodeCreator<Variable, true>
-    {
-        typedef ConstVariableAttributor<Variable> result_type;
-        static ConstVariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
-                                                     Variable & var);
-    };
-
 #endif
 
 }}}
index 2a63473..fc782b7 100644 (file)
@@ -51,6 +51,8 @@ namespace {
 
 SENF_AUTO_UNIT_TEST(variables)
 {
+    namespace fty = senf::console::factory;
+
     senf::console::Executor executor;
     senf::console::CommandParser parser;
     senf::console::ScopedDirectory<> dir;
@@ -59,12 +61,13 @@ SENF_AUTO_UNIT_TEST(variables)
     int var (5);
 
     std::stringstream ss;
-    dir.add("var", var)
+    dir.add("var", fty::Variable(var)
         .doc("Current blorg limit")
         .formatter(&testFormatter)
         .parser(&testParser)
         .typeName("number")
-        .onChange(&testCallback);
+        .onChange(&testCallback)
+        );
     parser.parse("test/var; test/var 10; test/var",
                  boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
     BOOST_CHECK_EQUAL( ss.str(), "[5]\n[0]\n" );
@@ -74,22 +77,24 @@ SENF_AUTO_UNIT_TEST(variables)
     dir("var").help(ss);
     BOOST_CHECK_EQUAL(ss.str(), 
                       "Usage:\n"
-                      "    1- var new_value:number\n"
-                      "    2- var\n"
+                      "    1- var\n"
+                      "    2- var new_value:number\n"
                       "\n"
                       "Current blorg limit\n");
 
-    senf::console::CommandNode & refvar (dir.add("refvar", boost::ref(var))
+    senf::console::CommandNode & refvar (dir.add("refvar", fty::Variable(boost::ref(var))
         .doc("Current blorg limit")
         .formatter(&testFormatter)
         .parser(&testParser)
-        .typeName("number"));
+        .typeName("number")
+    ));
 
     (void) refvar;
 
-    dir.add("crefvar", boost::cref(var))
+    dir.add("crefvar", fty::Variable(boost::cref(var))
         .doc("Current blorg limit")
-        .formatter(&testFormatter);
+        .formatter(&testFormatter)
+        );
 }
 
 namespace {
@@ -100,7 +105,7 @@ namespace {
         senf::console::ScopedDirectory<Test2> dir;
         
         Test2() : dir(this), var_(0)
-            { dir.add("var", boost::ref(var_)); }
+            { dir.add("var", senf::console::factory::Variable(boost::ref(var_))); }
         
     private:
         int var_;
index eda95c1..efa898f 100644 (file)
@@ -52,19 +52,22 @@ prefix_ senf::log::FileTarget::FileTarget(std::string const & filename,
       IOStreamTarget (getNodename(filename, nodename), ofstream_t::member), 
       file_ (filename)
 {
+    namespace fty = senf::console::factory;
+
     if (! ofstream_t::member)
         SENF_THROW_SYSTEM_EXCEPTION("logfile open") << ": " << filename;
-    consoleDir().add( "reopen", senf::membind(
-                          static_cast<void (FileTarget::*)()>(&FileTarget::reopen),
-                          this))
-        .doc("Reopen logfile");
-    consoleDir().add("reopen", senf::membind(
-                         static_cast<void (FileTarget::*)(std::string const &)>(&FileTarget::reopen),
-                         this))
-        .arg("filename","new filename")
-        .overloadDoc("Reopen logfile under new name");
-    consoleDir().add("file", boost::cref(file_))
-        .doc("Show filename log messages are sent to");
+    consoleDir()
+        .add( "reopen",
+              fty::BoundCommand(this, SENF_MEMFNP(void, FileTarget, reopen, ()))
+              .doc("Reopen logfile") );
+    consoleDir()
+        .add("reopen", 
+             fty::BoundCommand(this, SENF_MEMFNP(void, FileTarget, reopen, (std::string const &)))
+             .arg("filename","new filename")
+             .overloadDoc("Reopen logfile under new name") );
+    consoleDir()
+        .add("file", fty::Variable(boost::cref(file_))
+             .doc("Show filename log messages are sent to") );
 }
 
 prefix_ void senf::log::FileTarget::reopen()
@@ -92,24 +95,26 @@ prefix_ std::string const & senf::log::FileTarget::filename()
 prefix_ senf::log::FileTarget::RegisterConsole::RegisterConsole()
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    detail::TargetRegistry::instance().consoleDir().add("file-target",&RegisterConsole::create)
-        .arg("filename", "name of logfile")
-        .arg("nodename", "name of node in console. Defaults to the files basename",
-             kw::default_value = "")
-        .doc("Create new file target. Examples:\n"
-             "\n"
-             "Create new file target '/var/log/example.log\n"
-             "    $ file-target \"/var/log/example.log\"\n"
-             "    <Directory '/sys/log/example.log'>\n"
-             "\n"
-             "In a configuration file, create new file target '/var/log/example.log' and set\n"
-             "some parameters (If written on one line, this works at the console too:\n"
-             "    /sys/log/file-target \"/var/log/example.log\" mainlog {\n"
-             "        route (IMPORTANT);             # route all important messages\n"
-             "        timeFormat \"\";               # use non-formatted time format\n"
-             "        showArea false;                # don't show log area\n"
-             "    }\n");
+    detail::TargetRegistry::instance().consoleDir()
+        .add("file-target", fty::Command(&RegisterConsole::create)
+             .arg("filename", "name of logfile")
+             .arg("nodename", "name of node in console. Defaults to the files basename",
+                  kw::default_value = "")
+             .doc("Create new file target. Examples:\n"
+                  "\n"
+                  "Create new file target '/var/log/example.log\n"
+                  "    $ file-target \"/var/log/example.log\"\n"
+                  "    <Directory '/sys/log/example.log'>\n"
+                  "\n"
+                  "In a configuration file, create new file target '/var/log/example.log' and set\n"
+                  "some parameters (If written on one line, this works at the console too:\n"
+                  "    /sys/log/file-target \"/var/log/example.log\" mainlog {\n"
+                  "        route (IMPORTANT);             # route all important messages\n"
+                  "        timeFormat \"\";               # use non-formatted time format\n"
+                  "        showArea false;                # don't show log area\n"
+                  "    }\n") );
 }
 
 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
index 0f205a5..4fc05f8 100644 (file)
@@ -50,40 +50,41 @@ prefix_ senf::log::detail::LogFormat::LogFormat(console::ScopedDirectory<> & dir
       showStream_ (false), showLevel_ (true), showArea_ (true), timeBase_ (-1)
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
     timeFormat("%Y-%m-%d %H:%M:%S.%f-0000");
 
-    dir.add("showTime", senf::membind(&LogFormat::showTime, this))
-        .arg("flag","whether to display the time in log messages",
-             kw::default_value = true)
-        .doc("Set time display in log messages. If time display is enabled, see the 'timeFormat'\n"
-             "command to set the time format.");
-    dir.add("showStream", senf::membind(&LogFormat::showStream, this))
-        .arg("flag","whether to display the stream in log messages",
-             kw::default_value = true)
-        .doc("Set strean display in log messages.");
-    dir.add("showLevel", senf::membind(&LogFormat::showLevel, this))
-        .arg("flag","whether to display the log level in log messages",
-             kw::default_value = true)
-        .doc("Set log level display in log messages.");
-    dir.add("showArea", senf::membind(&LogFormat::showArea, this))
-        .arg("flag","whether to display the area in log messages",
-             kw::default_value = true)
-        .doc("Set area display in log messages.");
-    dir.add("timeFormat", senf::membind(&LogFormat::timeFormat, this))
-        .arg("format","time format")
-        .doc("Set time format. The time format is specified using a format string. This format\n"
-             "string follows the strftime format.\n"
-             "\n"
-             "As additional option, the format string may be set to the empty string. In this\n"
-             "case the time will be displayed as 'second.nanosecond' value. IN this case, the\n"
-             "time is displayed relative to the first message after changing the format.");
-    dir.add("tag", senf::membind(&LogFormat::tag, this))
-        .arg("tag","log message tag prefix")
-        .doc("Every log message is optionally prefixed with a tag value. This value defaults to\n"
-             "the executable name and pid.");
-    dir.add("format", senf::membind(&LogFormat::consoleFormat, this))
-        .doc("Show the current log message format.");
+    dir.add("showTime", fty::BoundCommand(this, &LogFormat::showTime)
+            .arg("flag","whether to display the time in log messages",
+                 kw::default_value = true)
+            .doc("Set time display in log messages. If time display is enabled, see the 'timeFormat'\n"
+                 "command to set the time format.") );
+    dir.add("showStream", fty::BoundCommand(this, &LogFormat::showStream)
+            .arg("flag","whether to display the stream in log messages",
+                 kw::default_value = true)
+            .doc("Set strean display in log messages.") );
+    dir.add("showLevel", fty::BoundCommand(this, &LogFormat::showLevel)
+            .arg("flag","whether to display the log level in log messages",
+                 kw::default_value = true)
+            .doc("Set log level display in log messages.") );
+    dir.add("showArea", fty::BoundCommand(this, &LogFormat::showArea)
+            .arg("flag","whether to display the area in log messages",
+                 kw::default_value = true)
+            .doc("Set area display in log messages.") );
+    dir.add("timeFormat", fty::BoundCommand(this, &LogFormat::timeFormat)
+            .arg("format","time format")
+            .doc("Set time format. The time format is specified using a format string. This format\n"
+                 "string follows the strftime format.\n"
+                 "\n"
+                 "As additional option, the format string may be set to the empty string. In this\n"
+                 "case the time will be displayed as 'second.nanosecond' value. IN this case, the\n"
+                 "time is displayed relative to the first message after changing the format.") );
+    dir.add("tag", fty::BoundCommand(this, &LogFormat::tag)
+            .arg("tag","log message tag prefix")
+            .doc("Every log message is optionally prefixed with a tag value. This value defaults to\n"
+                 "the executable name and pid.") );
+    dir.add("format", fty::BoundCommand(this, &LogFormat::consoleFormat)
+            .doc("Show the current log message format.") );
 }
 
 prefix_ void senf::log::detail::LogFormat::consoleFormat(std::ostream & os)
index dc49247..6aeec08 100644 (file)
@@ -59,25 +59,27 @@ namespace log {
 prefix_ senf::log::SyslogTarget::RegisterConsole::RegisterConsole()
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
-    detail::TargetRegistry::instance().consoleDir().add("syslog-target",&RegisterConsole::create)
-        .arg("facility", "syslog facility to send messages to. One of\n"
-             "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
-             "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
-             kw::default_value = USER)
-        .doc("Create new syslog target. Examples:\n"
-             "\n"
-             "Create new syslog target\n"
-             "    $ syslog-target\n"
-             "    <Directory '/sys/log/syslog'>\n"
-             "\n"
-             "In a configuration file, create new syslog target and set some parameters (If\n"
-             "written on one line, this works at the console too:\n"
-             "    /sys/log/syslog-target LOCAL2 {\n"
-             "        route (IMPORTANT);             # route all important messages\n"
-             "        timeFormat \"\";               # use non-formatted time format\n"
-             "        showArea false;                # don't show log area\n"
-             "    }\n");
+    detail::TargetRegistry::instance().consoleDir()
+        .add("syslog-target",fty::Command(&RegisterConsole::create)
+             .arg("facility", "syslog facility to send messages to. One of\n"
+                  "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+                  "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
+                  kw::default_value = USER)
+             .doc("Create new syslog target. Examples:\n"
+                  "\n"
+                  "Create new syslog target\n"
+                  "    $ syslog-target\n"
+                  "    <Directory '/sys/log/syslog'>\n"
+                  "\n"
+                  "In a configuration file, create new syslog target and set some parameters (If\n"
+                  "written on one line, this works at the console too:\n"
+                  "    /sys/log/syslog-target LOCAL2 {\n"
+                  "        route (IMPORTANT);             # route all important messages\n"
+                  "        timeFormat \"\";               # use non-formatted time format\n"
+                  "        showArea false;                # don't show log area\n"
+                  "    }\n") );
 }
 
 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
index d1e70a3..88b44ba 100644 (file)
 prefix_ void senf::log::SyslogUDPTarget::init()
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
     consoleDir().remove("format");
-    consoleDir().add("format", senf::membind(&SyslogUDPTarget::consoleFormat, this))
-        .doc("Show the current log message format.");
-    consoleDir().add("syslog", senf::membind(
-                         static_cast<void (SyslogUDPTarget::*)(bool)>(&SyslogUDPTarget::syslog),
-                         this))
-        .arg("flag","new syslog format state",
-             kw::default_value=true)
-        .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
-             "state, the udp target will send out minimal but valid syslog format messages.\n"
-             "\n"
-             "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
-             "sent using plain UDP.");
+    consoleDir()
+        .add("format", fty::BoundCommand(this, &SyslogUDPTarget::consoleFormat)
+             .doc("Show the current log message format.") );
+    consoleDir()
+        .add("syslog", fty::BoundCommand(this, SENF_MEMFNP(void, SyslogUDPTarget, syslog, (bool)))
+             .arg("flag","new syslog format state",
+                  kw::default_value=true)
+             .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
+                  "state, the udp target will send out minimal but valid syslog format messages.\n"
+                  "\n"
+                  "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
+                  "sent using plain UDP.") );
 }
 
 prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
@@ -108,49 +109,54 @@ namespace log {
 prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
 {
     namespace kw = senf::console::kw;
-
-    detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", 
-        static_cast<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &, LogFacility)>(
-            &RegisterConsole::create))
-        .arg("address", "target address to send log messages to")
-        .arg("facility", "syslog facility to send messages to. One of\n"
-             "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
-             "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
-             kw::default_value = USER)
-        .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
-             "number is omitted, it defaults to the default syslog port 514. Examples:\n"
-             "\n"
-             "Create new udp target sending messages to the syslog daemon running at localhost\n"
-             "    $ udp-target localhost\n"
-             "    <Directory '/sys/log/udp-127.0.0.1:514'>\n"
-             "\n"
-             "In a configuration file, create new udp target and set some parameters (If\n"
-             "written on one line, this works at the console too:\n"
-             "    /sys/log/udp-target localhost:2345 LOCAL2 {\n"
-             "        route (IMPORTANT);             # route all important messages\n"
-             "        timeFormat \"\";               # use non-formatted time format\n"
-             "        showArea false;                # don't show log area\n"
-             "        syslog false;                  # no syslog format, just plain udp\n"
-             "    }\n");
-    detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", 
-        static_cast<senf::console::DirectoryNode::ptr (*)(INet4Address const &, LogFacility)>(
-            &RegisterConsole::create))
-        .arg("address")
-        .arg("facility", kw::default_value = USER);
-    detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", 
-        static_cast<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &, LogFacility)>(
-            &RegisterConsole::create))
-        .arg("address")
-        .arg("facility", kw::default_value = USER);
-    detail::TargetRegistry::instance().consoleDir().add(
-        "udp-target", 
-        static_cast<senf::console::DirectoryNode::ptr (*)(INet6Address const &, LogFacility)>(
-            &RegisterConsole::create))
-        .arg("address")
-        .arg("facility", kw::default_value = USER);
+    namespace fty = senf::console::factory;
+
+    detail::TargetRegistry::instance().consoleDir()
+        .add("udp-target", 
+             fty::Command<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &, 
+                                                                LogFacility)
+             >(&RegisterConsole::create)
+             .arg("address", "target address to send log messages to")
+             .arg("facility", "syslog facility to send messages to. One of\n"
+                  "                  AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+                  "                  UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
+                  kw::default_value = USER)
+             .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
+                  "number is omitted, it defaults to the default syslog port 514. Examples:\n"
+                  "\n"
+                  "Create new udp target sending messages to the syslog daemon running at localhost\n"
+                  "    $ udp-target localhost\n"
+                  "    <Directory '/sys/log/udp-127.0.0.1:514'>\n"
+                  "\n"
+                  "In a configuration file, create new udp target and set some parameters (If\n"
+                  "written on one line, this works at the console too:\n"
+                  "    /sys/log/udp-target localhost:2345 LOCAL2 {\n"
+                  "        route (IMPORTANT);             # route all important messages\n"
+                  "        timeFormat \"\";               # use non-formatted time format\n"
+                  "        showArea false;                # don't show log area\n"
+                  "        syslog false;                  # no syslog format, just plain udp\n"
+                  "    }\n") );
+    detail::TargetRegistry::instance().consoleDir()
+        .add("udp-target", 
+             fty::Command<senf::console::DirectoryNode::ptr (*)(INet4Address const &, 
+                                                                LogFacility)
+             >(&RegisterConsole::create)
+             .arg("address")
+             .arg("facility", kw::default_value = USER) );
+    detail::TargetRegistry::instance().consoleDir()
+        .add("udp-target", 
+             fty::Command<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &, 
+                                                                LogFacility)
+             >(&RegisterConsole::create)
+             .arg("address")
+             .arg("facility", kw::default_value = USER) );
+    detail::TargetRegistry::instance().consoleDir()
+        .add("udp-target", 
+             fty::Command<senf::console::DirectoryNode::ptr (*)(INet6Address const &, 
+                                                                LogFacility)
+             >(&RegisterConsole::create)
+             .arg("address")
+             .arg("facility", kw::default_value = USER) );
 }
 
 prefix_ boost::shared_ptr<senf::console::DirectoryNode>
index 6b95524..a693279 100644 (file)
@@ -56,68 +56,75 @@ namespace detail {
 prefix_ senf::log::Target::Target(std::string const & name)
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
     detail::TargetRegistry::instance().registerTarget(this, name);
-    consoleDir_().add("list", senf::membind(&Target::consoleList, this))
-        .doc("Show routing table\n"
-             "\n"
-             "Columns:\n"
-             "    #       rule index\n"
-             "    STREAM  stream to match, empty to match all streams\n"
-             "    AREA    area to match, empty to match all targets\n"
-             "    LEVEL   match messages with level above this. Log levels in increasing order\n"
-             "            are:\n"
-             "                verbose, notice, message, important, critical, fatal\n"
-             "    ACTION  action to take: accept or reject");
-    consoleDir_().add("route", senf::membind(&Target::consoleRoute, this))
-        .arg("index", "index at which to insert new rule")
-        .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
-             "              and log level. You may specify any combination of these parameterse\n"
-             "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
-             "              to list all valid streams and areas. Valid log levels are:\n"
-             "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
-        .arg("action", "routing action, one of: ACCEPT, REJECT",
-             kw::default_value=ACCEPT)
-        .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
-             "with the first entry. The action of the first matching entry determines the\n"
-             "handling of the message.\n"
-             "\n"
-             "Examples:\n"
-             "\n"
-             "    route ()\n"
-             "        route all messages to this target.\n"
-             "\n"
-             "    route 1 (my::Class)\n"
-             "        route all messages which are in the my::Class area. Insert this route after\n"
-             "        the first route,\n"
-             "\n"
-             "    route (senf::log::Debug VERBOSE) REJECT\n"
-             "    route (VERBOSE)\n"
-             "        route all messages not in the senf::log::Debug stream to the current area.\n"
-             "\n"
-             "The additional optional index argument identifies the position in the routing table\n"
-             "where the new routing entry will be added. Positive numbers count from the\n"
-             "beginning, 0 being the first routing entry. Negative values count from the end.");
-    consoleDir_().add("route", boost::function<void (detail::LogParameters, action_t)>(
-                          boost::bind(&Target::consoleRoute, this, -1, _1, _2)))
-        .arg("parameters")
-        .arg("action", kw::default_value=ACCEPT);
-    consoleDir_().add("unroute",
-                      senf::membind(static_cast<void (Target::*)(int)>(&Target::unroute), this))
-        .arg("index", "index of routing entry to remove")
-        .overloadDoc("Remove routing entry with the given index");
-    consoleDir_().add("unroute", senf::membind(&Target::consoleUnroute, this))
-        .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
-             "              and log level. You may specify any combination of these parameterse\n"
-             "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
-             "              to list all valid streams and areas. Valid log levels are:\n"
-             "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
-        .arg("action", "routing action, one of: ACCEPT, REJECT",
-             kw::default_value=ACCEPT)
-        .overloadDoc("Remove the routing entry matching the specified arguments.");
-    consoleDir_().add("flush", senf::membind(&Target::flush, this))
-        .doc("Remove all routing entries clearing the routing table. This will disable all\n"
-             "logging output on this target.");
+    consoleDir_()
+        .add("list", fty::BoundCommand(this, &Target::consoleList)
+             .doc("Show routing table\n"
+                  "\n"
+                  "Columns:\n"
+                  "    #       rule index\n"
+                  "    STREAM  stream to match, empty to match all streams\n"
+                  "    AREA    area to match, empty to match all targets\n"
+                  "    LEVEL   match messages with level above this. Log levels in increasing order\n"
+                  "            are:\n"
+                  "                verbose, notice, message, important, critical, fatal\n"
+                  "    ACTION  action to take: accept or reject") );
+    consoleDir_()
+        .add("route", fty::BoundCommand(this, &Target::consoleRoute)
+             .arg("index", "index at which to insert new rule")
+             .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+                  "              and log level. You may specify any combination of these parameterse\n"
+                  "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+                  "              to list all valid streams and areas. Valid log levels are:\n"
+                  "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
+             .arg("action", "routing action, one of: ACCEPT, REJECT",
+                  kw::default_value=ACCEPT)
+             .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
+                  "with the first entry. The action of the first matching entry determines the\n"
+                  "handling of the message.\n"
+                  "\n"
+                  "Examples:\n"
+                  "\n"
+                  "    route ()\n"
+                  "        route all messages to this target.\n"
+                  "\n"
+                  "    route 1 (my::Class)\n"
+                  "        route all messages which are in the my::Class area. Insert this route after\n"
+                  "        the first route,\n"
+                  "\n"
+                  "    route (senf::log::Debug VERBOSE) REJECT\n"
+                  "    route (VERBOSE)\n"
+                  "        route all messages not in the senf::log::Debug stream to the current area.\n"
+                  "\n"
+                  "The additional optional index argument identifies the position in the routing table\n"
+                  "where the new routing entry will be added. Positive numbers count from the\n"
+                  "beginning, 0 being the first routing entry. Negative values count from the end.") );
+    consoleDir_()
+        .add("route", fty::Command<void (detail::LogParameters, action_t)>(
+                 boost::bind(&Target::consoleRoute, this, -1, _1, _2))
+             .arg("parameters")
+             .arg("action", kw::default_value=ACCEPT) );
+    consoleDir_()
+        .add("unroute",
+             fty::BoundCommand(this, static_cast<void (Target::*)(int)>(&Target::unroute))
+             .arg("index", "index of routing entry to remove")
+             .overloadDoc("Remove routing entry with the given index") );
+    consoleDir_()
+        .add("unroute", fty::BoundCommand(this, &Target::consoleUnroute)
+             .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+                  "              and log level. You may specify any combination of these parameterse\n"
+                  "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+                  "              to list all valid streams and areas. Valid log levels are:\n"
+                  "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
+             .arg("action", "routing action, one of: ACCEPT, REJECT",
+                  kw::default_value=ACCEPT)
+             .overloadDoc("Remove the routing entry matching the specified arguments.") );
+    consoleDir_()
+        .add("flush", fty::BoundCommand(this, &Target::flush)
+             .doc("Remove all routing entries clearing the routing table. This will disable all\n"
+                  "logging output on this target.") );
 }
 
 prefix_ senf::log::Target::~Target()
@@ -352,10 +359,12 @@ prefix_ void senf::log::Target::consoleUnroute(detail::LogParameters const & pm,
 
 prefix_ void senf::log::detail::TargetRegistry::dynamicTarget(std::auto_ptr<Target> target)
 {
-    target->consoleDir().add("remove", boost::function<void ()>(
-                                 boost::bind(
-                                     &TargetRegistry::consoleRemoveTarget, this, target.get())))
-        .doc("Remove target.");
+    namespace fty = senf::console::factory;
+
+    target->consoleDir()
+        .add("remove", fty::Command<void ()>(
+                 boost::bind(&TargetRegistry::consoleRemoveTarget, this, target.get()))
+             .doc("Remove target.") );
     dynamicTargets_.insert(target.release());
 }
 
@@ -389,36 +398,41 @@ prefix_ senf::log::detail::TargetRegistry::TargetRegistry()
     : fallbackRouting_(true)
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
 
     console::sysdir().add("log", consoleDir_());
-    consoleDir_().add("areas", senf::membind(&TargetRegistry::consoleAreas, this))
-        .doc("List all areas");
-    consoleDir_().add("streams", senf::membind(&TargetRegistry::consoleStreams, this))
-        .doc("List all streams");
-    consoleDir_().add("message", senf::membind(&TargetRegistry::consoleWrite, this))
-        .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
-             "              and log level. You may specify any combination of these parameterse\n"
-             "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
-             "              to list all valid streams and areas. Valid log levels are:\n"
-             "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL",
-             kw::default_value = LogParameters::defaultParameters())
-        .arg("message", "message to write")
-        .doc("Write log message.\n"
-             "\n"
-             "Examples:\n"
-             "    message \"Test\";\n"
-             "    message (senf::log::DefaultArea NOTICE) \"Test notice\";\n"
-             "    message (FATAL) \"Program on fire\";\n"
-             "    message (VERBOSE senf::log::Debug) \"Debug message\";");
-    consoleDir_().add("self", senf::membind(&TargetRegistry::consoleSelf, this))
-        .doc("Get the log directory of the current network client. Example usage:\n"
-             "\n"
-             "Just get the log config directory\n"
-             "    $ /sys/log/self\n"
-             "    <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n"
-             "\n"
-             "Route all messages to the currently connected client\n"
- "    $ /sys/log/self { route (); }");
+    consoleDir_()
+        .add("areas", fty::BoundCommand(this, &TargetRegistry::consoleAreas)
+             .doc("List all areas") );
+    consoleDir_()
+        .add("streams", fty::BoundCommand(this, &TargetRegistry::consoleStreams)
+             .doc("List all streams") );
+    consoleDir_()
+        .add("message", fty::BoundCommand(this, &TargetRegistry::consoleWrite)
+             .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+                  "              and log level. You may specify any combination of these parameterse\n"
+                  "              in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+                  "              to list all valid streams and areas. Valid log levels are:\n"
+                  "                  VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL",
+                  kw::default_value = LogParameters::defaultParameters())
+             .arg("message", "message to write")
+             .doc("Write log message.\n"
+                  "\n"
+                  "Examples:\n"
+                  "    message \"Test\";\n"
+                  "    message (senf::log::DefaultArea NOTICE) \"Test notice\";\n"
+                  "    message (FATAL) \"Program on fire\";\n"
+                  "    message (VERBOSE senf::log::Debug) \"Debug message\";") );
+    consoleDir_()
+        .add("self", fty::BoundCommand(this, &TargetRegistry::consoleSelf)
+             .doc("Get the log directory of the current network client. Example usage:\n"
+                  "\n"
+                  "Just get the log config directory\n"
+                  "    $ /sys/log/self\n"
+                  "    <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n"
+                  "\n"
+                  "Route all messages to the currently connected client\n"
+                  "    $ /sys/log/self { route () ); }") );
 }
 
 prefix_ senf::log::detail::TargetRegistry::~TargetRegistry()
index 079bb3c..2efca87 100644 (file)
@@ -153,58 +153,60 @@ prefix_ senf::Statistics::Statistics()
 #endif
 {
 #ifndef SENF_DISABLE_CONSOLE
-    dir.add("list", &Statistics::consoleList)
-        .doc("List statistics collection intervals and current values.\n"
-             "\n"
-             "Columns:\n"
-             "    RANK    Number of values collected. Since the statistics collectors form\n"
-             "            a tree, the value is indented according to it's tree location.\n"
-             "    WIN     Size of output average window.\n"
-             "    MIN     Last entered minimum value.\n"
-             "    AVG     Last entered average value.\n"
-             "    DEV     Standard deviation of average value over the collector rank.\n"
-             "    MAX     Last entered maximum value.");
-    dir.add("collect", &Statistics::consoleCollect)
-        .doc("Add statistics collection groups. The argument gives a sequence of collector\n"
-             "ranks each building on the preceding collector:\n"
-             "\n"
-             "    $ collect (10 60 60)\n"
-             "\n"
-             "Will start by collecting every 10 values together to a new value. 60 of such\n"
-             "combined values will be collected together in the next step again followed by\n"
-             "a collection of 60 values. If the statistics is entered with a frequency of\n"
-             "10 values per second, this will provide combined statistics over the second,\n"
-             "minutes and hours ranges.\n"
-             "\n"
-             "You may call collect multiple times. Any missing collection ranks will be\n"
-             "added.")
-        .arg("ranks","chain of collector ranks");
-    dir.add("output", &Statistics::consoleOutput)
-        .doc("Generate statistics output. This statement will add an additional output\n"
-             "generator. This generator will be attached to the collector specified by\n"
-             "the {rank} parameter. This parameter is a chain of successive rank values\n"
-             "which specifies the exact collector to use. If the collector does not\n"
-             "exist, it will be created (this is like automatically calling 'collect'\n"
-             "with {rank} as argument).\n"
-             "\n"
-             "If the output is to be sent somewhere it must be connected to a statistics\n"
-             "target.\n"
-             "\n"
-             "The output may optionally be built using a sliding average over the last\n"
-             "{window} values.\n"
-             "\n"
-             "    $ output ()\n"
-             "\n"
-             "will output the basic statistics value each time a new value is entered.\n"
-             "\n"
-             "    $ output (10 60) 5\n"
-             "\n"
-             "Assuming that new data values are entered 10 times per second, this command\n"
-             "will generate output once every minute. The value will be the average over\n"
-             "the last 5 minutes.")
-        .arg("rank","Rank chain selecting the value to generate output for")
-        .arg("window","Optional size of sliding average window",
-             senf::console::kw::default_value = 1u);
+    namespace fty = senf::console::factory;
+
+    dir.add("list", fty::BoundCommand(this,&Statistics::consoleList)
+            .doc("List statistics collection intervals and current values.\n"
+                 "\n"
+                 "Columns:\n"
+                 "    RANK    Number of values collected. Since the statistics collectors form\n"
+                 "            a tree, the value is indented according to it's tree location.\n"
+                 "    WIN     Size of output average window.\n"
+                 "    MIN     Last entered minimum value.\n"
+                 "    AVG     Last entered average value.\n"
+                 "    DEV     Standard deviation of average value over the collector rank.\n"
+                 "    MAX     Last entered maximum value.") );
+    dir.add("collect", fty::BoundCommand(this, &Statistics::consoleCollect)
+            .doc("Add statistics collection groups. The argument gives a sequence of collector\n"
+                 "ranks each building on the preceding collector:\n"
+                 "\n"
+                 "    $ collect (10 60 60)\n"
+                 "\n"
+                 "Will start by collecting every 10 values together to a new value. 60 of such\n"
+                 "combined values will be collected together in the next step again followed by\n"
+                 "a collection of 60 values. If the statistics is entered with a frequency of\n"
+                 "10 values per second, this will provide combined statistics over the second,\n"
+                 "minutes and hours ranges.\n"
+                 "\n"
+                 "You may call collect multiple times. Any missing collection ranks will be\n"
+                 "added.")
+            .arg("ranks","chain of collector ranks") );
+    dir.add("output", fty::BoundCommand(this, &Statistics::consoleOutput)
+            .doc("Generate statistics output. This statement will add an additional output\n"
+                 "generator. This generator will be attached to the collector specified by\n"
+                 "the {rank} parameter. This parameter is a chain of successive rank values\n"
+                 "which specifies the exact collector to use. If the collector does not\n"
+                 "exist, it will be created (this is like automatically calling 'collect'\n"
+                 "with {rank} as argument).\n"
+                 "\n"
+                 "If the output is to be sent somewhere it must be connected to a statistics\n"
+                 "target.\n"
+                 "\n"
+                 "The output may optionally be built using a sliding average over the last\n"
+                 "{window} values.\n"
+                 "\n"
+                 "    $ output ()\n"
+                 "\n"
+                 "will output the basic statistics value each time a new value is entered.\n"
+                 "\n"
+                 "    $ output (10 60) 5\n"
+                 "\n"
+                 "Assuming that new data values are entered 10 times per second, this command\n"
+                 "will generate output once every minute. The value will be the average over\n"
+                 "the last 5 minutes.")
+            .arg("rank","Rank chain selecting the value to generate output for")
+            .arg("window","Optional size of sliding average window",
+                 senf::console::kw::default_value = 1u) );
 #endif
 }
 
index 0ed4fbd..6fd93a5 100644 (file)
@@ -65,8 +65,10 @@ prefix_ senf::StatisticsBase::OutputEntry::OutputEntry(const OutputEntry& other)
 
 prefix_ void senf::StatisticsBase::OutputEntry::initDir()
 {
-    dir.add("list", senf::membind(&OutputEntry::consoleList, this))
-        .doc("List all known connected targets. This list might not be complete.");
+    namespace fty = senf::console::factory;
+
+    dir.add("list", fty::BoundCommand(this,&OutputEntry::consoleList)
+            .doc("List all known connected targets. This list might not be complete.") );
 }
 
 prefix_ senf::StatisticsBase::OutputEntry &
index f771789..712844f 100644 (file)
@@ -79,12 +79,13 @@ prefix_ void RegisterStatisticsLogger::adder(senf::StatisticsBase & stats,
                                              senf::console::DirectoryNode & dir)
 {
     namespace kw = senf::console::kw;
+    namespace fty = senf::console::factory;
     
-    dir.add("logger", boost::function<void (std::string const &)>(
-               boost::bind(&consoleCreate, boost::ref(stats), rank, _1)))
-       .arg("prefix","Optional prefix string to add to each log message",
-            kw::default_value = "")
-       .doc("Send log messages to statistics log stream");
+    dir.add("logger", fty::Command<void (std::string const &)>(
+                boost::bind(&consoleCreate, boost::ref(stats), rank, _1))
+            .arg("prefix","Optional prefix string to add to each log message",
+                 kw::default_value = "")
+            .doc("Send log messages to statistics log stream") );
 }
 
 prefix_ void RegisterStatisticsLogger::consoleCreate(senf::StatisticsBase & stats,