Как читать входной буфер терминала сразу после нажатия клавиши
Я хочу прочитать нажатия клавиш со стрелками в моей программе c и заменить их (непосредственно в самом терминале) какой-либо другой строкой. Я пытаюсь реализовать функциональность истории Bash, как в терминалах Unix. Я написал этот код.
int
main(int argc, char *argv[])
{
char c;
char str[1024];
int i = 0;
while((c = fgetc(stdin)) != '\n'){
if(((int)c) == 27){
c=fgetc(stdin);
c=fgetc(stdin);
if (c == 'A')
{
printf("%c[A%c[2K",27, 27);
printf("UP");
}
}
str[i++] = c;
}
printf("\n");
return 0;
}
Но это не работает, потому что терминалы ждут новой строки или EOF для отправки входного буфера в stdin. Итак, я должен нажать клавишу ввода / возврата, чтобы проанализировать пользовательский ввод.
Вот в этомответ пользователь упомянул использоватьsystem ("/bin/stty raw");
но это заменяет все поведение терминала по умолчанию (например, возврат, удаление и т. д.).
Итак, есть ли способ, которым я могу читать / манипулировать входным буфером терминала напрямую и настраивать сам буфер, если обнаружено нажатие клавиши со стрелкой?
Окружающая среда - Ubuntu (Linux)
Обновление 1: Есть ли способ изменить сигнал / прерывание (по умолчанию это нажатие клавиши ввода), который заставляет терминал отправлять сохраненный ввод в буфер? Это также может помочь мне достичь того же поведения.
Окончательный код:
Я узнал символы ASCII для определенных нажатий клавиш, проверив выводstrace bash
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#define ESCAPE '\33'
#define BACKSPACE '\177'
#define DELETE '~'
int main(){
struct termios termios_p;
struct termios termios_save;
tcgetattr(0, &termios_p);
termios_save = termios_p;
termios_p.c_lflag &= ~(ICANON|ECHO);
tcsetattr(0,TCSANOW, &termios_p);
char buff;
while(read(0, &buff, 1) >= 0){
if(buff > 0){
if(buff == ESCAPE){
read(0, &buff, 1);
read(0, &buff, 1);
if(buff == 'A'){
write(2, "up", 2);
}else if(buff == 'B'){
write(2, "down", 4);
}else if(buff == 'C'){
write(2, "\33[C", 3);
}else if(buff == 'D'){
write(2, "\10", 2);
}
}else if(buff == BACKSPACE){
write(2, "\10\33[1P", 5);
}else if(buff == DELETE){
write(2, "\33[1P", 4);
}else{
write(2,&buff,1);
}
// write(2,&buff,1);
if(buff == 'q'){
break;
}
}
}
tcsetattr(0,TCSANOW, &termios_save);
return 0;
}