diff --git a/Console/Executor.cc b/Console/Executor.cc index 5e4b6f21ee4b2f073a2fdffc9274cdacdcc05fef..da8aa49e32370985836df31567f047a526cf9dd8 100644 --- a/Console/Executor.cc +++ b/Console/Executor.cc @@ -56,9 +56,17 @@ prefix_ void senf::console::Executor::execute(std::ostream & output, try { switch(command.builtin()) { - case ParseCommandInfo::NoBuiltin : - traverseCommand(command.commandPath())(output, command); + case ParseCommandInfo::NoBuiltin : { + GenericNode & node ( traverseCommand(command.commandPath()) ); + DirectoryNode * dir ( dynamic_cast<DirectoryNode*>(&node) ); + if ( dir ) { + oldCwd_ = cwd_; + cwd_ = dir->thisptr(); + } else { + dynamic_cast<CommandNode &>(node)(output, command); + } break; + } case ParseCommandInfo::BuiltinCD : if ( command.arguments() ) { @@ -146,34 +154,34 @@ senf::console::Executor::traverseNode(ParseCommandInfo::argument_value_type cons } } -prefix_ senf::console::DirectoryNode & -senf::console::Executor::traverseDirectory(ParseCommandInfo::argument_value_type const & path) +prefix_ senf::console::GenericNode & +senf::console::Executor::traverseCommand(ParseCommandInfo::CommandPathRange const & path) { try { - return dynamic_cast<DirectoryNode&>( traverseNode(path) ); + return cwd().traverse(path); } catch (std::bad_cast &) { - throw InvalidDirectoryException(); + throw InvalidPathException(); } - catch (InvalidPathException &) { - throw InvalidDirectoryException(); + catch (UnknownNodeNameException &) { + throw InvalidPathException(); } } -prefix_ senf::console::CommandNode & -senf::console::Executor::traverseCommand(ParseCommandInfo::CommandPathRange const & path) +prefix_ senf::console::DirectoryNode & +senf::console::Executor::traverseDirectory(ParseCommandInfo::argument_value_type const & path) { try { - return dynamic_cast<CommandNode &>( cwd().traverse(path) ); + return dynamic_cast<DirectoryNode&>( traverseNode(path) ); } catch (std::bad_cast &) { - throw InvalidCommandException(); + throw InvalidDirectoryException(); + } + catch (InvalidPathException &) { + throw InvalidDirectoryException(); } - catch (UnknownNodeNameException &) { - throw InvalidCommandException(); - } } - + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "Executor.mpp" diff --git a/Console/Executor.hh b/Console/Executor.hh index 81dafd9468b3e77e79ee630b98fec9dd75ced674..441c3d78dca6a73a26ca6ef837678126b40ab133 100644 --- a/Console/Executor.hh +++ b/Console/Executor.hh @@ -90,8 +90,8 @@ namespace console { private: GenericNode & traverseNode(ParseCommandInfo::argument_value_type const & path); + GenericNode & traverseCommand(ParseCommandInfo::CommandPathRange const & path); DirectoryNode & traverseDirectory(ParseCommandInfo::argument_value_type const & path); - CommandNode & traverseCommand(ParseCommandInfo::CommandPathRange const & path); struct InvalidPathException {}; struct InvalidDirectoryException {}; diff --git a/Console/Node.cci b/Console/Node.cci index 6f24e9c3a6bb9271e8760caac9670c1f20900620..c0d76bc0e6c1cd45e37a29adb06025ddfb10a372 100644 --- a/Console/Node.cci +++ b/Console/Node.cci @@ -170,9 +170,19 @@ prefix_ senf::console::DirectoryNode::cptr senf::console::DirectoryNode::thisptr // senf::console::SyntaxErrorException prefix_ senf::console::SyntaxErrorException::SyntaxErrorException(std::string const & msg) - : Exception(msg) + : message_(msg) {} +prefix_ senf::console::SyntaxErrorException::~SyntaxErrorException() + throw() +{} + +prefix_ std::string const & senf::console::SyntaxErrorException::message() + const +{ + return message_; +} + /////////////////////////////////////////////////////////////////////////// // senf::console::CommandNode diff --git a/Console/Node.hh b/Console/Node.hh index 6a2732c4ba8b4f80718b3bf5f41f9af76000dce2..a93c23cccd5a5820589e669f26f8d20fd445e33d 100644 --- a/Console/Node.hh +++ b/Console/Node.hh @@ -518,11 +518,16 @@ namespace console { All errors while parsing the arguments of a command must be signaled by throwing an instance of SyntaxErrorException. This is important, so command overloading works. */ - struct SyntaxErrorException : public senf::Exception + struct SyntaxErrorException : public std::exception { explicit SyntaxErrorException(std::string const & msg = ""); + virtual ~SyntaxErrorException() throw(); virtual char const * what() const throw(); + std::string const & message() const; + + private: + std::string message_; }; /** \brief Config/console tree command node diff --git a/Console/Readline.cc b/Console/Readline.cc index 43da4470d42e59397d33052f50097a4e7f218da1..8d796e62f1300e6138e33957c028a3c6a5fd41e7 100644 --- a/Console/Readline.cc +++ b/Console/Readline.cc @@ -59,8 +59,13 @@ /////////////////////////////////////////////////////////////////////////// // senf::console::detail::ReadlineClientReader -extern int readline_echoing_p; -extern int _rl_bell_preference; +extern "C" { + extern int readline_echoing_p; + extern int _rl_bell_preference; + + void _rl_erase_entire_line(); +} + namespace { @@ -164,10 +169,14 @@ prefix_ void senf::console::detail::ReadlineClientReader::callback(std::string l } prefix_ void senf::console::detail::ReadlineClientReader::v_disablePrompt() -{} +{ + _rl_erase_entire_line(); +} prefix_ void senf::console::detail::ReadlineClientReader::v_enablePrompt() -{} +{ + rl_forced_update_display(); +} prefix_ void senf::console::detail::ReadlineClientReader::v_translate(std::string & data) { diff --git a/Console/Readline.hh b/Console/Readline.hh index 7ac5741ef73f541e12c1f77b5945bc078609d44e..7a348ef88117f7d49373f18a92f2c11ddc866775 100644 --- a/Console/Readline.hh +++ b/Console/Readline.hh @@ -78,6 +78,11 @@ namespace detail { char promptBuffer_[1024]; SchedulerBinding schedBinding_; bool terminate_; + + char * savedLineBuffer_; + int savedPoint_; + int savedEnd_; + int savedMark_; }; /** \brief Internal: Safe GNU readline based ClientReader implementation diff --git a/Console/Server.cci b/Console/Server.cci index 8e0d434b125eabcfc8baceefadebf68c66522edf..573773d32d4153ccce89a74bcc60c944719195a3 100644 --- a/Console/Server.cci +++ b/Console/Server.cci @@ -37,6 +37,12 @@ prefix_ senf::console::detail::NonblockingSocketSink::NonblockingSocketSink(Clie : client_ (client) {} +prefix_ senf::console::Client & senf::console::detail::NonblockingSocketSink::client() + const +{ + return client_; +} + /////////////////////////////////////////////////////////////////////////// // senf::console::Server @@ -129,6 +135,11 @@ prefix_ std::string senf::console::Client::promptString() return name_ + ":" + executor_.cwd().path() + "$ "; } +prefix_ senf::console::Client & senf::console::Client::get(std::ostream & os) +{ + return dynamic_cast<detail::NonblockingSocketOStream&>(os)->client(); +} + prefix_ senf::console::Client::ClientHandle senf::console::Client::handle() const { diff --git a/Console/Server.hh b/Console/Server.hh index abc70b78c18c559a2ac07f3e54a3db17a3a448bf..8d9b30a8ebd27cbefba9ca1ab854ef4e6b235d76 100644 --- a/Console/Server.hh +++ b/Console/Server.hh @@ -137,6 +137,8 @@ namespace console { std::ostream & stream(); std::string promptString() const; + static Client & get(std::ostream & os); + protected: private: diff --git a/Console/Server.ih b/Console/Server.ih index bffdacb0dc5a70c0a773385b89435a0f7ad3b648..eabef7e1150384dd5ff9d2f2ea626344d3bbe120 100644 --- a/Console/Server.ih +++ b/Console/Server.ih @@ -55,6 +55,8 @@ namespace detail { NonblockingSocketSink(Client & client); std::streamsize write(const char * s, std::streamsize n); + + Client & client() const; private: Client & client_; diff --git a/Console/testServer.cc b/Console/testServer.cc index 70b8d34e58bbaf2097bfcd4203b9a28126c389c1..bf413849ad3fa0e731fe61e2cabd5bb3c6341410 100644 --- a/Console/testServer.cc +++ b/Console/testServer.cc @@ -69,6 +69,11 @@ void shutdownServer() throw senf::console::Executor::ExitException(); } +void enableLogging(std::ostream & os) +{ + senf::console::Client::get(os).route<senf::SenfLog,senf::log::NOTICE>(); +} + int main(int, char **) { ::signal(SIGPIPE, SIG_IGN); @@ -76,11 +81,18 @@ int main(int, char **) senf::console::root() .doc("This is the console test application"); + senf::console::root() + .mkdir("console") + .doc("Console settings"); senf::console::root() .mkdir("test") - .doc("Network related settings"); + .doc("Test functions"); senf::console::root() .mkdir("server"); + + senf::console::root()["console"] + .add("showlog", &enableLogging) + .doc("Enable display of log messages on the current console"); senf::console::root()["server"] .add("shutdown", &shutdownServer) .doc("Terminate server application"); @@ -89,7 +101,7 @@ int main(int, char **) .doc("Example of a function utilizing manual argument parsing"); TestObject test; - senf::console::root() + senf::console::root()["test"] .add("testob", test.dir) .doc("Example of an instance directory");