ConsoleRegister::ConsoleRegister()
{
senf::ppi::ModuleManager::instance().consoleDir()
- .add("tracing", SENF_FNP(senf::ppi::connector::Connector::TraceState,
- senf::ppi::connector::Connector::tracing, ()))
- .doc("Log every packet sent or received by any module.\n"
- "There are three different tracing levels:\n"
- "\n"
- " NO_TRACING don't output any tracing information\n"
- " TRACE_IDS trace packet id's but do not show packet contents\n"
- " TRACE_CONTENTS trace complete packet contents\n"
- "\n"
- "A log message is generated whenever the packet traverses a connector. The\n"
- "TRACE_IDS log message has the following format:\n"
- "\n"
- " PPI packet trace: <direction> <packet-id> <packet-type>\n"
- " on <module-id> <module-type> connector <connector-id>\n"
- " PPI throttling trace: <direction> <throttle-msg>\n"
- " on <module-id> <module-type> connector <connector-id>\n"
- "\n"
- "The fields are:\n"
- "\n"
- " direction 'IN' for packets/throttle notifications entering the module,\n"
- " 'OUT' for packets/throttle notifications leaving it\n"
- " packet-id Numeric unique packet id. This value is unique for packets\n"
- " alive at the same time, packets at different times may (and\n"
- " will) share id's\n"
- " packet-type The type of the packet header\n"
- " module-id Unique module id\n"
- " module-type Type of the module the packet is sent to/from\n"
- " connector-id Unique connector id\n"
- " throttle-msg Type of throttling event\n");
+ .add("tracing", senf::console::factory::Command(
+ SENF_FNP(senf::ppi::connector::Connector::TraceState,
+ senf::ppi::connector::Connector::tracing, ()))
+ .doc("Log every packet sent or received by any module.\n"
+ "There are three different tracing levels:\n"
+ "\n"
+ " NO_TRACING don't output any tracing information\n"
+ " TRACE_IDS trace packet id's but do not show packet contents\n"
+ " TRACE_CONTENTS trace complete packet contents\n"
+ "\n"
+ "A log message is generated whenever the packet traverses a connector. The\n"
+ "TRACE_IDS log message has the following format:\n"
+ "\n"
+ " PPI packet trace: <direction> <packet-id> <packet-type>\n"
+ " on <module-id> <module-type> connector <connector-id>\n"
+ " PPI throttling trace: <direction> <throttle-msg>\n"
+ " on <module-id> <module-type> connector <connector-id>\n"
+ "\n"
+ "The fields are:\n"
+ "\n"
+ " direction 'IN' for packets/throttle notifications entering the module,\n"
+ " 'OUT' for packets/throttle notifications leaving it\n"
+ " packet-id Numeric unique packet id. This value is unique for packets\n"
+ " alive at the same time, packets at different times may (and\n"
+ " will) share id's\n"
+ " packet-type The type of the packet header\n"
+ " module-id Unique module id\n"
+ " module-type Type of the module the packet is sent to/from\n"
+ " connector-id Unique connector id\n"
+ " throttle-msg Type of throttling event\n")
+ );
senf::ppi::ModuleManager::instance().consoleDir()
- .add("tracing", SENF_FNP(void, senf::ppi::connector::Connector::tracing,
- (senf::ppi::connector::Connector::TraceState)))
- .arg("state", "new tracing state");
+ .add("tracing", senf::console::factory::Command(
+ SENF_FNP(void, senf::ppi::connector::Connector::tracing,
+ (senf::ppi::connector::Connector::TraceState)))
+ .arg("state", "new tracing state")
+ );
}
ConsoleRegister consoleRegister;
senf::console::sysdir().add("ppi", consoleDir_);
consoleDir_
- .add("dump", senf::membind(&ModuleManager::dumpModules, this))
- .doc("Dump complete PPI structure\n"
- "The dump will contain one paragraph for each module. The first line gives module\n"
- "information, additional lines list all connectors and their peers (if connected).\n"
- "\n"
- "This information can be processed by 'PPI/drawmodules.py' and 'dot' (from the\n"
- "graphviz package) to generate a graphic representation of the module structure:\n"
- "\n"
- " $ echo /sys/ppi/dump | nc -q1 <host> <port> \\\n"
- " | python PPI/drawmodules.py | dot -Tpng /dev/fd/0 >modules.png\n");
+ .add("dump", senf::console::factory::Command(
+ senf::membind(&ModuleManager::dumpModules, this))
+ .doc("Dump complete PPI structure\n"
+ "The dump will contain one paragraph for each module. The first line gives module\n"
+ "information, additional lines list all connectors and their peers (if connected).\n"
+ "\n"
+ "This information can be processed by 'PPI/drawmodules.py' and 'dot' (from the\n"
+ "graphviz package) to generate a graphic representation of the module structure:\n"
+ "\n"
+ " $ echo /sys/ppi/dump | nc -q1 <host> <port> \\\n"
+ " | python PPI/drawmodules.py | dot -Tpng /dev/fd/0 >modules.png\n")
+ );
}
prefix_ void senf::ppi::ModuleManager::dumpModules(std::ostream & os)
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"
" 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
: protocol(sh.protocol()), dir(this)
{
namespace kw = senf::console::kw;
- dir.add("buffersize", &DVBSectionProtocolWrapper::setBufferSize)
- .doc("Set the size of the circular buffer used for filtered data.")
- .arg("size", "in byte");
+ namespace fty = senf::console::factory;
- dir.add("start", &DVBSectionProtocolWrapper::startFiltering)
- .doc("Starts filtering");
+ dir.add("buffersize", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+ .doc("Set the size of the circular buffer used for filtered data.")
+ .arg("size", "in byte") );
- dir.add("stop", &DVBSectionProtocolWrapper::setBufferSize)
- .doc("Stops filtering");
+ dir.add("start", fty::BoundCommand(this,&DVBSectionProtocolWrapper::startFiltering)
+ .doc("Starts filtering") );
- dir.node().add("filter", boost::function<void (unsigned short int, unsigned, senf::console::FlagCollection<Flags>, unsigned, unsigned, unsigned)>(senf::membind(&DVBSectionProtocolWrapper::setSectionFilter, this)))
- .arg("pid", "pid to filter")
- .arg("filter", "filter", kw::default_value = 62, kw::default_doc = "0x3e")
- .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT", kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC, kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
- .arg("mask", "mask", kw::default_value = 0xff, kw::default_doc = "0xff")
- .arg("mode", "mode", kw::default_value = 0, kw::default_doc = "0x00")
- .arg("timeout", "timeout", kw::default_value = 0, kw::default_doc = "0x00")
- .doc("Sets parameters for section filter.");
+ dir.add("stop", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+ .doc("Stops filtering") );
- dir.add("stop", &DVBSectionProtocolWrapper::setBufferSize)
- .doc("Stops filtering");
+ dir.add("filter",
+ fty::BoundCommand<void (unsigned short int,
+ unsigned,
+ senf::console::FlagCollection<Flags>,
+ unsigned,
+ unsigned,
+ unsigned)
+ >(this, &DVBSectionProtocolWrapper::setSectionFilter)
+ .arg("pid", "pid to filter")
+ .arg("filter", "filter",
+ kw::default_value = 62,
+ kw::default_doc = "0x3e")
+ .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
+ kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+ kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+ .arg("mask", "mask",
+ kw::default_value = 0xff,
+ kw::default_doc = "0xff")
+ .arg("mode", "mode",
+ kw::default_value = 0,
+ kw::default_doc = "0x00")
+ .arg("timeout", "timeout",
+ kw::default_value = 0,
+ kw::default_doc = "0x00")
+ .doc("Sets parameters for section filter.") );
+
+ dir.add("stop", fty::BoundCommand(this, &DVBSectionProtocolWrapper::setBufferSize)
+ .doc("Stops filtering") );
}
: protocol(sh.protocol()), dir(this)
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
- dir.node().add("filter", boost::function<void ( unsigned short int, dmx_input_t, dmx_output_t, dmx_pes_type_t, senf::console::FlagCollection<Flags>)>(senf::membind(&DVBPESProtocolWrapper::setPESFilter, this)))
- .arg("pid", "pid to filter")
- .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
- .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
- .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], DMX_PES_OTHER")
- .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT", kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC, kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
- .doc("Sets parameters for PES filter.");
-
- dir.add("start", &DVBPESProtocolWrapper::startFiltering)
- .doc("Starts filtering");
+ dir.add("filter",
+ fty::BoundCommand<void (unsigned short int,
+ dmx_input_t,
+ dmx_output_t,
+ dmx_pes_type_t,
+ senf::console::FlagCollection<Flags>)
+ >(this,&DVBPESProtocolWrapper::setPESFilter)
+ .arg("pid", "pid to filter")
+ .arg("input", "input-filter: DMX_IN_FRONTEND DMX_IN_DVR ")
+ .arg("output", "output-filter: DMX_OUT_DECODER DMX_OUT_TAP DMX_OUT_TS_TAP ")
+ .arg("pesType", "PES type: DMX_PES_AUDIO[0-3] DMX_PES_VIDEO[0-3] "
+ "DMX_PES_TELETEXT[0-3], DMX_PES_SUBTITLE[0-3], DMX_PES_PCR[0-3], "
+ "DMX_PES_OTHER")
+ .arg("flags", "or-able: CHECK_CRC, ONESHOT, IMMEDIATE_START, KERNEL_CLIENT",
+ kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC,
+ kw::default_doc = "(IMMEDIATE_START CHECK_CRC)")
+ .doc("Sets parameters for PES filter.") );
+
+ dir.add("start", fty::BoundCommand(this, &DVBPESProtocolWrapper::startFiltering)
+ .doc("Starts filtering") );
- dir.add("stop", &DVBPESProtocolWrapper::stopFiltering)
- .doc("Stops filtering");
+ dir.add("stop", fty::BoundCommand(this, &DVBPESProtocolWrapper::stopFiltering)
+ .doc("Stops filtering") );
}
///////////////////////////////cc.e////////////////////////////////////////
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////////////////////////////////////////
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;
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());
SENF_AUTO_UNIT_TEST(configFileRestrict)
{
+ namespace fty = senf::console::factory;
+
TempFile cfgf ("test.cfg");
cfgf << "dir1/fun1 10;\n"
<< "dir2/fun2;\n"
senf::console::ScopedDirectory<> dir1;
senf::console::root().add("dir1", dir1);
- dir1.add("fun1",&fun1);
+ dir1.add("fun1",fty::Command(&fun1));
{
var1 = 0;
senf::console::ScopedDirectory<> dir2;
senf::console::root().add("dir2", dir2);
- dir2.add("fun2",&fun2);
+ dir2.add("fun2",fty::Command(&fun2));
var1 = 0;
var2 = false;
SENF_AUTO_UNIT_TEST(configFileSkipGroup)
{
+ namespace fty = senf::console::factory;
+
TempFile cfgf ("test.cfg");
cfgf << "dir1/fun1 10;\n"
<< "dir2 { dir3 { fun2; } fun1 5; }"
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;
SENF_AUTO_UNIT_TEST(configRestrictAndLink)
{
+ namespace fty = senf::console::factory;
+
TempFile cfgf ("test.cfg");
cfgf << "dir1/fun1 10;\n"
<< "link1 { dir3 { fun2; } fun1 5; }"
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);
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;
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;
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;
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
bool autocomplete)
: root_ (root), dir_ (dir.thisptr()), autocomplete_ (autocomplete), init_ (false)
{}
+
#endif
///////////////////////////////////////////////////////////////////////////
return boost::static_pointer_cast<SimpleCommandNode const>(shared_from_this());
}
-#ifndef DOXYGEN
+///////////////////////////////////////////////////////////////////////////
+// senf::console::factory::SimpleCommand
+
+prefix_ senf::console::factory::SimpleCommand::SimpleCommand(SimpleCommandNode::Function fn)
+ : node_ (SimpleCommandNode::create(fn))
+{}
prefix_ senf::console::SimpleCommandNode &
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
- SimpleCommandNode::Function fn, int)
+senf::console::factory::SimpleCommand::create(DirectoryNode & dir, std::string const & name)
+ const
{
- return node.add(name, SimpleCommandNode::create(fn));
+ return dir.add(name, node_);
}
-prefix_ senf::console::DirectoryNode &
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
- DirectoryNode & dir, int)
+prefix_ senf::console::factory::SimpleCommand const &
+senf::console::factory::SimpleCommand::doc(std::string const & doc)
+ const
{
- return node.add(name, dir.thisptr());
+ node_->doc(doc);
+ return *this;
}
-#endif
+prefix_ senf::console::factory::SimpleCommand const &
+senf::console::factory::SimpleCommand::shortdoc(std::string const & doc)
+ const
+{
+ node_->shortdoc(doc);
+ return *this;
+}
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::NodeCreateTraits<Object>::Creator
-
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::NodeCreateTraits<Object>::Creator::create(DirectoryNode & node,
- std::string const & name,
- Object & ob)
-{
- return senf_console_add_node(node, name, ob, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::DirectoryNode
template <class NodeType>
return *node;
}
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::DirectoryNode::add(std::string const & name, Object const & ob)
+template <class NodeType>
+prefix_ NodeType & senf::console::DirectoryNode::
+add(std::string const & name, NodeType & node,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
{
- return NodeCreateTraits<Object const>::Creator::create(*this, name, ob);
+ // This makes objects with implicit conversion operators work (hi, ScopedDirectory ..)
+ add(name, static_cast<GenericNode &>(node).thisptr());
+ return node;
}
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::DirectoryNode::add(std::string const & name, Object & ob)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::DirectoryNode::
+add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type *)
{
- return NodeCreateTraits<Object>::Creator::create(*this, name, ob);
+ return factory.create(*this, name);
}
///////////////////////////////cti.e///////////////////////////////////////
#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp>
#include <boost/range/iterator_range.hpp>
-#include <boost/typeof/typeof.hpp>
-#include <boost/type_traits/remove_reference.hpp>
#include <boost/any.hpp>
#include <senf/Utils/Exception.hh>
#include <senf/Utils/mpl.hh>
class DirectoryNode;
class CommandNode;
+ namespace detail { struct NodeFactory {}; }
+
/** \brief Get console root node */
DirectoryNode & root();
class SimpleCommandNode;
- /** \brief Internal: Node creation helper traits
-
- This class is used internally to find out the type of node to create for a specific argument
- type.
- */
- template <class Object>
- struct NodeCreateTraits
- {
- typedef BOOST_TYPEOF_TPL( senf_console_add_node(
- * static_cast<DirectoryNode *>(0),
- * static_cast<std::string const *>(0),
- * static_cast<Object *>(0),
- 0) ) base_type;
- typedef typename senf::remove_cvref<base_type>::type value_type;
-
- typedef typename value_type::node_type NodeType;
- typedef typename value_type::return_type result_type;
-
- /// Internal
- struct Creator {
- static result_type create(DirectoryNode & node, std::string const & name,
- Object & ob);
- };
- };
-
/** \brief Config/console tree directory node
This node type provides the internal and root nodes of the tree. It allows to add arbitrary
'-n' is added to the name until the name is unique. If
\a name is empty, it is set to 'unnamed'. */
- template <class Object>
- typename NodeCreateTraits<Object>::result_type add(std::string const & name,
- Object const & ob);
+ template <class NodeType>
+ NodeType & add(std::string const & name, NodeType & node,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+
+ template <class Factory>
+ typename Factory::result_type add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory const &, detail::NodeFactory const &> >::type * = 0);
///< Generic child node factory
/**< This member is used to create a new child node of the
current directory. The type of node created depends on
- the type of argument passed.
-
- The node type is selected by the NodeCreateTraits
- class. To allow adding a specific node type, you need
- to provide an overload for
- <tt>senf_console_add_node</tt> which must be visible at
- when you register the new node.
- \code
- MyNodeType & senf_console_add_node(
- DirectoryNode & dir,
- std::string const & name,
- MySpecialObject const & ob,
- int)
- {
- return dir.add(name, MyNodeType::create(ob));
- }
- \endcode
- (Do not forget the last unnamed 'int' parameter which
- is not used but serves to disambiguate the
- overloads). */
-
- template <class Object>
- typename NodeCreateTraits<Object>::result_type add(std::string const & name,
- Object & ob);
- ///< Generic child node factory
- /**< \see add() */
+ the type of argument passed. */
GenericNode::ptr remove(std::string const & name);
///< Remove node \a name from the tree
struct UnknownNodeNameException : public senf::Exception
{ UnknownNodeNameException() : senf::Exception("Unknown node name") {}};
-#ifndef DOXYGEN
- template <class Type>
- struct NodeCreateTraits< boost::shared_ptr<Type> >
- {};
-#endif
-
/** \brief Config/console tree command node
The CommandNode is the base-class for the tree leaf nodes. Concrete command node
#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"
};
}
-SENF_AUTO_UNIT_TEST(senfConsoleAddNode)
+SENF_AUTO_UNIT_TEST(factory)
{
- senf::console::root().add("fn1", &callback);
- senf::console::root().add("fn2", boost::function<void(std::ostream&,senf::console::ParseCommandInfo const &)>(Functor()));
+ namespace fty = senf::console::factory;
+ senf::console::root().add("fn1", fty::SimpleCommand(&callback));
+ senf::console::root().add("fn2", fty::SimpleCommand(Functor()));
senf::console::ParseCommandInfo info;
///////////////////////////////////////////////////////////////////////////
// senf::console::OverloadedCommandNode
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::OverloadedCommandNode::insertOverload(DirectoryNode & dir,
+ std::string const & name,
+ CommandOverload::ptr overload)
+{
+ OverloadedCommandNode & node (
+ dir.hasChild(name)
+ ? dynamic_cast<OverloadedCommandNode &>(dir(name))
+ : dir.add(name, OverloadedCommandNode::create()));
+ node.add(overload);
+ return node;
+}
+
///////////////////////////////////////////////////////////////////////////
// So soll die doku aussehen:
//
: fn_ (fn)
{}
-///////////////////////////////cci.e///////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+// senf::console::SimpleOverloadAttributor
+
+prefix_ senf::console::SimpleOverloadAttributor::
+SimpleOverloadAttributor(SimpleCommandOverload::Function fn)
+ : overload_ (SimpleCommandOverload::create(fn))
+{}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::doc(std::string const & doc)
+ const
+{
+ doc_ = doc;
+ return *this;
+}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::shortdoc(std::string const & doc)
+ const
+{
+ shortdoc_ = doc;
+ return *this;
+}
+
+prefix_ senf::console::SimpleOverloadAttributor const &
+senf::console::SimpleOverloadAttributor::overloadDoc(std::string const & doc)
+ const
+{
+ overload_->doc(doc);
+ return *this;
+}
+
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::SimpleOverloadAttributor::create(DirectoryNode & dir, std::string const & name)
+ const
+{
+ OverloadedCommandNode & node (OverloadedCommandNode::insertOverload(dir, name, overload_));
+ if (doc_) node.doc(*doc_);
+ if (shortdoc_) node.shortdoc(*shortdoc_);
+ return node;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+prefix_ senf::console::SimpleOverloadAttributor
+senf::console::factory::Command(SimpleCommandOverload::Function fn)
+{
+ return SimpleOverloadAttributor(fn);
+}
+
+/////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
\f
#include <boost/intrusive_ptr.hpp>
#include <boost/range/iterator_range.hpp>
#include <senf/Utils/intrusive_refcount.hh>
+#include <boost/optional.hpp>
//#include "OverloadedCommand.mpp"
///////////////////////////////hh.p////////////////////////////////////////
ptr thisptr();
cptr thisptr() const;
+ static OverloadedCommandNode & insertOverload(DirectoryNode & dir, std::string const & name,
+ CommandOverload::ptr overload);
+
private:
OverloadedCommandNode();
std::string doc_;
};
-}}
+ class SimpleOverloadAttributor
+ : public detail::NodeFactory
+ {
+ public:
+ typedef OverloadedCommandNode node_type;
+ typedef OverloadedCommandNode & result_type;
+
+ explicit SimpleOverloadAttributor(SimpleCommandOverload::Function fn);
+
+ SimpleOverloadAttributor const & doc(std::string const & doc) const;
+ SimpleOverloadAttributor const & shortdoc(std::string const & doc) const;
+ SimpleOverloadAttributor const & overloadDoc(std::string const & doc) const;
+
+ OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+
+ private:
+ SimpleCommandOverload::ptr overload_;
+ mutable boost::optional<std::string> doc_;
+ mutable boost::optional<std::string> shortdoc_;
+ };
+
+namespace factory {
+
+ SimpleOverloadAttributor Command(SimpleCommandOverload::Function fn);
+
+}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "OverloadedCommand.cci"
// 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///////////////////////////////////////
}
template <class Overload>
-prefix_
-senf::console::ParsedCommandAttributor<Overload>::ParsedCommandAttributor(Overload & overload,
- unsigned index)
+prefix_ senf::console::ParsedCommandAttributor<Overload>::
+ParsedCommandAttributor(typename Overload::ptr overload, unsigned index)
: ParsedCommandAttributorBase (overload, index)
{}
+template <class Overload>
+prefix_ senf::console::ParsedCommandAttributor<Overload>::
+ParsedCommandAttributor(ParsedCommandAttributorBase const & other, unsigned index)
+ : ParsedCommandAttributorBase (other, index)
+{}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::ParsedArgumentAttributorBase<Overload,Self>
template <class Overload, class Self, class ReturnType>
prefix_ Self
senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::doc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::nodeDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self, class ReturnType>
prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
shortdoc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::shortDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self, class ReturnType>
prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
overloadDoc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::overloadDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self, class ReturnType>
prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
formatter(typename Overload::Formatter f)
- const
{
this->overload().formatter(f);
return static_cast<Self const &>(*this);
template <class Overload, class Self, class ReturnType>
prefix_
senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
-ParsedArgumentAttributorBase(Overload & overload, unsigned index)
+ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index)
: ParsedCommandAttributor<Overload> (overload, index)
{}
+template <class Overload, class Self, class ReturnType>
+prefix_
+senf::console::ParsedArgumentAttributorBase<Overload,Self,ReturnType>::
+ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index)
+ : ParsedCommandAttributor<Overload> (other, index)
+{}
+
template <class Overload, class Self>
prefix_ Self
senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::doc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::nodeDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self>
prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
shortdoc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::shortDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self>
prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
overloadDoc(std::string const & doc)
- const
{
this->ParsedCommandAttributorBase::overloadDoc(doc);
return static_cast<Self const &>(*this);
template <class Overload, class Self>
prefix_
-senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
-ParsedArgumentAttributorBase(Overload & overload, unsigned index)
+senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
+ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index)
: ParsedCommandAttributor<Overload> (overload, index)
{}
+template <class Overload, class Self>
+prefix_
+senf::console::ParsedArgumentAttributorBase<Overload, Self, void>::
+ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index)
+ : ParsedCommandAttributor<Overload> (other, index)
+{}
+
///////////////////////////////////////////////////////////////////////////
// senf::console::ParsedArgumentAttributor<Overload,index,flag>
prefix_ typename senf::console::ParsedArgumentAttributor<Overload,index,flag>::next_type
senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(ArgumentPack const & args)
- const
{
# define ProcessArg(tag) \
argInfo( kw:: tag, args, senf::has_parameter< ArgumentPack, kw::type:: tag >() )
template <class Kw, class ArgumentPack>
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_)
- const
{}
template <class Overload, unsigned index, bool flag>
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::name> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
this->argName(args[kw::name]);
}
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::description> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
this->argDoc(args[kw::description]);
}
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::default_value> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
this->defaultValue(args[kw::default_value]);
}
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::type_name> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
this->typeName(args[kw::type_name]);
}
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::default_doc> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
BOOST_STATIC_ASSERT(( senf::has_parameter<ArgumentPack, kw::type::default_value>::value ));
this->defaultDoc(args[kw::default_doc]);
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
argInfo(boost::parameter::keyword<kw::type::parser> const &, ArgumentPack const & args,
boost::mpl::true_)
- const
{
this->parser(args[kw::parser]);
}
template <class Overload, unsigned index, bool flag>
-prefix_
-senf::console::ParsedArgumentAttributor<Overload,index,flag>::
-ParsedArgumentAttributor(Overload & overload)
- : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (overload, index)
+prefix_ senf::console::ParsedArgumentAttributor<Overload,index,flag>::
+ParsedArgumentAttributor(typename Overload::ptr overload)
+: ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (overload, index)
+{}
+
+template <class Overload, unsigned index, bool flag>
+prefix_ senf::console::ParsedArgumentAttributor<Overload,index,flag>::
+ParsedArgumentAttributor(ParsedCommandAttributorBase const & other)
+ : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (other, index)
{}
template <class Overload, unsigned index, bool flag>
senf::console::ParsedArgumentAttributor<Overload,index,flag>::next()
const
{
- return ParsedArgumentAttributor<Overload, index+1>(this->overload());
+ return ParsedArgumentAttributor<Overload, index+1>(*this);
}
template <class Overload, unsigned index, bool flag>
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::
defaultValue(value_type const & value)
- const
{
this->overload().arg<index>().defaultValue = value;
this->overload().arg(index).hasDefault = true;
template <class Overload, unsigned index, bool flag>
template <class Fn>
prefix_ void senf::console::ParsedArgumentAttributor<Overload,index,flag>::parser(Fn fn)
- const
{
this->overload().arg<index>().parser = fn;
}
template <class Overload, unsigned index>
prefix_
senf::console::ParsedArgumentAttributor<Overload, index, false>::
-ParsedArgumentAttributor(Overload & overload)
+ParsedArgumentAttributor(typename Overload::ptr overload)
: ParsedArgumentAttributorBase<
Overload, ParsedArgumentAttributor<Overload, index, false> > (overload, index)
{}
+template <class Overload, unsigned index>
+prefix_
+senf::console::ParsedArgumentAttributor<Overload, index, false>::
+ParsedArgumentAttributor(ParsedCommandAttributorBase const & other)
+ : ParsedArgumentAttributorBase<Overload, ParsedArgumentAttributor> (other, index)
+{}
+
///////////////////////////////////////////////////////////////////////////
// namespace members
struct ParsedCommandAddNodeAccess
{
- template <class Attributor, class Node>
- static Attributor attributor(Node & node)
- { return Attributor(node); }
- };
-
- // What is THIS about ??
-
- // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
- // this argument is given, then the function will be called with the console output stream as
- // it's first argument.
- //
- // This is implemented in the following way: ParsedCommandOverload (the class responsible for
- // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
- // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
- // function will be directly passed to ParsedCommandOverload.
- //
- // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
- // the create member will use boost::bind to DROP the first argument.
-
- template <class Traits,
- bool ignoreOneArg=! Traits::has_ostream_arg,
- unsigned arity=Traits::traits::arity>
- struct CreateParsedCommandOverload
- {};
-
- template <class Traits, unsigned arity>
- struct CreateParsedCommandOverload<Traits, false, arity>
- {
- typedef typename Traits::traits traits;
-
- template <class Function>
- static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
- { return senf::console::ParsedCommandOverload<traits>::create(fn); };
+ template <class Attributor, class NodePtr>
+ static Attributor attributor(NodePtr ptr)
+ { return Attributor(ptr); }
};
-# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
- SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
- 4))
-# include BOOST_PP_ITERATE()
-
template <class Signature, class Fn>
typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
- addOverloadedCommandNode(senf::console::DirectoryNode & node, std::string const & name, Fn fn)
+ addOverloadedCommandNode(Fn fn)
{
- senf::console::OverloadedCommandNode & cmdNode (
- node.hasChild(name)
- ? dynamic_cast<senf::console::OverloadedCommandNode &>(node(name))
- : node.add(name, senf::console::OverloadedCommandNode::create()) );
-
typedef senf::console::detail::ParsedCommandTraits<Signature> CmdTraits;
typedef senf::console::ParsedCommandOverload<typename CmdTraits::traits> Overload;
typedef senf::console::ParsedArgumentAttributor<Overload> Attributor;
- return senf::console::detail::ParsedCommandAddNodeAccess::attributor<Attributor>(
- cmdNode.add( CreateParsedCommandOverload<CmdTraits>::create(fn) ) );
+ return detail::ParsedCommandAddNodeAccess::attributor<Attributor>(
+ CreateParsedCommandOverload<CmdTraits>::create(fn));
}
#endif
}}}
-#ifndef DOXYGEN
+template <class CastTo, class Signature>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::Command(boost::function<Signature> fn)
+{
+ return detail::addOverloadedCommandNode<CastTo>(fn);
+}
-template <class Function>
-typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
- Function fn, int,
- typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
+template <class CastTo, class Function>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::
+Command(Function fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
{
- return senf::console::detail::addOverloadedCommandNode<Function>(node, name, fn);
+ return detail::addOverloadedCommandNode<CastTo>(fn);
}
template <class Signature>
-typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
- boost::function<Signature> fn, int)
+prefix_ typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
+senf::console::factory::Command(boost::function<Signature> fn)
{
- return senf::console::detail::addOverloadedCommandNode<Signature>(node, name, fn);
+ return detail::addOverloadedCommandNode<Signature>(fn);
}
-template <class Owner, class Function>
-typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
-senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- Function fn, int,
- typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_member>::type *)
+template <class Function>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
+senf::console::factory::
+Command(Function fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type *)
{
- return senf::console::detail::addOverloadedCommandNode<Function>(
- node, name, senf::membind(fn,&owner));
+ return detail::addOverloadedCommandNode<Function>(fn);
}
-#endif
+template <class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+senf::console::factory::BoundCommand(Owner * owner, Member memfn)
+{
+ return detail::addOverloadedCommandNode<Member>(senf::membind(memfn,owner));
+}
+
+template <class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+senf::console::factory::BoundCommand(Owner const * owner, Member memfn)
+{
+ return detail::addOverloadedCommandNode<Member>(senf::membind(memfn,owner));
+}
+
+template <class CastTo, class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::BoundCommand(Owner * owner, Member memfn)
+{
+ return detail::addOverloadedCommandNode<CastTo>(senf::membind(memfn,owner));
+}
+
+template <class CastTo, class Owner, class Member>
+prefix_ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+senf::console::factory::BoundCommand(Owner const * owner, Member memfn)
+{
+ return detail::addOverloadedCommandNode<CastTo>(senf::membind(memfn,owner));
+}
///////////////////////////////cti.e///////////////////////////////////////
#undef prefix_
#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.
\see \ref console_autoparse
*/
class ParsedCommandAttributorBase
+ : public detail::NodeFactory
{
public:
- OverloadedCommandNode & node() const; ///< Return the node object
- operator OverloadedCommandNode & () const; ///< Automatically convert to node object
+ typedef OverloadedCommandNode node_type;
+ typedef OverloadedCommandNode & result_type;
- protected:
- ParsedCommandAttributorBase(ParsedCommandOverloadBase & overload, unsigned index);
+ OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
- void argName(std::string const & name) const;
- void argDoc(std::string const & doc) const;
- void typeName(std::string const & doc) const;
- void defaultDoc(std::string const & doc) const;
+ protected:
+ ParsedCommandAttributorBase(ParsedCommandOverloadBase::ptr overload, unsigned index);
+ ParsedCommandAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
+ void argName(std::string const & name);
+ void argDoc(std::string const & doc);
+ void typeName(std::string const & doc);
+ void defaultDoc(std::string const & doc);
+
ParsedCommandOverloadBase & overload() const;
- void overloadDoc(std::string const & doc) const;
- void nodeDoc(std::string const & doc) const;
- void shortDoc(std::string const & doc) const;
+ void overloadDoc(std::string const & doc);
+ void nodeDoc(std::string const & doc);
+ void shortDoc(std::string const & doc);
private:
- ParsedCommandOverloadBase & overload_;
+ ParsedCommandOverloadBase::ptr overload_;
unsigned index_;
+ boost::optional<std::string> doc_;
+ boost::optional<std::string> shortdoc_;
};
/** \brief Non argument dependent ParsedCommandBase attributes
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:
};
: public ParsedCommandAttributor<Overload>
{
public:
- Self doc(std::string const & doc) const; ///< Set documentation for all overloads
- Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
- Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
- Self formatter(typename Overload::Formatter formatter) const;
+ Self doc(std::string const & doc); ///< Set documentation for all overloads
+ Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
+ Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
+ Self formatter(typename Overload::Formatter formatter);
///< Set return value formatter
/**< This member is only available, if the \a ReturnType of
the installed callback is not \c void.
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:
};
: public ParsedCommandAttributor<Overload>
{
public:
- Self doc(std::string const & doc) const; ///< Set documentation for all overloads
- Self shortdoc(std::string const & doc) const; ///< Set short documentation for all overloads
- Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
+ Self doc(std::string const & doc); ///< Set documentation for all overloads
+ Self shortdoc(std::string const & doc); ///< Set short documentation for all overloads
+ Self overloadDoc(std::string const & doc); ///< Set overload specific documentation
protected:
- ParsedArgumentAttributorBase(Overload & overload, unsigned index);
+ ParsedArgumentAttributorBase(typename Overload::ptr overload, unsigned index);
+ ParsedArgumentAttributorBase(ParsedCommandAttributorBase const & other, unsigned index);
private:
};
\see \ref console_autoparse
*/
- template < class Overload, unsigned index, bool flag>
+ template <class Overload, unsigned index, bool flag>
class ParsedArgumentAttributor
: public ParsedArgumentAttributorBase< Overload,
ParsedArgumentAttributor<Overload, index, flag> >
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;
#endif
private:
- explicit ParsedArgumentAttributor(Overload & overload);
+ explicit ParsedArgumentAttributor(typename Overload::ptr overload);
+ explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
template <class ArgumentPack>
- next_type argInfo(ArgumentPack const & args) const;
+ next_type argInfo(ArgumentPack const & args);
template <class Kw, class ArgumentPack>
- void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_)
- const;
+ void argInfo(Kw const &, ArgumentPack const &, boost::mpl::false_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::name> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::description> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::default_value> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::type_name> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::default_doc> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
template <class ArgumentPack>
void argInfo(boost::parameter::keyword<kw::type::parser> const &,
- ArgumentPack const & args, boost::mpl::true_)
- const;
+ ArgumentPack const & args, boost::mpl::true_);
next_type next() const;
- void defaultValue(value_type const & value) const;
- template <class Fn> void parser(Fn fn) const;
+ void defaultValue(value_type const & value);
+ template <class Fn> void parser(Fn fn);
template <class O, unsigned i, bool f>
friend class ParsedArgumentAttributor;
typedef ParsedArgumentAttributor return_type;
private:
- explicit ParsedArgumentAttributor(Overload & overload);
+ explicit ParsedArgumentAttributor(typename Overload::ptr overload);
+ explicit ParsedArgumentAttributor(ParsedCommandAttributorBase const & other);
template <class O, unsigned i, bool f>
friend class ParsedArgumentAttributor;
friend class detail::ParsedCommandAddNodeAccess;
};
- template <class Function>
- typename detail::ParsedCommandTraits<Function>::Attributor
- senf_console_add_node(DirectoryNode & node, std::string const & name, Function fn, int,
- typename boost::enable_if_c<
- detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
+#endif
+
+namespace factory {
+
+ template <class CastTo, class Signature>
+ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+ Command(boost::function<Signature> fn);
+
+ template <class CastTo, class Function>
+ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+ Command(Function fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
template <class Signature>
- typename detail::ParsedCommandTraits<Signature>::Attributor
- senf_console_add_node(DirectoryNode & node, std::string const & name,
- boost::function<Signature> fn, int);
+ typename senf::console::detail::ParsedCommandTraits<Signature>::Attributor
+ Command(boost::function<Signature> fn);
- template <class Owner, class Function>
- typename detail::ParsedCommandTraits<Function>::Attributor
- senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- Function fn, int,
- typename boost::enable_if_c<
- detail::ParsedCommandTraits<Function>::is_member>::type * = 0);
+ template <class Function>
+ typename senf::console::detail::ParsedCommandTraits<Function>::Attributor
+ Command(Function fn,
+ typename boost::enable_if_c<detail::ParsedCommandTraits<Function>::is_callable>::type * = 0);
-#endif
+ template <class Owner, class Member>
+ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+ BoundCommand(Owner * owner, Member memfn);
+
+ template <class Owner, class Member>
+ typename senf::console::detail::ParsedCommandTraits<Member>::Attributor
+ BoundCommand(Owner const * owner, Member memfn);
+
+ template <class CastTo, class Owner, class Member>
+ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+ BoundCommand(Owner * owner, Member memfn);
-}}
+ template <class CastTo, class Owner, class Member>
+ typename senf::console::detail::ParsedCommandTraits<CastTo>::Attributor
+ BoundCommand(Owner const * owner, Member memfn);
-#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
-BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedCommandOverload, (class,unsigned))
-BOOST_TYPEOF_REGISTER_TEMPLATE(senf::console::ParsedArgumentAttributor, (class, unsigned, bool))
-BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function_traits, 1)
+}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "ParsedCommand.cci"
struct ParsedCommandAddNodeAccess;
+ // What is THIS about ??
+
+ // Ok, here's the dope: parsed commands may optionally have an std::ostream & first argument. If
+ // this argument is given, then the function will be called with the console output stream as
+ // it's first argument.
+ //
+ // This is implemented in the following way: ParsedCommandOverload (the class responsible for
+ // calling the callback) will ALWAYS pass the stream as first argument. If the user callback
+ // expects os as it's first argument, 'ignoreOneArg' will be false and the user supplied
+ // function will be directly passed to ParsedCommandOverload.
+ //
+ // If however, it does NOT take an std::ostream first argument, 'ignoreOneArg' will be true and
+ // the create member will use boost::bind to DROP the first argument.
+
+ template <class Traits,
+ bool ignoreOneArg=! Traits::has_ostream_arg,
+ unsigned arity=Traits::traits::arity>
+ struct CreateParsedCommandOverload
+ {};
+
+ template <class Traits, unsigned arity>
+ struct CreateParsedCommandOverload<Traits, false, arity>
+ {
+ typedef typename Traits::traits traits;
+
+ template <class Function>
+ static typename senf::console::ParsedCommandOverload<traits>::ptr create(Function fn)
+ { return senf::console::ParsedCommandOverload<traits>::create(fn); };
+ };
+
+# define BOOST_PP_ITERATION_PARAMS_1 (4, (0, SENF_CONSOLE_MAX_COMMAND_ARITY, \
+ SENF_ABSOLUTE_INCLUDE_PATH(Utils/Console/ParsedCommand.mpp), \
+ 4))
+# include BOOST_PP_ITERATE()
+
#endif
}}}
template <BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), class A ) >
next_type arg ( BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PP_ITERATION(), A, const & a ),
typename arg_params::match< BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), A ) >::type
- kw = arg_params()) const {
+ kw = arg_params()) {
return argInfo( kw(BOOST_PP_ENUM_PARAMS( BOOST_PP_ITERATION(), a )) );
}
SENF_AUTO_UNIT_TEST(parsedCommand)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
{
std::stringstream ss;
- dir.add("cb1", &cb1);
+ dir.add("cb1", fty::Command(&cb1));
parser.parse("test/cb1 2 3.2",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "5\n" );
{
std::stringstream ss;
- dir.add("cb2", &cb2);
+ dir.add("cb2", fty::Command(&cb2));
parser.parse("test/cb2",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "1.2\n" );
{
std::stringstream ss;
- dir.add("cb3", &cb3);
+ dir.add("cb3", fty::Command(&cb3));
parser.parse("test/cb3 234",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "" );
{
std::stringstream ss;
- dir.add("cb4", &cb4);
+ dir.add("cb4", fty::Command(&cb4));
parser.parse("test/cb4",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "text\n" "value\n" );
{
std::stringstream ss;
- dir.add("cb5", &cb5);
+ dir.add("cb5", fty::Command(&cb5));
parser.parse("test/cb5 1234",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "Value: 1234\n" );
std::stringstream ss;
// Just for the fun of it, use a functor and not a function pointer as parser ...
- dir.add("cb6", &cb5)
- .arg( kw::parser = TestParser() );
+ dir.add("cb6",
+ fty::Command(&cb5)
+ .arg( kw::parser = TestParser() )
+ );
SENF_CHECK_NO_THROW(
parser.parse("test/cb6 false",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
// This tests adding boost::function objects and at the same time validates, that
// compatible types also work
- dir.add("cb7", boost::function<float()>(&cb2))
- .formatter( &testFormatter );
+ dir.add("cb7",
+ fty::Command(boost::function<float()>(&cb2))
+ .formatter( &testFormatter )
+ );
SENF_CHECK_NO_THROW(
parser.parse("test/cb7",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
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"
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;
}
namespace {
-
struct Test
{
senf::console::ScopedDirectory<Test> dir;
std::string name_;
Test(std::string const & name) : dir(this), name_ (name) {
- dir.add("name", &Test::name);
+ dir.add("name", senf::console::factory::Command(
+ SENF_MEMBINDFNP(std::string, Test, name, (std::string const &))));
}
std::string name(std::string const & suffix) {
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();
}
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;
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" };
SENF_AUTO_UNIT_TEST(vectorSupport)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
std::vector<int> defv (boost::assign::list_of(7)(2).to_container(defv));
- dir.add("test", &Summer<std::vector<int> >::test)
- .arg("data", "test data", senf::console::kw::default_value = defv);
+ dir.add("test", fty::Command(&Summer<std::vector<int> >::test)
+ .arg("data", "test data", senf::console::kw::default_value = defv)
+ );
std::stringstream ss;
SENF_CHECK_NO_THROW(
SENF_AUTO_UNIT_TEST(listSupport)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
std::list<int> defv (boost::assign::list_of(7)(2).to_container(defv));
- dir.add("test", &Summer<std::list<int> >::test)
- .arg("data", "test data", senf::console::kw::default_value = defv);
+ dir.add("test", fty::Command(&Summer<std::list<int> >::test)
+ .arg("data", "test data", senf::console::kw::default_value = defv)
+ );
std::stringstream ss;
SENF_CHECK_NO_THROW(
SENF_AUTO_UNIT_TEST(setSupport)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
std::set<int> defv (boost::assign::list_of(7)(2).to_container(defv));
- dir.add("test", &Summer<std::set<int> >::test)
- .arg("data", "test data", senf::console::kw::default_value = defv);
+ dir.add("test", fty::Command(&Summer<std::set<int> >::test)
+ .arg("data", "test data", senf::console::kw::default_value = defv)
+ );
std::stringstream ss;
SENF_CHECK_NO_THROW(
SENF_AUTO_UNIT_TEST(mapSupport)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
std::map<std::string, int> defv (
boost::assign::map_list_of("foo bar",7)("bar",2).to_container(defv));
- dir.add("test", &mapTest)
- .arg("data", "test data", senf::console::kw::default_value = defv);
+ dir.add("test", fty::Command(&mapTest)
+ .arg("data", "test data", senf::console::kw::default_value = defv)
+ );
std::stringstream ss;
SENF_CHECK_NO_THROW(
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator
-
-template <class Owner, class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner,Object>::result_type
-senf::console::OwnerNodeCreateTraits<Owner,Object>::Creator::create(DirectoryNode & node,
- Owner & owner,
- std::string const & name,
- Object & ob)
-{
- return senf_console_add_node(node, owner, name, ob, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////
// senf::console::ScopedDirectory<Owner>
template <class Owner>
}
template <class Owner>
-template <class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object const>::result_type
-senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object const & ob)
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<Owner>::add(std::string const & name,
+ boost::shared_ptr<NodeType> othernode)
{
- return OwnerNodeCreateTraits<Owner, Object const>::Creator::create(node(), *owner_, name, ob);
+ return node().add(name, othernode);
}
template <class Owner>
-template <class Object>
-prefix_ typename senf::console::OwnerNodeCreateTraits<Owner, Object>::result_type
-senf::console::ScopedDirectory<Owner>::add(std::string const & name, Object & ob)
-{
- return OwnerNodeCreateTraits<Owner, Object>::Creator::create(node(), *owner_, name, ob);
-}
-
-#ifndef DOXYGEN
-
-template <class Owner, class Function>
-prefix_ senf::console::SimpleCommandNode & senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & , std::string const & name,
- SimpleCommandNode::Function fn, int)
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, NodeType & othernode,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
{
- return node.add(name,fn);
+ return node().add(name,othernode);
}
template <class Owner>
-prefix_ senf::console::SimpleCommandNode & senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type *)
{
- return node.add(name, boost::function<void (std::ostream&,ParseCommandInfo const &)>(
- boost::bind(fn,boost::ref(owner),_1,_2)));
+ return factory.create(*owner_, name, node());
}
template <class Owner>
-prefix_ senf::console::DirectoryNode &
-senf::console::senf_console_add_node(DirectoryNode & node, Owner & owner,
- std::string const & name, DirectoryNode & dir, int)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<Owner>::
+add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type *,
+ typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type *)
{
- return node.add(name, dir.thisptr());
+ return node().add(name, factory);
}
-template <class Node>
-prefix_ senf::console::DirectoryNode & senf::console::
-senf_console_add_node(DirectoryNode & dir, std::string const & name, Node const & node, int,
- typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type *)
-{
- return dir.add(name, node.node().thisptr());
-}
-
-#endif
-
///////////////////////////////////////////////////////////////////////////
// senf::console::ScopedDirectory<void>
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::ScopedDirectory<void>::add(std::string const & name, Object const & ob)
+
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<void>::add(std::string const & name,
+ boost::shared_ptr<NodeType> othernode)
+{
+ return node().add(name,othernode);
+}
+
+template <class NodeType>
+prefix_ NodeType & senf::console::ScopedDirectory<void>::
+add(std::string const & name, NodeType & othernode,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type *)
{
- return node().add(name, ob);
+ return node().add(name,othernode);
}
-template <class Object>
-prefix_ typename senf::console::NodeCreateTraits<Object>::result_type
-senf::console::ScopedDirectory<void>::add(std::string const & name, Object & ob)
+template <class Factory>
+prefix_ typename Factory::result_type senf::console::ScopedDirectory<void>::
+add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type *)
{
- return node().add(name, ob);
+ return node().add(name,factory);
}
///////////////////////////////cti.e///////////////////////////////////////
namespace senf {
namespace console {
- /** \brief Internal: Node creation helper traits (ScopedDirectory proxy)
-
- This class is used like NodeCreateTraits to customize the child node creation. This trait
- class is used however by the ScopedDirectory proxy.
- */
- template <class Owner, class Object>
- struct OwnerNodeCreateTraits
- {
- typedef BOOST_TYPEOF_TPL( senf_console_add_node(
- * static_cast<DirectoryNode *>(0),
- * static_cast<Owner *>(0),
- * static_cast<std::string const *>(0),
- * static_cast<Object *>(0),
- * static_cast<int *>(0)) ) base_type;
- typedef typename senf::remove_cvref<base_type>::type value_type;
-
- typedef typename value_type::node_type NodeType;
- typedef typename value_type::return_type result_type;
-
- /// Internal
- struct Creator {
- static result_type create(DirectoryNode & node, Owner & owner,
- std::string const & name, Object & ob);
- };
- };
-
+ namespace detail { struct OwnedNodeFactory {}; }
+
/** \brief Internal: Marker base class for all ScopedDirectory proxies
*/
class ScopedDirectoryBase
///@}
///////////////////////////////////////////////////////////////////////////
- template <class Object>
- typename OwnerNodeCreateTraits<Owner, Object const>::result_type add(
- std::string const & name, Object const & ob);
- ///< Create new child node
- /**< Adds a new child node to the (proxied)
- DirectoryNode. How the node is added is configured
- using the OwnerNodeCreateTraits template. The default
- implementation just forwards the call to the proxied
- directory node. */
-
- template <class Object>
- typename OwnerNodeCreateTraits<Owner, Object>::result_type add(
- std::string const & name, Object & ob);
- ///< Create new child node
- /**< \see add() */
+ template <class NodeType>
+ NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
+ template <class NodeType>
+ NodeType & add(std::string const & name, NodeType & node,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+ template <class Factory>
+ typename Factory::result_type add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
+ template <class Factory>
+ typename Factory::result_type add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0,
+ typename boost::disable_if< boost::is_convertible<Factory*, detail::OwnedNodeFactory*> >::type * = 0);
protected:
class ScopedDirectory<void> : public ScopedDirectoryBase
{
public:
- template <class Object>
- typename NodeCreateTraits<Object>::result_type add(std::string const & name,
- Object const & ob);
-
- template <class Object>
- typename NodeCreateTraits<Object>::result_type add(std::string const & name,
- Object & ob);
+ template <class NodeType>
+ NodeType & add(std::string const & name, boost::shared_ptr<NodeType> node);
+ template <class NodeType>
+ NodeType & add(std::string const & name, NodeType & node,
+ typename boost::enable_if< boost::is_convertible<NodeType &, GenericNode &> >::type * = 0);
+ template <class Factory>
+ typename Factory::result_type add(std::string const & name, Factory const & factory,
+ typename boost::enable_if< boost::is_convertible<Factory*, detail::NodeFactory*> >::type * = 0);
};
- template <class Owner, class Function>
- SimpleCommandNode & senf_console_add_node(
- DirectoryNode & node, Owner & owner, std::string const & name,
- SimpleCommandNode::Function fn, int);
-
- template <class Owner>
- SimpleCommandNode & senf_console_add_node(
- DirectoryNode & node, Owner & owner, std::string const & name,
- void (Owner::*fn)(std::ostream &, ParseCommandInfo const &), int);
-
- template <class Owner>
- DirectoryNode & senf_console_add_node(DirectoryNode & node, Owner & owner,
- std::string const & name, DirectoryNode & dir, int);
-
- template <class Node>
- DirectoryNode & senf_console_add_node(
- DirectoryNode & dir, std::string const & name, Node const & node, int,
- typename boost::enable_if< boost::is_convertible<Node*, ScopedDirectoryBase*> >::type * = 0);
#endif
}}
senf::console::ScopedDirectory<Self> dir;
TestObject() : dir(this) {
- dir.add("member", &Self::member);
+ dir.add("member", senf::console::factory::Command(senf::membind(&Self::member,this)));
}
void member(std::ostream & os, senf::console::ParseCommandInfo const &) {
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);
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") );
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)
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",
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(
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL( ss.str(), "true\n" "true\n" );
- dir.add("test2", &boolTest).formatter( senf::console::formatEnabledDisabled );
+ dir.add("test2", fty::Command(&boolTest).formatter( senf::console::formatEnabledDisabled ));
ss.str("");
SENF_CHECK_NO_THROW(
parser.parse("test/test2 0; test/test2 -1",
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(
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )),
senf::console::SyntaxErrorException );
- dir.add("member", &TestClass::test);
+ dir.add("member", fty::Command(&TestClass::test));
ss.str("");
SENF_CHECK_NO_THROW(
SENF_AUTO_UNIT_TEST(charAsString)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
std::stringstream ss;
- dir.add("test", boost::function<
- senf::console::CharAsString<char> (senf::console::CharAsString<char>)>(&charTest));
+ dir.add("test",
+ fty::Command<senf::console::CharAsString<char> (senf::console::CharAsString<char>)>(
+ &charTest));
ss.str("");
SENF_CHECK_NO_THROW(
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(
{}
template <class Variable>
+prefix_ typename senf::console::detail::QueryVariable<Variable>::Traits::Overload::ptr
+senf::console::detail::QueryVariable<Variable>::create(Variable const & var)
+{
+ return CreateOverload::create(Function(QueryVariable(var)));
+}
+
+template <class Variable>
prefix_ Variable const & senf::console::detail::QueryVariable<Variable>::operator()()
const
{
{}
template <class Variable>
+prefix_ typename senf::console::detail::SetVariable<Variable>::Traits::Overload::ptr
+senf::console::detail::SetVariable<Variable>::create(Variable & var)
+{
+ typename Traits::Overload::ptr overload (CreateOverload::create(Function(SetVariable(var))));
+ overload->arg(0).name = "new_value";
+ return overload;
+}
+
+template <class Variable>
prefix_ void senf::console::detail::SetVariable<Variable>::operator()(Variable const & value)
const
{
}
///////////////////////////////////////////////////////////////////////////
-// senf::console::ConstVariableAttributor<Variable>
+// senf::console::ConstVariableFactory<Variable>
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::doc(std::string const & doc)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::doc(std::string const & doc)
{
- queryOverload_.node().doc(doc);
+ doc_ = doc;
return *this;
}
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::shortdoc(std::string const & doc)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::shortdoc(std::string const & doc)
{
- queryOverload_.node().shortdoc(doc);
+ shortdoc_ = doc;
return *this;
}
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::ConstVariableAttributor<Variable>::formatter(Formatter formatter)
+prefix_ senf::console::factory::ConstVariableFactory<Variable>
+senf::console::factory::ConstVariableFactory<Variable>::formatter(Formatter formatter)
{
- queryOverload_.formatter(formatter);
+ queryOverload_->formatter(formatter);
return *this;
}
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>::
-ConstVariableAttributor(QueryOverload & queryOverload)
- : queryOverload_ (queryOverload)
-{}
-
-template <class Variable>
prefix_ senf::console::OverloadedCommandNode &
-senf::console::ConstVariableAttributor<Variable>::node()
+senf::console::factory::ConstVariableFactory<Variable>::create(DirectoryNode & dir,
+ std::string const & name)
const
{
- return queryOverload_.node();
+ OverloadedCommandNode & node (OverloadedCommandNode::insertOverload(dir, name, queryOverload_));
+ if (doc_) node.doc(*doc_);
+ if (shortdoc_) node.shortdoc(*shortdoc_);
+ return node;
}
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>::
-operator senf::console::OverloadedCommandNode &()
- const
-{
- return node();
-}
+prefix_ senf::console::factory::ConstVariableFactory<Variable>::
+ConstVariableFactory(Variable const & var)
+ : queryOverload_ (detail::QueryVariable<Variable>::create(var))
+{}
///////////////////////////////////////////////////////////////////////////
-// senf::console::VariableAttributor<Variable>
+// senf::console::VariableFactory<Variable>
template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::parser(Parser parser)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::parser(Parser parser)
{
- setOverload_.template arg<0>().parser = parser;
+ setOverload_->template arg<0>().parser = parser;
return *this;
}
template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::typeName(std::string const & name)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::typeName(std::string const & name)
{
- setOverload_.arg(0).type = name;
+ setOverload_->arg(0).type = name;
return *this;
}
template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::onChange(OnChangeHandler handler)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::onChange(OnChangeHandler handler)
{
- setOverload_.function(
+ setOverload_->function(
boost::bind(detail::SetVariable<Variable>(var_, handler),_2));
return *this;
}
template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::doc(std::string const & doc)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::doc(std::string const & doc)
{
- ConstVariableAttributor<Variable>::doc(doc);
+ ConstVariableFactory<Variable>::doc(doc);
return *this;
}
template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::shortdoc(std::string const & doc)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::shortdoc(std::string const & doc)
{
- ConstVariableAttributor<Variable>::shortdoc(doc);
+ ConstVariableFactory<Variable>::shortdoc(doc);
return *this;
}
template <class Variable>
-prefix_ typename senf::console::VariableAttributor<Variable>
-senf::console::VariableAttributor<Variable>::formatter(Formatter formatter)
+prefix_ typename senf::console::factory::VariableFactory<Variable>
+senf::console::factory::VariableFactory<Variable>::formatter(Formatter formatter)
{
- ConstVariableAttributor<Variable>::formatter(formatter);
+ ConstVariableFactory<Variable>::formatter(formatter);
return *this;
}
template <class Variable>
-prefix_
-senf::console::VariableAttributor<Variable>::VariableAttributor(QueryOverload & queryOverload,
- SetOverload & setOverload,
- Variable & var)
- : ConstVariableAttributor<Variable> (queryOverload), setOverload_ (setOverload), var_ (var)
-{}
-
-///////////////////////////////////////////////////////////////////////////
-
-template <class Variable, bool isConst>
-prefix_ senf::console::VariableAttributor<Variable>
-senf::console::detail::VariableNodeCreator<Variable,isConst>::add(DirectoryNode & node,
- std::string const & name,
- Variable & var)
+prefix_ senf::console::OverloadedCommandNode &
+senf::console::factory::VariableFactory<Variable>::create(DirectoryNode & dir,
+ std::string const & name)
+ const
{
- typename VariableAttributor<Variable>::SetOverload & setOverload (
- node.add(name, typename detail::SetVariable<Variable>::Function(
- detail::SetVariable<Variable>(var)))
- .arg("new_value")
- .overload() );
- typename VariableAttributor<Variable>::QueryOverload & queryOverload (
- node.add(name, typename detail::QueryVariable<Variable>::Function(
- detail::QueryVariable<Variable>(var))).overload() );
-
- return VariableAttributor<Variable>(queryOverload, setOverload, var);
+ OverloadedCommandNode & node (ConstVariableFactory<Variable>::create(dir,name));
+ node.add(setOverload_);
+ return node;
}
template <class Variable>
-prefix_ senf::console::ConstVariableAttributor<Variable>
-senf::console::detail::VariableNodeCreator<Variable, true>::add(DirectoryNode & node,
- std::string const & name,
- Variable & var)
-{
- typename VariableAttributor<Variable>::QueryOverload & queryOverload (
- node.add(name, typename detail::QueryVariable<Variable>::Function(
- detail::QueryVariable<Variable>(var))).overload() );
-
- return ConstVariableAttributor<Variable>(queryOverload);
-}
+prefix_ senf::console::factory::VariableFactory<Variable>::VariableFactory(Variable & var)
+ : ConstVariableFactory<Variable> (var),
+ setOverload_ (detail::SetVariable<Variable>::create(var)),
+ var_ (var)
+{}
-#ifndef DOXYGEN
+///////////////////////////////////////////////////////////////////////////
-template <class Variable>
-prefix_ senf::console::VariableAttributor<Variable> senf::console::
-senf_console_add_node(DirectoryNode & node, std::string const & name, Variable & var, int,
- typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type *,
- typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type *,
- typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type *)
+template <class Var>
+prefix_ senf::console::factory::VariableFactory<Var>
+senf::console::factory::Variable(Var & var)
{
- return detail::VariableNodeCreator<Variable>::add(node, name, var);
+ return VariableFactory<Var>(var);
}
-template <class Variable>
-prefix_ typename senf::console::detail::VariableNodeCreator<Variable>::result_type
-senf::console::senf_console_add_node(DirectoryNode & node, std::string const & name,
- boost::reference_wrapper<Variable> var, int)
+template <class Var>
+prefix_ senf::console::factory::VariableFactory<Var>
+senf::console::factory::Variable(boost::reference_wrapper<Var> var)
{
- return detail::VariableNodeCreator<Variable>::add(node, name, var.get());
+ return VariableFactory<Var>(var);
}
-template <class Variable, class Owner>
-prefix_ senf::console::VariableAttributor<Variable> senf::console::
-senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- Variable & var, int,
- typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type *,
- typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type *,
- typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type *)
+template <class Var>
+prefix_ senf::console::factory::ConstVariableFactory<Var>
+senf::console::factory::Variable(Var const & var)
{
- return detail::VariableNodeCreator<Variable>::add(node, name, var);
+ return ConstVariableFactory<Var>(var);
}
-template <class Variable, class Owner>
-prefix_ typename senf::console::detail::VariableNodeCreator<Variable>::result_type
-senf::console::senf_console_add_node(DirectoryNode & node, Owner &,
- std::string const & name,
- boost::reference_wrapper<Variable> var, int)
+template <class Var>
+prefix_ senf::console::factory::ConstVariableFactory<Var>
+senf::console::factory::Variable(boost::reference_wrapper<Var const> var)
{
- return detail::VariableNodeCreator<Variable>::add(node, name, var.get());
+ return ConstVariableFactory<Var>(var);
}
-#endif
-
///////////////////////////////cti.e///////////////////////////////////////
#undef prefix_
class ScopedDirectoryBase;
template <class Variable> class VariableAttributor;
-
-
-#ifndef DOXYGEN
-
- template <class Variable>
- VariableAttributor<Variable> senf_console_add_node(
- DirectoryNode & node, std::string const & name, Variable & var, int,
- typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
- typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type * = 0,
- typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
-
- template <class Variable>
- typename detail::VariableNodeCreator<Variable>::result_type
- senf_console_add_node(DirectoryNode & node, std::string const & name,
- boost::reference_wrapper<Variable> var, int);
-
- template <class Variable, class Owner>
- VariableAttributor<Variable> senf_console_add_node(
- DirectoryNode & node, Owner & owner, std::string const & name, Variable & var, int,
- typename boost::disable_if< boost::is_convertible<Variable*, ScopedDirectoryBase*> >::type * = 0,
- typename boost::disable_if< boost::is_convertible<Variable*, GenericNode*> >::type * = 0,
- typename boost::disable_if_c<detail::ParsedCommandTraits<Variable>::is_callable>::type * = 0);
-
- template <class Variable, class Owner>
- typename detail::VariableNodeCreator<Variable>::result_type
- senf_console_add_node(DirectoryNode & node, Owner & owner, std::string const & name,
- boost::reference_wrapper<Variable> var, int);
-
-#endif
+namespace factory {
/** \brief Variable command attributes (const)
- \see VariableAttributor
+ \see VariableFactory
*/
template <class Variable>
- class ConstVariableAttributor
+ class ConstVariableFactory
+ : public detail::NodeFactory
{
public:
typedef typename detail::QueryVariable<Variable>::Traits::Overload QueryOverload;
typedef typename QueryOverload::Formatter Formatter;
typedef OverloadedCommandNode node_type;
- typedef ConstVariableAttributor return_type;
-
- ConstVariableAttributor doc(std::string const & doc);
- ConstVariableAttributor shortdoc(std::string const & doc);
- ConstVariableAttributor formatter(Formatter formatter);
+ typedef OverloadedCommandNode & result_type;
- OverloadedCommandNode & node() const; ///< Return the node object
- operator OverloadedCommandNode & () const; ///< Automatically convert to node object
+ ConstVariableFactory doc(std::string const & doc);
+ ConstVariableFactory shortdoc(std::string const & doc);
+ ConstVariableFactory formatter(Formatter formatter);
- protected:
- explicit ConstVariableAttributor(QueryOverload & queryOverload);
+ OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+
+ explicit ConstVariableFactory(Variable const & var);
private:
- QueryOverload & queryOverload_;
-
- friend class detail::VariableNodeCreator<Variable const>;
+ typename QueryOverload::ptr queryOverload_;
+ boost::optional<std::string> doc_;
+ boost::optional<std::string> shortdoc_;
};
/** \brief Variable command attributes
\ingroup console_commands
*/
template <class Variable>
- class VariableAttributor
- : public ConstVariableAttributor<Variable>
+ class VariableFactory
+ : public ConstVariableFactory<Variable>
{
public:
typedef typename detail::SetVariable<Variable>::Traits::Overload SetOverload;
typedef typename detail::ArgumentInfo<typename SetOverload::arg1_type>::Parser Parser;
typedef typename detail::SetVariable<Variable>::OnChangeHandler OnChangeHandler;
- typedef OverloadedCommandNode node_type;
- typedef VariableAttributor return_type;
-
- typedef typename ConstVariableAttributor<Variable>::Formatter Formatter;
- typedef typename ConstVariableAttributor<Variable>::QueryOverload QueryOverload;
-
- VariableAttributor doc(std::string const & doc); ///< Set documentation of the variable
- VariableAttributor shortdoc(std::string const & doc); ///< Set short documentation
- VariableAttributor formatter(Formatter formatter); ///< Set formatter
- /**< The \a formatter must be a callable with a signature
- compatible with
- \code
- void formatter(Variable const & value, std::ostream & os);
- \endcode
- The \a formatter takes the return value of the call \a
- value and writes it properly formated to \a os. */
-
- VariableAttributor parser(Parser parser); ///< Set argument parser
- /**< The parser is an arbitrary callable object with
- the signature
- \code
- void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
- \endcode
-
- where \c value_type is the type of the overload
- parameter. The parser must read and parse the complete
- \a tokens range and return the parsed value in \a
- out. If the parser fails, it must raise a
- senf::console::SyntaxErrorException. */
- VariableAttributor typeName(std::string const & name); ///< Set name of the variable type
- VariableAttributor onChange(OnChangeHandler handler); ///< Set change callback
- /**< The \a handler callback is called, whenever the value
- of the variable is changed. The new value has already
- been set, when the callback is called, the old value is
- passed to the callback. The callback must have a
- signature compatible to
- \code
- void handler(Variable const & oldValue);
- \endcode */
-
+
+ typedef typename ConstVariableFactory<Variable>::Formatter Formatter;
+ typedef typename ConstVariableFactory<Variable>::QueryOverload QueryOverload;
+
+ VariableFactory doc(std::string const & doc); ///< Set documentation of the variable
+ VariableFactory shortdoc(std::string const & doc); ///< Set short documentation
+ VariableFactory formatter(Formatter formatter); ///< Set formatter
+ /**< The \a formatter must be a callable with a signature
+ compatible with
+ \code
+ void formatter(Variable const & value, std::ostream & os);
+ \endcode
+ The \a formatter takes the return value of the call \a
+ value and writes it properly formated to \a os. */
+ VariableFactory parser(Parser parser); ///< Set argument parser
+ /**< The parser is an arbitrary callable object with
+ the signature
+ \code
+ void parser(senf::console::ParseCommandInfo::TokensRange const & tokens, value_type & out);
+ \endcode
+
+ where \c value_type is the type of the overload
+ parameter. The parser must read and parse the complete
+ \a tokens range and return the parsed value in \a
+ out. If the parser fails, it must raise a
+ senf::console::SyntaxErrorException. */
+ VariableFactory typeName(std::string const & name); ///< Set name of the variable type
+ VariableFactory onChange(OnChangeHandler handler); ///< Set change callback
+ /**< The \a handler callback is called, whenever the value
+ of the variable is changed. The new value has already
+ been set, when the callback is called, the old value is
+ passed to the callback. The callback must have a
+ signature compatible to
+ \code
+ void handler(Variable const & oldValue);
+ \endcode */
+
+ OverloadedCommandNode & create(DirectoryNode & dir, std::string const & name) const;
+
+ explicit VariableFactory(Variable & var);
+
protected:
private:
- VariableAttributor(QueryOverload & queryOverload, SetOverload & setOverload,
- Variable & var);
-
- SetOverload & setOverload_;
+ typename SetOverload::ptr setOverload_;
Variable & var_;
-
- friend class detail::VariableNodeCreator<Variable>;
};
-}}
+
+ template <class Var>
+ VariableFactory<Var> Variable(Var & var);
+
+ template <class Var>
+ VariableFactory<Var> Variable(boost::reference_wrapper<Var> var);
+
+ template <class Var>
+ ConstVariableFactory<Var> Variable(Var const & var);
+
+ template <class Var>
+ ConstVariableFactory<Var> Variable(boost::reference_wrapper<Var const> var);
+
+}}}
///////////////////////////////hh.e////////////////////////////////////////
//#include "Variables.cci"
typedef Variable const & Signature ();
typedef boost::function<Signature> Function;
typedef detail::ParsedCommandTraits<Signature> Traits;
+ typedef detail::CreateParsedCommandOverload<Traits> CreateOverload;
typedef Variable const & result_type;
QueryVariable(Variable const & var);
+ static typename Traits::Overload::ptr create(Variable const & var);
+
Variable const & operator()() const;
Variable const & var_;
typedef void Signature (Variable &);
typedef boost::function<Signature> Function;
typedef detail::ParsedCommandTraits<Signature> Traits;
+ typedef detail::CreateParsedCommandOverload<Traits> CreateOverload;
typedef boost::function<void (Variable const &)> OnChangeHandler;
typedef void result_type;
SetVariable(Variable & var, OnChangeHandler handler = OnChangeHandler());
+
+ static typename Traits::Overload::ptr create(Variable & var);
void operator()(Variable const & value) const;
OnChangeHandler handler_;
};
- template <class Variable, bool isConst=boost::is_const<Variable>::value>
- struct VariableNodeCreator
- {
- typedef VariableAttributor<Variable> result_type;
- static VariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
- Variable & var);
- };
-
- template <class Variable>
- struct VariableNodeCreator<Variable, true>
- {
- typedef ConstVariableAttributor<Variable> result_type;
- static ConstVariableAttributor<Variable> add(DirectoryNode & node, std::string const & name,
- Variable & var);
- };
-
#endif
}}}
SENF_AUTO_UNIT_TEST(variables)
{
+ namespace fty = senf::console::factory;
+
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
int var (5);
std::stringstream ss;
- dir.add("var", var)
+ dir.add("var", fty::Variable(var)
.doc("Current blorg limit")
.formatter(&testFormatter)
.parser(&testParser)
.typeName("number")
- .onChange(&testCallback);
+ .onChange(&testCallback)
+ );
parser.parse("test/var; test/var 10; test/var",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 ));
BOOST_CHECK_EQUAL( ss.str(), "[5]\n[0]\n" );
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 {
senf::console::ScopedDirectory<Test2> dir;
Test2() : dir(this), var_(0)
- { dir.add("var", boost::ref(var_)); }
+ { dir.add("var", senf::console::factory::Variable(boost::ref(var_))); }
private:
int var_;
IOStreamTarget (getNodename(filename, nodename), ofstream_t::member),
file_ (filename)
{
+ namespace fty = senf::console::factory;
+
if (! ofstream_t::member)
SENF_THROW_SYSTEM_EXCEPTION("logfile open") << ": " << filename;
- consoleDir().add( "reopen", senf::membind(
- static_cast<void (FileTarget::*)()>(&FileTarget::reopen),
- this))
- .doc("Reopen logfile");
- consoleDir().add("reopen", senf::membind(
- static_cast<void (FileTarget::*)(std::string const &)>(&FileTarget::reopen),
- this))
- .arg("filename","new filename")
- .overloadDoc("Reopen logfile under new name");
- consoleDir().add("file", boost::cref(file_))
- .doc("Show filename log messages are sent to");
+ consoleDir()
+ .add( "reopen",
+ fty::BoundCommand(this, SENF_MEMFNP(void, FileTarget, reopen, ()))
+ .doc("Reopen logfile") );
+ consoleDir()
+ .add("reopen",
+ fty::BoundCommand(this, SENF_MEMFNP(void, FileTarget, reopen, (std::string const &)))
+ .arg("filename","new filename")
+ .overloadDoc("Reopen logfile under new name") );
+ consoleDir()
+ .add("file", fty::Variable(boost::cref(file_))
+ .doc("Show filename log messages are sent to") );
}
prefix_ void senf::log::FileTarget::reopen()
prefix_ senf::log::FileTarget::RegisterConsole::RegisterConsole()
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
- detail::TargetRegistry::instance().consoleDir().add("file-target",&RegisterConsole::create)
- .arg("filename", "name of logfile")
- .arg("nodename", "name of node in console. Defaults to the files basename",
- kw::default_value = "")
- .doc("Create new file target. Examples:\n"
- "\n"
- "Create new file target '/var/log/example.log\n"
- " $ file-target \"/var/log/example.log\"\n"
- " <Directory '/sys/log/example.log'>\n"
- "\n"
- "In a configuration file, create new file target '/var/log/example.log' and set\n"
- "some parameters (If written on one line, this works at the console too:\n"
- " /sys/log/file-target \"/var/log/example.log\" mainlog {\n"
- " route (IMPORTANT); # route all important messages\n"
- " timeFormat \"\"; # use non-formatted time format\n"
- " showArea false; # don't show log area\n"
- " }\n");
+ detail::TargetRegistry::instance().consoleDir()
+ .add("file-target", fty::Command(&RegisterConsole::create)
+ .arg("filename", "name of logfile")
+ .arg("nodename", "name of node in console. Defaults to the files basename",
+ kw::default_value = "")
+ .doc("Create new file target. Examples:\n"
+ "\n"
+ "Create new file target '/var/log/example.log\n"
+ " $ file-target \"/var/log/example.log\"\n"
+ " <Directory '/sys/log/example.log'>\n"
+ "\n"
+ "In a configuration file, create new file target '/var/log/example.log' and set\n"
+ "some parameters (If written on one line, this works at the console too:\n"
+ " /sys/log/file-target \"/var/log/example.log\" mainlog {\n"
+ " route (IMPORTANT); # route all important messages\n"
+ " timeFormat \"\"; # use non-formatted time format\n"
+ " showArea false; # don't show log area\n"
+ " }\n") );
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
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)
prefix_ senf::log::SyslogTarget::RegisterConsole::RegisterConsole()
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
- detail::TargetRegistry::instance().consoleDir().add("syslog-target",&RegisterConsole::create)
- .arg("facility", "syslog facility to send messages to. One of\n"
- " AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
- " UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
- kw::default_value = USER)
- .doc("Create new syslog target. Examples:\n"
- "\n"
- "Create new syslog target\n"
- " $ syslog-target\n"
- " <Directory '/sys/log/syslog'>\n"
- "\n"
- "In a configuration file, create new syslog target and set some parameters (If\n"
- "written on one line, this works at the console too:\n"
- " /sys/log/syslog-target LOCAL2 {\n"
- " route (IMPORTANT); # route all important messages\n"
- " timeFormat \"\"; # use non-formatted time format\n"
- " showArea false; # don't show log area\n"
- " }\n");
+ detail::TargetRegistry::instance().consoleDir()
+ .add("syslog-target",fty::Command(&RegisterConsole::create)
+ .arg("facility", "syslog facility to send messages to. One of\n"
+ " AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+ " UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
+ kw::default_value = USER)
+ .doc("Create new syslog target. Examples:\n"
+ "\n"
+ "Create new syslog target\n"
+ " $ syslog-target\n"
+ " <Directory '/sys/log/syslog'>\n"
+ "\n"
+ "In a configuration file, create new syslog target and set some parameters (If\n"
+ "written on one line, this works at the console too:\n"
+ " /sys/log/syslog-target LOCAL2 {\n"
+ " route (IMPORTANT); # route all important messages\n"
+ " timeFormat \"\"; # use non-formatted time format\n"
+ " showArea false; # don't show log area\n"
+ " }\n") );
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
prefix_ void senf::log::SyslogUDPTarget::init()
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
consoleDir().remove("format");
- consoleDir().add("format", senf::membind(&SyslogUDPTarget::consoleFormat, this))
- .doc("Show the current log message format.");
- consoleDir().add("syslog", senf::membind(
- static_cast<void (SyslogUDPTarget::*)(bool)>(&SyslogUDPTarget::syslog),
- this))
- .arg("flag","new syslog format state",
- kw::default_value=true)
- .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
- "state, the udp target will send out minimal but valid syslog format messages.\n"
- "\n"
- "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
- "sent using plain UDP.");
+ consoleDir()
+ .add("format", fty::BoundCommand(this, &SyslogUDPTarget::consoleFormat)
+ .doc("Show the current log message format.") );
+ consoleDir()
+ .add("syslog", fty::BoundCommand(this, SENF_MEMFNP(void, SyslogUDPTarget, syslog, (bool)))
+ .arg("flag","new syslog format state",
+ kw::default_value=true)
+ .doc("Change the syslog format flag. By default, syslog formating is enabled. In this\n"
+ "state, the udp target will send out minimal but valid syslog format messages.\n"
+ "\n"
+ "Disabling syslog format will remove the syslog prefix. Log messages will then be\n"
+ "sent using plain UDP.") );
}
prefix_ void senf::log::SyslogUDPTarget::v_write(time_type timestamp, std::string const & stream,
prefix_ senf::log::SyslogUDPTarget::RegisterConsole::RegisterConsole()
{
namespace kw = senf::console::kw;
-
- detail::TargetRegistry::instance().consoleDir().add(
- "udp-target",
- static_cast<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &, LogFacility)>(
- &RegisterConsole::create))
- .arg("address", "target address to send log messages to")
- .arg("facility", "syslog facility to send messages to. One of\n"
- " AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
- " UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
- kw::default_value = USER)
- .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
- "number is omitted, it defaults to the default syslog port 514. Examples:\n"
- "\n"
- "Create new udp target sending messages to the syslog daemon running at localhost\n"
- " $ udp-target localhost\n"
- " <Directory '/sys/log/udp-127.0.0.1:514'>\n"
- "\n"
- "In a configuration file, create new udp target and set some parameters (If\n"
- "written on one line, this works at the console too:\n"
- " /sys/log/udp-target localhost:2345 LOCAL2 {\n"
- " route (IMPORTANT); # route all important messages\n"
- " timeFormat \"\"; # use non-formatted time format\n"
- " showArea false; # don't show log area\n"
- " syslog false; # no syslog format, just plain udp\n"
- " }\n");
- detail::TargetRegistry::instance().consoleDir().add(
- "udp-target",
- static_cast<senf::console::DirectoryNode::ptr (*)(INet4Address const &, LogFacility)>(
- &RegisterConsole::create))
- .arg("address")
- .arg("facility", kw::default_value = USER);
- detail::TargetRegistry::instance().consoleDir().add(
- "udp-target",
- static_cast<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &, LogFacility)>(
- &RegisterConsole::create))
- .arg("address")
- .arg("facility", kw::default_value = USER);
- detail::TargetRegistry::instance().consoleDir().add(
- "udp-target",
- static_cast<senf::console::DirectoryNode::ptr (*)(INet6Address const &, LogFacility)>(
- &RegisterConsole::create))
- .arg("address")
- .arg("facility", kw::default_value = USER);
+ namespace fty = senf::console::factory;
+
+ detail::TargetRegistry::instance().consoleDir()
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet4SocketAddress const &,
+ LogFacility)
+ >(&RegisterConsole::create)
+ .arg("address", "target address to send log messages to")
+ .arg("facility", "syslog facility to send messages to. One of\n"
+ " AUTHPRIV CRON DAEMON FTP KERN LPR MAIL NEWS SYSLOG USER\n"
+ " UUCP LOCAL0 LOCAL1 LOCAL2 LOCAL3 LOCAL4 LOCAL5 LOCAL6 LOCAL7",
+ kw::default_value = USER)
+ .doc("Create new udp target. The {address} can be an IPv4 or IPv6 address. If the port\n"
+ "number is omitted, it defaults to the default syslog port 514. Examples:\n"
+ "\n"
+ "Create new udp target sending messages to the syslog daemon running at localhost\n"
+ " $ udp-target localhost\n"
+ " <Directory '/sys/log/udp-127.0.0.1:514'>\n"
+ "\n"
+ "In a configuration file, create new udp target and set some parameters (If\n"
+ "written on one line, this works at the console too:\n"
+ " /sys/log/udp-target localhost:2345 LOCAL2 {\n"
+ " route (IMPORTANT); # route all important messages\n"
+ " timeFormat \"\"; # use non-formatted time format\n"
+ " showArea false; # don't show log area\n"
+ " syslog false; # no syslog format, just plain udp\n"
+ " }\n") );
+ detail::TargetRegistry::instance().consoleDir()
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet4Address const &,
+ LogFacility)
+ >(&RegisterConsole::create)
+ .arg("address")
+ .arg("facility", kw::default_value = USER) );
+ detail::TargetRegistry::instance().consoleDir()
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet6SocketAddress const &,
+ LogFacility)
+ >(&RegisterConsole::create)
+ .arg("address")
+ .arg("facility", kw::default_value = USER) );
+ detail::TargetRegistry::instance().consoleDir()
+ .add("udp-target",
+ fty::Command<senf::console::DirectoryNode::ptr (*)(INet6Address const &,
+ LogFacility)
+ >(&RegisterConsole::create)
+ .arg("address")
+ .arg("facility", kw::default_value = USER) );
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
prefix_ senf::log::Target::Target(std::string const & name)
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
detail::TargetRegistry::instance().registerTarget(this, name);
- consoleDir_().add("list", senf::membind(&Target::consoleList, this))
- .doc("Show routing table\n"
- "\n"
- "Columns:\n"
- " # rule index\n"
- " STREAM stream to match, empty to match all streams\n"
- " AREA area to match, empty to match all targets\n"
- " LEVEL match messages with level above this. Log levels in increasing order\n"
- " are:\n"
- " verbose, notice, message, important, critical, fatal\n"
- " ACTION action to take: accept or reject");
- consoleDir_().add("route", senf::membind(&Target::consoleRoute, this))
- .arg("index", "index at which to insert new rule")
- .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
- " and log level. You may specify any combination of these parameterse\n"
- " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
- " to list all valid streams and areas. Valid log levels are:\n"
- " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
- .arg("action", "routing action, one of: ACCEPT, REJECT",
- kw::default_value=ACCEPT)
- .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
- "with the first entry. The action of the first matching entry determines the\n"
- "handling of the message.\n"
- "\n"
- "Examples:\n"
- "\n"
- " route ()\n"
- " route all messages to this target.\n"
- "\n"
- " route 1 (my::Class)\n"
- " route all messages which are in the my::Class area. Insert this route after\n"
- " the first route,\n"
- "\n"
- " route (senf::log::Debug VERBOSE) REJECT\n"
- " route (VERBOSE)\n"
- " route all messages not in the senf::log::Debug stream to the current area.\n"
- "\n"
- "The additional optional index argument identifies the position in the routing table\n"
- "where the new routing entry will be added. Positive numbers count from the\n"
- "beginning, 0 being the first routing entry. Negative values count from the end.");
- consoleDir_().add("route", boost::function<void (detail::LogParameters, action_t)>(
- boost::bind(&Target::consoleRoute, this, -1, _1, _2)))
- .arg("parameters")
- .arg("action", kw::default_value=ACCEPT);
- consoleDir_().add("unroute",
- senf::membind(static_cast<void (Target::*)(int)>(&Target::unroute), this))
- .arg("index", "index of routing entry to remove")
- .overloadDoc("Remove routing entry with the given index");
- consoleDir_().add("unroute", senf::membind(&Target::consoleUnroute, this))
- .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
- " and log level. You may specify any combination of these parameterse\n"
- " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
- " to list all valid streams and areas. Valid log levels are:\n"
- " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
- .arg("action", "routing action, one of: ACCEPT, REJECT",
- kw::default_value=ACCEPT)
- .overloadDoc("Remove the routing entry matching the specified arguments.");
- consoleDir_().add("flush", senf::membind(&Target::flush, this))
- .doc("Remove all routing entries clearing the routing table. This will disable all\n"
- "logging output on this target.");
+ consoleDir_()
+ .add("list", fty::BoundCommand(this, &Target::consoleList)
+ .doc("Show routing table\n"
+ "\n"
+ "Columns:\n"
+ " # rule index\n"
+ " STREAM stream to match, empty to match all streams\n"
+ " AREA area to match, empty to match all targets\n"
+ " LEVEL match messages with level above this. Log levels in increasing order\n"
+ " are:\n"
+ " verbose, notice, message, important, critical, fatal\n"
+ " ACTION action to take: accept or reject") );
+ consoleDir_()
+ .add("route", fty::BoundCommand(this, &Target::consoleRoute)
+ .arg("index", "index at which to insert new rule")
+ .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+ " and log level. You may specify any combination of these parameterse\n"
+ " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+ " to list all valid streams and areas. Valid log levels are:\n"
+ " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
+ .arg("action", "routing action, one of: ACCEPT, REJECT",
+ kw::default_value=ACCEPT)
+ .doc("Add routing entry. Log messages are matched against the routing table beginning\n"
+ "with the first entry. The action of the first matching entry determines the\n"
+ "handling of the message.\n"
+ "\n"
+ "Examples:\n"
+ "\n"
+ " route ()\n"
+ " route all messages to this target.\n"
+ "\n"
+ " route 1 (my::Class)\n"
+ " route all messages which are in the my::Class area. Insert this route after\n"
+ " the first route,\n"
+ "\n"
+ " route (senf::log::Debug VERBOSE) REJECT\n"
+ " route (VERBOSE)\n"
+ " route all messages not in the senf::log::Debug stream to the current area.\n"
+ "\n"
+ "The additional optional index argument identifies the position in the routing table\n"
+ "where the new routing entry will be added. Positive numbers count from the\n"
+ "beginning, 0 being the first routing entry. Negative values count from the end.") );
+ consoleDir_()
+ .add("route", fty::Command<void (detail::LogParameters, action_t)>(
+ boost::bind(&Target::consoleRoute, this, -1, _1, _2))
+ .arg("parameters")
+ .arg("action", kw::default_value=ACCEPT) );
+ consoleDir_()
+ .add("unroute",
+ fty::BoundCommand(this, static_cast<void (Target::*)(int)>(&Target::unroute))
+ .arg("index", "index of routing entry to remove")
+ .overloadDoc("Remove routing entry with the given index") );
+ consoleDir_()
+ .add("unroute", fty::BoundCommand(this, &Target::consoleUnroute)
+ .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+ " and log level. You may specify any combination of these parameterse\n"
+ " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+ " to list all valid streams and areas. Valid log levels are:\n"
+ " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL")
+ .arg("action", "routing action, one of: ACCEPT, REJECT",
+ kw::default_value=ACCEPT)
+ .overloadDoc("Remove the routing entry matching the specified arguments.") );
+ consoleDir_()
+ .add("flush", fty::BoundCommand(this, &Target::flush)
+ .doc("Remove all routing entries clearing the routing table. This will disable all\n"
+ "logging output on this target.") );
}
prefix_ senf::log::Target::~Target()
prefix_ void senf::log::detail::TargetRegistry::dynamicTarget(std::auto_ptr<Target> target)
{
- target->consoleDir().add("remove", boost::function<void ()>(
- boost::bind(
- &TargetRegistry::consoleRemoveTarget, this, target.get())))
- .doc("Remove target.");
+ namespace fty = senf::console::factory;
+
+ target->consoleDir()
+ .add("remove", fty::Command<void ()>(
+ boost::bind(&TargetRegistry::consoleRemoveTarget, this, target.get()))
+ .doc("Remove target.") );
dynamicTargets_.insert(target.release());
}
: fallbackRouting_(true)
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
console::sysdir().add("log", consoleDir_());
- consoleDir_().add("areas", senf::membind(&TargetRegistry::consoleAreas, this))
- .doc("List all areas");
- consoleDir_().add("streams", senf::membind(&TargetRegistry::consoleStreams, this))
- .doc("List all streams");
- consoleDir_().add("message", senf::membind(&TargetRegistry::consoleWrite, this))
- .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
- " and log level. You may specify any combination of these parameterse\n"
- " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
- " to list all valid streams and areas. Valid log levels are:\n"
- " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL",
- kw::default_value = LogParameters::defaultParameters())
- .arg("message", "message to write")
- .doc("Write log message.\n"
- "\n"
- "Examples:\n"
- " message \"Test\";\n"
- " message (senf::log::DefaultArea NOTICE) \"Test notice\";\n"
- " message (FATAL) \"Program on fire\";\n"
- " message (VERBOSE senf::log::Debug) \"Debug message\";");
- consoleDir_().add("self", senf::membind(&TargetRegistry::consoleSelf, this))
- .doc("Get the log directory of the current network client. Example usage:\n"
- "\n"
- "Just get the log config directory\n"
- " $ /sys/log/self\n"
- " <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n"
- "\n"
- "Route all messages to the currently connected client\n"
- " $ /sys/log/self { route (); }");
+ consoleDir_()
+ .add("areas", fty::BoundCommand(this, &TargetRegistry::consoleAreas)
+ .doc("List all areas") );
+ consoleDir_()
+ .add("streams", fty::BoundCommand(this, &TargetRegistry::consoleStreams)
+ .doc("List all streams") );
+ consoleDir_()
+ .add("message", fty::BoundCommand(this, &TargetRegistry::consoleWrite)
+ .arg("parameters", "log parameters. The log parameters select the log stream, log area\n"
+ " and log level. You may specify any combination of these parameterse\n"
+ " in any order. Use the '/sys/log/stream' and '/sys/log/areas' commands\n"
+ " to list all valid streams and areas. Valid log levels are:\n"
+ " VERBOSE NOTICE MESSAGE IMPORTANT CRITICAL FATAL",
+ kw::default_value = LogParameters::defaultParameters())
+ .arg("message", "message to write")
+ .doc("Write log message.\n"
+ "\n"
+ "Examples:\n"
+ " message \"Test\";\n"
+ " message (senf::log::DefaultArea NOTICE) \"Test notice\";\n"
+ " message (FATAL) \"Program on fire\";\n"
+ " message (VERBOSE senf::log::Debug) \"Debug message\";") );
+ consoleDir_()
+ .add("self", fty::BoundCommand(this, &TargetRegistry::consoleSelf)
+ .doc("Get the log directory of the current network client. Example usage:\n"
+ "\n"
+ "Just get the log config directory\n"
+ " $ /sys/log/self\n"
+ " <Directory '/sys/log/client-xxx.xxx.xxx.xxx:xxx'>\n"
+ "\n"
+ "Route all messages to the currently connected client\n"
+ " $ /sys/log/self { route () ); }") );
}
prefix_ senf::log::detail::TargetRegistry::~TargetRegistry()
#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
}
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 &
senf::console::DirectoryNode & dir)
{
namespace kw = senf::console::kw;
+ namespace fty = senf::console::factory;
- dir.add("logger", boost::function<void (std::string const &)>(
- boost::bind(&consoleCreate, boost::ref(stats), rank, _1)))
- .arg("prefix","Optional prefix string to add to each log message",
- kw::default_value = "")
- .doc("Send log messages to statistics log stream");
+ dir.add("logger", fty::Command<void (std::string const &)>(
+ boost::bind(&consoleCreate, boost::ref(stats), rank, _1))
+ .arg("prefix","Optional prefix string to add to each log message",
+ kw::default_value = "")
+ .doc("Send log messages to statistics log stream") );
}
prefix_ void RegisterStatisticsLogger::consoleCreate(senf::StatisticsBase & stats,