diff --git a/lib/readline.js b/lib/readline.js index 586f42209e..7303bfb3c4 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -25,8 +25,7 @@ function Interface (output, isTTY) { this.setPrompt("node> "); // Current line - this.buf = new Buffer(kBufSize); - this.buf.used = 0; + this.line = "" if (!isTTY) { this._tty = false; @@ -57,7 +56,6 @@ Interface.prototype.setPrompt = function (prompt, length) { Interface.prototype.prompt = function () { if (this._tty) { - this.buf.used = 0; this.cursor = 0; this._refreshLine(); } else { @@ -67,13 +65,10 @@ Interface.prototype.prompt = function () { Interface.prototype._addHistory = function () { - if (this.buf.used === 0) return ""; + if (this.line.length === 0) return ""; - var b = new Buffer(this.buf.used); - this.buf.copy(b, 0, 0, this.buf.used); - this.buf.used = 0; - - this.history.unshift(b); + this.history.unshift(this.line); + this.line = ""; this.historyIndex = -1; this.cursor = 0; @@ -81,7 +76,7 @@ Interface.prototype._addHistory = function () { // Only store so many if (this.history.length > kHistorySize) this.history.pop(); - return b.toString('utf8'); + return this.history[0]; }; @@ -95,9 +90,7 @@ Interface.prototype._refreshLine = function () { // Write the prompt and the current buffer content. this.output.write(this._prompt); - if (this.buf.used > 0) { - this.output.write(this.buf.slice(0, this.buf.used)); - } + this.output.write(this.line); // Erase to right. this.output.write('\x1b[0K'); @@ -123,31 +116,22 @@ Interface.prototype.write = function (d) { Interface.prototype._normalWrite = function (b) { - for (var i = 0; i < b.length; i++) { - var code = b instanceof Buffer ? b[i] : b.charCodeAt(i); - if (code === '\n'.charCodeAt(0) || code === '\r'.charCodeAt(0)) { - var s = this.buf.toString('utf8', 0, this.buf.used); - this.emit('line', s); - this.buf.used = 0; - } else { - this.buf[this.buf.used++] = code; - } - } + // Very simple implementation right now. Should try to break on + // new lines. + this.emit('line', b.toString()); }; 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.line = this.history[this.historyIndex]; + this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } else if (this.historyIndex === 0) { this.historyIndex = -1; this.cursor = 0; - this.buf.used = 0; + this.line = ''; this._refreshLine(); } }; @@ -155,10 +139,8 @@ Interface.prototype._historyNext = function () { 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.line = this.history[this.historyIndex]; + this.cursor = this.line.length; // set cursor to end of line. this._refreshLine(); } @@ -174,13 +156,12 @@ Interface.prototype._ttyWrite = function (b) { break; case 4: // control-d, delete right or EOF - if (this.cursor === 0 && this.buf.used === 0) { + if (this.cursor === 0 && this.line.length === 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--; + } else if (this.cursor < this.line.length) { + this.line = this.line.slice(0, this.cursor) + + this.line.slice(this.cursor+1, this.line.length) + ; this._refreshLine(); } break; @@ -194,23 +175,23 @@ Interface.prototype._ttyWrite = function (b) { case 127: /* backspace */ case 8: /* ctrl+h */ - if (this.cursor > 0 && this.buf.used > 0) { - for (var i = this.cursor; i < this.buf.used; i++) { - this.buf[i-1] = this.buf[i]; - } + if (this.cursor > 0 && this.line.length > 0) { + this.line = this.line.slice(0, this.cursor-1) + + this.line.slice(this.cursor, this.line.length) + ; this.cursor--; - this.buf.used--; this._refreshLine(); } break; case 21: /* Ctrl+u, delete the whole line. */ - this.cursor = this.buf.used = 0; + this.cursor = 0; + this.line = ''; this._refreshLine(); break; case 11: /* Ctrl+k, delete from current to end of line. */ - this.buf.used = this.cursor; + this.line = this.line.slice(0, this.cursor); this._refreshLine(); break; @@ -220,7 +201,7 @@ Interface.prototype._ttyWrite = function (b) { break; case 5: /* ctrl+e, go to the end of the line */ - this.cursor = this.buf.used; + this.cursor = this.line.length; this._refreshLine(); break; @@ -232,7 +213,7 @@ Interface.prototype._ttyWrite = function (b) { break; case 6: // control-f, forward one character - if (this.cursor != this.buf.used) { + if (this.cursor != this.line.length) { this.cursor++; this._refreshLine(); } @@ -249,17 +230,17 @@ Interface.prototype._ttyWrite = function (b) { case 27: /* escape sequence */ 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] === 102 && this.cursor < this.line.length) { // meta-f - forward word } else if (b[1] === 91 && b[2] === 68) { // left arrow if (this.cursor > 0) { this.cursor--; - this._refreshLine(); + this.output.write('\x1b[0D'); } } else if (b[1] === 91 && b[2] === 67) { // right arrow - if (this.cursor != this.buf.used) { + if (this.cursor != this.line.length) { this.cursor++; - this._refreshLine(); + this.output.write('\x1b[0C'); } } else if (b[1] === 91 && b[2] === 65) { // up arrow this._historyPrev(); @@ -269,18 +250,17 @@ Interface.prototype._ttyWrite = function (b) { break; default: - if (this.buf.used < kBufSize) { - for (var i = this.buf.used + 1; this.cursor < i; i--) { - this.buf[i] = this.buf[i-1]; - } - this.buf[this.cursor++] = b[0]; - this.buf.used++; - - if (this.buf.used == this.cursor) { - this.output.write(b); - } else { - this._refreshLine(); - } + var c = b.toString('utf8'); + if (this.cursor < this.line.length) { + var beg = this.line.slice(0, this.cursor); + var end = this.line.slice(this.cursor, this.line.length); + this.line = beg + c + end; + this.cursor += c.length; + this._refreshLine(); + } else { + this.line += c; + this.cursor += c.length; + this.output.write(c); } break; }