感谢Jonathan Leffler 的评论,他的评论暗示了我正确的方向,底部是我带注释的第一个termios程序演示器(谢谢!)。
关键是使用tcgetattr(ttyfd, &attributes)当前终端的文件描述符将其当前属性检索到 a 中struct termios,编辑属性,然后使用 来应用更改tcsetattr(ttyfd, when, &attributes)。
属性之一是“kill”字符——该字符导致整个当前缓冲的行被丢弃。它是通过索引到 的c_cc成员数组struct termios并设置attr.c_cc[VKILL]为任何想要的值(此处为 to Esc,等于八进制033)来设置的。
退出时终止字符应恢复为之前的值。
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
int main(){
char buf[80];
int numBytes;
struct termios original, tattered;
int ttyfd;
/* Open the controlling terminal. */
ttyfd = open("/dev/tty", O_RDWR);
if(ttyfd < 0){
printf("Could not open tty!\n");
return -1;
}
/**
* Get current terminal properties, save them (including current KILL char),
* set the new KILL char, and make this the new setting.
*/
tcgetattr(ttyfd, &original);
tattered = original;
tattered.c_cc[VKILL] = 033;/* New killchar, 033 == ESC. */
tcsetattr(ttyfd, TCSANOW, &tattered);
/**
* Simple test to see whether it works.
*/
write(1, "Please enter a line: ", 21);
numBytes = read(0, buf, sizeof buf);
write(1, buf, numBytes);
/**
* Restore original settings.
*/
tcsetattr(ttyfd, TCSANOW, &original);
/* Clean up. */
close(ttyfd);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该演示似乎可以在 Mac OS X 10.6.8 上运行。我还在 Linux 上对此进行了测试,显然Esc终止缓冲区似乎是默认设置,就好像我打印出c_cc[VKILL]我获得的一样27 == 033 == ESC。
以下尝试尽可能模仿您在评论中描述的行为。它设置c_cc[VEOL2]为Esc;EOL2 是备用行尾。它还会删除 Esc作为终止字符,因为您想要接收该行。
现在发生的情况是,如果Ret按下法线,一切都会正常。但是,如果Esc按下,缓冲区中的最后一个字符将设置为Esc,这是可以测试的条件(尽管仅在首先读取并缓冲整行之后)。
以下是根据您明确的规格制作的演示器。它等待一行输入并回显它
<CANCELLED> Esc如果该行以和终止<NORMAL > 如果该行以 终止Ret。享受!
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
int main(){
char buf[80];
int numBytes;
struct termios original, tattered;
int ttyfd;
/* Open the controlling terminal. */
ttyfd = open("/dev/tty", O_RDWR);
if(ttyfd < 0){
printf("Could not open tty!\n");
return -1;
}
/**
* Get current terminal properties, save them (including current KILL char),
* set the new KILL char, and make this the new setting.
*/
tcgetattr(ttyfd, &original);
tattered = original;
tattered.c_cc[VKILL] = 0; /* <Nada> */
tattered.c_cc[VEOL2] = 033;/* Esc */
tcsetattr(ttyfd, TCSANOW, &tattered);
/**
* Simple test to see whether it works.
*/
fputs("Please enter a line: ", stdout);
fflush(stdout);
numBytes = read(0, buf, sizeof buf);
if(buf[numBytes-1]==033){/* Last character is Esc? */
buf[numBytes-1] = '\n';/* Substitute with newline */
fputs("\n<CANCELLED> ", stdout); /* Print newline to move to next line */
}else{
fputs("<NORMAL > ", stdout);
}
fwrite(buf, 1, numBytes, stdout);
/**
* Restore original settings.
*/
tcsetattr(ttyfd, TCSANOW, &original);
/* Clean up. */
close(ttyfd);
return 0;
}
Run Code Online (Sandbox Code Playgroud)