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
{
if (tifo_.hasProperty(Terminfo::properties::KeypadXmit))
write(tifo_.getString(Terminfo::properties::KeypadXmit));
+ return true;
}
prefix_ void senf::term::BaseEditor::cb_charReceived(char c)
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);
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)
if (enabled_)
return;
enabled_ = true;
- redisplay();
+ forceRedisplay();
}
prefix_ void senf::term::LineEditor::hide()
if (enabled_)
newline();
hide();
+ pushHistory(text_);
callback_(text_);
clear();
}
prefix_ void senf::term::LineEditor::clear()
{
set("");
+ historyPoint_ = history_.size();
}
prefix_ void senf::term::LineEditor::redisplay()
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_;
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"
// Custom includes
#include <map>
+#include <vector>
+#include <string>
#include <senf/Scheduler/ClockService.hh>
#include <senf/Scheduler/TimerEvent.hh>
#include "AbstractTerminal.hh"
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();
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);
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();
virtual void v_keyReceived(keycode_t key);
typedef std::map<keycode_t, KeyBinding> KeyMap;
+ typedef std::vector<std::string> History;
bool enabled_;
bool redisplayNeeded_;
keycode_t lastKey_;
AcceptCallback callback_;
KeyMap bindings_;
+ History history_;
+ unsigned historyPoint_;
};
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);
}