NodeJS 在 readline 中获取颜色
NodeJS get color in readline
我有一个 NodeJS 应用程序需要使用 spawn
执行一些命令,我正在使用 readline
读取输出以供稍后处理,它工作得很好。
但是我还需要得到文字的颜色,例如:
当执行另一个使用 chalk
模块的 Node.js
脚本时。
如何实现?
到目前为止,这是我的代码:
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
脚本时它 return 空颜色。
我的代码(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!'));
我的结果:
问题:
因为你在createInterface中将terminal
选项设置为true
,所以打印回你阅读的文本流时看不到颜色。这导致 createInterface() 不进行 return 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(options) documentation
readline.createInterface({
input: myCommand.stdout,
terminal: true//<== NEEDS TO BE SET TO FALSE
}).on('line', (line) => handleOutput(myCommand.pid, line));
将 terminal
设置为 false
后,returned 文本将被 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);
}
以上代码的输出:
编辑:
如果您正在写入 TTY 或终端不支持颜色,Chalk 会自动检测并禁用着色。您可以通过设置环境变量 FORCE_COLOR=1
或传递 --color
作为参数来强制执行它。
如果您将代码更改为以下代码段中的行,Chalk 应该会正确添加样式。
let myCommand = spawn('node', ['test.js', '--color', ], {
});
输出:
我有一个 NodeJS 应用程序需要使用 spawn
执行一些命令,我正在使用 readline
读取输出以供稍后处理,它工作得很好。
但是我还需要得到文字的颜色,例如:
当执行另一个使用 chalk
模块的 Node.js
脚本时。
如何实现?
到目前为止,这是我的代码:
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
脚本时它 return 空颜色。
我的代码(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!'));
我的结果:
问题:
因为你在createInterface中将terminal
选项设置为true
,所以打印回你阅读的文本流时看不到颜色。这导致 createInterface() 不进行 return 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(options) documentation
readline.createInterface({
input: myCommand.stdout,
terminal: true//<== NEEDS TO BE SET TO FALSE
}).on('line', (line) => handleOutput(myCommand.pid, line));
将 terminal
设置为 false
后,returned 文本将被 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);
}
以上代码的输出:
编辑:
如果您正在写入 TTY 或终端不支持颜色,Chalk 会自动检测并禁用着色。您可以通过设置环境变量 FORCE_COLOR=1
或传递 --color
作为参数来强制执行它。
如果您将代码更改为以下代码段中的行,Chalk 应该会正确添加样式。
let myCommand = spawn('node', ['test.js', '--color', ], {
});
输出: