From 09af242c898888697933b00a38a7c84a9a55ac38 Mon Sep 17 00:00:00 2001 From: Matt Ranney Date: Mon, 7 Jun 2010 16:43:50 -0700 Subject: [PATCH] Support more readline navigation keys. --- lib/readline.js | 105 ++++++++++++++++++++++++++++++++---------------- lib/repl.js | 3 +- 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/lib/readline.js b/lib/readline.js index 9a1c21e83f..586f42209e 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -135,7 +135,36 @@ Interface.prototype._normalWrite = function (b) { } }; +Interface.prototype._historyNext = function () { + if (this.historyIndex > 0) { + this.historyIndex--; + this.history[this.historyIndex].copy(this.buf, 0); + this.buf.used = this.history[this.historyIndex].length; + // set cursor to end of line. + this.cursor = this.buf.used; + this._refreshLine(); + } else if (this.historyIndex === 0) { + this.historyIndex = -1; + this.cursor = 0; + this.buf.used = 0; + this._refreshLine(); + } +}; + +Interface.prototype._historyPrev = function () { + if (this.historyIndex + 1 < this.history.length) { + this.historyIndex++; + this.history[this.historyIndex].copy(this.buf, 0); + this.buf.used = this.history[this.historyIndex].length; + // set cursor to end of line. + this.cursor = this.buf.used; + + this._refreshLine(); + } +}; + +// handle a write from the tty Interface.prototype._ttyWrite = function (b) { switch (b[0]) { /* ctrl+c */ @@ -144,8 +173,16 @@ Interface.prototype._ttyWrite = function (b) { this.close(); break; - case 4: /* ctrl+d */ - this.close(); + case 4: // control-d, delete right or EOF + if (this.cursor === 0 && this.buf.used === 0) { + this.close(); + } else if (this.cursor < this.buf.used) { + for (var i = this.cursor; i < this.buf.used; i++) { + this.buf[i] = this.buf[i+1]; + } + this.buf.used--; + this._refreshLine(); + } break; case 13: /* enter */ @@ -187,47 +224,47 @@ Interface.prototype._ttyWrite = function (b) { this._refreshLine(); break; + case 2: // control-b, back one character + if (this.cursor > 0) { + this.cursor--; + this._refreshLine(); + } + break; + + case 6: // control-f, forward one character + if (this.cursor != this.buf.used) { + this.cursor++; + this._refreshLine(); + } + break; + + case 14: // control-n, next history item + this._historyNext(); + break; + + case 16: // control-p, previous history item + this._historyPrev(); + break; + case 27: /* escape sequence */ - if (b[1] === 91 && b[2] === 68) { - // left arrow + if (b[1] === 98 && this.cursor > 0) { // meta-b - backward word + + } else if (b[1] === 102 && this.cursor < this.buf.used) { // meta-f - forward word + + } else if (b[1] === 91 && b[2] === 68) { // left arrow if (this.cursor > 0) { this.cursor--; this._refreshLine(); } - } else if (b[1] === 91 && b[2] === 67) { - // right arrow + } else if (b[1] === 91 && b[2] === 67) { // right arrow if (this.cursor != this.buf.used) { this.cursor++; this._refreshLine(); } - } else if (b[1] === 91 && b[2] === 65) { - // up arrow - if (this.historyIndex + 1 < this.history.length) { - this.historyIndex++; - this.history[this.historyIndex].copy(this.buf, 0); - this.buf.used = this.history[this.historyIndex].length; - // set cursor to end of line. - this.cursor = this.buf.used; - - this._refreshLine(); - } - - } else if (b[1] === 91 && b[2] === 66) { - // down arrow - if (this.historyIndex > 0) { - this.historyIndex--; - this.history[this.historyIndex].copy(this.buf, 0); - this.buf.used = this.history[this.historyIndex].length; - // set cursor to end of line. - this.cursor = this.buf.used; - this._refreshLine(); - - } else if (this.historyIndex === 0) { - this.historyIndex = -1; - this.cursor = 0; - this.buf.used = 0; - this._refreshLine(); - } + } else if (b[1] === 91 && b[2] === 65) { // up arrow + this._historyPrev(); + } else if (b[1] === 91 && b[2] === 66) { // down arrow + this._historyNext(); } break; diff --git a/lib/repl.js b/lib/repl.js index afb28ea1e2..8df05f65c5 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -68,8 +68,7 @@ function REPLServer(prompt, stream) { // This try is for determining if the command is complete, or should // continue onto the next line. try { - // Scope the readline with self.scope - // with(){} and eval() are considered bad. + // Use evalcx to supply the global scope var ret = evalcx(self.buffered_cmd, scope, "repl"); if (ret !== undefined) { scope._ = ret;