【问题标题】:Adding colors to terminal prompt results in large white space向终端提示添加颜色会产生大的空白
【发布时间】:2012-08-22 14:29:36
【问题描述】:

我正在编写一个简单的 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_

它有效,但我不希望有大量空白。有没有人知道如何处理这个问题?

编辑:

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

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

此时退格无效。

【问题讨论】:

    标签: javascript node.js command-line-interface ansi readline


    【解决方案1】:

    当你调用 rl.setPrompt(prompt, length) 时没有第二个参数,the internal _promptLength variable is set to the length of the prompt string; 解释 ANSI X3.64 转义序列。内部_getCursorPos 方法从_promptLength][3] 计算光标位置;因此,在长度中包含转义序列会导致光标的位置超出其应有的位置。

    为了彻底解决这个问题,Node 的 readline 库在设置 _promptLength 时应该解析 ANSI 转义序列。要解决此问题,您可以手动计算不带转义序列的提示字符串的长度,并将其作为第二个参数传递给 rl.setPrompt(prompt, length)

    【讨论】:

    • setPrompt 似乎根本不会影响question。我将重构以使用更详细的方法,看看是否可行。
    【解决方案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);
    });
    


    两者的结果相同:

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

    希望这对某人有所帮助!

    编辑——另见:https://github.com/joyent/node/issues/3860

    【讨论】:

      【解决方案3】:

      当然,您需要使用 CSI 序列 n D 修改您的 rl.write 字符串,其中 n 是要向后移动光标的字符数。

      这是一个可以试验的 sn-p:

      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

      【讨论】:

      • 不高兴它没有效果,它似乎不是正常的字符请看我的编辑
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 1970-01-01
      • 2011-08-30
      相关资源
      最近更新 更多