【问题标题】:Returning the terminal cursor to start-of-line with wrapping enabled在启用换行的情况下将终端光标返回到行首
【发布时间】:2010-11-06 05:31:13
【问题描述】:

我正在编写一个过滤器(在一个用于终端输出的管道中),它有时需要“覆盖”刚刚发生的一行。它的工作原理是逐个字符地将标准输入传递给标准输出,直到达到\n,然后调用特殊行为。我的问题是如何返回到行首。

我首先想到的是使用\r 或ANSI 序列\033[1G。但是,如果行长到足以在终端上换行(并因此导致它滚动),这些只会将光标移回当前 physical 行。

我的第二个想法是跟踪行的长度(自上一个\n 以来传递的字符数),然后多次回显\b。但是,如果该行包含控制字符或转义序列(可能还有 Unicode?),就会出错。

没有搜索所有特殊序列并使用它来调整我的字符数,有没有简单的方法来实现这一点?

【问题讨论】:

    标签: c linux terminal pipe c89


    【解决方案1】:

    即使有一个“神奇的序列”,当写入控制台时会可靠地擦除最后写入的行,您仍然会在输出中获得该行和序列(尽管隐藏在控制台上)。想想如果有人将输出写入文件,或者将其通过管道传递给其他过滤器会发生什么?他们会知道如何处理这样的输入吗?并且不要告诉我您排除了在其他地方写入而不是直接写入控制台的可能性。迟早会有人想要重定向输出 - 甚至可能是你!

    这样做的正确方法是在处理每一行时将其缓冲在内存中,然后决定是否输出。真的没有办法解决这个问题。

    【讨论】:

    • 确实,这是我最初的解决方案。唯一中断的地方是诸如随着时间增加的进度百分比(用 \b 覆盖自身)之类的东西,在几秒或几分钟内没有 \n,因此 fgets() 等会阻塞相当长的一段时间。顺便说一句,我已经排除了我的过滤器不是管道中最后一件事的可能性(尽管我在之前的评论中说过),因为除了作为美化控制台输出的工具之外没有理由使用它!
    • 关于成为管道中最后一项的快速评论:您不能确保 stdout 像 ls 那样进入终端吗?
    【解决方案2】:
    $ cat >test.sh #!/bin/sh > 输入 sc > echo '这是一个非常长的多行字符串:.................................. ..................................................... ......' > tput rc > echo '我回去重写了一些东西!!!!' > 回声 > EOF $ sh test.sh 我回去重写了一些东西!!!! …………………………………………………………………………………………………………………………………… ..................................................... ……

    terminfo 数据库中查找save_cursorrestore_cursor 字符串功能。

    【讨论】:

    • 我的理解是rc和sc保存了光标的物理位置(相当于\033[s和\033[u)。如果终端的全部内容由于换行而滚动,则字符串的开头不再位于相同的物理位置。 (至少,这是我在 xterm 中观察到的行为。)
    【解决方案3】:

    您可以通过简单的ioctl查询终端尺寸:

    #include <sys/types.h>
    #include <sys/ioctl.h>
    
    // ...
    
    struct winsize ws;
    ioctl(1, TIOCGWINSZ, &ws);
    
    // ws.ws_col, ws.ws_row should now contain terminal dimensions
    

    这样您可以防止打印超出行尾的任何内容,只需使用\r 方法即可。

    【讨论】:

    • 感谢您的建议!不幸的是,我认为这对我不起作用有几个原因: * 我仍然需要跟踪特殊情况序列以了解我离边缘有多近 * 我可能不是管道中的最后一件事对于上下文;我的过滤器是模式匹配的,并且“重写”匹配字符串包围在颜色转义序列中。我不能使用fgets() 并一次对整个字符串进行操作,因为我的某些输入会产生“动态”输出(例如递增的进度状态),而这一段时间不会输出\n
    猜你喜欢
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多