From 72106003eead96c158f4dac4f559ea6e115c74fb Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Mon, 28 Apr 2008 23:13:49 +0000
Subject: [PATCH] Console: Add console routing to testServer example Console:
 Remove backtrace from syntax error messages Console: auto-cd when specifying
 a directory as command

---
 Console/Executor.cc   | 40 ++++++++++++++++++++++++----------------
 Console/Executor.hh   |  2 +-
 Console/Node.cci      | 12 +++++++++++-
 Console/Node.hh       |  7 ++++++-
 Console/Readline.cc   | 17 +++++++++++++----
 Console/Readline.hh   |  5 +++++
 Console/Server.cci    | 11 +++++++++++
 Console/Server.hh     |  2 ++
 Console/Server.ih     |  2 ++
 Console/testServer.cc | 16 ++++++++++++++--
 10 files changed, 89 insertions(+), 25 deletions(-)

diff --git a/Console/Executor.cc b/Console/Executor.cc
index 5e4b6f21e..da8aa49e3 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 81dafd946..441c3d78d 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 6f24e9c3a..c0d76bc0e 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 6a2732c4b..a93c23ccc 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 43da4470d..8d796e62f 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 7ac5741ef..7a348ef88 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 8e0d434b1..573773d32 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 abc70b78c..8d9b30a8e 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 bffdacb0d..eabef7e11 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 70b8d34e5..bf413849a 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");
 
-- 
GitLab