彩色终端输出不复位
Colored terminal output does not reset
在编写较大的程序时,我偶然发现了彩色文本输出的一个小问题。这是重现此问题的更简单的程序。
#include <stdio.h>
#define COL_RESET "3[0m"
#define COL_BG_RED "\x1B[41m"
char *str = "the quick brown fox jumped over the lazy dog";
int main(int argc, char *argv[])
{
int i = 10;
while (i) {
puts(COL_BG_RED);
puts(str);
puts(COL_RESET);
puts(str);
i--;
}
return 0;
}
现在这是我 运行 程序得到的结果:
第一次 - 预期结果
第二次
如您所知,即使在将颜色重置为红色后,程序仍决定随机打印线条。当在一个新的终端启动时,它总是打印出预期的结果。除非我 运行 clear
,否则不能保证输出不会像第二张图片那样被破坏。
在我使用的图片中xterm
,尽管其他终端也做同样的事情。
我能做些什么来防止这种情况发生?
问题似乎是在终端开始滚动时出现的。
问题可能是puts
追加了一个换行符引起的。使用 printf
.
修改您的代码
printf(COL_BG_RED);
printf(str);
puts(COL_RESET);
puts(str);
当我在本地 运行 时,我也观察到一些奇怪的行为。
使用:
#define COL_RESET "[=10=]x1b[39;49m" // reset fore/back ground to normal
#define COL_BG_RED "3[41m"
输出:
将 #define
更改为使用八进制而不是十六进制时,我得到了不同的(预期的)结果。
使用:
#define COL_RESET "3[39;49m"
输出:
您也可以考虑创建一个宏来使用 printf
颜色。
#include <stdio.h>
#define COL_RESET "3[39;49m"
#define COL_BG_RED "3[41m"
#define COL_BG_NORMAL "3[49m"
#define COLOR_NORMAL "3[m"
#define COLOR_RESET "3[0m"
#define COLOR_BLACK "3[30m"
#define COLOR_RED "3[31m"
#define COLOR_GREEN "3[32m"
#define COLOR_YELLOW "3[33m"
#define COLOR_BLUE "3[34m"
#define COLOR_MAGENTA "3[35m"
#define COLOR_CYAN "3[36m"
#define COLOR_WHITE "3[37m"
#define COLOR_PRINTF(colorCode,fmt,...) printf("%s" fmt "%s", colorCode, __VA_ARGS__, COL_RESET)
char *str = "the quick brown fox jumped over the lazy dog";
int main(int argc, char *argv[])
{
int i = 1;
while (i) {
COLOR_PRINTF(COLOR_GREEN, "%s\n", str);
COLOR_PRINTF(COL_BG_RED, "%s\n", str);
i--;
}
return 0;
}
如评论所述,这是一些知名终端的已知行为:滚动(或反向滚动)时,屏幕上新清除的区域会填充当前背景色。 Linux 控制台执行此操作(除了几年前的一个故障,在 terminal database). xterm does it.
中指出
在 ncurses 中,几个相关的行为被集中在一起作为 bce
(背景颜色擦除)功能:
- 填充由于滚动而新清除的行
- 擦除显示,同时擦除以光标结束或开始的部分。
- 擦除一行,或擦除光标到行尾或从光标到行尾的部分
- 正在光标位置插入(一个空格)
- 删除一个字符
通常 ncurses 会填空(只有当终端输入 poorly chosen 时才会出现问题),您不会看到这一点。但是使用简单的转义序列意味着您可以稍微探索 bce
的细微差别。
直接使用转义序列打印颜色的终端应用程序应在写入 任何 其他不打算着色的文本之前重置颜色。其他应用程序(例如 shell 中的行编辑)在擦除行内的文本时必须牢记此规则
在编写较大的程序时,我偶然发现了彩色文本输出的一个小问题。这是重现此问题的更简单的程序。
#include <stdio.h>
#define COL_RESET "3[0m"
#define COL_BG_RED "\x1B[41m"
char *str = "the quick brown fox jumped over the lazy dog";
int main(int argc, char *argv[])
{
int i = 10;
while (i) {
puts(COL_BG_RED);
puts(str);
puts(COL_RESET);
puts(str);
i--;
}
return 0;
}
现在这是我 运行 程序得到的结果:
第一次 - 预期结果
第二次
如您所知,即使在将颜色重置为红色后,程序仍决定随机打印线条。当在一个新的终端启动时,它总是打印出预期的结果。除非我 运行 clear
,否则不能保证输出不会像第二张图片那样被破坏。
在我使用的图片中xterm
,尽管其他终端也做同样的事情。
我能做些什么来防止这种情况发生?
问题似乎是在终端开始滚动时出现的。
问题可能是puts
追加了一个换行符引起的。使用 printf
.
printf(COL_BG_RED);
printf(str);
puts(COL_RESET);
puts(str);
当我在本地 运行 时,我也观察到一些奇怪的行为。
使用:
#define COL_RESET "[=10=]x1b[39;49m" // reset fore/back ground to normal
#define COL_BG_RED "3[41m"
输出:
将 #define
更改为使用八进制而不是十六进制时,我得到了不同的(预期的)结果。
使用:
#define COL_RESET "3[39;49m"
输出:
您也可以考虑创建一个宏来使用 printf
颜色。
#include <stdio.h>
#define COL_RESET "3[39;49m"
#define COL_BG_RED "3[41m"
#define COL_BG_NORMAL "3[49m"
#define COLOR_NORMAL "3[m"
#define COLOR_RESET "3[0m"
#define COLOR_BLACK "3[30m"
#define COLOR_RED "3[31m"
#define COLOR_GREEN "3[32m"
#define COLOR_YELLOW "3[33m"
#define COLOR_BLUE "3[34m"
#define COLOR_MAGENTA "3[35m"
#define COLOR_CYAN "3[36m"
#define COLOR_WHITE "3[37m"
#define COLOR_PRINTF(colorCode,fmt,...) printf("%s" fmt "%s", colorCode, __VA_ARGS__, COL_RESET)
char *str = "the quick brown fox jumped over the lazy dog";
int main(int argc, char *argv[])
{
int i = 1;
while (i) {
COLOR_PRINTF(COLOR_GREEN, "%s\n", str);
COLOR_PRINTF(COL_BG_RED, "%s\n", str);
i--;
}
return 0;
}
如评论所述,这是一些知名终端的已知行为:滚动(或反向滚动)时,屏幕上新清除的区域会填充当前背景色。 Linux 控制台执行此操作(除了几年前的一个故障,在 terminal database). xterm does it.
中指出在 ncurses 中,几个相关的行为被集中在一起作为 bce
(背景颜色擦除)功能:
- 填充由于滚动而新清除的行
- 擦除显示,同时擦除以光标结束或开始的部分。
- 擦除一行,或擦除光标到行尾或从光标到行尾的部分
- 正在光标位置插入(一个空格)
- 删除一个字符
通常 ncurses 会填空(只有当终端输入 poorly chosen 时才会出现问题),您不会看到这一点。但是使用简单的转义序列意味着您可以稍微探索 bce
的细微差别。
直接使用转义序列打印颜色的终端应用程序应在写入 任何 其他不打算着色的文本之前重置颜色。其他应用程序(例如 shell 中的行编辑)在擦除行内的文本时必须牢记此规则