Skip to content

Commit

Permalink
readline: fix position computation
Browse files Browse the repository at this point in the history
The implementation of _getDisplayPos, used to compute the cursor
position and to find out how many lines to clear up when re-rendering
the readline output, was counting each line (except the last one) from
the input as one row, even if they were wraping.  This caused some
rendering issues when the 'prompt' have at least one wide line ending
with a newline char, duplicating the lines at the top of the prompt when
calling _refreshLine (ex: when the user hits backspace).

This patch fixes the issue by computing the real rows count for each new
line in the input string.

PR-URL: nodejs#28272
Reviewed-By: Rich Trott <[email protected]>
Reviewed-By: Anna Henningsen <[email protected]>
  • Loading branch information
BenoitZugmeyer authored and addaleax committed Jul 3, 2019
1 parent 285e036 commit 46a73b9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
3 changes: 2 additions & 1 deletion lib/readline.js
Original file line number Diff line number Diff line change
Expand Up @@ -732,8 +732,9 @@ Interface.prototype._getDisplayPos = function(str) {
i++;
}
if (code === 0x0a) { // new line \n
// row must be incremented by 1 even if offset = 0 or col = +Infinity
row += Math.ceil(offset / col) || 1;
offset = 0;
row += 1;
continue;
}
const width = getStringWidth(code);
Expand Down
19 changes: 18 additions & 1 deletion test/parallel/test-readline-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -1062,7 +1062,7 @@ function isWarned(emitter) {
rli.close();
}

// multi-line cursor position
// Multi-line input cursor position
{
const fi = new FakeInput();
const rli = new readline.Interface({
Expand All @@ -1079,6 +1079,23 @@ function isWarned(emitter) {
rli.close();
}

// Multi-line prompt cursor position
{
const fi = new FakeInput();
const rli = new readline.Interface({
input: fi,
output: fi,
prompt: '\nfilledline\nwraping text\n> ',
terminal: terminal
});
fi.columns = 10;
fi.emit('data', 't');
const cursorPos = rli._getCursorPos();
assert.strictEqual(cursorPos.rows, 4);
assert.strictEqual(cursorPos.cols, 3);
rli.close();
}

// Clear the whole screen
{
const fi = new FakeInput();
Expand Down

0 comments on commit 46a73b9

Please sign in to comment.