c - 构建文本编辑器。以原始模式从终端读取字符
问题描述
我正在关注如何编写自己的文本编辑器的教程构建您自己的文本编辑器。
我目前处于低级按键读取并将其映射到编辑器操作(部分:重构键盘输入)。但是当我在我的代码中实现相同并运行它时,我的终端只是冻结了,我必须重新启动才能恢复正常。我正在使用 Parrot OS(如果重要的话)。这是我的源代码的相关部分:
char editorReadKey() {
int nread;
char c;
while ((nread = read(STDIN_FILENO, &c, 1) != 1)) {
if (nread == -1 && errno != EAGAIN)
die("read");
/*if (iscntrl(c))
printf("%d\r\n", c);
else
printf("%d('%c')\r\n", c, c);
*/
}
return c;
}
void editorProcessKeypress() {
char c = editorReadKey();
switch (c) {
case CTRL_KEY('q') : exit(0);
break;
}
}
int main(void) {
enableRawMode();
while (1) {
editorProcessKeypress();
}
return 0;
函数enableRawMode和disableRawMode没有区别,或多或少是本教程的确切实现。
void disableRawMode() {
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1)
die("tcsetattr");
}
void enableRawMode() {
if(tcgetattr(STDIN_FILENO, &orig_termios) == -1)
die("tcgetattr");
atexit(disableRawMode);
struct termios raw = orig_termios;
tcgetattr(STDIN_FILENO, &raw);
//turns off echoing the command on the screen
//turn off cannonical mode
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] = 0;
raw.c_cc[VTIME] = 1;
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1)
die("tcsetattr");
}
关于为什么会发生这种情况的任何原因?还是我做错了什么?
编辑:editorReadKey()
添加了我以某种方式错过将其放在这里的返回值。
解决方案
Ctrl-S并Ctrl-Q用于在熟模式下暂停和恢复到控制台的输出,这可以解释您的观察结果,尽管您通过IXON
在raw.c_iflag
. 和设置VMIN
也VTIME
可能不正确:设置VMIN
为零似乎是错误的。
在 Quick Emacs 中,我使用以下代码设置原始模式:
tcgetattr(fileno(s->STDIN), &tty);
ts->oldtty = tty;
/* input modes: no break, no CR to NL, no parity check, no strip char,
* no start/stop output control. */
tty.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON |
IGNBRK | PARMRK | INLCR | IGNCR);
/* output modes - enable post processing? */
tty.c_oflag &= ~(OPOST);
/* control modes - set 8 bit chars, no parity checking */
tty.c_cflag &= ~(CSIZE | PARENB);
tty.c_cflag |= CS8;
/* local modes - echoing off, canonical off, no extended functions,
* no signal chars (^Z,^C) */
tty.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG | ECHONL);
/* control chars - set return condition: min number of bytes and timer.
* We want read to return every single byte, without timeout. */
tty.c_cc[VMIN] = 1; /* 1 byte */
tty.c_cc[VTIME] = 0; /* no timer */
tcsetattr(fileno(s->STDIN), TCSANOW, &tty);
有关这些标志的详细说明,请参见termios 的 Linux 手册页。
推荐阅读
- r - RStudio:在源文件位置运行 .Rprofile
- date - 我需要在 Access 中拆分以 MM/YYYY 和 MM/DD/YYYY 格式存储日期的文本列,以删除日期格式
- python - 如何使用numpy有效地获取矩阵数组(6749568、3、3)与向量数组(6749568、3)的点积
- python-3.x - 有没有办法将循环输出写入文件?
- sql - 需要从其他表的结果更新一个表
- python - 如何读取压缩文件夹中的 .pkl 文件
- reactjs - 我如何在来自 firebase 的 react js 中迭代这些数据并捕获用户生成的关键数据
- swift - RealityKit – 无法正确旋转对象
- excel - 如何跨多个工作簿/工作站维护 Power Query 代码?
- javascript - 如何根据注入的组件对组件中的 *ngFor 进行切片?