0

我正在尝试用 C 语言为学校项目编写一个迷你 shell,我想做的是做一种命令历史记录(就像在 shell 中一样),当我按下 UP 键时,它将先前的输入写入输入部分, DOWN 则相反,等等...,您可以在按 Enter 之前对其进行编辑以将其发送到程序,如下所示(抱歉英语不好): [] 代表用户光标

my_shell$ some input wrote by me
my_shell$ []
my_shell$ some other input
my_shell$ []
and now if I press UP
my_shell$ some other input[]
If I press UP again
my_shell$ some input wrote by me[]

我可以使用 termcaps 和其他一些功能isatty, ttyname, ttyslot, ioctl, getenv, tcsetattr, tcgetattr, tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs

问题是我无法理解ioctltty函数的文档,也找不到关于这些函数的详细解释的示例教程,也找不到我正在尝试使用它们的文档。

有人可以以一种可以理解的方式向我解释这些功能吗?以及我应该如何将它们应用于我正在尝试做的事情(我正在寻找一种 Linux-MacOs 兼容方式)感谢您的帮助。

4

1 回答 1

4

您要问的不是微不足道的,并且需要大量的工作。基本上,您需要做的是使用tcsetattr将终端置于非规范模式,其中终端的输入行缓冲被禁用,并且每次击键都将立即返回,而不是等待换行符。然后,您必须自己处理每个按键,包括退格/删除和向上/向下箭头。由于您想对行编辑进行什么操作,您可能还必须禁用回显并自己执行回显。

您需要自己维护当前行缓冲区,并且您还需要一个数据结构来存储所有较旧的输入行(历史),并且当向上箭头被击中时,您需要擦除您的内容'当前已为输入缓冲,并将其从屏幕上擦除,然后将历史记录复制到当前缓冲区并将其回显到终端。

另一个复杂因素是向上箭头和向下箭头之类的键不是 ascii 的一部分,因此不会被读取为单个字节——相反,它们将是多字节转义序列(可能以 ESC ( '\x1b') 字符开头)。您可以使用tgetstr查询终端数据库来确定它们是什么,或者只是硬编码您的 shell 以使用ANSI 序列,这些序列几乎是您现在看到的所有终端都使用的。

于 2021-03-21T01:58:53.013 回答