NodeJS получает цвет в readline - PullRequest
2 голосов
/ 17 марта 2019

У меня есть приложение 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 ..
});

ОБНОВЛЕНИЕ

Ответ Амра К. Али работает, но при выполнении внешнего 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);
}

cmd.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

1 Ответ

1 голос
/ 27 марта 2019

Проблема:

Вы не можете видеть цвета при печати текста, который вы прочитали, потому что вы установили параметр terminal в createInterface на true. Это приводит к тому, что createInterface () не возвращает кодировку ANSI / VT100.

Решение:

Для параметра terminal необходимо установить значение 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 (опции) документация

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

После установки terminal в false возвращаемый текст будет закодирован в 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:

РЕДАКТИРОВАТЬ:

Chalk автоматически определяет, пишете ли вы в TTY или терминал не поддерживает цвета и отключает раскраску. Вы можете принудительно установить его, задав переменную окружения FORCE_COLOR=1 или передав в качестве аргумента --color.

Если вы измените свой код на строку из фрагмента ниже, Chalk должен правильно добавить стиль.

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


}); 

Выход:

Code Output

...