【问题标题】:ANSI escape code CSI 6n always returns column=1 [duplicate]ANSI 转义码 CSI 6n 始终返回 column=1 [重复]
【发布时间】:2021-07-16 14:53:55
【问题描述】:

我正在编写一个程序,它可以根据字符在终端中的位置来更改字符的颜色。为了做到这一点,我需要至少获得一次光标位置。我不需要行,只需要列。

我查了一下,发现ANSI转义序列ESC[6n应该返回stdin中光标的当前位置,格式如下:ESC[<row>;<col>R

我写了一个小测试程序(很大程度上受到this answer的启发),通过它我试图隔离这个转义序列的行为,它能够正确获取行号,但是由于某种原因,列总是1.

这是一段相关的C代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>

int main() {
    // This will shift the cursor right a few places
    printf("some text");

    struct termios restore;
    tcgetattr(0, &restore);

    // Disable flags in order to read the response
    struct termios term;
    tcgetattr(0, &term);
    term.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(0, TCSANOW, &term);

    // Write ANSI escape sequence for cursor position
    write(1, "\033[6n", 4);

    // Read back response
    char buffer[16] = { 0 };
    int idx = 0;
    char ch;
    while (ch != 'R') {
        read(0, &ch, 1);
        buffer[idx] = ch;
        ++idx;
    }
    buffer[idx] = '\0';

    // Restore original settings
    tcsetattr(0, TCSANOW, &restore);

    // +1 because the first character is ESC
    puts(buffer + 1);

    return 0;
}

在我的终端 (mintty) 上,此代码具有以下输出:

$ ./main
some text[3;1R

该行确实是 3。但是,由于之前打印的文本,该列应该是 10,而不是 1。这种行为的原因是什么?我的代码有问题,还是终端有问题?或者,是否有另一种标准/更正确的方法来获取光标所在的列?

提前致谢。

【问题讨论】:

  • 我希望这是因为printf() 的输出被缓冲了。之后尝试fflush(stdout)
  • @ssbssa 是的,这实际上解决了问题。非常感谢!我建议写一个答案,以便我可以将其标记为已接受。

标签: c terminal ansi-escape termios


【解决方案1】:

printf("some text"); 替换为write(1,"some text", 9);,您将获得预期的光标位置。

您对使用 clib printf 移动的光标位置做出了错误的断言,POSIX/ANSI C 没有指定这个应该移动光标。

【讨论】:

  • 谢谢,我没想到。我希望有某种方法可以获得实际位置。我想我会尝试解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 2014-07-07
  • 2021-03-05
  • 2017-08-10
  • 2015-06-27
相关资源
最近更新 更多