diff --git a/Utils/Console/Server.cc b/Utils/Console/Server.cc index d3261331bc6c3b71f05067576bf0921eb58c641b..b3bf694ea06bf28bc55d66250bafe766f9c3adc7 100644 --- a/Utils/Console/Server.cc +++ b/Utils/Console/Server.cc @@ -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; diff --git a/Utils/Termlib/Editor.cc b/Utils/Termlib/Editor.cc index 57e1e78adc427fb91a88f042ac35c2037282ab4f..d8bd15e9aa7516e6d9f0e30d31c44a12401965c3 100644 --- a/Utils/Termlib/Editor.cc +++ b/Utils/Termlib/Editor.cc @@ -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" diff --git a/Utils/Termlib/Editor.hh b/Utils/Termlib/Editor.hh index e5cb475cdc75745ea4358adc7144b74bc265fa25..d654a3578ffd650214430436f84b7caff72278c7 100644 --- a/Utils/Termlib/Editor.hh +++ b/Utils/Termlib/Editor.hh @@ -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); } diff --git a/Utils/Termlib/Telnet.cc b/Utils/Termlib/Telnet.cc index b32747af07940e60c73dce8fc54241954a90e7ec..d962808e7e1bd4fafa47700a063a9fd6ecdfe359 100644 --- a/Utils/Termlib/Telnet.cc +++ b/Utils/Termlib/Telnet.cc @@ -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)) {}