From this information the command callback gets a list of arguments or tokens which then can be
interpreted in an arbitrary way.
\code
- void test1(std::ostream & os, senf::console::ParseCommandInfo const & command)
+ void fun1(std::ostream & os, senf::console::ParseCommandInfo const & command)
{
// We take exactly one argument
if (command.arguments().size() != 1)
'doc()':
\code
senf::console::root()
- .add("test1", &test1)
+ .add("test1", &fun1)
.doc("Usage:\n"
" test1 arg\n"
"\n"
feature allows to register (almost) arbitrary callbacks.
\code
- std::string test2(std::string const & arg)
+ std::string fun(std::string const & arg)
{
return arg;
}
senf::console::DirectoryNode.
\code
senf::console::root()
- .add("test2", &test2);
+ .add("test2", &fun2);
\endcode
The functionality is now identical to \c test1:
\htmlonly
raised.
\code
- void test3(std::ostream & os, unsigned n, std::string text)
+ void fun3(std::ostream & os, unsigned n, std::string text)
{
// It's perfectly valid to check additional constraints here and throw a
// SyntaxErrorException. In this case, the next overload will be tried. However, you must
using namespace senf::console::kw;
senf::console::root()
- .add("test3", &test3)
+ .add("test3", &fun3)
.doc("Echo text to the console")
.overloadDoc("Repeat 'text' for 'n' lines")
.arg( name = "n", description = "Number of repetitions" )
.arg( name = "text", description = "Message to output" );
senf::console::root()
- .add("test3", &test2)
+ .add("test3", &fun2)
.overloadDoc("Echo the 'text' argument")
- .arg( name = "text", description = "Message to output" );
+ .arg( name = "text" );
\endcode
- We can now call \c test2 with one or two arguments:
+ We can now call \c test3 with one or two arguments:
\htmlonly
<pre>
using namespace senf::console::kw;
senf::console::root()
- .add("test4", &test2b)
- .arg()
- .arg( default_value = "ok" );
+ .add("test4", &fun3)
+ .arg( name = "n", description = "Number of repetitions", default_value = 1 )
+ .arg( name = "text", description = "Message to output" );
\endcode
- (Default values must not necessarily be declared in the callback function too.) Of course,
- default values can be used together with overloading.
- There must be no argument without default value after an argument with a default value
- declared. This fill fail at compile time.
+ (Default values must not necessarily be declared in the callback function too.) Of course,
+ default values can be used together with overloading. Default (optional) value support is quite
+ flexible, it is not mandatory, for default values to be specified only for the trailing
+ arguments.
+
+ \htmlonly
+ <pre>
+ server:/$ test4 echo
+ echo
+ server:/$ test4 4 ok
+ ok
+ ok
+ ok
+ ok
+ server:/$ help test4
+ Usage:
+ test4 n:unsigned [text:string]
+
+ With:
+ n Number of repetitions
+ text Message to output
+ default value: ok
+ server:/$
+ </pre>
+ \endhtmlonly
\subsection console_auto_summary Attribute summary
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
+#include <boost/preprocessor/arithmetic/sub.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_const.hpp>
v_execute(std::ostream & os, ParseCommandInfo const & command)
const
{
- if ( command.arguments().size() > BOOST_PP_ITERATION()
- || (command.arguments().size() < BOOST_PP_ITERATION()
- && ! arg( command.arguments().size() ).hasDefault) )
+ if ( command.arguments().size() > BOOST_PP_ITERATION() )
throw SyntaxErrorException("invalid number of arguments");
+ int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() );
- ParseCommandInfo::argument_iterator i (command.arguments().begin());
- ParseCommandInfo::argument_iterator const i_end (command.arguments().end());
+ typedef typename boost::range_const_reverse_iterator<ParseCommandInfo::ArgumentsRange>::type
+ riterator;
+ riterator i (boost::rbegin(command.arguments()));
+ riterator const i_end (boost::rend(command.arguments()));
# define mpp_l(z,n,d) \
+ if (i == i_end) \
+ throw SyntaxErrorException("invalid number of arguments"); \
mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue); \
- if (i != i_end) \
+ if (! arg(n).hasDefault || nDefaults-- <= 0) \
ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) );
- BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+# define mpp_l_(z,n,d) mpp_l(z, BOOST_PP_SUB(BOOST_PP_DEC(BOOST_PP_ITERATION()), n), d)
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l_, _ )
# undef mpp_l
+# undef mpp_l_
detail::CheckVoidReturn<typename traits::result_type>::call(
boost::bind(function_, boost::ref(os)