From: g0dil Date: Mon, 1 Feb 2010 14:44:21 +0000 (+0000) Subject: Utils/Console: Fix DirectoryNode::add(...) API X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=f13780e9e4da7df981d6f6542fbdc714beb34765;hp=6019c18e7b74d3e91293f35df660a80346ef7a1e;p=senf.git Utils/Console: Fix DirectoryNode::add(...) API git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1558 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/senf/PPI/Connectors.cc b/senf/PPI/Connectors.cc index 065d36f..04ce2bd 100644 --- a/senf/PPI/Connectors.cc +++ b/senf/PPI/Connectors.cc @@ -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: \n" - " on connector \n" - " PPI throttling trace: \n" - " on connector \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: \n" + " on connector \n" + " PPI throttling trace: \n" + " on connector \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; diff --git a/senf/PPI/ModuleManager.cc b/senf/PPI/ModuleManager.cc index 3d2b3d5..66190d4 100644 --- a/senf/PPI/ModuleManager.cc +++ b/senf/PPI/ModuleManager.cc @@ -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 \\\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 \\\n" + " | python PPI/drawmodules.py | dot -Tpng /dev/fd/0 >modules.png\n") + ); } prefix_ void senf::ppi::ModuleManager::dumpModules(std::ostream & os) diff --git a/senf/Scheduler/EventManager.cc b/senf/Scheduler/EventManager.cc index ec4d1be..4dd2064 100644 --- a/senf/Scheduler/EventManager.cc +++ b/senf/Scheduler/EventManager.cc @@ -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 diff --git a/senf/Socket/Protocols/DVB/DVBProtocolWrapper.cc b/senf/Socket/Protocols/DVB/DVBProtocolWrapper.cc index 0d615ca..42dd6b5 100644 --- a/senf/Socket/Protocols/DVB/DVBProtocolWrapper.cc +++ b/senf/Socket/Protocols/DVB/DVBProtocolWrapper.cc @@ -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, 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, + 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)>(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) + >(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//////////////////////////////////////// diff --git a/senf/Socket/Protocols/DVB/DVBSocketController.cc b/senf/Socket/Protocols/DVB/DVBSocketController.cc index a24d566..c72ba15 100644 --- a/senf/Socket/Protocols/DVB/DVBSocketController.cc +++ b/senf/Socket/Protocols/DVB/DVBSocketController.cc @@ -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//////////////////////////////////////// diff --git a/senf/Utils/Console/Config.test.cc b/senf/Utils/Console/Config.test.cc index d319966..a952491 100644 --- a/senf/Utils/Console/Config.test.cc +++ b/senf/Utils/Console/Config.test.cc @@ -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; diff --git a/senf/Utils/Console/ConfigFile.test.cc b/senf/Utils/Console/ConfigFile.test.cc index ddb9067..5d424c0 100644 --- a/senf/Utils/Console/ConfigFile.test.cc +++ b/senf/Utils/Console/ConfigFile.test.cc @@ -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); diff --git a/senf/Utils/Console/Executor.test.cc b/senf/Utils/Console/Executor.test.cc index 0826459..551c0ab 100644 --- a/senf/Utils/Console/Executor.test.cc +++ b/senf/Utils/Console/Executor.test.cc @@ -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 diff --git a/senf/Utils/Console/Node.cci b/senf/Utils/Console/Node.cci index c7107f1..61c3646 100644 --- a/senf/Utils/Console/Node.cci +++ b/senf/Utils/Console/Node.cci @@ -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(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_ diff --git a/senf/Utils/Console/Node.cti b/senf/Utils/Console/Node.cti index b7f118b..260c9a3 100644 --- a/senf/Utils/Console/Node.cti +++ b/senf/Utils/Console/Node.cti @@ -31,18 +31,6 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::console::NodeCreateTraits::Creator - -template -prefix_ typename senf::console::NodeCreateTraits::result_type -senf::console::NodeCreateTraits::Creator::create(DirectoryNode & node, - std::string const & name, - Object & ob) -{ - return senf_console_add_node(node, name, ob, 0); -} - -/////////////////////////////////////////////////////////////////////////// // senf::console::DirectoryNode template @@ -55,18 +43,22 @@ prefix_ NodeType & senf::console::DirectoryNode::add(std::string const & name, return *node; } -template -prefix_ typename senf::console::NodeCreateTraits::result_type -senf::console::DirectoryNode::add(std::string const & name, Object const & ob) +template +prefix_ NodeType & senf::console::DirectoryNode:: +add(std::string const & name, NodeType & node, + typename boost::enable_if< boost::is_convertible >::type *) { - return NodeCreateTraits::Creator::create(*this, name, ob); + // This makes objects with implicit conversion operators work (hi, ScopedDirectory ..) + add(name, static_cast(node).thisptr()); + return node; } -template -prefix_ typename senf::console::NodeCreateTraits::result_type -senf::console::DirectoryNode::add(std::string const & name, Object & ob) +template +prefix_ typename Factory::result_type senf::console::DirectoryNode:: +add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type *) { - return NodeCreateTraits::Creator::create(*this, name, ob); + return factory.create(*this, name); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/senf/Utils/Console/Node.hh b/senf/Utils/Console/Node.hh index 3158023..0b854fb 100644 --- a/senf/Utils/Console/Node.hh +++ b/senf/Utils/Console/Node.hh @@ -204,8 +204,6 @@ #include #include #include -#include -#include #include #include #include @@ -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 - struct NodeCreateTraits - { - typedef BOOST_TYPEOF_TPL( senf_console_add_node( - * static_cast(0), - * static_cast(0), - * static_cast(0), - 0) ) base_type; - typedef typename senf::remove_cvref::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 - typename NodeCreateTraits::result_type add(std::string const & name, - Object const & ob); + template + NodeType & add(std::string const & name, NodeType & node, + typename boost::enable_if< boost::is_convertible >::type * = 0); + + template + typename Factory::result_type add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::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 - senf_console_add_node 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 - typename NodeCreateTraits::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 - struct NodeCreateTraits< boost::shared_ptr > - {}; -#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" diff --git a/senf/Utils/Console/Node.test.cc b/senf/Utils/Console/Node.test.cc index e837142..be5964c 100644 --- a/senf/Utils/Console/Node.test.cc +++ b/senf/Utils/Console/Node.test.cc @@ -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(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; diff --git a/senf/Utils/Console/OverloadedCommand.cc b/senf/Utils/Console/OverloadedCommand.cc index c9e7529..8205ec5 100644 --- a/senf/Utils/Console/OverloadedCommand.cc +++ b/senf/Utils/Console/OverloadedCommand.cc @@ -35,6 +35,19 @@ /////////////////////////////////////////////////////////////////////////// // 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(dir(name)) + : dir.add(name, OverloadedCommandNode::create())); + node.add(overload); + return node; +} + /////////////////////////////////////////////////////////////////////////// // So soll die doku aussehen: // diff --git a/senf/Utils/Console/OverloadedCommand.cci b/senf/Utils/Console/OverloadedCommand.cci index c891fda..8a5c382 100644 --- a/senf/Utils/Console/OverloadedCommand.cci +++ b/senf/Utils/Console/OverloadedCommand.cci @@ -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_ diff --git a/senf/Utils/Console/OverloadedCommand.hh b/senf/Utils/Console/OverloadedCommand.hh index 349159c..ab339f3 100644 --- a/senf/Utils/Console/OverloadedCommand.hh +++ b/senf/Utils/Console/OverloadedCommand.hh @@ -31,6 +31,7 @@ #include #include #include +#include //#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 doc_; + mutable boost::optional shortdoc_; + }; + +namespace factory { + + SimpleOverloadAttributor Command(SimpleCommandOverload::Function fn); + +}}} ///////////////////////////////hh.e//////////////////////////////////////// #include "OverloadedCommand.cci" diff --git a/senf/Utils/Console/ParsedCommand.cci b/senf/Utils/Console/ParsedCommand.cci index 5d168ec..5c71e65 100644 --- a/senf/Utils/Console/ParsedCommand.cci +++ b/senf/Utils/Console/ParsedCommand.cci @@ -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/////////////////////////////////////// diff --git a/senf/Utils/Console/ParsedCommand.cti b/senf/Utils/Console/ParsedCommand.cti index 2ef3adc..43a2cff 100644 --- a/senf/Utils/Console/ParsedCommand.cti +++ b/senf/Utils/Console/ParsedCommand.cti @@ -85,19 +85,23 @@ prefix_ Overload & senf::console::ParsedCommandAttributor::overload() } template -prefix_ -senf::console::ParsedCommandAttributor::ParsedCommandAttributor(Overload & overload, - unsigned index) +prefix_ senf::console::ParsedCommandAttributor:: +ParsedCommandAttributor(typename Overload::ptr overload, unsigned index) : ParsedCommandAttributorBase (overload, index) {} +template +prefix_ senf::console::ParsedCommandAttributor:: +ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index) + : ParsedCommandAttributorBase (other, index) +{} + /////////////////////////////////////////////////////////////////////////// // senf::console::ParsedArgumentAttributorBase template prefix_ Self senf::console::ParsedArgumentAttributorBase::doc(std::string const & doc) - const { this->ParsedCommandAttributorBase::nodeDoc(doc); return static_cast(*this); @@ -106,7 +110,6 @@ senf::console::ParsedArgumentAttributorBase::doc(std:: template prefix_ Self senf::console::ParsedArgumentAttributorBase:: shortdoc(std::string const & doc) - const { this->ParsedCommandAttributorBase::shortDoc(doc); return static_cast(*this); @@ -115,7 +118,6 @@ shortdoc(std::string const & doc) template prefix_ Self senf::console::ParsedArgumentAttributorBase:: overloadDoc(std::string const & doc) - const { this->ParsedCommandAttributorBase::overloadDoc(doc); return static_cast(*this); @@ -124,7 +126,6 @@ overloadDoc(std::string const & doc) template prefix_ Self senf::console::ParsedArgumentAttributorBase:: formatter(typename Overload::Formatter f) - const { this->overload().formatter(f); return static_cast(*this); @@ -133,14 +134,20 @@ formatter(typename Overload::Formatter f) template prefix_ senf::console::ParsedArgumentAttributorBase:: -ParsedArgumentAttributorBase(Overload & overload, unsigned index) +ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index) : ParsedCommandAttributor (overload, index) {} +template +prefix_ +senf::console::ParsedArgumentAttributorBase:: +ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index) + : ParsedCommandAttributor (other, index) +{} + template prefix_ Self senf::console::ParsedArgumentAttributorBase::doc(std::string const & doc) - const { this->ParsedCommandAttributorBase::nodeDoc(doc); return static_cast(*this); @@ -149,7 +156,6 @@ senf::console::ParsedArgumentAttributorBase::doc(std::string template prefix_ Self senf::console::ParsedArgumentAttributorBase:: shortdoc(std::string const & doc) - const { this->ParsedCommandAttributorBase::shortDoc(doc); return static_cast(*this); @@ -158,7 +164,6 @@ shortdoc(std::string const & doc) template prefix_ Self senf::console::ParsedArgumentAttributorBase:: overloadDoc(std::string const & doc) - const { this->ParsedCommandAttributorBase::overloadDoc(doc); return static_cast(*this); @@ -166,11 +171,18 @@ overloadDoc(std::string const & doc) template prefix_ -senf::console::ParsedArgumentAttributorBase:: -ParsedArgumentAttributorBase(Overload & overload, unsigned index) +senf::console::ParsedArgumentAttributorBase:: +ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index) : ParsedCommandAttributor (overload, index) {} +template +prefix_ +senf::console::ParsedArgumentAttributorBase:: +ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index) + : ParsedCommandAttributor (other, index) +{} + /////////////////////////////////////////////////////////////////////////// // senf::console::ParsedArgumentAttributor @@ -187,7 +199,6 @@ template prefix_ typename senf::console::ParsedArgumentAttributor::next_type senf::console::ParsedArgumentAttributor:: argInfo(ArgumentPack const & args) - const { # define ProcessArg(tag) \ argInfo( kw:: tag, args, senf::has_parameter< ArgumentPack, kw::type:: tag >() ) @@ -208,7 +219,6 @@ template template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_) - const {} template @@ -216,7 +226,6 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { this->argName(args[kw::name]); } @@ -226,7 +235,6 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { this->argDoc(args[kw::description]); } @@ -236,7 +244,6 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { this->defaultValue(args[kw::default_value]); } @@ -246,7 +253,6 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { this->typeName(args[kw::type_name]); } @@ -256,7 +262,6 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { BOOST_STATIC_ASSERT(( senf::has_parameter::value )); this->defaultDoc(args[kw::default_doc]); @@ -267,16 +272,20 @@ template prefix_ void senf::console::ParsedArgumentAttributor:: argInfo(boost::parameter::keyword const &, ArgumentPack const & args, boost::mpl::true_) - const { this->parser(args[kw::parser]); } template -prefix_ -senf::console::ParsedArgumentAttributor:: -ParsedArgumentAttributor(Overload & overload) - : ParsedArgumentAttributorBase (overload, index) +prefix_ senf::console::ParsedArgumentAttributor:: +ParsedArgumentAttributor(typename Overload::ptr overload) +: ParsedArgumentAttributorBase (overload, index) +{} + +template +prefix_ senf::console::ParsedArgumentAttributor:: +ParsedArgumentAttributor(ParsedCommandAttributorBase const & other) + : ParsedArgumentAttributorBase (other, index) {} template @@ -284,13 +293,12 @@ prefix_ typename senf::console::ParsedArgumentAttributor::n senf::console::ParsedArgumentAttributor::next() const { - return ParsedArgumentAttributor(this->overload()); + return ParsedArgumentAttributor(*this); } template prefix_ void senf::console::ParsedArgumentAttributor:: defaultValue(value_type const & value) - const { this->overload().arg().defaultValue = value; this->overload().arg(index).hasDefault = true; @@ -299,7 +307,6 @@ defaultValue(value_type const & value) template template prefix_ void senf::console::ParsedArgumentAttributor::parser(Fn fn) - const { this->overload().arg().parser = fn; } @@ -310,11 +317,18 @@ prefix_ void senf::console::ParsedArgumentAttributor::parse template prefix_ senf::console::ParsedArgumentAttributor:: -ParsedArgumentAttributor(Overload & overload) +ParsedArgumentAttributor(typename Overload::ptr overload) : ParsedArgumentAttributorBase< Overload, ParsedArgumentAttributor > (overload, index) {} +template +prefix_ +senf::console::ParsedArgumentAttributor:: +ParsedArgumentAttributor(ParsedCommandAttributorBase const & other) + : ParsedArgumentAttributorBase (other, index) +{} + /////////////////////////////////////////////////////////////////////////// // namespace members @@ -326,97 +340,86 @@ namespace detail { struct ParsedCommandAddNodeAccess { - template - 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 - struct CreateParsedCommandOverload - {}; - - template - struct CreateParsedCommandOverload - { - typedef typename Traits::traits traits; - - template - static typename senf::console::ParsedCommandOverload::ptr create(Function fn) - { return senf::console::ParsedCommandOverload::create(fn); }; + template + 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 typename senf::console::detail::ParsedCommandTraits::Attributor - addOverloadedCommandNode(senf::console::DirectoryNode & node, std::string const & name, Fn fn) + addOverloadedCommandNode(Fn fn) { - senf::console::OverloadedCommandNode & cmdNode ( - node.hasChild(name) - ? dynamic_cast(node(name)) - : node.add(name, senf::console::OverloadedCommandNode::create()) ); - typedef senf::console::detail::ParsedCommandTraits CmdTraits; typedef senf::console::ParsedCommandOverload Overload; typedef senf::console::ParsedArgumentAttributor Attributor; - return senf::console::detail::ParsedCommandAddNodeAccess::attributor( - cmdNode.add( CreateParsedCommandOverload::create(fn) ) ); + return detail::ParsedCommandAddNodeAccess::attributor( + CreateParsedCommandOverload::create(fn)); } #endif }}} -#ifndef DOXYGEN +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::Command(boost::function fn) +{ + return detail::addOverloadedCommandNode(fn); +} -template -typename senf::console::detail::ParsedCommandTraits::Attributor -senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name, - Function fn, int, - typename boost::enable_if_c::is_callable>::type *) +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory:: +Command(Function fn, + typename boost::enable_if_c::is_callable>::type *) { - return senf::console::detail::addOverloadedCommandNode(node, name, fn); + return detail::addOverloadedCommandNode(fn); } template -typename senf::console::detail::ParsedCommandTraits::Attributor -senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name, - boost::function fn, int) +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::Command(boost::function fn) { - return senf::console::detail::addOverloadedCommandNode(node, name, fn); + return detail::addOverloadedCommandNode(fn); } -template -typename senf::console::detail::ParsedCommandTraits::Attributor -senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, - Function fn, int, - typename boost::enable_if_c::is_member>::type *) +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory:: +Command(Function fn, + typename boost::enable_if_c::is_callable>::type *) { - return senf::console::detail::addOverloadedCommandNode( - node, name, senf::membind(fn,&owner)); + return detail::addOverloadedCommandNode(fn); } -#endif +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::BoundCommand(Owner * owner, Member memfn) +{ + return detail::addOverloadedCommandNode(senf::membind(memfn,owner)); +} + +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::BoundCommand(Owner const * owner, Member memfn) +{ + return detail::addOverloadedCommandNode(senf::membind(memfn,owner)); +} + +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::BoundCommand(Owner * owner, Member memfn) +{ + return detail::addOverloadedCommandNode(senf::membind(memfn,owner)); +} + +template +prefix_ typename senf::console::detail::ParsedCommandTraits::Attributor +senf::console::factory::BoundCommand(Owner const * owner, Member memfn) +{ + return detail::addOverloadedCommandNode(senf::membind(memfn,owner)); +} ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/senf/Utils/Console/ParsedCommand.hh b/senf/Utils/Console/ParsedCommand.hh index 0fdccd7..ce9cad5 100644 --- a/senf/Utils/Console/ParsedCommand.hh +++ b/senf/Utils/Console/ParsedCommand.hh @@ -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 doc_; + boost::optional 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 { 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 { 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 ParsedArgumentAttributor : public ParsedArgumentAttributorBase< Overload, ParsedArgumentAttributor > @@ -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 - next_type argInfo(ArgumentPack const & args) const; + next_type argInfo(ArgumentPack const & args); template - void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_) - const; + void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_); template void argInfo(boost::parameter::keyword const &, - ArgumentPack const & args, boost::mpl::true_) - const; + ArgumentPack const & args, boost::mpl::true_); template void argInfo(boost::parameter::keyword const &, - ArgumentPack const & args, boost::mpl::true_) - const; + ArgumentPack const & args, boost::mpl::true_); template void argInfo(boost::parameter::keyword const &, - ArgumentPack const & args, boost::mpl::true_) - const; + ArgumentPack const & args, boost::mpl::true_); template void argInfo(boost::parameter::keyword const &, - ArgumentPack const & args, boost::mpl::true_) - const; + ArgumentPack const & args, boost::mpl::true_); template void argInfo(boost::parameter::keyword const &, - ArgumentPack const & args, boost::mpl::true_) - const; + ArgumentPack const & args, boost::mpl::true_); template void argInfo(boost::parameter::keyword 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 void parser(Fn fn) const; + void defaultValue(value_type const & value); + template void parser(Fn fn); template 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 friend class ParsedArgumentAttributor; @@ -566,33 +568,46 @@ namespace console { friend class detail::ParsedCommandAddNodeAccess; }; - template - typename detail::ParsedCommandTraits::Attributor - senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int, - typename boost::enable_if_c< - detail::ParsedCommandTraits::is_callable>::type * = 0); +#endif + +namespace factory { + + template + typename senf::console::detail::ParsedCommandTraits::Attributor + Command(boost::function fn); + + template + typename senf::console::detail::ParsedCommandTraits::Attributor + Command(Function fn, + typename boost::enable_if_c::is_callable>::type * = 0); template - typename detail::ParsedCommandTraits::Attributor - senf_console_add_node(DirectoryNode & node, std::string const & name, - boost::function fn, int); + typename senf::console::detail::ParsedCommandTraits::Attributor + Command(boost::function fn); - template - typename detail::ParsedCommandTraits::Attributor - senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, - Function fn, int, - typename boost::enable_if_c< - detail::ParsedCommandTraits::is_member>::type * = 0); + template + typename senf::console::detail::ParsedCommandTraits::Attributor + Command(Function fn, + typename boost::enable_if_c::is_callable>::type * = 0); -#endif + template + typename senf::console::detail::ParsedCommandTraits::Attributor + BoundCommand(Owner * owner, Member memfn); + + template + typename senf::console::detail::ParsedCommandTraits::Attributor + BoundCommand(Owner const * owner, Member memfn); + + template + typename senf::console::detail::ParsedCommandTraits::Attributor + BoundCommand(Owner * owner, Member memfn); -}} + template + typename senf::console::detail::ParsedCommandTraits::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" diff --git a/senf/Utils/Console/ParsedCommand.ih b/senf/Utils/Console/ParsedCommand.ih index 0dbe33b..5ee1a84 100644 --- a/senf/Utils/Console/ParsedCommand.ih +++ b/senf/Utils/Console/ParsedCommand.ih @@ -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 + struct CreateParsedCommandOverload + {}; + + template + struct CreateParsedCommandOverload + { + typedef typename Traits::traits traits; + + template + static typename senf::console::ParsedCommandOverload::ptr create(Function fn) + { return senf::console::ParsedCommandOverload::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 }}} diff --git a/senf/Utils/Console/ParsedCommand.mpp b/senf/Utils/Console/ParsedCommand.mpp index 340e073..ab3caa6 100644 --- a/senf/Utils/Console/ParsedCommand.mpp +++ b/senf/Utils/Console/ParsedCommand.mpp @@ -356,7 +356,7 @@ struct CreateParsedCommandOverload template 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 )) ); } diff --git a/senf/Utils/Console/ParsedCommand.test.cc b/senf/Utils/Console/ParsedCommand.test.cc index 7e03013..13402dd 100644 --- a/senf/Utils/Console/ParsedCommand.test.cc +++ b/senf/Utils/Console/ParsedCommand.test.cc @@ -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( 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( 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( 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( 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( 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( 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(&cb2)) - .formatter( &testFormatter ); + dir.add("cb7", + fty::Command(boost::function(&cb2)) + .formatter( &testFormatter ) + ); SENF_CHECK_NO_THROW( parser.parse("test/cb7", boost::bind( 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 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; diff --git a/senf/Utils/Console/ProgramOptions.test.cc b/senf/Utils/Console/ProgramOptions.test.cc index a186106..fd8bfd0 100644 --- a/senf/Utils/Console/ProgramOptions.test.cc +++ b/senf/Utils/Console/ProgramOptions.test.cc @@ -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" }; diff --git a/senf/Utils/Console/STLSupport.test.cc b/senf/Utils/Console/STLSupport.test.cc index 0b86895..9ce13ad 100644 --- a/senf/Utils/Console/STLSupport.test.cc +++ b/senf/Utils/Console/STLSupport.test.cc @@ -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 defv (boost::assign::list_of(7)(2).to_container(defv)); - dir.add("test", &Summer >::test) - .arg("data", "test data", senf::console::kw::default_value = defv); + dir.add("test", fty::Command(&Summer >::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 defv (boost::assign::list_of(7)(2).to_container(defv)); - dir.add("test", &Summer >::test) - .arg("data", "test data", senf::console::kw::default_value = defv); + dir.add("test", fty::Command(&Summer >::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 defv (boost::assign::list_of(7)(2).to_container(defv)); - dir.add("test", &Summer >::test) - .arg("data", "test data", senf::console::kw::default_value = defv); + dir.add("test", fty::Command(&Summer >::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 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( diff --git a/senf/Utils/Console/ScopedDirectory.cti b/senf/Utils/Console/ScopedDirectory.cti index f379c4e..8b18ff0 100644 --- a/senf/Utils/Console/ScopedDirectory.cti +++ b/senf/Utils/Console/ScopedDirectory.cti @@ -32,19 +32,6 @@ ///////////////////////////////cti.p/////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// -// senf::console::OwnerNodeCreateTraits::Creator - -template -prefix_ typename senf::console::OwnerNodeCreateTraits::result_type -senf::console::OwnerNodeCreateTraits::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 template @@ -55,73 +42,66 @@ prefix_ senf::console::ScopedDirectory::ScopedDirectory(Owner * owner) } template -template -prefix_ typename senf::console::OwnerNodeCreateTraits::result_type -senf::console::ScopedDirectory::add(std::string const & name, Object const & ob) +template +prefix_ NodeType & senf::console::ScopedDirectory::add(std::string const & name, + boost::shared_ptr othernode) { - return OwnerNodeCreateTraits::Creator::create(node(), *owner_, name, ob); + return node().add(name, othernode); } template -template -prefix_ typename senf::console::OwnerNodeCreateTraits::result_type -senf::console::ScopedDirectory::add(std::string const & name, Object & ob) -{ - return OwnerNodeCreateTraits::Creator::create(node(), *owner_, name, ob); -} - -#ifndef DOXYGEN - -template -prefix_ senf::console::SimpleCommandNode & senf::console:: -senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name, - SimpleCommandNode::Function fn, int) +template +prefix_ NodeType & senf::console::ScopedDirectory:: +add(std::string const & name, NodeType & othernode, + typename boost::enable_if< boost::is_convertible >::type *) { - return node.add(name,fn); + return node().add(name,othernode); } template -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 +prefix_ typename Factory::result_type senf::console::ScopedDirectory:: +add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type *) { - return node.add(name, boost::function( - boost::bind(fn,boost::ref(owner),_1,_2))); + return factory.create(*owner_, name, node()); } template -prefix_ senf::console::DirectoryNode & -senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner, - std::string const & name, DirectoryNode & dir, int) +template +prefix_ typename Factory::result_type senf::console::ScopedDirectory:: +add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type *, + typename boost::disable_if< boost::is_convertible >::type *) { - return node.add(name, dir.thisptr()); + return node().add(name, factory); } -template -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 >::type *) -{ - return dir.add(name, node.node().thisptr()); -} - -#endif - /////////////////////////////////////////////////////////////////////////// // senf::console::ScopedDirectory -template -prefix_ typename senf::console::NodeCreateTraits::result_type -senf::console::ScopedDirectory::add(std::string const & name, Object const & ob) + +template +prefix_ NodeType & senf::console::ScopedDirectory::add(std::string const & name, + boost::shared_ptr othernode) +{ + return node().add(name,othernode); +} + +template +prefix_ NodeType & senf::console::ScopedDirectory:: +add(std::string const & name, NodeType & othernode, + typename boost::enable_if< boost::is_convertible >::type *) { - return node().add(name, ob); + return node().add(name,othernode); } -template -prefix_ typename senf::console::NodeCreateTraits::result_type -senf::console::ScopedDirectory::add(std::string const & name, Object & ob) +template +prefix_ typename Factory::result_type senf::console::ScopedDirectory:: +add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type *) { - return node().add(name, ob); + return node().add(name,factory); } ///////////////////////////////cti.e/////////////////////////////////////// diff --git a/senf/Utils/Console/ScopedDirectory.hh b/senf/Utils/Console/ScopedDirectory.hh index 0613d10..ddbf292 100644 --- a/senf/Utils/Console/ScopedDirectory.hh +++ b/senf/Utils/Console/ScopedDirectory.hh @@ -38,32 +38,8 @@ 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 - struct OwnerNodeCreateTraits - { - typedef BOOST_TYPEOF_TPL( senf_console_add_node( - * static_cast(0), - * static_cast(0), - * static_cast(0), - * static_cast(0), - * static_cast(0)) ) base_type; - typedef typename senf::remove_cvref::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 - typename OwnerNodeCreateTraits::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 - typename OwnerNodeCreateTraits::result_type add( - std::string const & name, Object & ob); - ///< Create new child node - /**< \see add() */ + template + NodeType & add(std::string const & name, boost::shared_ptr node); + template + NodeType & add(std::string const & name, NodeType & node, + typename boost::enable_if< boost::is_convertible >::type * = 0); + template + typename Factory::result_type add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type * = 0); + template + typename Factory::result_type add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type * = 0, + typename boost::disable_if< boost::is_convertible >::type * = 0); protected: @@ -178,33 +151,16 @@ namespace console { class ScopedDirectory : public ScopedDirectoryBase { public: - template - typename NodeCreateTraits::result_type add(std::string const & name, - Object const & ob); - - template - typename NodeCreateTraits::result_type add(std::string const & name, - Object & ob); + template + NodeType & add(std::string const & name, boost::shared_ptr node); + template + NodeType & add(std::string const & name, NodeType & node, + typename boost::enable_if< boost::is_convertible >::type * = 0); + template + typename Factory::result_type add(std::string const & name, Factory const & factory, + typename boost::enable_if< boost::is_convertible >::type * = 0); }; - template - SimpleCommandNode & senf_console_add_node( - DirectoryNode & node, Owner & owner, std::string const & name, - SimpleCommandNode::Function fn, int); - - template - SimpleCommandNode & senf_console_add_node( - DirectoryNode & node, Owner & owner, std::string const & name, - void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int); - - template - DirectoryNode & senf_console_add_node(DirectoryNode & node, Owner & owner, - std::string const & name, DirectoryNode & dir, int); - - template - DirectoryNode & senf_console_add_node( - DirectoryNode & dir, std::string const & name, Node const & node, int, - typename boost::enable_if< boost::is_convertible >::type * = 0); #endif }} diff --git a/senf/Utils/Console/ScopedDirectory.test.cc b/senf/Utils/Console/ScopedDirectory.test.cc index 8cf9c6c..92e30aa 100644 --- a/senf/Utils/Console/ScopedDirectory.test.cc +++ b/senf/Utils/Console/ScopedDirectory.test.cc @@ -43,7 +43,7 @@ namespace { senf::console::ScopedDirectory 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") ); diff --git a/senf/Utils/Console/Server.cc b/senf/Utils/Console/Server.cc index 6ed4b3b..b46cd6e 100644 --- a/senf/Utils/Console/Server.cc +++ b/senf/Utils/Console/Server.cc @@ -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) diff --git a/senf/Utils/Console/Traits.test.cc b/senf/Utils/Console/Traits.test.cc index 59f848a..cc5697f 100644 --- a/senf/Utils/Console/Traits.test.cc +++ b/senf/Utils/Console/Traits.test.cc @@ -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( 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( 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( diff --git a/senf/Utils/Console/Utility.test.cc b/senf/Utils/Console/Utility.test.cc index 2496f3b..3333cd5 100644 --- a/senf/Utils/Console/Utility.test.cc +++ b/senf/Utils/Console/Utility.test.cc @@ -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 (senf::console::CharAsString)>(&charTest)); + dir.add("test", + fty::Command (senf::console::CharAsString)>( + &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( diff --git a/senf/Utils/Console/Variables.cti b/senf/Utils/Console/Variables.cti index e5a311c..80d5d73 100644 --- a/senf/Utils/Console/Variables.cti +++ b/senf/Utils/Console/Variables.cti @@ -39,6 +39,13 @@ prefix_ senf::console::detail::QueryVariable::QueryVariable(Variable c {} template +prefix_ typename senf::console::detail::QueryVariable::Traits::Overload::ptr +senf::console::detail::QueryVariable::create(Variable const & var) +{ + return CreateOverload::create(Function(QueryVariable(var))); +} + +template prefix_ Variable const & senf::console::detail::QueryVariable::operator()() const { @@ -55,6 +62,15 @@ prefix_ senf::console::detail::SetVariable::SetVariable(Variable & var {} template +prefix_ typename senf::console::detail::SetVariable::Traits::Overload::ptr +senf::console::detail::SetVariable::create(Variable & var) +{ + typename Traits::Overload::ptr overload (CreateOverload::create(Function(SetVariable(var)))); + overload->arg(0).name = "new_value"; + return overload; +} + +template prefix_ void senf::console::detail::SetVariable::operator()(Variable const & value) const { @@ -68,189 +84,150 @@ prefix_ void senf::console::detail::SetVariable::operator()(Variable c } /////////////////////////////////////////////////////////////////////////// -// senf::console::ConstVariableAttributor +// senf::console::ConstVariableFactory template -prefix_ senf::console::ConstVariableAttributor -senf::console::ConstVariableAttributor::doc(std::string const & doc) +prefix_ senf::console::factory::ConstVariableFactory +senf::console::factory::ConstVariableFactory::doc(std::string const & doc) { - queryOverload_.node().doc(doc); + doc_ = doc; return *this; } template -prefix_ senf::console::ConstVariableAttributor -senf::console::ConstVariableAttributor::shortdoc(std::string const & doc) +prefix_ senf::console::factory::ConstVariableFactory +senf::console::factory::ConstVariableFactory::shortdoc(std::string const & doc) { - queryOverload_.node().shortdoc(doc); + shortdoc_ = doc; return *this; } template -prefix_ senf::console::ConstVariableAttributor -senf::console::ConstVariableAttributor::formatter(Formatter formatter) +prefix_ senf::console::factory::ConstVariableFactory +senf::console::factory::ConstVariableFactory::formatter(Formatter formatter) { - queryOverload_.formatter(formatter); + queryOverload_->formatter(formatter); return *this; } template -prefix_ senf::console::ConstVariableAttributor:: -ConstVariableAttributor(QueryOverload & queryOverload) - : queryOverload_ (queryOverload) -{} - -template prefix_ senf::console::OverloadedCommandNode & -senf::console::ConstVariableAttributor::node() +senf::console::factory::ConstVariableFactory::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 -prefix_ senf::console::ConstVariableAttributor:: -operator senf::console::OverloadedCommandNode &() - const -{ - return node(); -} +prefix_ senf::console::factory::ConstVariableFactory:: +ConstVariableFactory(Variable const & var) + : queryOverload_ (detail::QueryVariable::create(var)) +{} /////////////////////////////////////////////////////////////////////////// -// senf::console::VariableAttributor +// senf::console::VariableFactory template -prefix_ senf::console::VariableAttributor -senf::console::VariableAttributor::parser(Parser parser) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::parser(Parser parser) { - setOverload_.template arg<0>().parser = parser; + setOverload_->template arg<0>().parser = parser; return *this; } template -prefix_ senf::console::VariableAttributor -senf::console::VariableAttributor::typeName(std::string const & name) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::typeName(std::string const & name) { - setOverload_.arg(0).type = name; + setOverload_->arg(0).type = name; return *this; } template -prefix_ typename senf::console::VariableAttributor -senf::console::VariableAttributor::onChange(OnChangeHandler handler) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::onChange(OnChangeHandler handler) { - setOverload_.function( + setOverload_->function( boost::bind(detail::SetVariable(var_, handler),_2)); return *this; } template -prefix_ typename senf::console::VariableAttributor -senf::console::VariableAttributor::doc(std::string const & doc) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::doc(std::string const & doc) { - ConstVariableAttributor::doc(doc); + ConstVariableFactory::doc(doc); return *this; } template -prefix_ typename senf::console::VariableAttributor -senf::console::VariableAttributor::shortdoc(std::string const & doc) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::shortdoc(std::string const & doc) { - ConstVariableAttributor::shortdoc(doc); + ConstVariableFactory::shortdoc(doc); return *this; } template -prefix_ typename senf::console::VariableAttributor -senf::console::VariableAttributor::formatter(Formatter formatter) +prefix_ typename senf::console::factory::VariableFactory +senf::console::factory::VariableFactory::formatter(Formatter formatter) { - ConstVariableAttributor::formatter(formatter); + ConstVariableFactory::formatter(formatter); return *this; } template -prefix_ -senf::console::VariableAttributor::VariableAttributor(QueryOverload & queryOverload, - SetOverload & setOverload, - Variable & var) - : ConstVariableAttributor (queryOverload), setOverload_ (setOverload), var_ (var) -{} - -/////////////////////////////////////////////////////////////////////////// - -template -prefix_ senf::console::VariableAttributor -senf::console::detail::VariableNodeCreator::add(DirectoryNode & node, - std::string const & name, - Variable & var) +prefix_ senf::console::OverloadedCommandNode & +senf::console::factory::VariableFactory::create(DirectoryNode & dir, + std::string const & name) + const { - typename VariableAttributor::SetOverload & setOverload ( - node.add(name, typename detail::SetVariable::Function( - detail::SetVariable(var))) - .arg("new_value") - .overload() ); - typename VariableAttributor::QueryOverload & queryOverload ( - node.add(name, typename detail::QueryVariable::Function( - detail::QueryVariable(var))).overload() ); - - return VariableAttributor(queryOverload, setOverload, var); + OverloadedCommandNode & node (ConstVariableFactory::create(dir,name)); + node.add(setOverload_); + return node; } template -prefix_ senf::console::ConstVariableAttributor -senf::console::detail::VariableNodeCreator::add(DirectoryNode & node, - std::string const & name, - Variable & var) -{ - typename VariableAttributor::QueryOverload & queryOverload ( - node.add(name, typename detail::QueryVariable::Function( - detail::QueryVariable(var))).overload() ); - - return ConstVariableAttributor(queryOverload); -} +prefix_ senf::console::factory::VariableFactory::VariableFactory(Variable & var) + : ConstVariableFactory (var), + setOverload_ (detail::SetVariable::create(var)), + var_ (var) +{} -#ifndef DOXYGEN +/////////////////////////////////////////////////////////////////////////// -template -prefix_ senf::console::VariableAttributor senf::console:: -senf_console_add_node(DirectoryNode & node, std::string const & name, Variable & var, int, - typename boost::disable_if< boost::is_convertible >::type *, - typename boost::disable_if< boost::is_convertible >::type *, - typename boost::disable_if_c::is_callable>::type *) +template +prefix_ senf::console::factory::VariableFactory +senf::console::factory::Variable(Var & var) { - return detail::VariableNodeCreator::add(node, name, var); + return VariableFactory(var); } -template -prefix_ typename senf::console::detail::VariableNodeCreator::result_type -senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name, - boost::reference_wrapper var, int) +template +prefix_ senf::console::factory::VariableFactory +senf::console::factory::Variable(boost::reference_wrapper var) { - return detail::VariableNodeCreator::add(node, name, var.get()); + return VariableFactory(var); } -template -prefix_ senf::console::VariableAttributor senf::console:: -senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, - Variable & var, int, - typename boost::disable_if< boost::is_convertible >::type *, - typename boost::disable_if< boost::is_convertible >::type *, - typename boost::disable_if_c::is_callable>::type *) +template +prefix_ senf::console::factory::ConstVariableFactory +senf::console::factory::Variable(Var const & var) { - return detail::VariableNodeCreator::add(node, name, var); + return ConstVariableFactory(var); } -template -prefix_ typename senf::console::detail::VariableNodeCreator::result_type -senf::console::senf_console_add_node(DirectoryNode & node, Owner &, - std::string const & name, - boost::reference_wrapper var, int) +template +prefix_ senf::console::factory::ConstVariableFactory +senf::console::factory::Variable(boost::reference_wrapper var) { - return detail::VariableNodeCreator::add(node, name, var.get()); + return ConstVariableFactory(var); } -#endif - ///////////////////////////////cti.e/////////////////////////////////////// #undef prefix_ diff --git a/senf/Utils/Console/Variables.hh b/senf/Utils/Console/Variables.hh index 4f93a93..92df05d 100644 --- a/senf/Utils/Console/Variables.hh +++ b/senf/Utils/Console/Variables.hh @@ -42,63 +42,34 @@ namespace console { class ScopedDirectoryBase; template class VariableAttributor; - - -#ifndef DOXYGEN - - template - VariableAttributor senf_console_add_node( - DirectoryNode & node, std::string const & name, Variable & var, int, - typename boost::disable_if< boost::is_convertible >::type * = 0, - typename boost::disable_if< boost::is_convertible >::type * = 0, - typename boost::disable_if_c::is_callable>::type * = 0); - - template - typename detail::VariableNodeCreator::result_type - senf_console_add_node(DirectoryNode & node, std::string const & name, - boost::reference_wrapper var, int); - - template - VariableAttributor senf_console_add_node( - DirectoryNode & node, Owner & owner, std::string const & name, Variable & var, int, - typename boost::disable_if< boost::is_convertible >::type * = 0, - typename boost::disable_if< boost::is_convertible >::type * = 0, - typename boost::disable_if_c::is_callable>::type * = 0); - - template - typename detail::VariableNodeCreator::result_type - senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name, - boost::reference_wrapper var, int); - -#endif +namespace factory { /** \brief Variable command attributes (const) - \see VariableAttributor + \see VariableFactory */ template - class ConstVariableAttributor + class ConstVariableFactory + : public detail::NodeFactory { public: typedef typename detail::QueryVariable::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; + typename QueryOverload::ptr queryOverload_; + boost::optional doc_; + boost::optional shortdoc_; }; /** \brief Variable command attributes @@ -132,65 +103,74 @@ namespace console { \ingroup console_commands */ template - class VariableAttributor - : public ConstVariableAttributor + class VariableFactory + : public ConstVariableFactory { public: typedef typename detail::SetVariable::Traits::Overload SetOverload; typedef typename detail::ArgumentInfo::Parser Parser; typedef typename detail::SetVariable::OnChangeHandler OnChangeHandler; - typedef OverloadedCommandNode node_type; - typedef VariableAttributor return_type; - - typedef typename ConstVariableAttributor::Formatter Formatter; - typedef typename ConstVariableAttributor::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::Formatter Formatter; + typedef typename ConstVariableFactory::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; }; -}} + + template + VariableFactory Variable(Var & var); + + template + VariableFactory Variable(boost::reference_wrapper var); + + template + ConstVariableFactory Variable(Var const & var); + + template + ConstVariableFactory Variable(boost::reference_wrapper var); + +}}} ///////////////////////////////hh.e//////////////////////////////////////// //#include "Variables.cci" diff --git a/senf/Utils/Console/Variables.ih b/senf/Utils/Console/Variables.ih index 0f703aa..3e3f2f5 100644 --- a/senf/Utils/Console/Variables.ih +++ b/senf/Utils/Console/Variables.ih @@ -48,10 +48,13 @@ namespace detail { typedef Variable const & Signature (); typedef boost::function Function; typedef detail::ParsedCommandTraits Traits; + typedef detail::CreateParsedCommandOverload 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 Function; typedef detail::ParsedCommandTraits Traits; + typedef detail::CreateParsedCommandOverload CreateOverload; typedef boost::function 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 ::value> - struct VariableNodeCreator - { - typedef VariableAttributor result_type; - static VariableAttributor add(DirectoryNode & node, std::string const & name, - Variable & var); - }; - - template - struct VariableNodeCreator - { - typedef ConstVariableAttributor result_type; - static ConstVariableAttributor add(DirectoryNode & node, std::string const & name, - Variable & var); - }; - #endif }}} diff --git a/senf/Utils/Console/Variables.test.cc b/senf/Utils/Console/Variables.test.cc index 2a63473..fc782b7 100644 --- a/senf/Utils/Console/Variables.test.cc +++ b/senf/Utils/Console/Variables.test.cc @@ -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( 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 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_; diff --git a/senf/Utils/Logger/FileTarget.cc b/senf/Utils/Logger/FileTarget.cc index eda95c1..efa898f 100644 --- a/senf/Utils/Logger/FileTarget.cc +++ b/senf/Utils/Logger/FileTarget.cc @@ -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(&FileTarget::reopen), - this)) - .doc("Reopen logfile"); - consoleDir().add("reopen", senf::membind( - static_cast(&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" - " \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" + " \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 diff --git a/senf/Utils/Logger/LogFormat.cc b/senf/Utils/Logger/LogFormat.cc index 0f205a5..4fc05f8 100644 --- a/senf/Utils/Logger/LogFormat.cc +++ b/senf/Utils/Logger/LogFormat.cc @@ -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) diff --git a/senf/Utils/Logger/SyslogTarget.cc b/senf/Utils/Logger/SyslogTarget.cc index dc49247..6aeec08 100644 --- a/senf/Utils/Logger/SyslogTarget.cc +++ b/senf/Utils/Logger/SyslogTarget.cc @@ -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" - " \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" + " \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 diff --git a/senf/Utils/Logger/SyslogUDPTarget.cc b/senf/Utils/Logger/SyslogUDPTarget.cc index d1e70a3..88b44ba 100644 --- a/senf/Utils/Logger/SyslogUDPTarget.cc +++ b/senf/Utils/Logger/SyslogUDPTarget.cc @@ -39,20 +39,21 @@ 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(&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( - &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" - " \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( - &RegisterConsole::create)) - .arg("address") - .arg("facility", kw::default_value = USER); - detail::TargetRegistry::instance().consoleDir().add( - "udp-target", - static_cast( - &RegisterConsole::create)) - .arg("address") - .arg("facility", kw::default_value = USER); - detail::TargetRegistry::instance().consoleDir().add( - "udp-target", - static_cast( - &RegisterConsole::create)) - .arg("address") - .arg("facility", kw::default_value = USER); + namespace fty = senf::console::factory; + + detail::TargetRegistry::instance().consoleDir() + .add("udp-target", + fty::Command(&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" + " \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(&RegisterConsole::create) + .arg("address") + .arg("facility", kw::default_value = USER) ); + detail::TargetRegistry::instance().consoleDir() + .add("udp-target", + fty::Command(&RegisterConsole::create) + .arg("address") + .arg("facility", kw::default_value = USER) ); + detail::TargetRegistry::instance().consoleDir() + .add("udp-target", + fty::Command(&RegisterConsole::create) + .arg("address") + .arg("facility", kw::default_value = USER) ); } prefix_ boost::shared_ptr diff --git a/senf/Utils/Logger/Target.cc b/senf/Utils/Logger/Target.cc index 6b95524..a693279 100644 --- a/senf/Utils/Logger/Target.cc +++ b/senf/Utils/Logger/Target.cc @@ -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( - boost::bind(&Target::consoleRoute, this, -1, _1, _2))) - .arg("parameters") - .arg("action", kw::default_value=ACCEPT); - consoleDir_().add("unroute", - senf::membind(static_cast(&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( + boost::bind(&Target::consoleRoute, this, -1, _1, _2)) + .arg("parameters") + .arg("action", kw::default_value=ACCEPT) ); + consoleDir_() + .add("unroute", + fty::BoundCommand(this, static_cast(&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->consoleDir().add("remove", boost::function( - boost::bind( - &TargetRegistry::consoleRemoveTarget, this, target.get()))) - .doc("Remove target."); + namespace fty = senf::console::factory; + + target->consoleDir() + .add("remove", fty::Command( + 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" - " \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" + " \n" + "\n" + "Route all messages to the currently connected client\n" + " $ /sys/log/self { route () ); }") ); } prefix_ senf::log::detail::TargetRegistry::~TargetRegistry() diff --git a/senf/Utils/Statistics.cc b/senf/Utils/Statistics.cc index 079bb3c..2efca87 100644 --- a/senf/Utils/Statistics.cc +++ b/senf/Utils/Statistics.cc @@ -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 } diff --git a/senf/Utils/Statistics.cci b/senf/Utils/Statistics.cci index 0ed4fbd..6fd93a5 100644 --- a/senf/Utils/Statistics.cci +++ b/senf/Utils/Statistics.cci @@ -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 & diff --git a/senf/Utils/StatisticsTargets.cc b/senf/Utils/StatisticsTargets.cc index f771789..712844f 100644 --- a/senf/Utils/StatisticsTargets.cc +++ b/senf/Utils/StatisticsTargets.cc @@ -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( - 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( + 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,