是否有对话框(ncurses)的最低术语功能列表?

是否有对话框(ncurses)的最低术语功能列表?

我正在尝试使用 ncurses 对话框库(随处可用,源镜像在这里),我试图在代码中动态决定是使用对话框还是仅打印到 stderr 并根据 stdin/out/err 是否连接到 char 块设备、ttys 以及它们拥有的 termcaps 进行提示。我从 less 中窃取了一些代码,这些代码在检测它是否可以正确渲染方面似乎相当可靠,并且它会查找 termcaps cecdclcm、 或hollalsr,否则它会切换到哑模式。但 less 的要求可能比dialog低(很多?)(至少我只需要 yesno 框)。我有点惊讶对话框或 ncurses 中没有检查大写字母,也没有办法只询问终端是否可以处理事情,或者如果没有大写字母则 initscr 失败? emacs shell 上的对话框(不是在 ansi-term 上,它在 obvs 上工作得很好)只是吐出无意义的文本,因为它是一个哑终端(与export TERM=dumb普通的 xterm 相同),所以这里显然没有进行功能检查。

我大部分时间都不是 UNIX 程序员,那么有没有一些可靠的标准方法可以做到这一点?让我感到奇怪的是,这不是一件容易检查的事情。

显然,我可以通过对话框 yesno 代码并尝试记录它调用的所有 ncurses 内容,但这很痛苦,所以我希望我只是未能在某处找到清晰的终端功能要求列表。

更新:因此,我决定尝试制作自己的自定义 terminfo 条目,以测试我可以在多大程度上仍然获得“yesno”对话框,而且它非常小,因此测试越少越好。很难弄清楚如何做到这一点,因此以下是来自 THE FUTURE 的其他人的简短总结:

  • 以下是 termcap 定义你需要把事情弄清楚;您可以直接使用 terminfo 定义并跳过几个步骤,但是像 less 这样的旧软件正在使用 termcap 版本,因此在该空间中工作会更容易。
  • 假设您有一个在当前终端(或dialog --title Hi --yesno There 0 0)上运行的 ncurses 应用程序,请找出您的 TERM envvar 是什么。我正在 screen 和 emacs ansi-term 中工作,所以它们screeneterm-color我的测试中,当然dumb
  • 使用 转储您想要处理的版本(您正在运行测试,因为您希望新版本成为工作版本的子集)infocmp eterm > eterm2.info,这将为您提供要使用的信息版本。
  • 将其转换为上限infotocap eterm2.info > eterm2.cap
  • 看看里面,然后把它剪下来,就像这是我的最小上限文件,在没有警告的情况下几乎不会运行更少:
#       hacked eterm for testing dialog
eterm2|gnu emacs term.el terminal emulation:\
        :am:mi:xn:\
        :co#80:li#24:\
        :ce=\E[K:cd=\E[J:cl=\E[H\E[J:\
        :ho=\E[H:\
        :cm=\E[%i%d;%dH:\
        :al=\E[L:
  • 请注意,我也将开头的名称更改为 eterm2。
  • 将其转换回信息captoinfo eterm2.cap > eterm2.info
  • mkdir infodb创建要编译此测试信息的本地目录。
  • export TERMINFO=$(pwd)/infodb告诉 termcap/terminfo 在哪里可以找到它
  • tic -D应该首先输出本地目录
  • tic -s eterm2.info将其编译到该目录
  • export TERM=eterm2设置你的新的黑客终端
  • 运行你的 ncurses 应用程序,或者dialog --title Hi --yesno There 0 0它应该以黑白简单的方式显示出来。
  • 您可以尝试重新添加其他命令以查看发生的变化,但完成后rm -rf infodbexport TERMINFO=export TERM=<oldterm>确保一切正常运行。

更新2: 这是我最终得到的代码,它似乎在我的所有测试中都有效:

    if(TermMode == TERM_UNINITIALIZED) {
        struct stat s;
        if((isatty(STDOUT_FILENO) && (fstat(STDOUT_FILENO,&s) == 0) && S_ISCHR(s.st_mode)) &&
           (isatty( STDIN_FILENO) && (fstat( STDIN_FILENO,&s) == 0) && S_ISCHR(s.st_mode)))
        {
            // both stdout and stdin are char block device ttys, now check termcaps
            // mostly stolen from the gnu less source code, since it seems robust
            // https://github.com/gwsw/less/blob/22e4af5cccbfab633000c7d610f868a868ad6e1a/screen.c#L1280
            char termbuf[2048];
            char const* term = getenv("TERM");
            int const TGETENT_OK = 1;
            if(tgetent(termbuf,term) == TGETENT_OK) {
                char sbuf[2048];
                char* sp = sbuf;
                char* sr = 0;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings"
                // ce ce cl are required
                if((sr = tgetstr("ce",&sp)) && *sr &&   // eol clear
                   (sr = tgetstr("cd",&sp)) && *sr &&   // eos clear
                   (sr = tgetstr("cl",&sp)) && *sr)     // screen clear
                {
                    // cm or (ho and ll)
                    if(((sr = tgetstr("cm",&sp)) && *sr) ||   // cursor move
                       (((sr = tgetstr("ho",&sp)) && *sr) &&  // home
                        ((sr = tgetstr("ll",&sp)) && *sr)))   // lower left
                    {
                        // al or sr
                        if(((sr = tgetstr("al",&sp)) && *sr) || // add line
                           ((sr = tgetstr("sr",&sp)) && *sr))   // scroll reverse
                        {
                            // we've got what we need for ncurses dialog!
                            TermMode = TERM_DIALOG;
                            goto term_detected;
                        }
                    }
                }
#pragma GCC diagnostic pop
            }
            // we're at least connected to a tty
            TermMode = TERM_STDIO;
        } else {
            // no interaction, so gotta just abort
            TermMode = TERM_ABORT;
        }
term_detected:
        ;
    }

不管怎样,知道最小的 termcap 是什么还是非常好的,但至少上面列出的那些可以减少工作量,所以我将使用它们。

谢谢,克里斯

相关内容