readline: support TERM=dumb

When TERM=dumb and .isTTY=true don't use ANSI escape codes
and ignore all keys, except 'escape', 'return' and 'ctrl-c'.

PR-URL: https://github.com/nodejs/node/pull/26261
Fixes: https://github.com/nodejs/node/issues/26187
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
This commit is contained in:
Vladislav Kaminsky 2019-02-22 16:07:43 +04:00 committed by Ruben Bridgewater
parent 99523758dc
commit d3a62fe7fc
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
3 changed files with 75 additions and 7 deletions

View File

@ -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) {

View File

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

View File

@ -0,0 +1,3 @@
text
text
text