Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

readline has incorrect cursor with ANSI escape codes #3860

Closed
indexzero opened this Issue · 7 comments

7 participants

@indexzero

A simple code example:

var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: process.stdout.isTTY
});

rl.setPrompt('\u001b[90musername: \u001b[39m');
rl.prompt();

Yields the output:

username:           Cursor-Here

Without ANSI escape codes:

var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: process.stdout.isTTY
});

rl.setPrompt('username: ');
rl.prompt();

Yields the expected output:

username: Cursor-Here

The bug appears to be in Interface.prototype.setPrompt:

Interface.prototype.setPrompt = function(prompt, length) {
  this._prompt = prompt;
  if (length) {
    this._promptLength = length;
  } else {
    var lines = prompt.split(/[\r\n]/);
    var lastLine = lines[lines.length - 1];
    this._promptLength = lastLine.length;
  }
};

Changing:

  this._promptLength = lastLine.length;

To:

  this._promptLength = lastLine.replace(/\u001b\[(\d+(;\d+)*)?m/g, '').length;

Should do the trick.

@isaacs

Care to rephrase that suggestion in the form of a pull req? ;)

@bnoordhuis

@indexzero That regex won't handle all cases. Have a look at emitKey() in lib/readline.js, it should be decomposed so the ANSI parser can be reused.

@piscisaureus

@bnoordhuis EmitKey also won't handle all cases, unfortunately...

@Mithgol

If that regex won't handle all cases, then what are the unhandled cases and how that regex could be improved to handle them?

@rlidwka

We could try to partially implement that parser in plain javascript. It would be useful for readline testing anyway, I thought about it some time ago.

The question is: doesn't such thing feel too heavy there?

@OhJeez OhJeez referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@OhJeez OhJeez referenced this issue from a commit in OhJeez/node
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
@bnoordhuis bnoordhuis closed this issue from a commit
@OhJeez 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.
ffcd8b9
@SBoudrias SBoudrias referenced this issue in SBoudrias/Inquirer.js
Closed

Cursor misplaced on Mint #68

@TooTallNate TooTallNate referenced this issue from a commit in TooTallNate/browser-repl
@TooTallNate TooTallNate repl: don't use ansi escape codes in prompt
Breaks the cursor in the `readline` module in node.
See: joyent/node#3860
d807b49
@TooTallNate TooTallNate referenced this issue in Automattic/browser-repl
Merged

repl: don't use ansi escape codes in prompt #1

@freeformsystems

This fix is available in >0.11.3 but for those of us using the stable 0.10.x series this is still an issue.

The workaround is to calculate the prompt length without any ANSI escape sequences and pass the length as the second argument to setPrompt(), something like:

var rl = ... // create readline interface
var prompt = '>';
var len = prompt.length;
var colorized = colorize(prompt) // add ANSI sequences
rl.setPrompt(colorized, len);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.