diff --git a/lib/readline.js b/lib/readline.js index 133ef1cf3f6c6e..15f4b9022a9d17 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -670,13 +670,14 @@ Interface.prototype._getDisplayPos = function(str) { row += 1; continue; } - if (isFullWidthCodePoint(code)) { + const width = getStringWidth(code); + if (width === 0 || width === 1) { + offset += width; + } else { // width === 2 if ((offset + 1) % col === 0) { offset++; } offset += 2; - } else { - offset++; } } var cols = offset % col; diff --git a/test/parallel/test-readline-position.js b/test/parallel/test-readline-position.js new file mode 100644 index 00000000000000..9a1a011b0056ee --- /dev/null +++ b/test/parallel/test-readline-position.js @@ -0,0 +1,31 @@ +'use strict'; +require('../common'); +const { PassThrough } = require('stream'); +const readline = require('readline'); +const assert = require('assert'); + +const ctrlU = { ctrl: true, name: 'u' }; + +{ + const input = new PassThrough(); + const rl = readline.createInterface({ + terminal: true, + input: input, + prompt: '' + }); + + for (const [cursor, string] of [ + [1, 'a'], + [2, 'ab'], + [2, '丁'], + [0, '\u0301'], // COMBINING ACUTE ACCENT + [1, 'a\u0301'], // á + [0, '\u20DD'], // COMBINING ENCLOSING CIRCLE + [2, 'a\u20DDb'], // a⃝b + [0, '\u200E'] // LEFT-TO-RIGHT MARK + ]) { + rl.write(string); + assert.strictEqual(rl._getCursorPos().cols, cursor); + rl.write(null, ctrlU); + } +}