在Windows上,ANSI转义序列不会打印到标准输出(stdout)。

5
我正在尝试使用node.js在Windows上将ANSI转义序列写入stdout,但似乎无效。
具体而言,我使用ConEmu,它支持一部分 ANSI代码。我创建了一个测试文件,应该重命名当前的控制台选项卡:
process.stdout.write('\x1b]9;3;"abc"\x1b\x5c');

然而,当我运行它时,什么也没有发生。如果我运行node test > out.txt,正确的字节将被写入输出文件。

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

1个回答

7
当node的标准输出连接到非交互式汇流处(即被管道或重定向到文件),写入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"\x1b\x5c');

(当然,这并不会赋予 Windows 控制台任何神奇的新功能;它只会直接打印该序列并且看起来很糟糕。你必须实际上使用某种支持 ANSI 转义代码的终端仿真器。)
为了更好地实现我的特定目的,我编写了一个模块——console-title——通过在Unix上编写ANSI转义序列并在Windows下调用适当的本机API来更改控制台的标题。这使我能够在Windows的默认控制台窗口和像ConEmu这样的仿真器中更改标题。

好奇心驱使我想知道ConEmu是如何将标准输出显示为控制台窗口的?这是一个偶尔会出现的问题,例如:https://dev59.com/jWcs5IYBdhLWcg3w1ndq,并且目前没有已知的解决方案。或者说node.js使用了一种非标准的方法来判断stdout是否是交互式的?我需要深入研究一下... - Harry Johnston
因为有一个真正的控制台窗口。ConEmu隐藏了真正的Windows控制台窗口并复制了它的输出。转到菜单>调试>真实控制台以查看它。 - josh3736

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接