【问题标题】:Escape sequences unprocessed under the "cygwin" terminal在“cygwin”终端下未处理的转义序列
【发布时间】:2016-10-11 14:34:48
【问题描述】:

我有一个 Java 应用程序,它使用 ANSI escape sequences 来显示颜色、定位光标等。

在常规 Unices 下运行良好, 以及在xtermmintty(在Cygwin 中)下, 但我无法在cygwin 终端下运行它(即从cmd.exe 启动的bash)。

从屏幕截图中可以看出:

转义序列“按原样”输出,无需处理。另一方面,我可以像echo -e '\033[1;31mTest' 这样轻松地运行smth -- 并且彩色文本就在那里。

同时,如果我从Midnight Commander 子shell 启动完全相同的应用程序,应用程序产生的转义序列将被正确解释:

另外,如果我使用 SSH 登录到我的 Windows 机器(即用远程连接替换本地连接,但保留相同的 cygwin 终端),同样,转义序列处理得很好。

看起来当创建某种子shell(mcssh)时,终端会进入其他模式。但是使用stty 并没有帮助,导出TERM=ansi 也没有帮助。

有人可以提出任何解决方案吗?

我在跑步

CYGWIN_NT-6.3 UNIT-725 2.5.1(0.297/5/3) 2016-04-21 22:14 x86_64 Cygwin

和 Windows 8.1。

【问题讨论】:

  • 我很确定,如果您从 cmd.exe 启动 Cygwin 的 bash,它将继续使用 Windows 提供的控制台窗口,而不是创建自己的控制台窗口。最新版本的 Windows 10 中的控制台支持 ANSI 转义序列(尽管我相信它必须显式打开),但以前的版本不支持。我不知道是否有任何方法可以使这项工作。您最好的选择可能是提供一个启动器,以正确的方式启动您的应用程序。
  • ...虽然echo 工作的事实表明Cygwin 有某种翻译层。如果您以某种方式通过 Cygwin 提供输出,那可能会起作用。也许是一个 bash 脚本,它可以重定向进程的输出并将其回显到控制台?或者基于 Cygwin 的 Java 解释器,如果有的话。
  • @HarryJohnston 的重点是,bash.exe 在作为cmd.exe 的直接子级运行时已经说过翻译层(转义序列-> Win32 API 控制台调用)。问题是为什么上述翻译有时有效,有时无效。
  • 输出并没有通过bash.exe,而是直接从Java 到控制台。 echo 工作的原因是它是一个 Cygwin 应用程序,有自己的翻译层,它与你是否从 bash 运行它无关。 (即使在 Linux 上本地运行时,bash 也不会拦截其子级的输出;为什么会这样?)

标签: java windows cygwin ansi-escape


【解决方案1】:

为了让应用程序在从 cmd.exe (TERM=cygwin) 启动时能够使用 ANSI 转义序列,应用程序本身需要与 cygwin1.dll 链接,或者它的输出需要通过另一个过滤(例如:mcssh 子shell)。

同样的C程序:

#include <stdio.h>

int main() {
    const char esc = 0x1b;
    printf("%c[31;91;1mHello, World!%c[0m\n", esc, esc);
    return 0;
}

使用Cygwin GCC编译时支持颜色输出:

$ ldd test-ansi-escape.exe
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x7ffeeb450000)
    KERNEL32.DLL => /cygdrive/c/Windows/system32/KERNEL32.DLL (0x7ffee92c0000)
    KERNELBASE.dll => /cygdrive/c/Windows/system32/KERNELBASE.dll (0x7ffee8700000)
    cygwin1.dll => /usr/bin/cygwin1.dll (0x180040000)

但显示像垃圾

←[31;91;1mHello, World!←[0m

当使用 MSVCmingw64-x86_64-gcc 编译时:

$ ldd test-ansi-escape.exe
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x7ffeeb450000)
    ntdll.dll => /cygdrive/c/Windows/SYSTEM32/ntdll.dll (0x770a0000)
    wow64.dll => /cygdrive/c/Windows/SYSTEM32/wow64.dll (0x76fd0000)
    wow64win.dll => /cygdrive/c/Windows/system32/wow64win.dll (0x77020000)
    wow64cpu.dll => /cygdrive/c/Windows/system32/wow64cpu.dll (0x77090000)
    ??? => ??? (0x1040000)
    KERNEL32.DLL => /cygdrive/c/Windows/SYSTEM32/KERNEL32.DLL (0x76480000)
    ??? => ??? (0x1040000)
    ??? => ??? (0x1040000)
    KERNEL32.DLL => /cygdrive/c/Windows/SYSTEM32/KERNEL32.DLL (0x76480000)
    KERNELBASE.dll => /cygdrive/c/Windows/SYSTEM32/KERNELBASE.dll (0x74b40000)
    MSVCR120D.dll => /cygdrive/c/Windows/SYSTEM32/MSVCR120D.dll (0x62b90000)

另一种解决方案是使用ConEmu 作为外部输出过滤器(bash.exe 作为ConEmu.exe 的直接子级运行)。这种方法不需要与cygwin1.dll 链接,因为输出过滤由ConEmu 本身执行。缺点是 ConEmu 对转义序列的支持有限(特别是它不理解用于线条绘制的 VT100 替代字符集)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多