diff --git a/lib/readline.js b/lib/readline.js index 64d8efb30f1138..c3484000d80545 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -34,7 +34,6 @@ const { const { validateString } = require('internal/validators'); const { inspect } = require('util'); const { emitExperimentalWarning } = require('internal/util'); -const { Buffer } = require('buffer'); const EventEmitter = require('events'); const { CSI, @@ -161,6 +160,10 @@ function Interface(input, output, completer, terminal) { this.terminal = !!terminal; + if (process.env.TERM === 'dumb') { + this._ttyWrite = _ttyWriteDumb.bind(this); + } + function ondata(data) { self._normalWrite(data); } @@ -276,7 +279,7 @@ Interface.prototype._setRawMode = function(mode) { Interface.prototype.prompt = function(preserveCursor) { if (this.paused) this.resume(); - if (this.terminal) { + if (this.terminal && process.env.TERM !== 'dumb') { if (!preserveCursor) this.cursor = 0; this._refreshLine(); } else { @@ -417,7 +420,11 @@ Interface.prototype.resume = function() { Interface.prototype.write = function(d, key) { if (this.paused) this.resume(); - this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d); + if (this.terminal) { + this._ttyWrite(d, key); + } else { + this._normalWrite(d); + } }; Interface.prototype._normalWrite = function(b) { @@ -789,6 +796,46 @@ Interface.prototype._moveCursor = function(dx) { } }; +function _ttyWriteDumb(s, key) { + key = key || {}; + + if (key.name === 'escape') return; + + if (this._sawReturnAt && key.name !== 'enter') + this._sawReturnAt = 0; + + if (key.ctrl && key.name === 'c') { + if (this.listenerCount('SIGINT') > 0) { + this.emit('SIGINT'); + } else { + // This readline instance is finished + this.close(); + } + } + + switch (key.name) { + case 'return': // carriage return, i.e. \r + this._sawReturnAt = Date.now(); + this._line(); + break; + + case 'enter': + // When key interval > crlfDelay + if (this._sawReturnAt === 0 || + Date.now() - this._sawReturnAt > this.crlfDelay) { + this._line(); + } + this._sawReturnAt = 0; + break; + + default: + if (typeof s === 'string' && s) { + this.line += s; + this.cursor += s.length; + this._writeToOutput(s); + } + } +} // handle a write from the tty Interface.prototype._ttyWrite = function(s, key) { @@ -1007,10 +1054,7 @@ Interface.prototype._ttyWrite = function(s, key) { // falls through default: - if (s instanceof Buffer) - s = s.toString('utf-8'); - - if (s) { + if (typeof s === 'string' && s) { var lines = s.split(/\r\n|\n|\r/); for (var i = 0, len = lines.length; i < len; i++) { if (i > 0) { diff --git a/test/pseudo-tty/readline-dumb-tty.js b/test/pseudo-tty/readline-dumb-tty.js new file mode 100644 index 00000000000000..6b9a3b59ad96e8 --- /dev/null +++ b/test/pseudo-tty/readline-dumb-tty.js @@ -0,0 +1,21 @@ +'use strict'; +require('../common'); + +process.env.TERM = 'dumb'; + +const readline = require('readline'); + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout +}); + +rl.write('text'); +rl.write(null, { ctrl: true, name: 'u' }); +rl.write(null, { name: 'return' }); +rl.write('text'); +rl.write(null, { name: 'backspace' }); +rl.write(null, { name: 'escape' }); +rl.write(null, { name: 'enter' }); +rl.write('text'); +rl.write(null, { ctrl: true, name: 'c' }); diff --git a/test/pseudo-tty/readline-dumb-tty.out b/test/pseudo-tty/readline-dumb-tty.out new file mode 100644 index 00000000000000..6841116ad12836 --- /dev/null +++ b/test/pseudo-tty/readline-dumb-tty.out @@ -0,0 +1,3 @@ +text +text +text