|
|
@ -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; |
|
|
|
} |
|
|
|