如何确定终端是否支持颜色?

发布于 2024-08-25 23:12:41 字数 692 浏览 8 评论 0原文

我想更改一个程序来自动检测终端是否支持颜色,因此当我从不支持颜色的终端(例如 (X)Emacs 中的 Mx shell)运行所述程序时,颜色会自动关闭。

我不想对程序进行硬编码来检测 TERM={emacs,dumb}。

我认为 termcap/terminfo 应该能够帮助解决这个问题,但到目前为止,我只能拼凑出这个使用 (n)curses 的代码片段,当它找不到终端时,它会严重失败:

#include <stdlib.h>
#include <curses.h>

int main(void) {
 int colors=0;

 initscr();
 start_color();
 colors=has_colors() ? 1 : 0;
 endwin();

 printf(colors ? "YES\n" : "NO\n");

 exit(0);
}

即我明白了:

$ gcc -Wall -lncurses -o hep hep.c
$ echo $TERM
xterm
$ ./hep
YES
$ export TERM=dumb
$ ./hep           
NO
$ export TERM=emacs
$ ./hep            
Error opening terminal: emacs.
$ 

这是......次优的。

I would like to change a program to automatically detect whether a terminal is color-capable or not, so when I run said program from within a non-color capable terminal (say M-x shell in (X)Emacs), color is automatically turned off.

I don't want to hardcode the program to detect TERM={emacs,dumb}.

I am thinking that termcap/terminfo should be able to help with this, but so far I've only managed to cobble together this (n)curses-using snippet of code, which fails badly when it can't find the terminal:

#include <stdlib.h>
#include <curses.h>

int main(void) {
 int colors=0;

 initscr();
 start_color();
 colors=has_colors() ? 1 : 0;
 endwin();

 printf(colors ? "YES\n" : "NO\n");

 exit(0);
}

I.e. I get this:

$ gcc -Wall -lncurses -o hep hep.c
$ echo $TERM
xterm
$ ./hep
YES
$ export TERM=dumb
$ ./hep           
NO
$ export TERM=emacs
$ ./hep            
Error opening terminal: emacs.
$ 

which is... suboptimal.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑶笙 2024-09-01 23:12:41

一位朋友向我指出 tput(1),我提出了这个解决方案:

#!/bin/sh

# ack-wrapper - use tput to try and detect whether the terminal is
#               color-capable, and call ack-grep accordingly.

OPTION='--nocolor'

COLORS=$(tput colors 2> /dev/null)
if [ $? = 0 ] && [ $COLORS -gt 2 ]; then
    OPTION=''
fi

exec ack-grep $OPTION "$@"

这对我有用。不过,如果我有办法将其集成到 ack 中,那就太好了。

A friend pointed me towards tput(1), and I cooked up this solution:

#!/bin/sh

# ack-wrapper - use tput to try and detect whether the terminal is
#               color-capable, and call ack-grep accordingly.

OPTION='--nocolor'

COLORS=$(tput colors 2> /dev/null)
if [ $? = 0 ] && [ $COLORS -gt 2 ]; then
    OPTION=''
fi

exec ack-grep $OPTION "$@"

which works for me. It would be great if I had a way to integrate it into ack, though.

記憶穿過時間隧道 2024-09-01 23:12:41

您几乎已经完成了,只是您需要使用较低级别的curses 函数setupterm 而不是initscrsetupterm 只是执行足够的初始化来读取 terminfo 数据,如果您传入一个指向错误结果值(最后一个参数)的指针,它将返回一个错误值,而不是发出错误消息并退出(默认) initscr 的行为)。

#include <stdlib.h>
#include <curses.h>

int main(void) {
  char *term = getenv("TERM");

  int erret = 0;
  if (setupterm(NULL, 1, &erret) == ERR) {
    char *errmsg = "unknown error";
    switch (erret) {
    case 1: errmsg = "terminal is hardcopy, cannot be used for curses applications"; break;
    case 0: errmsg = "terminal could not be found, or not enough information for curses applications"; break;
    case -1: errmsg = "terminfo entry could not be found"; break;
    }
    printf("Color support for terminal \"%s\" unknown (error %d: %s).\n", term, erret, errmsg);
    exit(1);
  }

  bool colors = has_colors();

  printf("Terminal \"%s\" %s colors.\n", term, colors ? "has" : "does not have");

  return 0;
}

有关使用 setupterm 的更多信息,请参阅 curs_terminfo(3X) 手册页 (x-man-page://3x/curs_terminfo) 和 使用 NCURSES 编写程序

You almost had it, except that you need to use the lower-level curses function setupterm instead of initscr. setupterm just performs enough initialization to read terminfo data, and if you pass in a pointer to an error result value (the last argument) it will return an error value instead of emitting error messages and exiting (the default behavior for initscr).

#include <stdlib.h>
#include <curses.h>

int main(void) {
  char *term = getenv("TERM");

  int erret = 0;
  if (setupterm(NULL, 1, &erret) == ERR) {
    char *errmsg = "unknown error";
    switch (erret) {
    case 1: errmsg = "terminal is hardcopy, cannot be used for curses applications"; break;
    case 0: errmsg = "terminal could not be found, or not enough information for curses applications"; break;
    case -1: errmsg = "terminfo entry could not be found"; break;
    }
    printf("Color support for terminal \"%s\" unknown (error %d: %s).\n", term, erret, errmsg);
    exit(1);
  }

  bool colors = has_colors();

  printf("Terminal \"%s\" %s colors.\n", term, colors ? "has" : "does not have");

  return 0;
}

Additional information about using setupterm is available in the curs_terminfo(3X) man page (x-man-page://3x/curs_terminfo) and Writing Programs with NCURSES.

云淡月浅 2024-09-01 23:12:41

查找终端类型的 terminfo(5) 条目并检查 Co (max_colors) 条目。这就是终端支持的颜色数量。

Look up the terminfo(5) entry for the terminal type and check the Co (max_colors) entry. That's how many colors the terminal supports.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文