You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断终端光标可见性?求Linux及跨平台无库实现方案

Linux下获取光标可见性的实现

在Linux终端中,你可以通过发送ANSI查询序列并读取终端响应来获取光标可见状态,具体实现步骤如下:

  1. 保存当前终端属性,将终端切换为非规范模式(禁用行缓冲,支持立即读取输入)
  2. 发送查询光标可见性的ANSI序列:\x1b[?25n
  3. 读取终端返回的响应,解析出光标状态
  4. 恢复终端原有属性,避免影响后续操作

对应的C++代码示例:

#include <iostream>
#include <termios.h>
#include <unistd.h>
#include <cstring>

bool IsCursorVisible() {
    // 保存原终端属性
    termios originalTerm;
    if (tcgetattr(STDIN_FILENO, &originalTerm) == -1) {
        return true; // 错误时默认假设光标可见
    }

    // 配置终端为非规范模式,禁用回显
    termios term = originalTerm;
    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 1; // 至少读取1个字符
    term.c_cc[VTIME] = 0; // 无超时等待
    if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1) {
        tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
        return true;
    }

    // 发送光标状态查询序列
    const char query[] = "\x1b[?25n";
    write(STDOUT_FILENO, query, strlen(query));

    // 读取终端响应:"\x1b[?25h"表示可见,"\x1b[?25l"表示隐藏
    char response[10];
    ssize_t bytesRead = read(STDIN_FILENO, response, sizeof(response)-1);
    bool visible = true;
    if (bytesRead > 0) {
        response[bytesRead] = '\0';
        visible = (strcmp(response, "\x1b[?25h") == 0);
    }

    // 恢复原终端属性
    tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
    return visible;
}
跨平台无第三方库解决方案

通过预编译宏区分Windows和类Unix平台,分别实现对应逻辑,提供统一的调用接口:

#include <iostream>

#ifdef _WIN32
#include <windows.h>
bool IsCursorVisible() {
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cursorInfo;
    GetConsoleCursorInfo(out, &cursorInfo);
    return cursorInfo.bVisible;
}
#else
#include <termios.h>
#include <unistd.h>
#include <cstring>
bool IsCursorVisible() {
    termios originalTerm;
    if (tcgetattr(STDIN_FILENO, &originalTerm) == -1) {
        return true;
    }

    termios term = originalTerm;
    term.c_lflag &= ~(ICANON | ECHO);
    term.c_cc[VMIN] = 1;
    term.c_cc[VTIME] = 0;
    if (tcsetattr(STDIN_FILENO, TCSANOW, &term) == -1) {
        tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
        return true;
    }

    const char query[] = "\x1b[?25n";
    write(STDOUT_FILENO, query, strlen(query));

    char response[10];
    ssize_t bytesRead = read(STDIN_FILENO, response, sizeof(response)-1);
    bool visible = true;
    if (bytesRead > 0) {
        response[bytesRead] = '\0';
        visible = (strcmp(response, "\x1b[?25h") == 0);
    }

    tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm);
    return visible;
}
#endif

// 使用示例:启动时保存状态,退出前恢复
int main() {
    bool originalCursorState = IsCursorVisible();

    // 执行你的业务逻辑,例如隐藏光标:std::cout << "\x1b[?25l";

    // 程序结束前恢复光标原有状态
    if (originalCursorState) {
        std::cout << "\x1b[?25h";
    } else {
        std::cout << "\x1b[?25l";
    }

    return 0;
}

注意事项

  • Linux下的实现依赖ANSI兼容终端,现代Linux终端(如xterm、GNOME Terminal、Konsole)均支持该序列;macOS终端也可复用此逻辑。
  • 处理终端属性时需确保出错时恢复原配置,避免破坏终端的正常输入输出行为。

内容的提问来源于stack exchange,提问作者Chupakabra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 00:12:44