29 : terminal_ (&terminal),
30 keyTimeout_ (
ClockService::milliseconds(DEFAULT_KEY_TIMEOUT_MS)),
31 timer_ (
"senf::term::BaseEditor::keySequenceTimeout",
33 column_ (0u), displayHeight_ (1u), line_ (0u)
63 else if (c < column_) {
80 if (column_ >=
width()-1)
88 if (text.size() >
width()-column_-1) {
89 write(text.substr(0,
width()-column_-1));
90 column_ =
width() - 1;
94 column_ += text.size();
130 if (ll >= displayHeight_)
131 ll = displayHeight_-1;
145 else if (ll < line_) {
170 for (
unsigned i (1); i < displayHeight_; ++i) {
194 keyParser_.
load(tifo_);
211 prefix_ void senf::term::BaseEditor::cb_charReceived(
char c)
214 timer_.
timeout(scheduler::eventTime() + keyTimeout_);
220 if (column_ >=
width())
224 prefix_ void senf::term::BaseEditor::keySequenceTimeout()
226 while (!inputBuffer_.empty()) {
229 inputBuffer_.erase(0, 1);
233 prefix_ void senf::term::BaseEditor::processKeys()
236 std::pair<KeyParser::keycode_t, std::string::size_type> result
237 (keyParser_.
lookup(inputBuffer_));
241 inputBuffer_.erase(0, result.second);
242 }
while (! inputBuffer_.empty());
249 return terminal_->
width();
255 return terminal_->
height();
258 prefix_ void senf::term::BaseEditor::write(
char ch)
260 terminal_->
write(ch);
263 prefix_ void senf::term::BaseEditor::write(std::string
const & s)
265 for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
272 :
BaseEditor(terminal), enabled_ (false), redisplayNeeded_ (false), prompt_ (
"$"),
273 promptWidth_ (1u), editWidth_ (0u), text_ (
""), point_ (0u), displayPos_ (0u),
274 lastKey_ (0u), callback_ (cb), historyPoint_ (0u)
296 promptWidth_ = prompt_.size();
297 if (promptWidth_ >
width() - 4 &&
width() > 4)
298 promptWidth_ =
width() - 4;
299 editWidth_ =
width() - promptWidth_ - 3;
308 if (point_ > text.size())
309 point_ = text.size();
311 if (point_ > editWidth_)
312 displayPos_ = point_ - editWidth_;
321 for (
unsigned n (0); n < auxDisplay_.size(); ++n) {
351 historyPoint_ = history_.size();
356 redisplayNeeded_ =
true;
365 if (prompt_.size() > promptWidth_)
366 put(prompt_.substr(prompt_.size()-promptWidth_));
369 put( displayPos_ > 0 ?
'<' :
' ' );
370 if (text_.size() > displayPos_ + editWidth_) {
371 toColumn(editWidth_ + promptWidth_ + 1);
376 put(text_.substr(displayPos_, editWidth_));
377 toColumn(point_ - displayPos_ + promptWidth_ + 1);
378 redisplayNeeded_ =
false;
384 if (point_ > text_.size())
385 point_ = text_.size();
386 if (point_ < displayPos_)
387 displayPos_ = point_;
388 if (point_ > displayPos_+editWidth_)
389 displayPos_ = point_-editWidth_;
396 if (displayPos_ > text_.size())
397 displayPos_ = text_.size();
398 if (point_ < displayPos_)
399 point_ = displayPos_;
400 if (point_ > displayPos_+editWidth_)
401 point_ = displayPos_+editWidth_;
407 if (point_ >= text_.size())
409 text_.erase(point_, n);
415 text_.insert(point_, std::string(1, ch));
422 text_.insert(point_, text);
430 && (accept || historyPoint_ == history_.size() || history_[historyPoint_] !=
text)
431 && (history_.empty() || history_.back() !=
text)) {
432 history_.push_back(text);
434 history_.erase(history_.begin());
436 historyPoint_ = history_.size() - 1;
442 if (historyPoint_ <= 0)
445 std::string entry (history_[--historyPoint_]);
446 set(entry, entry.size());
451 if (historyPoint_ >= history_.size())
455 if (historyPoint_ >= history_.size())
458 std::string entry (history_[historyPoint_]);
459 set(entry, entry.size());
468 while (auxDisplay_.size() < line+1)
469 auxDisplay_.push_back(
"");
470 auxDisplay_[line] =
text;
506 bindings_[key] = binding;
511 bindings_.erase(key);
514 prefix_ bool senf::term::LineEditor::cb_init()
523 prefix_ void senf::term::LineEditor::cb_windowSizeChanged()
538 KeyMap::iterator i (bindings_.find(key));
539 if (i != bindings_.end())
541 else if (key >=
' ' && key < 256)
545 if (redisplayNeeded_)
548 toColumn(point_ - displayPos_ + promptWidth_ + 1);
556 if (key >=
' ' && key < 256)
567 unsigned p (editor.
point());
579 if (editor.
text().empty()) {
588 unsigned p (editor.
point());
641 typedef std::vector<std::string> Completions;
644 Completions completions;
646 unsigned e (editor.
point());
648 completer(editor, b, e, prefix, completions);
649 if (completions.empty())
657 unsigned commonStart (completions[0].size());
658 unsigned maxLen (commonStart);
659 for (Completions::const_iterator i (boost::next(completions.begin()));
660 i != completions.end(); ++i) {
661 if (i->size() > maxLen)
664 for (; n < commonStart && n < i->size() && completions[0][n] == (*i)[n]; ++n) ;
669 std::string completion (prefix+completions[0].substr(0, commonStart));
670 bool didComplete (
false);
671 if (
text.substr(b, e) != completion) {
673 text.insert(b, completion);
678 editor.
set(
text, b+prefix.size()+commonStart);
679 if (didComplete || completions.size() == 1)
683 unsigned colWidth (maxLen+2);
684 unsigned nColumns ((editor.
width()-1) / colWidth);
685 if (nColumns < 1) nColumns = 1;
686 unsigned nRows ((completions.size()+nColumns-1) / nColumns);
688 editor.
auxDisplay(0,
"(too many completions)");
691 Completions::iterator i (completions.begin());
692 for (
unsigned row (0); row < nRows; ++row) {
694 for (
unsigned column (0); column < nColumns && i != completions.end(); ++column, ++i) {
695 std::string entry (colWidth,
' ');
696 std::copy(i->begin(),
697 i->size() > colWidth-2 ? i->begin()+colWidth-2 : i->end(),
unsigned currentLine() const
Return number of current relative line.
Provide editor support terminal functionality.
void load(std::string const &term)
Load terminfo entry term.
void nextHistory()
Switch to next history entry.
void acceptWithRepeat(LineEditor &editor)
Accept, possibly repeat last history entry.
std::pair< keycode_t, size_type > lookup(std::string const &key) const
Lookup up string key.
void clear()
Clear editor buffer.
void deleteChar(unsigned n=1)
Delete n characters at point.
void defineKey(keycode_t key, KeyBinding binding)
Bind key key to binding.
boost::function< void(LineEditor &, unsigned &b, unsigned &e, std::string &prefix, std::vector< std::string > &)> Completer
void redisplay()
Mark the editor buffer for redisplay.
void auxDisplay(unsigned line, std::string const &text)
Display text on aux display line line.
bool hasProperty(properties::Boolean p) const
true, if boolean property p exists
unsigned height() const
Return current screen height.
void selfInsertCommand(LineEditor &editor)
Insert key as literal character.
void accept()
Accept current user input and call the accept callback.
virtual void cb_windowSizeChanged()
Called whenever the terminal window size changes.
void nextHistory(LineEditor &editor)
Move to next history entry.
virtual unsigned height() const =0
Get current terminal window height.
void clearLine()
Clear current line and move cursor to first column.
void unsetKey(keycode_t key)
Remove all bindings for key.
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
void gotoChar(unsigned n)
Move cursor to position n.
void restartEdit(LineEditor &editor)
Clear edit buffer and restart edit.
void toLine(unsigned l)
Move to relative display line l.
void prevHistory()
Switch to previous history entry.
void scrollTo(unsigned n)
Move position to beginning of display line.
static unsigned const MAX_HISTORY_SIZE
void backwardChar(LineEditor &editor)
Move one char backwards.
void insert(char ch)
Insert ch at point.
BaseEditor(AbstractTerminal &terminal)
virtual void v_keyReceived(keycode_t key)=0
Called whenever a key is received.
void accept(LineEditor &editor)
Accept input line.
void complete(LineEditor &editor, Completer completer)
Complete text at cursor.
void deleteToEndOfLine(LineEditor &editor)
Delete from cursor to end of line.
Invalid, incomplete or non-existent terminfo entry exception.
void backwardDeleteChar(LineEditor &editor)
Delete char before cursor.
virtual bool cb_init()
Called when terminal is initialized.
string_t getString(properties::String p) const
Get string property value.
void prompt(std::string const &text)
Set prompt string.
LineEditor(AbstractTerminal &terminal, AcceptCallback cb)
Create a LineEditor.
void forwardChar(LineEditor &editor)
Move one char forward.
unsigned displayPos()
Get current display position.
void put(char ch)
Write ch at current column.
void timeout(ClockService::clock_type const &timeout, bool initiallyEnabled=true)
virtual void write(char ch)=0
Write character to terminal.
std::string const & text()
Get current editor buffer contents.
void hide()
Disable editor widget.
boost::function< void(std::string const &)> AcceptCallback
Callback function type.
void prevHistory(LineEditor &editor)
Move to previous history entry.
void forceRedisplay()
Redisplay the editor buffer now.
static keycode_t Ctrl(char ch)
Helper to convert uppercase char to Control key code.
void setNormal()
Set normal char display.
unsigned currentColumn() const
Return number of current column.
Terminfo property constants.
void pushHistory(std::string const &text, bool accept=false)
Add string text to history.
virtual std::string terminalType()=0
Get the terminal type.
boost::function< void(LineEditor &)> KeyBinding
Type of a key binding function.
void show()
Enable editor widget.
unsigned maxAuxDisplayHeight()
Get maximum height of the aux display area.
void beginningOfLine(LineEditor &editor)
Move to beginning of line.
Single line interactive text editor.
virtual void setCallbacks(Callbacks &cb)=0
Register terminal callbacks.
unsigned point()
Get current cursor position.
void set(std::string const &text, unsigned pos=0u)
Set edit buffer contents.
void newline()
Move to beginning of a new, empty line.
void clearScreen(LineEditor &editor)
Clear screen and redisplay editor.
void maybeClrScr()
Clear screen if possible.
std::string formatString(properties::String p, number_t arg1=NoValue, number_t arg2=NoValue, number_t arg3=NoValue, number_t arg4=NoValue, number_t arg5=NoValue, number_t arg6=NoValue, number_t arg7=NoValue, number_t arg8=NoValue, number_t arg9=NoValue) const
Format string property value.
void clearAuxDisplay()
Clear the aux display area.
void reset()
Reset display area to single line.
KeyParser::keycode_t keycode_t
void deleteChar(LineEditor &editor)
Delete char at cursor.
void setBold()
Set bold char display.
virtual unsigned width() const =0
Get current terminal window width.
void toColumn(unsigned c)
Move cursor to column c.
void load(Terminfo const &ti)
Load keymap information from ti.
unsigned width() const
Return current screen width.
Abstract terminal interface.
keycode_t lastKey()
Get last key code received.
void endOfLine(LineEditor &editor)
Move to end of line.