将颜色添加到终端提示符会导致大量的空白空间。

5
我正在开发一个简单的命令行脚本,并想要为以下代码添加一些颜色:
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_

它可以工作,但有大量的空白区域,我希望它们不存在。有人有什么想法来处理这个问题吗?

编辑:

我无法通过反向删除来删除空格...当我尝试使用退格键时,空格会跳到另一端,就像这样。

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

此时退格键无效。

3个回答

4
当您调用没有第二个参数的rl.setPrompt(prompt, length)时,内部的_promptLength变量将设置为提示字符串的长度;不会解释ANSI X3.64转义序列。内部的_getCursorPos方法从_promptLength计算光标位置]; 因此,在长度中包含转义序列会导致光标定位得比应该定位的更远。
为了完全解决这个问题,Node的readline库应该在设置_promptLength时解析ANSI转义序列。为了解决这个问题,您可以手动计算不包括转义序列的提示字符串的长度,并将其作为第二个参数传递给rl.setPrompt(prompt, length)

似乎 setPrompt 并没有影响到 question。我将重构代码,使用更冗长的方法来看看是否有效。 - JaredMcAteer

2
我也遇到了类似的问题。Basil Crow在他出色的答案中指出了问题的原因是ANSI转义序列确实导致了长度故障; 然而,Interface.setPrompt()不仅是问题所在,它还是解决方案!
看起来这种误读长度(我在玩bash时巧妙地避免了这种情况)会影响整个Interface对象的写入过程,即任何以任何方式调用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 + '".');
});

重新定义Interface.write()方法,使用Interface.setPrompt()方法,将写入字符串和字符串的实际长度同时传递给setPrompt方法:
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);
});

两种方法输出结果相同:output of the above scripts 你也可以同时使用这两种方法。或者直接修改readline.Interface.prototype (全局应用)而不是对象实例本身,选项很多。
希望这能帮到某些人!
编辑—请参见:https://github.com/joyent/node/issues/3860

0
当然,您需要使用 CSI 序列 n D 修改 rl.write 字符串,其中 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');

注意最后一行的11D吗?D代表要向后移动的字符数。显然,11是字符数。

查看此链接以获取所有有趣的终端代码:http://en.wikipedia.org/wiki/ANSI_escape_code


无效,它没有任何作用。这似乎不是正常字符,请查看我的编辑。 - JaredMcAteer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接