Javascript 向终端提示添加颜色会导致较大的空白

Javascript 向终端提示添加颜色会导致较大的空白,javascript,node.js,command-line-interface,ansi,readline,Javascript,Node.js,Command Line Interface,Ansi,Readline,我正在编写一个简单的cli脚本,希望为以下代码添加一些颜色: rl.question('Enter destination path: ', function(answer) { // ... });

我正在编写一个简单的cli脚本,希望为以下代码添加一些颜色:

rl.question('Enter destination path: ', function(answer) {
     // ...                                                                                                                                
});                                                                                                                                  
rl.write('/home/' + user + '/bin');
将在终端中显示:

Enter destination path: /home/jmcateer/bin_
但我想为提示符添加一些颜色,我做了以下操作:

rl.question('\u001b[1;36mEnter destination path:\u001b[0m ', function(answer) {

});                                                                                                                                  
rl.write('/home/' + user + '/bin');
命令行提示符最后显示:

Enter destination path:                 /home/jmcateer/bin_
它可以工作,但有大量的空白,我更希望没有。有人对如何处理这件事有什么想法吗

编辑:

我不能通过退格删除空白。。。当我尝试使用backspace键时,空白会像这样跳到另一端

Enter destination path:                 /home/jmcateer/bin_
Enter destination path: /home/jmcateer/bi                _
Enter destination path: /home/jmcateer/b                _
...
Enter destination path:                 _

此时退格无效。

当然,您需要修改
rl。使用CSI序列
nd
写入
字符串,其中
n
是要将光标移回的字符数

下面是一个要尝试的片段:

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

rl.question('\u001b[1;36mEnter destination path: \u001b[0m', function(answer) {

});                                                                                               
rl.write('\u001b[11 D/home/jp/bin');
注意最后一行的
11
D
D
表示要向后移动的字符数
11显然是字符数


查看所有有趣的终端代码:

当您调用
rl.setPrompt(prompt,length)
而不使用第二个参数时;不解释ANSI X3.64转义序列。内部
\u getCursorPos
方法从
\u promplength
][3]计算光标位置;因此,在长度中包含转义序列会导致光标的位置超出其应有的距离


要完全解决此问题,在设置
\u promplength
时,节点的readline库应该解析ANSI转义序列。为了解决这个问题,您可以在不使用转义序列的情况下手动计算提示字符串的长度,并将其作为第二个参数传递给
rl。setPrompt(prompt,length)
我也遇到了类似的问题。巴兹尔·克罗(Basil Crow)对问题原因的出色回答是正确的,因为确实是ANSI转义序列导致了长度故障;然而,
Interface.setPrompt()
不仅仅是问题,而是解决方案

似乎这种对长度的误读(我在bash中玩时巧妙地避免了这一点)会影响整个接口对象的写出过程,即当未指定长度参数时,任何以任何容量调用
Interface.setPrompt()
的操作都会受到影响

为了克服此问题,您可以执行以下两项操作之一:


重新定义
Interface.setPrompt()
始终为提示输出指定长度,以便
Interface.question()
等方法再次正常工作:

// I'm using the 'color' npm library for the sake of convenience. It is not required
// and you can use normal regex to strip color codes and what not.
var colors   = require('colors'),
    readline = require('readline');

var rl = readline.createInterface(process.stdin, process.stdout);

/* Overcome some bugs in the Nodejs readline implementation */
rl._setPrompt = rl.setPrompt;
rl.setPrompt = function(prompt, length)
{
    rl._setPrompt(prompt, length ? length : prompt.split(/[\r\n]/).pop().stripColors.length);
};

var str = '[' + '?'.green + '] Blackbeard walks under the black flag with a ____? ';

rl.question(str, function(answer)
{
    var answ = 'scallywag swagger';
    console.log(
        'You answered "' + ((answer == answ) ? answer.green : answer.red)
        + '". The correct answer is', '"' + answ.green + '".');
});
var colors   = require('colors'),
    readline = require('readline');

var rl = readline.createInterface(process.stdin, process.stdout);

/* Overcome some bugs in the Nodejs readline implementation */
rl._write = rl.write; 
rl.write = function(d, key)
{
    // "key" functionality is lost, but if you care enough you can add it back
    rl.setPrompt(d, d.split(/[\r\n]/).pop().stripColors.length);
    rl.prompt(true);
};

var str = '[' + '?'.green + '] Blackbeard walks under the black flag with a ____? ';
rl.write(str);

rl.on('line', function(answer)
{
    var answ = 'scallywag swagger';
    console.log(
        'You answered "' + ((answer == answ) ? answer.green : answer.red)
        + '". The correct answer is', '"' + answ.green + '".');
    rl.prompt(true);
});

重新定义
Interface.write()
以使用
Interface.setPrompt()
将写出字符串和字符串的真实长度传递给setPrompt方法:

// I'm using the 'color' npm library for the sake of convenience. It is not required
// and you can use normal regex to strip color codes and what not.
var colors   = require('colors'),
    readline = require('readline');

var rl = readline.createInterface(process.stdin, process.stdout);

/* Overcome some bugs in the Nodejs readline implementation */
rl._setPrompt = rl.setPrompt;
rl.setPrompt = function(prompt, length)
{
    rl._setPrompt(prompt, length ? length : prompt.split(/[\r\n]/).pop().stripColors.length);
};

var str = '[' + '?'.green + '] Blackbeard walks under the black flag with a ____? ';

rl.question(str, function(answer)
{
    var answ = 'scallywag swagger';
    console.log(
        'You answered "' + ((answer == answ) ? answer.green : answer.red)
        + '". The correct answer is', '"' + answ.green + '".');
});
var colors   = require('colors'),
    readline = require('readline');

var rl = readline.createInterface(process.stdin, process.stdout);

/* Overcome some bugs in the Nodejs readline implementation */
rl._write = rl.write; 
rl.write = function(d, key)
{
    // "key" functionality is lost, but if you care enough you can add it back
    rl.setPrompt(d, d.split(/[\r\n]/).pop().stripColors.length);
    rl.prompt(true);
};

var str = '[' + '?'.green + '] Blackbeard walks under the black flag with a ____? ';
rl.write(str);

rl.on('line', function(answer)
{
    var answ = 'scallywag swagger';
    console.log(
        'You answered "' + ((answer == answ) ? answer.green : answer.red)
        + '". The correct answer is', '"' + answ.green + '".');
    rl.prompt(true);
});

两者的结果相同:

或者两者都可以。或者,您可以直接修改
readline.Interface.prototype
(并将您的修复程序全局应用),而不是对象实例本身。这里有很多选择

希望这对别人有帮助


编辑另请参见:

No joy它没有效果,它似乎不是正常字符请参见我的编辑它似乎根本不影响
setPrompt
问题。我将进行重构,以使用更详细的方法,并看看这是否有效。