[SERVER-18065] Prompt ANSI escapes not working Created: 15/Apr/15  Updated: 15/May/15  Resolved: 15/May/15

Status: Closed
Project: Core Server
Component/s: Shell
Affects Version/s: 3.0.2
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Dmitry Gening Assignee: Ramon Fernandez Marina
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Operating System: ALL
Participants:

 Description   

Currently is not possible to use ANSI escapes in prompt.

prompt = function(){
  csi = String.fromCharCode(0x1b) + '[';
  reset = csi + '0m';
  return '{0}db{1}'.format(csi + '44m', reset);
}

Will produce prompt like:

[44mdb[0m

I'm not sure if it's desired behavior for shell prompt. It would be nice if users could use color for shell prompt cusomization



 Comments   
Comment by Dmitry Gening [ 16/Apr/15 ]

Thank you, Stephen, Kevin. I'll use workaround for the moment since it's really usefull to color denote database/host currently in use.
Also i'll try to look in to `linenoise` source code and see if it possilbe to me to fix this issue. Again thanks for fast responce.

Comment by Kevin Pulo [ 16/Apr/15 ]

Hi Dimitry,

I believe this is a limitation in the linenoise library that the mongo shell uses for user input. Non-printing characters are deliberately stripped from the prompt, because if ANSI/VT/other escape codes are allowed to be interpreted then the shell will not know how many characters have actually been output. In an interactive line editor, this interferes with correct cursor behaviour when lines are longer than the width of the terminal (and so require wrapping).

You can see a similar effect in bash if you run a command like "echo -n foo", then at the next prompt type beyond the end of the line, and then try to left-arrow to go backwards (or up-arrow to go backwards in history).

As my colleague Stephen points out, using print() is the workaround, but note that it always issues a newline at the end, which means that you will need to have a multi-line "prompt" of at least 2 lines.

Actual possible solutions would include making linenoise aware of the various escape codes (and their formats and meanings), or allowing the user to denote sections of the prompt which are non-printing, e.g. the way bash allows the use of "\[" and "\]" in its PS1 prompt.

Best regards,
Kev

Comment by Stennie Steneker (Inactive) [ 15/Apr/15 ]

Hi Dimitry,

It doesn't appear possible to use ANSI escapes in the return value of prompt() at the moment but a workaround would be to use a print statement eg:

prompt = function() {
  csi = String.fromCharCode(0x1b) + '[';
  reset = csi + '0m';
  red   = csi + '41m';
  blue  = csi + '44m';
 
  version = db.serverBuildInfo().version;
  conns = db.serverStatus().connections;
 
  print('[{0}{1}{2}] {3} {4}/{5} {6} connections current/available'.format(
     blue, version, reset,
     red, conns.current, conns.available, reset ))
}

Regards,
Stephen

Comment by Dmitry Gening [ 15/Apr/15 ]

I'm using format string polyfill like this:

if (!String.prototype.format) {
  String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
  };
}

Generated at Thu Feb 08 03:46:28 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.