【问题标题】:Building a very simple wrapper for ANSI escape sequences为 ANSI 转义序列构建一个非常简单的包装器
【发布时间】:2023-11-20 08:33:01
【问题描述】:

也许是不可能完成的任务。曾几何时,我为 DOS 窗口中的文本着色编写了一个 Ruby 模块 SimpleDialog。它通过与 Windows API 对话来实现。现在我想让它也适用于 Mac OS,甚至适用于整个 unix 世界。好的,目前只有 Terminal 和 xterm 可以满足我的需求。 ANSI 转义序列似乎是适合这项工作的武器。但是使用它们我不能总是按照我的意愿处理事情。这是我尝试实现的功能:

def clear_screen
  print "\e[H\e[2J\ec"
  color( ... old colors stored in an instance variable ... )
end

"\e[H\e[2J" 部分与clear 命令相同(这就是我发现此序列的方式[在一些实验后第二天编辑:"\e[2J" 不会删除任何发送的文本之前 "\e[H" 序列,即使它在屏幕上可见])。终端和 xterm 仅清除屏幕的可见部分[问题 1]"\ec" 部分对终端不再有意义,但这次 xterm 确实成功清除了整个屏幕缓冲区。这样做时,它会响铃[issue 2],而终端保持沉默。由于"\ec" 序列重置了颜色,因此必须再次恢复最后的设置。完全不是很优雅。从命令行提交的clear 命令通常会清除xterm 的整个屏幕缓冲区。但是,它无法清除我尝试通过从 Ruby 发送 "\e[H\e[2J" 来清除屏幕留下的部分。

def color( ... )
  ... too big to show here ...
end

color 方法几乎可以正常工作,只有一个令人失望。在 Windows 中,我可以更改矩形的颜色,而无需修改已放置在其中的文本。我看不出如何通过 ANSI 转义序列 [issue 3] 来做到这一点。当然,作为一种解决方法,我可以记住所涉及的文本并在之后恢复它。而这个真的让我很困惑:对"\e[6n"(报告光标位置)的响应被打印到屏幕上,最后几个 命令提示符后重复的字符。是否可以被 Ruby[issue 4]拦截?

其他方法都是小菜一碟:

def shrink_window # to its original size
  print "\e[9;0t"
end

def stretch_window # to the maximum size that fits on the screen
  print "\e[9;1t"
end

def title(title = nil)
  print "\e]2;#{title}\a"
end

def write(... text containing human-friendly color codes ...)
  ... trivial ...
end

MS-Windows 也允许我获取当前窗口标题,但我看不到它的真正用途(当title 参数为空时,xterm 根本不听字符串,顺便说一句)。 write 方法利用了color 方法。这里没有问题。所以,最后,要克服四个障碍。还是一起生活?

【问题讨论】:

    标签: ruby macos terminal ansi-escape


    【解决方案1】:

    如果您需要有关所有这些 Mac OS 和 Unix 终端 UI 问题的帮助,请尝试通过 Curses gem 使用 curses/ncurses 库。

    由于您已经为此创建了一个有效的 Windows 解决方案,因此您可以创建两个驱动对话框的类。我建议这样做是因为 Windows 上存在的 curses 库并不总是可靠或易于安装(see this question and its answers 是该问题的实际示例)。保留你的 DOS 实现,然后做一个使用 curses/ncurses 的替代方案。然后,您的代码可以根据操作系统或是否存在有效的 curses/ncurses 库来选择要使用的实现。当然,这条路径也简化了以后添加更多用户界面的方法。

    【讨论】:

    • 我也尝试过该选项。然而,诅咒有点太突兀了。在 Windows 中,它在工作完成后将光标移动到 300 行的屏幕缓冲区的末尾,而在 Mac OS 中,它完全接管了屏幕(如手册页)。我希望与同一终端屏幕上的其他应用程序更和谐地合作。尽管如此,现在明确提到诅咒是件好事(抱歉没有资格投票赞成答案)。
    最近更新 更多