Haskell 和 Brick 的 RGB 终端颜色

RGB Terminal Colors with Haskell and Brick

我知道 Brick and the VTY hackage do not support escape sequences. VTY 只支持 240 种颜色。

是否有任何解决方法可以使用真正的 RGB 颜色而不弄乱布局?

这是我做的一个例子,但是我无法正确设置边框:

module BrickTest where

import Brick                (simpleMain, Widget, str)
import Brick.Widgets.Border (border)
import Text.Printf          (printf)

main :: IO ()
main = simpleMain $ colorWidget (255, 0, 0)

type RGB = (Int, Int, Int)

colorWidget :: RGB -> Widget ()
colorWidget (r, g, b) = border $ str (prefix ++ "a" ++ postfix)
    where
        prefix = printf "\ESC[38;2;%d;%d;%dm" r g b
        postfix = "\ESC[0m"

输出:

┌──────────────────┐
│a│
└──────────────────┘

我找到了解决方法。我设法实现了一个可以打印任何字符串的函数 zeroWidthStr,并且 Brick 处理它时就好像它的宽度为 0。但我无法真正解释它在内部是如何工作的,而且它可能有一些其他的副作用。

module BrickTest where

import           Brick                       (Widget, raw, simpleMain, str,
                                              (<+>))
import           Brick.Widgets.Border        (border)
import           Data.List                   (intercalate)
import           Data.Text.Lazy              (pack)
import           Graphics.Vty                (defAttr)
import           Graphics.Vty.Image.Internal (Image (HorizText))
import           Text.Printf                 (printf)

main :: IO ()
main = simpleMain $ colorWidget (255, 0, 0)

type RGB = (Int, Int, Int)

colorWidget :: RGB -> Widget ()
colorWidget (r, g, b) = border $ prefix <+> str "a" <+> postfix
    where
        prefix = zeroWidthStr $ printf "\ESC[38;2;%d;%d;%dm" r g b
        postfix = zeroWidthStr $ "\ESC[0m"

zeroWidthStr :: String -> Widget ()
-- | workaround to print any string in terminal, and hackage Brick (vty) handles it as if it has width 0
zeroWidthStr str = raw image
    where
        image = HorizText defAttr (pack modStr) 0 0
        modStr = str ++ repeatN "\ESC\ESCa" (length str)
        repeatN :: String -> Int -> String
        repeatN str n = intercalate "" $ take n $ repeat str

输出: