Skip to content

Commit 687cdf5

Browse files
committed
readline: inform line event about separator used
pass separator as a parameter to the callback alongwith line to inform line event about separator used to break lines fixes: #7952 (comment)
1 parent c829202 commit 687cdf5

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

lib/readline.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ let StringDecoder;
5757
const kHistorySize = 30;
5858
const kMincrlfDelay = 100;
5959
// \r\n, \n, or \r followed by something other than \n
60-
const lineEnding = /\r?\n|\r(?!\n)/;
60+
const lineEndingWithSeparator = /(?<=\r?\n|\r(?!\n))/;
61+
const lineEndingSeparatorInclusion = /[\r?\n|\r(?!\n)]$/;
6162

6263
const KEYPRESS_DECODER = Symbol('keypress-decoder');
6364
const ESCAPE_DECODER = Symbol('escape-decoder');
@@ -290,14 +291,14 @@ Interface.prototype.question = function(query, cb) {
290291
};
291292

292293

293-
Interface.prototype._onLine = function(line) {
294+
Interface.prototype._onLine = function(line, separator = '\n') {
294295
if (this._questionCallback) {
295296
var cb = this._questionCallback;
296297
this._questionCallback = null;
297298
this.setPrompt(this._oldPrompt);
298299
cb(line);
299300
} else {
300-
this.emit('line', line);
301+
this.emit('line', line, separator);
301302
}
302303
};
303304

@@ -425,7 +426,7 @@ Interface.prototype._normalWrite = function(b) {
425426
}
426427

427428
// Run test() on the new string chunk, not on the entire line buffer.
428-
var newPartContainsEnding = lineEnding.test(string);
429+
var newPartContainsEnding = lineEndingWithSeparator.test(string);
429430

430431
if (this._line_buffer) {
431432
string = this._line_buffer + string;
@@ -435,12 +436,21 @@ Interface.prototype._normalWrite = function(b) {
435436
this._sawReturnAt = string.endsWith('\r') ? Date.now() : 0;
436437

437438
// got one or more newlines; process into "line" events
438-
var lines = string.split(lineEnding);
439+
var lines = string.split(lineEndingWithSeparator);
439440
// either '' or (conceivably) the unfinished portion of the next line
440441
string = lines.pop();
441442
this._line_buffer = string;
442-
for (var n = 0; n < lines.length; n++)
443-
this._onLine(lines[n]);
443+
for (var n = 0; n < lines.length; n++) {
444+
const _line = lines[n];
445+
if (lineEndingSeparatorInclusion.test(_line)) {
446+
const lineWithoutSeparator = _line.slice(0, -1);
447+
const separator = _line.slice(-1);
448+
449+
this._onLine(lineWithoutSeparator, separator);
450+
} else {
451+
this._onLine(_line, '\n');
452+
}
453+
}
444454
} else if (string) {
445455
// no newlines this time, save what we have for next time
446456
this._line_buffer = string;
@@ -642,10 +652,10 @@ Interface.prototype.clearLine = function() {
642652
};
643653

644654

645-
Interface.prototype._line = function() {
655+
Interface.prototype._line = function(separator = '\n') {
646656
var line = this._addHistory();
647657
this.clearLine();
648-
this._onLine(line);
658+
this._onLine(line, separator);
649659
};
650660

651661

@@ -924,7 +934,7 @@ Interface.prototype._ttyWrite = function(s, key) {
924934
switch (key.name) {
925935
case 'return': // carriage return, i.e. \r
926936
this._sawReturnAt = Date.now();
927-
this._line();
937+
this._line('\r');
928938
break;
929939

930940
case 'enter':

test/parallel/test-readline-interface.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ function isWarned(emitter) {
118118
{ input: fi, output: fi, terminal: terminal }
119119
);
120120
let called = false;
121-
rli.on('line', function(line) {
121+
rli.on('line', function(line, separator) {
122122
called = true;
123123
assert.strictEqual(line, 'asdf');
124+
assert.strictEqual(separator, '\n');
124125
});
125126
fi.emit('data', 'asdf\n');
126127
assert.ok(called);

0 commit comments

Comments
 (0)