ANSI转义序列不会在Windows上打印到stdout

jos*_*736 2 windows terminal node.js

我正在尝试使用Windows上的node.js将一个ANSI转义序列写入stdout,但它似乎不起作用.

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

process.stdout.write('\x1b]9;3;"abc"\x1b\x5c');
Run Code Online (Sandbox Code Playgroud)

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

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

jos*_*736 5

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

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

默认忽略未知和不受支持的序列.

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

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

var rawStdout = new fs.SyncWriteStream(1, { autoClose: false });
Run Code Online (Sandbox Code Playgroud)

编写ANSI转义序列rawStdout将正确发送到终端.

rawStdout.write('\x1b]9;3;"abc"\x1b\x5c');
Run Code Online (Sandbox Code Playgroud)

(当然这并不会给Windows控制台带来任何神奇的新功能;它只是简单地打印序列并且看起来像垃圾.你必须实际上使用某种支持ANSI转义码的终端模拟器.)


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