ANSI 转义序列不会打印到 Windows 上的标准输出



我正在尝试在Windows上使用node.js编写ANSI转义序列到stdout,但它似乎不起作用。

具体来说,我使用ConEmu,它确实支持ANSI代码的子集。 我创建了一个测试文件,该文件应该重命名当前控制台选项卡:

process.stdout.write('x1b]9;3;"abc"x1bx5c');

但是,当我运行它时没有任何反应。 如果我运行node test > out.txt,正确的字节将写入输出文件。

为什么转义序列不起作用?

当节点的 stdout 连接到非交互式接收器(即管道或重定向到文件(时,写入process.stdout的字节将按原样写入。 因此,运行node test > out.txt会产生预期的结果。

但是,当节点连接到Windows中的交互式终端时,它(通过libuv(实际上解析了所有ANSI转义码,以便它可以使用Windows API透明地模拟unix TTY终端。 这就是使颜色和重新定位光标等功能在Windows中起作用的原因,因为Windows控制台不支持ANSI转义序列。

未知和不受支持的序列将被静默忽略。

因此,在JS调用process.stdout.write()和内部调用WriteConsoleW()(节点实际输出到终端(之间,任何无法识别的命令都会被丢弃。

这可以通过在 fd 1 上打开原始文件系统流从用户代码中解决。

var rawStdout = new fs.SyncWriteStream(1, { autoClose: false });

将 ANSI 转义序列写入rawStdout将正确发送到终端。

rawStdout.write('x1b]9;3;"abc"x1bx5c');

(当然,这并没有给Windows控制台带来任何神奇的新能力;它只会逐字打印序列,看起来像垃圾。 您实际上必须使用某种支持 ANSI 转义代码的终端仿真器。


为了更好地实现我的特定目标,我最终编写了一个模块 - 控制台标题 - 通过在 unix 上编写 ANSI 转义序列并在 Windows 下调用相应的本机 API 来更改控制台的标题。 这允许我在Windows的默认控制台窗口和ConEmu等模拟器中更改标题。

最新更新