break;
try {
// The parser ensures, we have exactly one argument
- cd(*command.arguments().begin());
+ cd(command.commandPath());
}
catch (IgnoreCommandException &) {
throw SyntaxErrorException(
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 :
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;
}
prefix_ void senf::console::Executor::exec(std::ostream & output,
ParseCommandInfo const & command)
{
- GenericNode & node ( traverseNode(command.commandPath()) );
- DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&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<CommandNode &>(node)(output, command);
+ try {
+ GenericNode & node ( traverseNode(command.commandPath()) );
+ DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&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<CommandNode &>(node)(rv, output, command);
+ if (command.builtin() == ParseCommandInfo::BuiltinPUSHD) {
+ DirectoryNode::ptr rvdir;
+ try {
+ rvdir = boost::any_cast<DirectoryNode::ptr>(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;
}
}
return name;
}
+prefix_ void senf::console::senf_console_format_value(DirectoryNode::ptr value,
+ std::ostream & os)
+{
+ if (value)
+ os << "<Directory at '" << value->path() << "'>";
+ else
+ os << "<Null Directory>";
+}
+
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "Executor.mpp"
bool autocomplete_;
};
+ void senf_console_format_value(DirectoryNode::ptr value, std::ostream & os);
+
}}
///////////////////////////////hh.e////////////////////////////////////////
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////////////////////////////////////////
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,
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
#include <boost/range/iterator_range.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/type_traits/remove_reference.hpp>
+#include <boost/any.hpp>
#include "../../Utils/Exception.hh"
#include "../../Utils/mpl.hh"
#include "../../Utils/Logger/SenfLog.hh"
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
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;
#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. */
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_;
}
}
-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
{
SyntaxErrorException err;
for (; i != i_end; ++i) {
try {
- (**i)(output, command);
+ (**i)(rv, os, command);
return;
}
catch (SyntaxErrorException & ex) {
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
{
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()
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.
/**< 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. */
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<CommandOverload::ptr> Overloads;
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_;
info_->builtin(ParseCommandInfo::BuiltinLS);
setBuiltinPathArg(path); }
- void pushDirectory(std::vector<Token> & 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();
void setBuiltinPathArg(std::vector<Token> & path)
{
- pushToken(ArgumentGroupOpenToken());
- for (std::vector<Token>::const_iterator i (path.begin());
- i != path.end(); ++i)
- pushToken(*i);
- pushToken(ArgumentGroupCloseToken());
+ info_->command(path);
+// pushToken(ArgumentGroupOpenToken());
+// for (std::vector<Token>::const_iterator i (path.begin());
+// i != path.end(); ++i)
+// pushToken(*i);
+// pushToken(ArgumentGroupCloseToken());
}
};
void throwParserError(Error const & err)
{
static char const * msg [] = { "end of statement expected",
- "'{' or arguments expected",
"path expected",
"')' expected",
"'\"' expected" };
prefix_ void senf::console::ParseCommandInfo::builtin(BuiltinCommand builtin)
{
builtin_ = builtin;
- commandPath_.clear();
}
prefix_ void
{
commandPath_.clear();
commandPath_.swap(commandPath);
- builtin_ = NoBuiltin;
}
prefix_ void senf::console::ParseCommandInfo::addToken(Token const & token)
enum Errors {
EndOfStatementExpected,
- GroupOrArgumentsExpected,
PathExpected,
ClosingParenExpected,
QuoteExpected
actor< variable< ParseDispatcher > > d_ (self.dispatcher);
assertion<Errors> end_of_statement_expected (EndOfStatementExpected);
- assertion<Errors> group_or_arguments_expected (GroupOrArgumentsExpected);
assertion<Errors> path_expected (PathExpected);
assertion<Errors> closing_paren_expected (ClosingParenExpected);
assertion<Errors> quote_expected (QuoteExpected);
= 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
;
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
;
std::ostream & os_;
- void pushDirectory(std::vector<senf::console::Token> const & path)
- { os_ << "pushDirectory( " << senf::stringJoin(path, "/") << " )\n"; }
+ void pushDirectory()
+ { os_ << "pushDirectory()\n"; }
void popDirectory()
{ os_ << "popDirectory()\n"; }
"foo/bar/ {",
grammar.use_parser<Grammar::CommandParser>(),
grammar.use_parser<Grammar::SkipParser>() ) . 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" );
}
{
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 <unknown>:2:3" );
CheckParseEx( "cd /foo/bar foo/bar", "end of statement expected\nat <unknown>:1:13" );
CheckParseEx( "/foo/bar foo /", "end of statement expected\nat <unknown>:1:14" );
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_;
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_;
};
template <class FunctionTraits, class ReturnValue>
prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, ReturnValue, BOOST_PP_ITERATION() >::
-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
# 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<result_type>::format( function_(os mpp_TrailingArgs()), os );
+ ReturnValueTraits<result_type>::format(rvv, os);
os << "\n";
}
template <class FunctionTraits>
prefix_ void senf::console::ParsedCommandOverload<FunctionTraits, void, BOOST_PP_ITERATION() >::
-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
}
}
+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<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL( ss.str(), "<Directory at '/test/dircb'>\ncb1\n" );
+ }
+
+}
+
#ifdef COMPILE_CHECK
COMPILE_FAIL(argParser)
.doc("Create new file target.");
}
-prefix_ void senf::log::FileTarget::RegisterConsole::create(std::string const & filename)
+prefix_ boost::shared_ptr<senf::console::DirectoryNode>
+senf::log::FileTarget::RegisterConsole::create(std::string const & filename)
{
- detail::TargetRegistry::instance().dynamicTarget(
- std::auto_ptr<Target>(new FileTarget(filename)));
+ std::auto_ptr<Target> tp (new FileTarget(filename));
+ Target & target (*tp.get());
+ detail::TargetRegistry::instance().dynamicTarget(tp);
+ return target.consoleDir().node().thisptr();
}
///////////////////////////////cc.e////////////////////////////////////////
// Custom includes
#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
#include <fstream>
#include "IOStreamTarget.hh"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
+
+ namespace console { class DirectoryNode; }
+
namespace log {
/** \brief Log target writing to a %log file.
struct RegisterConsole {
RegisterConsole();
- static void create(std::string const & filename);
+ static boost::shared_ptr<senf::console::DirectoryNode> create(
+ std::string const & filename);
static RegisterConsole instance;
};
};
void flush(); ///< Clear routing table
- protected:
senf::console::ScopedDirectory<> & consoleDir(); ///< Get console/config directory
private: