代码之家  ›  专栏  ›  技术社区  ›  Benjie Wheeler

NodeJS在readline中获取颜色

  •  0
  • Benjie Wheeler  · 技术社区  · 6 年前

    我有一个NodeJS应用程序,需要使用 spawn ,我正在读取输出以便稍后使用 readline 完美无瑕。

    但我也需要得到文本的颜色,例如: 当执行另一个 Node.js 使用的脚本 chalk 模块。

    如何才能做到这一点?

    到目前为止这是我的代码:

    const spawn = require('child_process').spawn;
    const readline = require('readline');
    
    let myCommand = spawn(<command>, [<args...>], { cwd: dirPath });
    
    readline.createInterface({
      input    : myCommand.stdout,
      terminal : true
    }).on('line', (line) => handleOutput(myCommand.pid, line));
    
    readline.createInterface({
      input    : myCommand.stderr,
      terminal : true
    }).on('line', (line) => handleErrorOutput(myCommand.pid, line));
    
    myCommand.on('exit', (code) => {
      // Do more stuff ..
    });
    

    更新

    Amr K. Aly's answer 在执行外部 NodeJS 脚本返回空颜色。

    我的代码(index.js) :

    const spawn = require('child_process').spawn;
    const readline = require('readline');
    
    let myCommand = spawn('node', ['cmd.js']);
    
    readline.createInterface({
      input: myCommand.stdout,
      terminal: true
    }).on('line', (line) => handleOutput(myCommand.pid, line));
    
    readline.createInterface({
      input: myCommand.stderr,
      terminal: true
    }).on('line', (line) => handleErrorOutput(myCommand.pid, line));
    
    myCommand.on('exit', (code) => {
      // Do more stuff ..
    });
    
    function handleErrorOutput(obj, obj2) {}
    
    function handleOutput(obj, line, a, b, c) {
      //PRINT TEXT WITH ANSI FORMATING
      console.log(line);
    
      //REGEX PATTERN TO EXTRACT COLOR
      var options = Object.assign({
        onlyFirst: false
      });
    
      const pattern = [
        '[\\u001B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
        '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
      ].join('|');
    
      var regex = new RegExp(pattern, options.onlyFirst ? undefined : 'g');
      var ansiColor = (line.match(regex));
    
      //PRINT EXTRACTED ANSI
      console.log("ANSI COLOR CODE :");
      console.log(ansiColor);
    }
    

    命令.js :

    const chalk = require('chalk');
    
    console.log(chalk.blue('Blue Hello world!'));
    console.log(chalk.green('green Hello world!'));
    console.log(chalk.red('red Hello world!'));
    

    我的结果 :

    Index.js result

    0 回复  |  直到 6 年前
        1
  •  1
  •   Amr Aly    6 年前

    问题:

    当打印回所读的文本流时,您看不到颜色,因为您已设置 terminal createInterface中的选项 true . 这导致createInterface()不返回ANSI/VT100编码。

    解决方案:

    这个 终端 选项需要设置为 false 所以文本将用ANSI/VT100编码 从Nodejs文档: terminal <boolean> true if the input and output streams should be treated like a TTY, and have ANSI/VT100 escape codes written to it. Default: checking isTTY on the output stream upon instantiation. readline.createInterface(options) documentation

    readline.createInterface({
    input: myCommand.stdout,
    terminal: true//<== NEEDS TO BE SET TO FALSE 
    }).on('line', (line) => handleOutput(myCommand.pid, line));
    

    设置后 终端 ,返回的文本将是ANSI/VT100编码的。然后需要提取与颜色相关的ANSI/VT100编码,并将其更改为所需的任何颜色格式。

    请参阅下面的修改代码和输出,并添加正则表达式以提取ANSI颜色代码。您需要添加自己的逻辑来处理ANSI转义的颜色。

    const spawn = require('child_process').spawn;
    const readline = require('readline');
    const chalk = require('chalk');
    
     //Testing on windows 10
    let myCommand = spawn(process.env.comspec, ['/c', 'echo ' + chalk.red('Hello world!'), ], {
        // cwd: dirPath
    });
    
    readline.createInterface({
        input: myCommand.stdout,
        terminal: false
    }).on('line', (line) => handleOutput(myCommand.pid, line));
    
    readline.createInterface({
        input: myCommand.stderr,
        terminal: false
    }).on('line', (line) => handleErrorOutput(myCommand.pid, line));
    
    myCommand.on('exit', (code) => {
        // Do more stuff ..
    });
    
    function handleErrorOutput(obj, obj2) {}
    
    function handleOutput(obj, line) {
    
        //PRINT TEXT WITH ANSI FORMATING
        console.log(line);
    
        //REGEX PATTERN TO EXTRACT COLOR
        var options = Object.assign({
            onlyFirst: false
        });
    
        const pattern = [
            '[\\u001B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
            '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
        ].join('|');
    
        var regex = new RegExp(pattern, options.onlyFirst ? undefined : 'g');
        var ansiColor = (line.match(regex));
    
        //PRINT EXTRACTED ANSI
        console.log("ANSI COLOR CODE :");
        console.log(ansiColor);
    }
    

    以上代码的输出:

    Output for code above:

    编辑:

    粉笔自动检测,如果你写的TTY或终端不支持颜色,并禁用颜色。可以通过设置环境变量强制执行 FORCE_COLOR=1 或者通过 --color 作为论据。

    如果您将代码更改为下面代码片段中的行,那么粉笔应该正确地添加样式。

    let myCommand = spawn('node', ['test.js', '--color', ], {
    
    
    }); 
    

    输出:

    Code Output