C 避免光标定位在按键上
C Avoid cursor positioning on key press
我正在尝试在 C 中实现一种终端。我正在尝试通过上下键压力构建终端历史记录,但是如果我按下这些键,光标将向上(或向下)一行.如何"control"这个功能?
编辑:
让我们举个例子:
fgets(cmd, sizeof(cmd), stdin);
if (cmd[0] == '3')
if (cmd[2] == 'A')
printf("up-arrow pressed!\n");
这段代码很糟糕,但它是一个很好的起点。有用。问题是,如果您按向上箭头键(光标),它会移动到上一行并打印 "up-arrow pressed!"。如何在没有外部库的情况下避免光标上下移动?
作为初学者,请举例说明如何初始化您的终端和一些基本代码:
#include <stdio.h>
#include <termios.h>
int main (void) {
struct termios t;
tcgetattr(0, &t);
t.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSANOW, &t);
while (1) {
char ch = getchar();
if (ch == '\x1b') {
do {
ch = getchar();
} while (!isalpha(ch));
printf("Got escape sequence: ");
switch (ch) {
case 'A':
printf("Cursor up\n");
break;
case 'B':
printf("Cursor down\n");
break;
case 'D':
printf("Cursor left\n");
break;
case 'C':
printf("Cursor right\n");
break;
default:
printf("%c\n", ch);
}
// handle escape sequence
} else {
printf("Got %c\n", ch);
}
}
return 0;
}
现在您必须输出键入的字符并在收到游标-* 或其他控制序列(而不是调试-printf
s 以上)。为此,您必须密切跟踪当前 screen-layout。
正如我在评论中所建议的那样,这是一项非常乏味的工作,除了学习(或者可能是嵌入式系统)之外,与使用 libreadline 或类似的 API 相比,我看不到任何好处。
一个真正的应用程序将提供退出程序而不是 ^C
。这是一个例子,修改@ctx 的示例来做到这一点(并改进转义序列的处理),当连续读取两个转义符时退出:
#include <stdio.h>
#include <termios.h>
int main (void) {
struct termios t, save;
int last;
tcgetattr(0, &t);
save = t;
t.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSANOW, &t);
while (1) {
int ch = getchar();
if (ch == '3') {
if (last == ch)
break;
do {
last = ch;
ch = getchar();
} while (ispunct(ch) || isdigit(ch));
if (isalpha(ch)) {
printf("Got escape sequence: ");
switch (ch) {
case 'A':
printf("Cursor up\n");
break;
case 'B':
printf("Cursor down\n");
break;
case 'D':
printf("Cursor left\n");
break;
case 'C':
printf("Cursor right\n");
break;
default:
printf("%c\n", ch);
break;
break;
}
}
} else if (ch > 0) {
printf("Got %c\n", ch);
}
last = ch;
}
tcsetattr(0, TCSANOW, &save);
return 0;
}
curses 中的等价物(具有不同的消息)更简单:
#include <curses.h>
int main (void) {
int last = 0;
filter();
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
while (1) {
int ch = getch();
if (ch >= 0) {
if (ch >= KEY_MIN) {
printf("Got special key %s\r\n", keyname(ch));
} else {
if (ch == '3' && last == ch)
break;
printf("Got %s\r\n", unctrl(ch));
}
last = ch;
fflush(stdout);
}
}
endwin();
return 0;
}
我正在尝试在 C 中实现一种终端。我正在尝试通过上下键压力构建终端历史记录,但是如果我按下这些键,光标将向上(或向下)一行.如何"control"这个功能?
编辑: 让我们举个例子:
fgets(cmd, sizeof(cmd), stdin);
if (cmd[0] == '3')
if (cmd[2] == 'A')
printf("up-arrow pressed!\n");
这段代码很糟糕,但它是一个很好的起点。有用。问题是,如果您按向上箭头键(光标),它会移动到上一行并打印 "up-arrow pressed!"。如何在没有外部库的情况下避免光标上下移动?
作为初学者,请举例说明如何初始化您的终端和一些基本代码:
#include <stdio.h>
#include <termios.h>
int main (void) {
struct termios t;
tcgetattr(0, &t);
t.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSANOW, &t);
while (1) {
char ch = getchar();
if (ch == '\x1b') {
do {
ch = getchar();
} while (!isalpha(ch));
printf("Got escape sequence: ");
switch (ch) {
case 'A':
printf("Cursor up\n");
break;
case 'B':
printf("Cursor down\n");
break;
case 'D':
printf("Cursor left\n");
break;
case 'C':
printf("Cursor right\n");
break;
default:
printf("%c\n", ch);
}
// handle escape sequence
} else {
printf("Got %c\n", ch);
}
}
return 0;
}
现在您必须输出键入的字符并在收到游标-* 或其他控制序列(而不是调试-printf
s 以上)。为此,您必须密切跟踪当前 screen-layout。
正如我在评论中所建议的那样,这是一项非常乏味的工作,除了学习(或者可能是嵌入式系统)之外,与使用 libreadline 或类似的 API 相比,我看不到任何好处。
一个真正的应用程序将提供退出程序而不是 ^C
。这是一个例子,修改@ctx 的示例来做到这一点(并改进转义序列的处理),当连续读取两个转义符时退出:
#include <stdio.h>
#include <termios.h>
int main (void) {
struct termios t, save;
int last;
tcgetattr(0, &t);
save = t;
t.c_lflag &= ~(ECHO | ICANON);
tcsetattr(0, TCSANOW, &t);
while (1) {
int ch = getchar();
if (ch == '3') {
if (last == ch)
break;
do {
last = ch;
ch = getchar();
} while (ispunct(ch) || isdigit(ch));
if (isalpha(ch)) {
printf("Got escape sequence: ");
switch (ch) {
case 'A':
printf("Cursor up\n");
break;
case 'B':
printf("Cursor down\n");
break;
case 'D':
printf("Cursor left\n");
break;
case 'C':
printf("Cursor right\n");
break;
default:
printf("%c\n", ch);
break;
break;
}
}
} else if (ch > 0) {
printf("Got %c\n", ch);
}
last = ch;
}
tcsetattr(0, TCSANOW, &save);
return 0;
}
curses 中的等价物(具有不同的消息)更简单:
#include <curses.h>
int main (void) {
int last = 0;
filter();
initscr();
noecho();
cbreak();
keypad(stdscr, TRUE);
while (1) {
int ch = getch();
if (ch >= 0) {
if (ch >= KEY_MIN) {
printf("Got special key %s\r\n", keyname(ch));
} else {
if (ch == '3' && last == ch)
break;
printf("Got %s\r\n", unctrl(ch));
}
last = ch;
fflush(stdout);
}
}
endwin();
return 0;
}