diff --git a/Utils/Console/Config.cc b/Utils/Console/Config.cc index e6723aa53212633f3e30085132210f09b5e04fd5..f844f8a0ec04181d37104a4648d2180cacb664c8 100644 --- a/Utils/Console/Config.cc +++ b/Utils/Console/Config.cc @@ -57,6 +57,12 @@ senf::console::detail::RestrictedExecutor::operator()(std::ostream & output, execute(output, command); } +prefix_ senf::console::GenericNode & +senf::console::detail::RestrictedExecutor::getNode(ParseCommandInfo const & command) +{ + return executor_.getNode(command); +} + prefix_ bool senf::console::detail::RestrictedExecutor::parsed(GenericNode & node) const { diff --git a/Utils/Console/Config.ih b/Utils/Console/Config.ih index 4b54736a106d2141554646e11d6c6e289ab958ce..d85a646eee901e2db9604a30f0804b199563946a 100644 --- a/Utils/Console/Config.ih +++ b/Utils/Console/Config.ih @@ -69,6 +69,8 @@ namespace detail { /**< Output will be written to \a output. Same as execute(). */ + GenericNode & getNode(ParseCommandInfo const & command); + bool complete() const; ///< \c true, if all nodes have been parsed bool parsed(GenericNode & node) const; ///< \c true. if \a node has been parsed void reset(); ///< Reset node parse info state diff --git a/Utils/Console/Executor.cc b/Utils/Console/Executor.cc index 10d45df3aca7cdb1f602502ccbd59d88a95e88fb..141565abf9b7a7aa007902ec02575dd2be6ac45e 100644 --- a/Utils/Console/Executor.cc +++ b/Utils/Console/Executor.cc @@ -161,6 +161,12 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, catch (IgnoreCommandException &) {} } +prefix_ senf::console::GenericNode & +senf::console::Executor::getNode(ParseCommandInfo const & command) +{ + return traverseNode(command.commandPath()); +} + prefix_ void senf::console::Executor::exec(std::ostream & output, ParseCommandInfo const & command) { diff --git a/Utils/Console/Executor.hh b/Utils/Console/Executor.hh index 2fc9c06ee911789f0ca0674c40ddea1c0578df92..ce8b86c04f598fb1450dedf8bc637fd6c659997b 100644 --- a/Utils/Console/Executor.hh +++ b/Utils/Console/Executor.hh @@ -92,6 +92,7 @@ namespace console { ///< Execute command /**< Output will be written to \a output. Same as execute(). */ + GenericNode & getNode(ParseCommandInfo const & command); DirectoryNode & cwd() const; ///< Current working directory std::string cwdPath() const; ///< Return pathname of current directory bool skipping() const; ///< \c true, if currently skipping a directory group diff --git a/Utils/Console/OverloadedCommand.cci b/Utils/Console/OverloadedCommand.cci index dbbb7c0668f5dea535ec99883bb3305bcaae004e..c891fda6dec276d7d7c8928856071dcc3f3b6eaa 100644 --- a/Utils/Console/OverloadedCommand.cci +++ b/Utils/Console/OverloadedCommand.cci @@ -70,6 +70,13 @@ senf::console::OverloadedCommandNode::overloadIndex(CommandOverload const & over - overloads_.begin() + 1; } +prefix_ senf::console::OverloadedCommandNode::OverloadsRange +senf::console::OverloadedCommandNode::overloads() + const +{ + return boost::make_iterator_range(overloads_.begin(), overloads_.end()); +} + prefix_ senf::console::OverloadedCommandNode::OverloadedCommandNode() {} diff --git a/Utils/Console/OverloadedCommand.hh b/Utils/Console/OverloadedCommand.hh index fb374ec301b35e21ba1a8881bc26d98d63d7d771..4402742127428f1cae5c1eb72d9ee4a67b0847de 100644 --- a/Utils/Console/OverloadedCommand.hh +++ b/Utils/Console/OverloadedCommand.hh @@ -29,6 +29,7 @@ // Custom includes #include "Node.hh" #include <boost/intrusive_ptr.hpp> +#include <boost/range/iterator_range.hpp> #include "../../Utils/intrusive_refcount.hh" //#include "OverloadedCommand.mpp" @@ -48,6 +49,7 @@ namespace console { std::string type; ///< Argument type (string representation) std::string defaultValue; ///< Default value (string representation) or empty string std::string doc; ///< Documentation for this argument + bool singleToken; ///< \c true, if argument is parsed from single token }; /** \brief Base class for command overload of OverloadedCommandNode @@ -159,6 +161,8 @@ namespace console { class OverloadedCommandNode : public CommandNode { + typedef std::vector<CommandOverload::ptr> Overloads; + public: /////////////////////////////////////////////////////////////////////////// // Types @@ -170,6 +174,8 @@ namespace console { typedef OverloadedCommandNode node_type; typedef OverloadedCommandNode & return_type; + typedef boost::iterator_range<Overloads::const_iterator> OverloadsRange; + /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members ///@{ @@ -192,6 +198,8 @@ namespace console { /**< overloadIndex returns the index of \a overload in the internal list of overloads. */ + OverloadsRange overloads() const; ///< Get all overloads + ptr thisptr(); cptr thisptr() const; @@ -203,8 +211,6 @@ namespace console { virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) const; - typedef std::vector<CommandOverload::ptr> Overloads; - Overloads overloads_; std::string doc_; std::string shortdoc_; diff --git a/Utils/Console/ParsedCommand.cc b/Utils/Console/ParsedCommand.cc index da6144b4c5ec4b71aa7b81484257c6309f9d03f1..bca4793e8db9db206a076ce4e5ab6611e92cd0d7 100644 --- a/Utils/Console/ParsedCommand.cc +++ b/Utils/Console/ParsedCommand.cc @@ -65,6 +65,7 @@ prefix_ void senf::console::ParsedCommandOverloadBase::v_argumentDoc(unsigned in doc.defaultValue = "(empty)"; } doc.doc = arg.doc; + doc.singleToken = arg.singleToken; } prefix_ std::string senf::console::ParsedCommandOverloadBase::v_doc() diff --git a/Utils/Console/ParsedCommand.cci b/Utils/Console/ParsedCommand.cci index 1ec6a29601d02effac45b2c4d60da154c0dbbc8d..5d168ecafeef6510e5f6eaa2ecb567ed0440440d 100644 --- a/Utils/Console/ParsedCommand.cci +++ b/Utils/Console/ParsedCommand.cci @@ -33,8 +33,9 @@ /////////////////////////////////////////////////////////////////////////// // senf::console::detail::ArgumentInfoBase -prefix_ senf::console::detail::ArgumentInfoBase::ArgumentInfoBase(std::string const & type_) - : type (type_), name (), hasDefault (false) +prefix_ senf::console::detail::ArgumentInfoBase::ArgumentInfoBase(std::string const & type_, + bool singleToken_) + : type (type_), name (), hasDefault (false), singleToken (singleToken_) {} /////////////////////////////////////////////////////////////////////////// diff --git a/Utils/Console/ParsedCommand.cti b/Utils/Console/ParsedCommand.cti index 7e9710f35c446f069686619499c74ccaccc80a6b..a35a827be51e2f43b3690b88f406aae6fa721a6c 100644 --- a/Utils/Console/ParsedCommand.cti +++ b/Utils/Console/ParsedCommand.cti @@ -45,7 +45,8 @@ senf::console::detail::ArgumentInfo<ParameterType>::create() template <class ParameterType> prefix_ senf::console::detail::ArgumentInfo<ParameterType>::ArgumentInfo() - : ArgumentInfoBase ( ArgumentTraits<ParameterType>::description() ), + : ArgumentInfoBase ( ArgumentTraits<ParameterType>::description(), + ArgumentTraits<ParameterType>::singleToken ), defaultValue () {} diff --git a/Utils/Console/ParsedCommand.ih b/Utils/Console/ParsedCommand.ih index 65a02f769db5adce3831c4226b44ea0be8d7ba78..0dbe33be296344602a924a35676ac716e58831f5 100644 --- a/Utils/Console/ParsedCommand.ih +++ b/Utils/Console/ParsedCommand.ih @@ -64,8 +64,9 @@ namespace detail { std::string defaultDoc; bool hasDefault; std::string doc; + bool singleToken; - ArgumentInfoBase(std::string const & type); + explicit ArgumentInfoBase(std::string const & type, bool singleToken=false); virtual ~ArgumentInfoBase(); virtual std::string defaultValueStr() const = 0; diff --git a/Utils/Console/ProgramOptions.cc b/Utils/Console/ProgramOptions.cc index 245cce36f9a3d07933230767f526ef6809ad3848..951c5f0410f2a9188b86ff18dec3877d042fb4e7 100644 --- a/Utils/Console/ProgramOptions.cc +++ b/Utils/Console/ProgramOptions.cc @@ -30,6 +30,7 @@ #include <boost/algorithm/string/predicate.hpp> #include <boost/format.hpp> #include "../../Utils/range.hh" +#include "OverloadedCommand.hh" //#include "ProgramOptions.mpp" #define prefix_ @@ -151,8 +152,35 @@ senf::console::detail::ProgramOptionsSource::parseLongOption(std::string const & } cmd.command(path); - parser_.parseArguments(value, cmd); - executor(executor.stream(), cmd); + // Here we check, whether the command + // - is an overloaded/parsed command + // - with a single overload + // - taking only a single argument + // - which consists of a single token + // If all these conditions are met, we pass the parameter value as a single WordToken + // otherwise we parse it using the config parser + try { + GenericNode const & node (executor.getNode(cmd)); + OverloadedCommandNode const * cmdnode (dynamic_cast<OverloadedCommandNode const *>(&node)); + if (cmdnode && cmdnode->overloads().size() == 1) { + CommandOverload const & overload (**cmdnode->overloads().begin()); + if (overload.numArguments() == 1) { + ArgumentDoc argdoc; + argdoc.singleToken = false; + overload.argumentDoc(0, argdoc); + if (argdoc.singleToken) { + cmd.addToken(WordToken(value)); + goto execute; + } + } + } /* else */ { + parser_.parseArguments(value, cmd); + } + execute: + executor(executor.stream(), cmd); + } + catch (Executor::IgnoreCommandException &) + {} } prefix_ void diff --git a/Utils/Console/STLSupport.hh b/Utils/Console/STLSupport.hh index 68794836f2319034a8b5ad24b1dc9803a1eddda7..69a6e14bf48074e6f8a96fae8d3b3ea3fc263159 100644 --- a/Utils/Console/STLSupport.hh +++ b/Utils/Console/STLSupport.hh @@ -43,6 +43,7 @@ namespace console { struct SequenceArgumentTraits { typedef Sequence type; + static bool const singleToken = false; static void parse(ParseCommandInfo::TokensRange const & tokens, type & out); static std::string description(); diff --git a/Utils/Console/Traits.ct b/Utils/Console/Traits.ct index 0f8da26ef09b54813f198f047e4e88769570d147..8749e9a8f2d6f8c1349366fcf21174ad0b64376f 100644 --- a/Utils/Console/Traits.ct +++ b/Utils/Console/Traits.ct @@ -31,7 +31,7 @@ ///////////////////////////////ct.p//////////////////////////////////////// template <class Type> -prefix_ void +prefix_ bool senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out) { @@ -44,6 +44,7 @@ senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const & catch (std::bad_cast & ex) { throw SyntaxErrorException("parameter syntax error"); } + return false; } /////////////////////////////////////////////////////////////////////////// diff --git a/Utils/Console/Traits.hh b/Utils/Console/Traits.hh index 2e848821939f8f153d75a9da2db930b07d5c45ab..a5b0ccd77db6c96e75acc12f876c3215d3688160 100644 --- a/Utils/Console/Traits.hh +++ b/Utils/Console/Traits.hh @@ -29,6 +29,7 @@ // Custom includes #include <iostream> #include <boost/intrusive_ptr.hpp> +#include <boost/type_traits/is_same.hpp> #include "../../Utils/intrusive_refcount.hh" #include "Parse.hh" #include "Node.hh" @@ -94,6 +95,12 @@ namespace console { { typedef Type type; + static bool const singleToken = + boost::is_same< typeof(senf_console_parse_argument( + *static_cast<ParseCommandInfo::TokensRange const *>(0), + *static_cast<Type*>(0))), + bool >::value; + static void parse(ParseCommandInfo::TokensRange const & tokens, Type & out); ///< Parse token range into value /**< This function needs to parse \a tokens and write the @@ -121,7 +128,7 @@ namespace console { \related ArgumentTraits */ template <class Type> - void senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out); + bool senf_console_parse_argument(ParseCommandInfo::TokensRange const & tokens, Type & out); /** \brief Parse token range @@ -143,6 +150,7 @@ namespace console { struct ArgumentTraits<bool> { typedef bool type; + static bool const singleToken = true; static void parse(ParseCommandInfo::TokensRange const & tokens, bool & out); static std::string description(); @@ -225,6 +233,7 @@ namespace console { struct ArgumentTraits< FlagCollection<Enum> > { typedef FlagCollection<Enum> type; + static bool const singleToken = false; static void parse(ParseCommandInfo::TokensRange const & tokens, type & out); static std::string description(); static std::string str(type const & value); diff --git a/Utils/Console/Traits.test.cc b/Utils/Console/Traits.test.cc index 03dc80ede1f39f6871944e3b3722f20587b1b568..1e77cf73bc20f91d163f2dd573b86706228c56c2 100644 --- a/Utils/Console/Traits.test.cc +++ b/Utils/Console/Traits.test.cc @@ -191,6 +191,14 @@ BOOST_AUTO_UNIT_TEST(flagCollection) BOOST_CHECK_EQUAL( ss.str(), "()\n" ); } +BOOST_AUTO_UNIT_TEST(singleToken) +{ + BOOST_CHECK( senf::console::ArgumentTraits<std::string>::singleToken ); + BOOST_CHECK( senf::console::ArgumentTraits<int>::singleToken ); + BOOST_CHECK( ! senf::console::ArgumentTraits< + senf::console::FlagCollection<TestEnum> >::singleToken ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_