haskell - 如果我想使用 pretty-print 库来添加颜色,如何将终端中的最后一行输出设为 "refresh"?

标签 haskell terminal pretty-print

有一个程序通过重复覆盖stderr中的最后一行文本来与用户交互。其做法如下:

  • 有一个状态单子(monad)会记住最后打印的一行的长度。
  • 当它想用另一行s'覆盖一行s时,它会用空格填充s',直到它被覆盖。至少与 s 一样长,并在其前面添加“回车符” 字符:

    n <- gets lastLineLength
    let s'Padded | 0 < n     = '\r': s' ++ replicate (n - length s') ' '
                 | otherwise = s'
    hPutStr stderr s'Padded
    

这工作得很好。 (尽管我个人没有在通常的 Linux 终端以外的环境中测试过它。)

我开始改进这个程序,用 ansi-wl-pprint 中的 Doc 类型替换普通的 String 。这样我就可以用颜色来绘制文本,就像最近的 GHC 运动一样。像这样的库可能有点矫枉过正,因为我只需要一次输出几行,并且没有任何缩进,但我想尝试一下它的抽象着色功能。但是,我不认为这个库(或任何 pretty-print 库)会具有旨在删除以前打印的文档的功能。

我想到的一个解决方案是将Doc渲染为String并测量其长度。但是,我将不得不对颜色代码打折扣;此外,这总体上是对库提供的抽象的侵入:具体来说,我必须依赖这样的假设:我手动执行的渲染将与 hPutDoc 隐式完成的渲染相匹配。

我是否应该完全放弃该库并继续处理String,手动添加 ANSI 转义序列和回车符?有没有更好的方法来覆盖以前的输出?我欢迎任何建议。

最佳答案

ansi-wl-pprint 依赖于 ansi-terminal,它有 clearLine方法和其他实用程序来移动并记录控制台中的位置。

在底层,clearLine 发送特定的ANSI 控制序列来删除当前行。还有一个控制序列可将光标倒回到当前行(或任何行)的开头。这有点晦涩难懂,但你会惊讶地看到 how many control sequences有。

您可以手动操纵控制序列。例如,如果您putStr“\ESC[2K\ESC[0G”,它应该删除当前行,然后将光标置于其开头 - 类似于您的代码正在执行的操作,但是清洁工。但如果您依赖 ansi-terminal 并使用其中定义的操作 hClearLinehSetCursorColumn ,它可能会为您提供最好的服务。如果您已经通过 ansi-wl-pprint 间接依赖于 ansi-terminal,则不应产生额外的构建时间成本。

关于haskell - 如果我想使用 pretty-print 库来添加颜色,如何将终端中的最后一行输出设为 "refresh"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48975919/

相关文章:

regex - 如何在 regex-tdfa 正则表达式中控制 CompOption "multiline"? ( haskell )

emacs - 在 Macintosh 上将文本粘贴到 emacs

java - VSCode 中没有安装 'java' 文件的格式化程序

linux - 使新创建的用户的主目录对其他用户不可见

language-agnostic - 从终端发送 NUL 字节的组合键是什么?

python - 在 Python 中漂亮地打印 XML

c - 如何在C中将数字矩阵打印成字符串?

haskell - maxTotalHeaderLength 是否按预期工作?

haskell - 限制效果,例如 `Freer` ,使用 MTL 样式

Haskell 学习练习给出了奇怪的结果