From: g0dil Date: Tue, 10 Feb 2009 02:12:06 +0000 (+0000) Subject: Utils/Console: Implement command node return value support X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=a22f6d21df6c911d65f76d7731bcf92b1906bb09;p=senf.git Utils/Console: Implement command node return value support Utils/Console: Implement directory return value support in Executor Utils/Logger: Make file-target return the new directory node git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1111 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Utils/Console/Executor.cc b/Utils/Console/Executor.cc index a228c33..7733e07 100644 --- a/Utils/Console/Executor.cc +++ b/Utils/Console/Executor.cc @@ -96,7 +96,7 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, break; try { // The parser ensures, we have exactly one argument - cd(*command.arguments().begin()); + cd(command.commandPath()); } catch (IgnoreCommandException &) { throw SyntaxErrorException( @@ -108,13 +108,15 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, if (skipping()) break; // The parser ensures, we have either one or no argument - ls( output, - command.tokens().empty() ? command.tokens() : *command.arguments().begin() ); + ls( output, command.commandPath() ); break; case ParseCommandInfo::BuiltinPUSHD : // The parser ensures, we have exactly one argument - pushd( *command.arguments().begin() ); + if (skipping()) + pushd(command.commandPath()); + else + exec(output, command); break; case ParseCommandInfo::BuiltinPOPD : @@ -133,8 +135,7 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, if (skipping()) break; // The parser ensures, we have either one or no arguments - help( output, - command.tokens().empty() ? command.tokens() : *command.arguments().begin() ); + help( output, command.commandPath() ); break; } @@ -154,17 +155,45 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, prefix_ void senf::console::Executor::exec(std::ostream & output, ParseCommandInfo const & command) { - GenericNode & node ( traverseNode(command.commandPath()) ); - DirectoryNode * dir ( dynamic_cast(&node) ); - if ( dir ) { - if (autocd_ && command.tokens().empty()) { - cd( boost::make_iterator_range( - command.commandPath().begin(), - command.commandPath().end()) ); - } else - throw InvalidCommandException(); - } else { - dynamic_cast(node)(output, command); + try { + GenericNode & node ( traverseNode(command.commandPath()) ); + DirectoryNode * dir ( dynamic_cast(&node) ); + if ( dir ) { + if (! command.tokens().empty()) + throw InvalidCommandException(); + if (command.builtin() == ParseCommandInfo::BuiltinPUSHD) + pushd( command.commandPath() ); + else if (autocd_) { + cd(command.commandPath()); + } + else + throw InvalidCommandException(); + } else { + boost::any rv; + dynamic_cast(node)(rv, output, command); + if (command.builtin() == ParseCommandInfo::BuiltinPUSHD) { + DirectoryNode::ptr rvdir; + try { + rvdir = boost::any_cast(rv); + } + catch (boost::bad_any_cast &) { + throw InvalidCommandException(); + } + Path newDir (cwd_); + newDir.push_back(rvdir); + dirstack_.push_back(Path()); + dirstack_.back().swap(cwd_); + cwd_.swap(newDir); + } + } + } + catch (IgnoreCommandException &) { + if (command.builtin() == ParseCommandInfo::BuiltinPUSHD) { + dirstack_.push_back(Path()); + dirstack_.back().swap(cwd_); + } + else + throw; } } @@ -320,6 +349,15 @@ prefix_ std::string senf::console::Executor::complete(DirectoryNode & dir, return name; } +prefix_ void senf::console::senf_console_format_value(DirectoryNode::ptr value, + std::ostream & os) +{ + if (value) + os << "path() << "'>"; + else + os << ""; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Executor.mpp" diff --git a/Utils/Console/Executor.hh b/Utils/Console/Executor.hh index 7538eff..540472d 100644 --- a/Utils/Console/Executor.hh +++ b/Utils/Console/Executor.hh @@ -163,6 +163,8 @@ namespace console { bool autocomplete_; }; + void senf_console_format_value(DirectoryNode::ptr value, std::ostream & os); + }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Console/Node.cc b/Utils/Console/Node.cc index 39c2685..5096ba8 100644 --- a/Utils/Console/Node.cc +++ b/Utils/Console/Node.cc @@ -209,11 +209,11 @@ prefix_ void senf::console::SimpleCommandNode::v_help(std::ostream & output) output << doc_ << "\n"; } -prefix_ void senf::console::SimpleCommandNode::v_execute(std::ostream & output, +prefix_ void senf::console::SimpleCommandNode::v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) const { - fn_(output, command); + fn_(os, command); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Utils/Console/Node.cci b/Utils/Console/Node.cci index 1c130cb..3c21bc9 100644 --- a/Utils/Console/Node.cci +++ b/Utils/Console/Node.cci @@ -282,7 +282,16 @@ prefix_ void senf::console::CommandNode::execute(std::ostream & output, ParseCommandInfo const & command) const { - v_execute(output, command); + boost::any rv; + execute(rv, output, command); +} + +prefix_ void senf::console::CommandNode::execute(boost::any & rv, std::ostream & output, + ParseCommandInfo const & command) + const +{ + rv = boost::any(); + v_execute(rv, output, command); } prefix_ void senf::console::CommandNode::operator()(std::ostream & output, @@ -292,6 +301,13 @@ prefix_ void senf::console::CommandNode::operator()(std::ostream & output, execute(output, command); } +prefix_ void senf::console::CommandNode::operator()(boost::any & rv, std::ostream & output, + ParseCommandInfo const & command) + const +{ + execute(rv, output, command); +} + /////////////////////////////////////////////////////////////////////////// // senf::console::SimpleCommandNode diff --git a/Utils/Console/Node.hh b/Utils/Console/Node.hh index 6caef96..0367f5a 100644 --- a/Utils/Console/Node.hh +++ b/Utils/Console/Node.hh @@ -206,6 +206,7 @@ #include #include #include +#include #include "../../Utils/Exception.hh" #include "../../Utils/mpl.hh" #include "../../Utils/Logger/SenfLog.hh" @@ -606,7 +607,15 @@ namespace console { void execute(std::ostream & output, ParseCommandInfo const & command) const; ///< Execute the command - /**< Same as operator()() + /**< \param[in] output stream where result messages may be + written to + \param[in] arguments command arguments. This is a + range of ranges of Token instances. */ + + void execute(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) + const; + ///< Execute the command + /**< \param[out] rv command return value \param[in] output stream where result messages may be written to \param[in] arguments command arguments. This is a @@ -619,6 +628,8 @@ namespace console { written to \param[in] arguments command arguments. This is a range of ranges of Token instances. */ + void operator()(boost::any & rv, std::ostream & output, ParseCommandInfo const & command) + const; ptr thisptr(); cptr thisptr() const; @@ -629,10 +640,10 @@ namespace console { #ifndef DOXYGEN private: #endif - virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const = 0; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const = 0; ///< Called to execute the command - /**< \param[in] output stream where result messages may be - written to + /**< \param[out] rv return value holder \param[in] arguments command arguments. This is a range of ranges of Token instances. */ @@ -686,7 +697,8 @@ namespace console { private: virtual void v_help(std::ostream & output) const; - virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const; Function fn_; diff --git a/Utils/Console/OverloadedCommand.cc b/Utils/Console/OverloadedCommand.cc index ecc5c44..abae95e 100644 --- a/Utils/Console/OverloadedCommand.cc +++ b/Utils/Console/OverloadedCommand.cc @@ -155,7 +155,8 @@ prefix_ void senf::console::OverloadedCommandNode::v_help(std::ostream & os) } } -prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & output, +prefix_ void senf::console::OverloadedCommandNode::v_execute(boost::any & rv, + std::ostream & os, ParseCommandInfo const & command) const { @@ -164,7 +165,7 @@ prefix_ void senf::console::OverloadedCommandNode::v_execute(std::ostream & outp SyntaxErrorException err; for (; i != i_end; ++i) { try { - (**i)(output, command); + (**i)(rv, os, command); return; } catch (SyntaxErrorException & ex) { @@ -193,7 +194,8 @@ prefix_ std::string senf::console::SimpleCommandOverload::v_doc() return doc_; } -prefix_ void senf::console::SimpleCommandOverload::v_execute(std::ostream & os, +prefix_ void senf::console::SimpleCommandOverload::v_execute(boost::any & rv, + std::ostream & os, ParseCommandInfo const & command) const { diff --git a/Utils/Console/OverloadedCommand.cci b/Utils/Console/OverloadedCommand.cci index d48d9d6..c2fbdc6 100644 --- a/Utils/Console/OverloadedCommand.cci +++ b/Utils/Console/OverloadedCommand.cci @@ -72,16 +72,16 @@ prefix_ senf::console::OverloadedCommandNode::OverloadedCommandNode() prefix_ senf::console::CommandOverload::~CommandOverload() {} -prefix_ void senf::console::CommandOverload::execute(std::ostream & os, +prefix_ void senf::console::CommandOverload::execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) { - v_execute(os, command); + v_execute(rv, os, command); } -prefix_ void senf::console::CommandOverload::operator()(std::ostream & os, +prefix_ void senf::console::CommandOverload::operator()(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) { - execute(os, command); + execute(rv, os, command); } prefix_ unsigned senf::console::CommandOverload::numArguments() diff --git a/Utils/Console/OverloadedCommand.hh b/Utils/Console/OverloadedCommand.hh index ee9bde9..bb80f23 100644 --- a/Utils/Console/OverloadedCommand.hh +++ b/Utils/Console/OverloadedCommand.hh @@ -69,13 +69,13 @@ namespace console { virtual ~CommandOverload(); - void execute(std::ostream & os, ParseCommandInfo const & command); + void execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command); ///< Call the overload /**< If the \a arguments are not acceptable for this overload, a SyntaxErrorException must be thrown. Same as operator()() */ - void operator()(std::ostream & os, ParseCommandInfo const & command); + void operator()(boost::any & rv, std::ostream & os, ParseCommandInfo const & command); ///< Call the overload /**< If the \a arguments are not acceptable for this overload, a SyntaxErrorException must be thrown. @@ -120,7 +120,8 @@ namespace console { /**< This member must be implemented in the derived class to return the overloads documentation string. */ - virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const = 0; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const = 0; ///< Execute the overload /**< This member must be implemented in the derived class o execute the overload. */ @@ -196,7 +197,8 @@ namespace console { OverloadedCommandNode(); virtual void v_help(std::ostream & output) const; - virtual void v_execute(std::ostream & output, ParseCommandInfo const & command) const; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const; typedef std::vector Overloads; @@ -240,7 +242,8 @@ namespace console { virtual unsigned v_numArguments() const; virtual void v_argumentDoc(unsigned index, ArgumentDoc & doc) const; virtual std::string v_doc() const; - virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const; Function fn_; std::string doc_; diff --git a/Utils/Console/Parse.cc b/Utils/Console/Parse.cc index e4e1e66..dece5df 100644 --- a/Utils/Console/Parse.cc +++ b/Utils/Console/Parse.cc @@ -76,10 +76,10 @@ namespace detail { info_->builtin(ParseCommandInfo::BuiltinLS); setBuiltinPathArg(path); } - void pushDirectory(std::vector & path) - { info_->clear(); - info_->builtin(ParseCommandInfo::BuiltinPUSHD); - setBuiltinPathArg(path); } + void pushDirectory() + { // Do NOT call clear since pushDirectory is set in ADDITION + // to an ordinary command (which may be only a directory name) + info_->builtin(ParseCommandInfo::BuiltinPUSHD); } void popDirectory() { info_->clear(); @@ -96,11 +96,12 @@ namespace detail { void setBuiltinPathArg(std::vector & path) { - pushToken(ArgumentGroupOpenToken()); - for (std::vector::const_iterator i (path.begin()); - i != path.end(); ++i) - pushToken(*i); - pushToken(ArgumentGroupCloseToken()); + info_->command(path); +// pushToken(ArgumentGroupOpenToken()); +// for (std::vector::const_iterator i (path.begin()); +// i != path.end(); ++i) +// pushToken(*i); +// pushToken(ArgumentGroupCloseToken()); } }; @@ -249,7 +250,6 @@ namespace { void throwParserError(Error const & err) { static char const * msg [] = { "end of statement expected", - "'{' or arguments expected", "path expected", "')' expected", "'\"' expected" }; diff --git a/Utils/Console/Parse.cci b/Utils/Console/Parse.cci index 563cd6f..374d366 100644 --- a/Utils/Console/Parse.cci +++ b/Utils/Console/Parse.cci @@ -178,7 +178,6 @@ prefix_ bool senf::console::ParseCommandInfo::empty() prefix_ void senf::console::ParseCommandInfo::builtin(BuiltinCommand builtin) { builtin_ = builtin; - commandPath_.clear(); } prefix_ void @@ -186,7 +185,6 @@ senf::console::ParseCommandInfo::command(std::vector & commandPath) { commandPath_.clear(); commandPath_.swap(commandPath); - builtin_ = NoBuiltin; } prefix_ void senf::console::ParseCommandInfo::addToken(Token const & token) diff --git a/Utils/Console/Parse.ih b/Utils/Console/Parse.ih index 8d3d35d..38b9fc9 100644 --- a/Utils/Console/Parse.ih +++ b/Utils/Console/Parse.ih @@ -83,7 +83,6 @@ namespace detail { enum Errors { EndOfStatementExpected, - GroupOrArgumentsExpected, PathExpected, ClosingParenExpected, QuoteExpected @@ -145,7 +144,6 @@ namespace detail { actor< variable< ParseDispatcher > > d_ (self.dispatcher); assertion end_of_statement_expected (EndOfStatementExpected); - assertion group_or_arguments_expected (GroupOrArgumentsExpected); assertion path_expected (PathExpected); assertion closing_paren_expected (ClosingParenExpected); assertion quote_expected (QuoteExpected); @@ -192,8 +190,16 @@ namespace detail { = builtin >> end_of_statement_expected(statement_end) | group_close | ch_p(';') // Ignore empty commands - | path_expected(path) - >> group_or_arguments_expected( group_start | statement ) + | statement + ; + + statement + = path_expected(path) [ bind(&PD::beginCommand)(d_, path_) ] + >> arguments + >> end_of_statement_expected( + ( group_start | statement_end ) + [ bind(&PD::endCommand)(d_) ] + ) ; builtin @@ -210,20 +216,13 @@ namespace detail { ; group_start - = ch_p('{') [ bind(&PD::pushDirectory)(d_, path_) ] + = ch_p('{') [ bind(&PD::pushDirectory)(d_) ] ; group_close = ch_p('}') [ bind(&PD::popDirectory)(d_) ] ; - statement - = eps_p [ bind(&PD::beginCommand)(d_, path_) ] - >> arguments - >> end_of_statement_expected(statement_end) - [ bind(&PD::endCommand)(d_) ] - ; - arguments = * argument ; diff --git a/Utils/Console/Parse.test.cc b/Utils/Console/Parse.test.cc index 4570fb0..7b9e7be 100644 --- a/Utils/Console/Parse.test.cc +++ b/Utils/Console/Parse.test.cc @@ -49,8 +49,8 @@ namespace std::ostream & os_; - void pushDirectory(std::vector const & path) - { os_ << "pushDirectory( " << senf::stringJoin(path, "/") << " )\n"; } + void pushDirectory() + { os_ << "pushDirectory()\n"; } void popDirectory() { os_ << "popDirectory()\n"; } @@ -154,7 +154,10 @@ BOOST_AUTO_UNIT_TEST(commandGrammar) "foo/bar/ {", grammar.use_parser(), grammar.use_parser() ) . full ); - BOOST_CHECK_EQUAL( ss.str(), "pushDirectory( Word('foo')/Word('bar')/None('') )\n" ); + BOOST_CHECK_EQUAL( ss.str(), + "beginCommand( Word('foo')/Word('bar')/None('') )\n" + "pushDirectory()\n" + "endCommand()\n" ); } { @@ -330,7 +333,7 @@ BOOST_AUTO_UNIT_TEST(parseExceptions) try { parser.parse(c, &setInfo); } \ catch (std::exception & ex) { msg = parseErrorMessage(ex.what()); } \ BOOST_CHECK_EQUAL( msg, e ) - + CheckParseEx( "/foo/bar;\n ()", "path expected\nat :2:3" ); CheckParseEx( "cd /foo/bar foo/bar", "end of statement expected\nat :1:13" ); CheckParseEx( "/foo/bar foo /", "end of statement expected\nat :1:14" ); diff --git a/Utils/Console/ParsedCommand.mpp b/Utils/Console/ParsedCommand.mpp index a8598fa..340e073 100644 --- a/Utils/Console/ParsedCommand.mpp +++ b/Utils/Console/ParsedCommand.mpp @@ -102,7 +102,8 @@ protected: private: ParsedCommandOverload(Function fn); - virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const; Function function_; Formatter formatter_; @@ -140,7 +141,8 @@ protected: private: ParsedCommandOverload(Function fn); - virtual void v_execute(std::ostream & os, ParseCommandInfo const & command) const; + virtual void v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) + const; Function function_; }; @@ -249,7 +251,7 @@ ParsedCommandOverload(Function fn) template prefix_ void senf::console::ParsedCommandOverload:: -v_execute(std::ostream & os, ParseCommandInfo const & command) +v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) const { // We NEED to know the number of arguments beforehand so we can assign default values @@ -280,16 +282,18 @@ v_execute(std::ostream & os, ParseCommandInfo const & command) # undef mpp_l # undef mpp_l_ + ReturnValue rvv (function_(os mpp_TrailingArgs())); + rv = rvv; if (formatter_) - formatter_( function_(os mpp_TrailingArgs()), os ); + formatter_(rvv, os); else - ReturnValueTraits::format( function_(os mpp_TrailingArgs()), os ); + ReturnValueTraits::format(rvv, os); os << "\n"; } template prefix_ void senf::console::ParsedCommandOverload:: -v_execute(std::ostream & os, ParseCommandInfo const & command) +v_execute(boost::any & rv, std::ostream & os, ParseCommandInfo const & command) const { // We NEED to know the number of arguments beforehand so we can assign default values diff --git a/Utils/Console/ParsedCommand.test.cc b/Utils/Console/ParsedCommand.test.cc index 0ad7fc6..42a5097 100644 --- a/Utils/Console/ParsedCommand.test.cc +++ b/Utils/Console/ParsedCommand.test.cc @@ -273,6 +273,36 @@ BOOST_AUTO_UNIT_TEST(memberParsedCommand) } } +namespace { + + senf::console::DirectoryNode::ptr dircb() + { + senf::console::DirectoryNode & dir ( + senf::console::root()["test"].mkdir("dircb")); + dir.add("cb1", &cb1); + return dir.thisptr(); + } + +} + +BOOST_AUTO_UNIT_TEST(directoryReturn) +{ + senf::console::Executor executor; + senf::console::CommandParser parser; + senf::console::ScopedDirectory<> dir; + senf::console::root().add("test", dir); + dir.add("test", &dircb); + + { + std::stringstream ss; + SENF_CHECK_NO_THROW( + parser.parse("test/test { ls; }", + boost::bind( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( ss.str(), "\ncb1\n" ); + } + +} + #ifdef COMPILE_CHECK COMPILE_FAIL(argParser) diff --git a/Utils/Logger/FileTarget.cc b/Utils/Logger/FileTarget.cc index 7cc2ad0..52ebaf8 100644 --- a/Utils/Logger/FileTarget.cc +++ b/Utils/Logger/FileTarget.cc @@ -71,10 +71,13 @@ prefix_ senf::log::FileTarget::RegisterConsole::RegisterConsole() .doc("Create new file target."); } -prefix_ void senf::log::FileTarget::RegisterConsole::create(std::string const & filename) +prefix_ boost::shared_ptr +senf::log::FileTarget::RegisterConsole::create(std::string const & filename) { - detail::TargetRegistry::instance().dynamicTarget( - std::auto_ptr(new FileTarget(filename))); + std::auto_ptr tp (new FileTarget(filename)); + Target & target (*tp.get()); + detail::TargetRegistry::instance().dynamicTarget(tp); + return target.consoleDir().node().thisptr(); } ///////////////////////////////cc.e//////////////////////////////////////// diff --git a/Utils/Logger/FileTarget.hh b/Utils/Logger/FileTarget.hh index ccd78fc..11543d7 100644 --- a/Utils/Logger/FileTarget.hh +++ b/Utils/Logger/FileTarget.hh @@ -28,6 +28,7 @@ // Custom includes #include +#include #include #include "IOStreamTarget.hh" @@ -35,6 +36,9 @@ ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { + + namespace console { class DirectoryNode; } + namespace log { /** \brief Log target writing to a %log file. @@ -79,7 +83,8 @@ namespace log { struct RegisterConsole { RegisterConsole(); - static void create(std::string const & filename); + static boost::shared_ptr create( + std::string const & filename); static RegisterConsole instance; }; }; diff --git a/Utils/Logger/Target.hh b/Utils/Logger/Target.hh index e371443..6f26ddd 100644 --- a/Utils/Logger/Target.hh +++ b/Utils/Logger/Target.hh @@ -342,7 +342,6 @@ namespace log { void flush(); ///< Clear routing table - protected: senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory private: