///////////////////////////////////////////////////////////////////////////
// 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>::
+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)
+ : ParsedCommandAttributor<Overload> (overload, index)
+{}
+
template <class Overload, class Self>
prefix_ Self
-senf::console::ParsedArgumentAttributorBase<Overload,Self>::doc(std::string const & doc)
+senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::doc(std::string const & doc)
const
{
this->ParsedCommandAttributorBase::nodeDoc(doc);
}
template <class Overload, class Self>
-prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self>::
+prefix_ Self senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
overloadDoc(std::string const & doc)
const
{
template <class Overload, class Self>
prefix_
-senf::console::ParsedArgumentAttributorBase<Overload,Self>::
+senf::console::ParsedArgumentAttributorBase<Overload,Self,void>::
ParsedArgumentAttributorBase(Overload & overload, unsigned index)
: ParsedCommandAttributor<Overload> (overload, index)
{}
senf::membind(fn,&owner)) ) );
}
-///////////////////////////////////////////////////////////////////////////
-// senf::console::detail::CheckVoidReturn<Type>
-
-template <class Type>
-template <class Fn>
-prefix_ void senf::console::detail::CheckVoidReturn<Type>::call(Fn fn, std::ostream & os)
-{
- ReturnValueTraits<Type>::format(fn(),os);
- os << "\n";
-}
-
-template <class Fn>
-prefix_ void senf::console::detail::CheckVoidReturn<void>::call(Fn fn, std::ostream & os)
-{
- fn();
-}
-
///////////////////////////////cti.e///////////////////////////////////////
#undef prefix_
\c std::ostream first argument.
\implementation This class is specialized for each supported number of command arguments.
+
+ \todo Implement automatic binding of member functions for parser and formatter
*/
- template <class FunctionTraits, unsigned arity=FunctionTraits::arity>
+ template <class FunctionTraits, class ReturnType=typename FunctionTraits::result_type,
+ unsigned arity=FunctionTraits::arity>
class ParsedCommandOverload : public ParsedCommandOverloadBase
{
public:
template <class Type> void defaultValue(Type const & value) const;
void typeName(std::string const & doc) const;
void defaultDoc(std::string const & doc) const;
- template <class Type, class Fn> void parser(Fn fn) const;
ParsedCommandOverloadBase & overload() const;
void overloadDoc(std::string const & doc) const;
-
void nodeDoc(std::string const & doc) const;
+ template <class Type, class Fn> void parser(Fn fn) const;
private:
ParsedCommandOverloadBase & overload_;
\see \ref console_autoparse
*/
- template <class Overload, class Self>
+ template <class Overload, class Self, class ReturnType=typename Overload::traits::result_type>
class ParsedArgumentAttributorBase
: public ParsedCommandAttributor<Overload>
{
public:
Self doc(std::string const & doc) const; ///< Set documentation for all overloads
Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
+ Self formatter(typename Overload::Formatter f) const; ///< Set return value formatter
protected:
ParsedArgumentAttributorBase(Overload & overload, unsigned index);
private:
};
+#ifndef DOXYGEN
+
+ template <class Overload, class Self>
+ class ParsedArgumentAttributorBase<Overload, Self, void>
+ : public ParsedCommandAttributor<Overload>
+ {
+ public:
+ Self doc(std::string const & doc) const; ///< Set documentation for all overloads
+ Self overloadDoc(std::string const & doc) const; ///< Set overload specific documentation
+
+ protected:
+ ParsedArgumentAttributorBase(Overload & overload, unsigned index);
+
+ private:
+ };
+
+#endif
/** \brief Argument dependent ParsedCommandBase attributes
base_traits>
::type traits;
+ typedef typename senf::remove_cvref<typename base_traits::result_type>::type result_type;
+
static const bool is_member = boost::is_member_pointer<base_type>::value;
typedef typename senf::member_class<base_type>::type class_type;
};
- template <class Type>
- struct CheckVoidReturn
- {
- template <class Fn>
- static void call(Fn fn, std::ostream & os);
- };
-
- template <>
- struct CheckVoidReturn<void>
- {
- template <class Fn>
- static void call(Fn fn, std::ostream & os);
- };
-
#endif
}}}
#define mpp_ArgTypes_(z,n,d) typename traits::mpp_ArgTypeN(n)
#define mpp_TrailingArgTypes() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_ArgTypes_, _ )
-#define mpp_Args_(z,n,d) boost::cref(mpp_ArgN(n))
+#define mpp_Args_(z,n,d) mpp_ArgN(n)
#define mpp_TrailingArgs() BOOST_PP_ENUM_TRAILING( BOOST_PP_ITERATION(), mpp_Args_, _ )
#define mpp_BindArgs_(z,n,d) BOOST_PP_CAT( _, BOOST_PP_INC(BOOST_PP_INC(n)))
// Header file (.hh)
+template <class FunctionTraits, class ReturnValue>
+class ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >
+ : public ParsedCommandOverloadBase
+{
+public:
+ typedef boost::intrusive_ptr<ParsedCommandOverload> ptr;
+ typedef FunctionTraits traits;
+ typedef boost::function<typename traits::result_type(std::ostream &
+ mpp_TrailingArgTypes())> Function;
+ typedef typename senf::remove_cvref<typename traits::result_type>::type result_type;
+ typedef boost::function<void (result_type const &, std::ostream &)> Formatter;
+
+# define mpp_l(z,n,d) \
+ typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
+ mpp_ArgTypeN(n);
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+# undef mpp_l
+
+ static ptr create(Function fn);
+
+ void formatter(Formatter f);
+
+protected:
+
+private:
+ ParsedCommandOverload(Function fn);
+
+ virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const;
+
+ Function function_;
+ Formatter formatter_;
+};
+
template <class FunctionTraits>
-class ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >
+class ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >
: public ParsedCommandOverloadBase
{
public:
typedef FunctionTraits traits;
typedef boost::function<typename traits::result_type(std::ostream &
mpp_TrailingArgTypes())> Function;
+ typedef void result_type;
# define mpp_l(z,n,d) \
typedef typename senf::remove_cvref< typename traits::mpp_ArgTypeN(n) >::type \
// inline template implementation (.cti)
+template <class FunctionTraits, class ReturnValue>
+prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::ptr
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+create(Function fn)
+{
+ return ptr(new ParsedCommandOverload(fn));
+}
+
+template <class FunctionTraits, class ReturnValue>
+void
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+formatter(Formatter f)
+{
+ formatter_ = f;
+}
+
+template <class FunctionTraits, class ReturnValue>
+prefix_
+senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION()>::
+ParsedCommandOverload(Function fn)
+ : function_ (fn)
+{
+# define mpp_l(z,n,d) addParameter< mpp_ArgTypeN(n) >();
+ BOOST_PP_REPEAT( BOOST_PP_ITERATION(), mpp_l, _ )
+# undef mpp_l
+}
+
template <class FunctionTraits>
-prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::ptr
-senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::create(Function fn)
+prefix_ typename senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::ptr
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
+create(Function fn)
{
return ptr(new ParsedCommandOverload(fn));
}
template <class FunctionTraits>
prefix_
-senf::console::ParsedCommandOverload<FunctionTraits,BOOST_PP_ITERATION()>::
+senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
ParsedCommandOverload(Function fn)
: function_ (fn)
{
// non-inline template implementation (.ct)
+template <class FunctionTraits, class ReturnValue>
+prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
+v_execute(std::ostream & os, ParseCommandInfo const & command)
+ const
+{
+ if ( command.arguments().size() > BOOST_PP_ITERATION() )
+ throw SyntaxErrorException("invalid number of arguments");
+ int nDefaults ( BOOST_PP_ITERATION() - command.arguments().size() );
+
+ 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) \
+ mpp_ArgTypeN(n) mpp_ArgN(n) (arg< mpp_ArgTypeN(n) >( n ).defaultValue); \
+ if (! arg(n).hasDefault || nDefaults-- <= 0) { \
+ if (i == i_end) \
+ throw SyntaxErrorException("invalid number of arguments"); \
+ if (arg< mpp_ArgTypeN(n) >(n).parser) \
+ arg< mpp_ArgTypeN(n) >(n).parser( *(i++), mpp_ArgN(n) ); \
+ else \
+ ArgumentTraits< mpp_ArgTypeN(n) >::parse( *(i++), mpp_ArgN(n) ); \
+ }
+# 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_
+
+ if (formatter_)
+ formatter_( function_(os mpp_TrailingArgs()), os );
+ else
+ ReturnValueTraits<result_type>::format( function_(os mpp_TrailingArgs()), os );
+ os << "\n";
+}
+
template <class FunctionTraits>
-prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, BOOST_PP_ITERATION() >::
+prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
v_execute(std::ostream & os, ParseCommandInfo const & command)
const
{
# undef mpp_l
# undef mpp_l_
- detail::CheckVoidReturn<typename traits::result_type>::call(
- boost::bind(function_, boost::ref(os)
- mpp_TrailingArgs()),
- os );
+ function_(os mpp_TrailingArgs());
}
// ////////////////////////////////////////////////////////////////////////
{ out = "true"; }
};
+ void testFormatter(double, std::ostream & os)
+ { os << "formatter"; }
}
BOOST_AUTO_UNIT_TEST(parsedCommand)
parser.parse("test/cb6 false",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL( ss.str(), "Value: true\n" );
-
+ }
+
+ {
+ std::stringstream ss;
+
+ dir.add("cb7", &cb2)
+ .formatter( &testFormatter );
+ BOOST_CHECK_NO_THROW(
+ parser.parse("test/cb7",
+ boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL( ss.str(), "formatter\n" );
}
{