From: g0dil Date: Thu, 4 Jun 2009 13:57:01 +0000 (+0000) Subject: Utils/Console: Implement special single-token argument parsing for program options... X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=2d9b8768b1a5fa77e1abde6e48664e2d5eecd7a2;p=senf.git Utils/Console: Implement special single-token argument parsing for program options (remove double quoting) git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1222 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Console/Config.cc b/Utils/Console/Config.cc index e6723aa..f844f8a 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 4b54736..d85a646 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 10d45df..141565a 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 2fc9c06..ce8b86c 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 dbbb7c0..c891fda 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 fb374ec..4402742 100644 --- a/Utils/Console/OverloadedCommand.hh +++ b/Utils/Console/OverloadedCommand.hh @@ -29,6 +29,7 @@ // Custom includes #include "Node.hh" #include +#include #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 Overloads; + public: /////////////////////////////////////////////////////////////////////////// // Types @@ -170,6 +174,8 @@ namespace console { typedef OverloadedCommandNode node_type; typedef OverloadedCommandNode & return_type; + typedef boost::iterator_range 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 Overloads; - Overloads overloads_; std::string doc_; std::string shortdoc_; diff --git a/Utils/Console/ParsedCommand.cc b/Utils/Console/ParsedCommand.cc index da6144b..bca4793 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 1ec6a29..5d168ec 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 7e9710f..a35a827 100644 --- a/Utils/Console/ParsedCommand.cti +++ b/Utils/Console/ParsedCommand.cti @@ -45,7 +45,8 @@ senf::console::detail::ArgumentInfo::create() template prefix_ senf::console::detail::ArgumentInfo::ArgumentInfo() - : ArgumentInfoBase ( ArgumentTraits::description() ), + : ArgumentInfoBase ( ArgumentTraits::description(), + ArgumentTraits::singleToken ), defaultValue () {} diff --git a/Utils/Console/ParsedCommand.ih b/Utils/Console/ParsedCommand.ih index 65a02f7..0dbe33b 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 245cce3..951c5f0 100644 --- a/Utils/Console/ProgramOptions.cc +++ b/Utils/Console/ProgramOptions.cc @@ -30,6 +30,7 @@ #include #include #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(&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 6879483..69a6e14 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 0f8da26..8749e9a 100644 --- a/Utils/Console/Traits.ct +++ b/Utils/Console/Traits.ct @@ -31,7 +31,7 @@ ///////////////////////////////ct.p//////////////////////////////////////// template -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 2e84882..a5b0ccd 100644 --- a/Utils/Console/Traits.hh +++ b/Utils/Console/Traits.hh @@ -29,6 +29,7 @@ // Custom includes #include #include +#include #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(0), + *static_cast(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 - 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 { 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 > { typedef FlagCollection 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 03dc80e..1e77cf7 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::singleToken ); + BOOST_CHECK( senf::console::ArgumentTraits::singleToken ); + BOOST_CHECK( ! senf::console::ArgumentTraits< + senf::console::FlagCollection >::singleToken ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_