Q

经过测试(我的环境上),矮人要塞的菜单界面在不同模式/环境下的显示情况有所不同:

环境 模式 效果
st TEXT NG
st & tmux TEXT NG
kitty TEXT NG
kitty & tmux TEXT NG
xterm TEXT GOOD
xterm & tmux TEXT GOOD
tty TEXT GOOD
tty & tmux TEXT GOOD
/ 2D GOOD

对比一下效果:

GOOD

NG

~

df的TEXT模式目测是用ncurses库的,我将问题定位分为软件、配色、终端三个方向。当我在ttyst使用同一个tmux session时,tty显示了GOOD的效果,但是在st下还是NG,这一现象很关键,基本可以排除软件问题。配色方向经过重新编译st验证也被排除了。

只剩一个方向,既然是显示在终端上,那程序必须要输出字符,这里有两种方式可以捕获到这些字符。

# tmux
tmux capture-pane -peJ -t {pane_id} > xxx.log

# 通用
script xxx.log
...
<Ctrl-D>

tmux dump终端字符

根据日志,可以发现基本都是使用esc控制字符来实现各种颜色的。下面给出问题的最小重现样例。

echo "^[[1m^[[30m^[[40mcontinue"

# PS: ^[需要使用<c-v> + <esc>键入

在公司摸鱼的时候就往这个方向去探索,最后发现了根因。这类^[格式的字符是ANSI的转义字符,官方标准中,样例中的各字符功能如下:

字符 功能
[1m 加粗增加前景强度
[30m 设置前景色为黑色(0号颜色)
[40m 设置背景色为黑色(0号颜色)

背景和前景色都用黑色,那当然应该是NG的效果,只有将前景色的颜色加深了,才能看到文本内容。所以stkitty处理转义字符^[[1m时是进行了加粗处理,其他使用了后者的处理。

A

下面给出patch。

diff --git a/st.c b/st.c
index 6fbf4e2..e53de0c 100644
--- a/st.c
+++ b/st.c
@@ -1413,7 +1413,7 @@ tsetattr(const int *attr, int l)
 {
    int i;
    int32_t idx;
-
+        static char enhance = 0;
    for (i = 0; i < l; i++) {
        switch (attr[i]) {
        case 0:
@@ -1428,9 +1428,14 @@ tsetattr(const int *attr, int l)
                ATTR_STRUCK     );
            term.c.attr.fg = defaultfg;
            term.c.attr.bg = defaultbg;
+			enhance = 0;
            break;
        case 1:
            term.c.attr.mode |= ATTR_BOLD;
+			enhance = 1;
+			if (term.c.attr.fg < 8) {
+				term.c.attr.fg |= 8;
+			}
            break;
        case 2:
            term.c.attr.mode |= ATTR_FAINT;
@@ -1492,7 +1497,7 @@ tsetattr(const int *attr, int l)
            break;
        default:
            if (BETWEEN(attr[i], 30, 37)) {
-				term.c.attr.fg = attr[i] - 30;
+				term.c.attr.fg = (attr[i] - 30) + (enhance * 8);
            } else if (BETWEEN(attr[i], 40, 47)) {
                term.c.attr.bg = attr[i] - 40;
            } else if (BETWEEN(attr[i], 90, 97)) {