0

私は C++ で readline の置き換えを書いています。「上向き矢印」のような特別な/エスケープされたキーを含む端末入力を raw モードで処理したいと考えています\e[A\eただし、エスケープキーを1回押した後、上矢印を押した場合[と押した場合を区別できるようにしたいと考えています。A

これら 2 つの状況の主な違いは、上向き矢印が押されたときに入力文字が 1 ミリ秒以内に入力されることだと思います。そのため、次のようなことができると考えました。

#include <termios.h>
#include <absl/strings/escaping.h>
#include <iostream>

termios enter_raw() {
    termios orig;
    termios raw;
    tcgetattr(STDOUT_FILENO, &orig);
    tcgetattr(STDOUT_FILENO, &raw);
    raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    raw.c_oflag &= ~OPOST;
    raw.c_cflag |= CS8;
    raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
    raw.c_cc[VMIN]  = 1;
    raw.c_cc[VTIME] = 0;
    tcsetattr(STDOUT_FILENO, TCSAFLUSH, &raw);
    return orig;
}

int main() {
    termios orig = enter_raw();
    while(true) {
        char buf[10];
        memset(buf, 0, sizeof(buf));
        std::cin >> buf[0];
        usleep(1000);
        int actual = std::cin.readsome(buf + 1, sizeof(buf) - 2);
        std::cout << "Got string: \"" << absl::CEscape(buf) << "\"\n";
        if(buf[0] == 35) { break; } // received ctrl-c
    }
    tcsetattr(STDOUT_FILENO, TCSAFLUSH, &orig);
    return 0;
}

ただし、これの出力はGot string: "\033[A"期待どおりではありません。代わりにGot string、単純な文字のループであるかのように、3 回実行します。スリープするマイクロ秒数を変更しても、何の影響もないようです。

このようなことを C++ で簡単に実装する方法はありますか? ほとんどの端末に移植可能ですか?Windows のサポートは気にしません。答えは使用する必要はありません<iostream>; ジョブが完了する限り、C スタイルのターミナル IO を使用できます。

4

2 に答える 2