Utils/Console: Remove endless exception tracebacks from console error display
g0dil [Thu, 8 Jan 2009 10:24:12 +0000 (10:24 +0000)]
Utils/Termlib: Implement LineEditor history

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1046 270642c3-0616-0410-b53a-bc976706d245

Utils/Console/Server.cc
Utils/Termlib/Editor.cc
Utils/Termlib/Editor.hh
Utils/Termlib/Telnet.cc

index d326133..b3bf694 100644 (file)
@@ -291,7 +291,11 @@ prefix_ std::string::size_type senf::console::Client::handleInput(std::string da
         handle_.facet<senf::TCPSocketProtocol>().shutdown(senf::TCPSocketProtocol::ShutRD);
     }
     catch (std::exception & ex) {
-        stream() << ex.what() << std::endl;
+        std::string msg (ex.what());
+        std::string::size_type i (msg.find("-- \n"));
+        if (i != std::string::npos)
+            msg = msg.substr(i+4);
+        stream() << msg << std::endl;
     }
     catch (...) {
         stream() << "unidentified error (unknown exception thrown)" << std::endl;
index 57e1e78..d8bd15e 100644 (file)
@@ -124,6 +124,12 @@ prefix_ void senf::term::BaseEditor::setNormal()
         write(tifo_.getString(Terminfo::properties::ExitAttributeMode));
 }
 
+prefix_ void senf::term::BaseEditor::maybeClrScr()
+{
+    if (tifo_.hasProperty(Terminfo::properties::ClearScreen))
+        write(tifo_.getString(Terminfo::properties::ClearScreen));
+}
+
 prefix_ unsigned senf::term::BaseEditor::currentColumn()
    const
 {
@@ -148,6 +154,7 @@ prefix_ bool senf::term::BaseEditor::cb_init()
 
     if (tifo_.hasProperty(Terminfo::properties::KeypadXmit))
         write(tifo_.getString(Terminfo::properties::KeypadXmit));
+    return true;
 }
 
 prefix_ void senf::term::BaseEditor::cb_charReceived(char c)
@@ -205,11 +212,13 @@ prefix_ void senf::term::BaseEditor::write(std::string const & s)
 
 prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCallback cb)
     : BaseEditor(terminal), enabled_ (true), prompt_ ("$"), promptWidth_ (1u), editWidth_ (0u), 
-      text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb)
+      text_ (""), point_ (0u), displayPos_ (0u), lastKey_ (0u), callback_ (cb), historyPoint_ (0u)
 {
     defineKey(KeyParser::Return,    &bindings::accept);
     defineKey(KeyParser::Right,     &bindings::forwardChar);
     defineKey(KeyParser::Left,      &bindings::backwardChar);
+    defineKey(KeyParser::Up,        &bindings::prevHistory);
+    defineKey(KeyParser::Down,      &bindings::nextHistory);
     defineKey(KeyParser::Backspace, &bindings::backwardDeleteChar);
     defineKey(KeyParser::Delete,    &bindings::deleteChar);
     defineKey(KeyParser::Home,      &bindings::beginningOfLine);
@@ -219,6 +228,7 @@ prefix_ senf::term::LineEditor::LineEditor(AbstractTerminal & terminal, AcceptCa
     defineKey(KeyParser::Ctrl('E'), &bindings::endOfLine);
     defineKey(KeyParser::Ctrl('D'), &bindings::deleteChar);
     defineKey(KeyParser::Ctrl('C'), &bindings::restartEdit);
+    defineKey(KeyParser::Ctrl('L'), &bindings::clearScreen);
 }
 
 prefix_ void senf::term::LineEditor::prompt(std::string const & text)
@@ -249,7 +259,7 @@ prefix_ void senf::term::LineEditor::show()
     if (enabled_)
         return;
     enabled_ = true;
-    redisplay();
+    forceRedisplay();
 }
 
 prefix_ void senf::term::LineEditor::hide()
@@ -265,6 +275,7 @@ prefix_ void senf::term::LineEditor::accept()
     if (enabled_)
         newline();
     hide();
+    pushHistory(text_);
     callback_(text_);
     clear();
 }
@@ -272,6 +283,7 @@ prefix_ void senf::term::LineEditor::accept()
 prefix_ void senf::term::LineEditor::clear()
 {
     set("");
+    historyPoint_ = history_.size();
 }
 
 prefix_ void senf::term::LineEditor::redisplay()
@@ -347,6 +359,41 @@ prefix_ void senf::term::LineEditor::insert(std::string const & text)
     redisplay();
 }
 
+prefix_ void senf::term::LineEditor::pushHistory(std::string const & text)
+{
+    if (! text.empty()
+        && (historyPoint_ == history_.size() || history_[historyPoint_] != text)
+        && (history_.empty() || history_.back() != text)) {
+        history_.push_back(text);
+        while (history_.size() > MAX_HISTORY_SIZE)
+            history_.erase(history_.begin());
+        historyPoint_ = history_.size() - 1;
+    }
+}
+
+prefix_ void senf::term::LineEditor::prevHistory()
+{
+    if (historyPoint_ <= 0)
+        return;
+    pushHistory(text_);
+    std::string entry (history_[--historyPoint_]);
+    set(entry, entry.size());
+}
+
+prefix_ void senf::term::LineEditor::nextHistory()
+{
+    if (historyPoint_ >= history_.size())
+        return;
+    pushHistory(text_);
+    ++ historyPoint_;
+    if (historyPoint_ >= history_.size())
+        set("");
+    else {
+        std::string entry (history_[historyPoint_]);
+        set(entry, entry.size());
+    }
+}
+
 prefix_ std::string const & senf::term::LineEditor::text()
 {
     return text_;
@@ -470,6 +517,23 @@ prefix_ void senf::term::bindings::restartEdit(LineEditor & editor)
     editor.redisplay();
 }
 
+prefix_ void senf::term::bindings::prevHistory(LineEditor & editor)
+{
+    editor.prevHistory();
+}
+
+prefix_ void senf::term::bindings::nextHistory(LineEditor & editor)
+{
+    editor.nextHistory();
+}
+
+prefix_ void senf::term::bindings::clearScreen(LineEditor & editor)
+{
+    editor.maybeClrScr();
+    editor.clearLine();
+    editor.forceRedisplay();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 //#include "Editor.mpp"
index e5cb475..d654a35 100644 (file)
@@ -28,6 +28,8 @@
 
 // Custom includes
 #include <map>
+#include <vector>
+#include <string>
 #include <senf/Scheduler/ClockService.hh>
 #include <senf/Scheduler/TimerEvent.hh>
 #include "AbstractTerminal.hh"
@@ -56,6 +58,7 @@ namespace term {
         void clearLine();               ///< Clear current line and move cursor to first column
         void setBold();                 ///< Set bold char display
         void setNormal();               ///< Set normal char display
+        void maybeClrScr();             ///< Clear screen if possible
 
         unsigned currentColumn() const; ///< Return number of current column
         unsigned width();
@@ -94,6 +97,8 @@ namespace term {
         typedef boost::function<void (LineEditor&)> KeyBinding;
         typedef boost::function<void (std::string const &)> AcceptCallback;
 
+        static unsigned const MAX_HISTORY_SIZE = 1024u;
+
         ///////////////////////////////////////////////////////////////////////////
 
         LineEditor(AbstractTerminal & terminal, AcceptCallback cb);
@@ -120,6 +125,11 @@ namespace term {
         void insert(char ch);
         void insert(std::string const & text);
 
+        // History
+        void pushHistory(std::string const & text);
+        void prevHistory();
+        void nextHistory();
+
         // Get information
         std::string const & text();
         unsigned point();
@@ -136,6 +146,7 @@ namespace term {
         virtual void v_keyReceived(keycode_t key);
 
         typedef std::map<keycode_t, KeyBinding> KeyMap;
+        typedef std::vector<std::string> History;
 
         bool enabled_;
         bool redisplayNeeded_;
@@ -148,6 +159,8 @@ namespace term {
         keycode_t lastKey_;
         AcceptCallback callback_;
         KeyMap bindings_;
+        History history_;
+        unsigned historyPoint_;
     };
 
 namespace bindings {
@@ -162,6 +175,9 @@ namespace bindings {
     void endOfLine           (LineEditor & editor);
     void deleteToEndOfLine   (LineEditor & editor);
     void restartEdit         (LineEditor & editor);
+    void prevHistory         (LineEditor & editor);
+    void nextHistory         (LineEditor & editor);
+    void clearScreen         (LineEditor & editor);
 
 }
 
index b32747a..d962808 100644 (file)
@@ -44,7 +44,7 @@ prefix_ senf::term::BaseTelnetProtocol::BaseTelnetProtocol(Handle handle)
                     senf::scheduler::FdEvent::EV_WRITE, false),
       pendingRequests_ (0u),
       requestTimeout_ (ClockService::milliseconds(DEFAULT_REQUEST_TIMEOUT_MS)),
-      timeout_ ("senf::term::BaseTelnetProtocol::timeout",
+      timeout_ ("senf::term::BaseTelnetProtocol::configTimeout",
                 senf::membind(&BaseTelnetProtocol::timeout, this))
 {}