Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

readline: strip ctrl chars for prompt width calc #5629

Closed
wants to merge 1 commit into from

4 participants

Christopher Chrapka Nodejs Jenkins Simon Boudrias Chris Dickinson
Christopher Chrapka

Use regular expression to strip vt ansi escape codes from display when
calulating prompt display width and cursor position

Fixes #3860 and #5628

Nodejs Jenkins

Thank you for contributing this pull request! Here are a few pointers to make sure your submission will be considered for inclusion.

The following commiters were not found in the CLA:

  • OhJeez

You can fix all these things without opening another issue.

Please see CONTRIBUTING.md for more information

Christopher Chrapka

I signed the CLA earlier using the real name when submitting #5481

OhJeez readline: strip ctrl chars for prompt width calc
Use regular expression to strip vt ansi escape codes from display when
calulating prompt display width and cursor position

Fixes #3860 and #5628
2cbb876
Christopher Chrapka

Forced update of the branch - fixed bug that prevented handling of arrow keys etc.

Simon Boudrias

+1 Been hit by this bug earlier on. Can you think of any currently appliable fix on top of 0.10?

Christopher Chrapka
Chris Dickinson

Looks like this was merged (or at least the same functionality was introduced in another commit.) Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jun 7, 2013
  1. readline: strip ctrl chars for prompt width calc

    OhJeez authored
    Use regular expression to strip vt ansi escape codes from display when
    calulating prompt display width and cursor position
    
    Fixes #3860 and #5628
This page is out of date. Refresh to see the latest.
Showing with 29 additions and 4 deletions.
  1. +19 −4 lib/readline.js
  2. +10 −0 test/simple/test-readline-interface.js
23 lib/readline.js
View
@@ -557,6 +557,7 @@ Interface.prototype._getDisplayPos = function(str) {
var offset = 0;
var col = this.columns;
var code;
+ str = stripVTControlCharacters(str);
for (var i = 0, len = str.length; i < len; i++) {
code = codePointAt(str, i);
if (code >= 0x10000) { // surrogates
@@ -581,7 +582,7 @@ Interface.prototype._getDisplayPos = function(str) {
Interface.prototype._getCursorPos = function() {
var columns = this.columns;
var strBeforeCursor = this._prompt + this.line.substring(0, this.cursor);
- var dispPos = this._getDisplayPos(strBeforeCursor);
+ var dispPos = this._getDisplayPos(stripVTControlCharacters(strBeforeCursor));
var cols = dispPos.cols;
var rows = dispPos.rows;
// If the cursor is on a full-width character which steps over the line,
@@ -921,9 +922,11 @@ exports.emitKeypressEvents = emitKeypressEvents;
*/
// Regexes used for ansi escape code splitting
-var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
-var functionKeyCodeRe =
- /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
+var metaKeyCodeReAnywhere = /(?:\x1b)([a-zA-Z0-9])/;
+var metaKeyCodeRe = new RegExp('^' + metaKeyCodeReAnywhere.source + '$');
+var functionKeyCodeReAnywhere =
+ /(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
+var functionKeyCodeRe = new RegExp('^' + functionKeyCodeReAnywhere.source);
function emitKey(stream, s) {
var ch,
@@ -1207,6 +1210,7 @@ exports.clearScreenDown = clearScreenDown;
function getStringWidth(str) {
var width = 0;
+ str = stripVTControlCharacters(str);
for (var i = 0, len = str.length; i < len; i++) {
var code = codePointAt(str, i);
if (code >= 0x10000) { // surrogates
@@ -1289,3 +1293,14 @@ function codePointAt(str, index) {
return code;
}
exports.codePointAt = codePointAt;
+
+
+/**
+ * Tries to remove all VT control characters. Use to estimate displayed
+ * string width. May be buggy due to not running a real state machine
+ */
+function stripVTControlCharacters(str) {
+ str = str.replace(new RegExp(functionKeyCodeReAnywhere.source, 'g'), '');
+ return str.replace(new RegExp(metaKeyCodeReAnywhere.source, 'g'), '');
+}
+exports.stripVTControlCharacters = stripVTControlCharacters;
10 test/simple/test-readline-interface.js
View
@@ -191,6 +191,16 @@ FakeInput.prototype.end = function() {};
assert.equal(readline.getStringWidth('你好'), 4);
assert.equal(readline.getStringWidth('안녕하세요'), 10);
assert.equal(readline.getStringWidth('A\ud83c\ude00BC'), 5); // surrogate
+
+ // check if vt control chars are stripped
+ assert.equal(readline.stripVTControlCharacters('\u001b[31m> \u001b[39m'), '> ');
+ assert.equal(readline.stripVTControlCharacters('\u001b[31m> \u001b[39m> '), '> > ');
+ assert.equal(readline.stripVTControlCharacters('\u001b[31m\u001b[39m'), '');
+ assert.equal(readline.stripVTControlCharacters('> '), '> ');
+ assert.equal(readline.getStringWidth('\u001b[31m> \u001b[39m'), 2);
+ assert.equal(readline.getStringWidth('\u001b[31m> \u001b[39m> '), 4);
+ assert.equal(readline.getStringWidth('\u001b[31m\u001b[39m'), 0);
+ assert.equal(readline.getStringWidth('> '), 2);
assert.deepEqual(fi.listeners('end'), []);
assert.deepEqual(fi.listeners(terminal ? 'keypress' : 'data'), []);
Something went wrong with that request. Please try again.