I/O 传递有几个点,其中一些(据我所知)是 shell、pty、tty、termios、终端仿真器应用程序。在大多数终端模拟器中,长命令行(超过当前 $COLUMNS 的命令行)会在用户按 Enter 键提交命令之前换行。此外,当按照预期从命令行中删除适当数量的字符时,该行将向后换行到上面的行。
我的问题是:这个魔法通常在哪里处理?它是 termios 设置,还是 shell 的一部分,还是终端仿真器应用程序对此负责?
对于更多上下文,我在 Ubuntu 上使用 Terminator 终端模拟器应用程序 - 其中换行工作得很好(所以我的 $PS1 提示符应该没有问题)。但是我正在开发自己的终端模拟器应用程序,该应用程序与 go pty spawner (github.com/kr/pty) 一起使用,并且我遇到了长行没有换行的问题,而是在行的开头同一条线。
答案1
在大多数终端模拟器中,在用户按 Enter 键提交命令之前,长命令行 [...] 会换行。
这不是终端仿真器的功能。
这是你的 shell 的一个功能。你的 shell 不是全屏应用程序,但它正在做光标寻址。
当您在 shell 中编辑命令行时,shell 中的行编辑库完全负责正在编辑的行的显示方式。在 Bourne Again shell 中,这是 GNU readline 库。 Almquist shell 使用 libedit。其他 shell(例如 Z Shell)有自己的库。
这些库位于 termcap/terminfo 库之上,这些库记录终端仿真器的终端功能。这些功能包括用于以相对或绝对方式定位光标的控制序列、用于清除到行尾和屏幕末尾的序列,以及您的终端是否具有自动边距。
有了这个和关于终端宽度的信息,从TIOCGWINSZ
ioctl
(回落到COLUMNS
,或者对于其他库,则返回 termcap/terminfo 数据库),shell 中的行编辑库可以跟踪命令行长度以及有多少行。它显示在终端线上。它会在编辑输入行时智能地移动光标以重新绘制输入行。有时它可能依赖于自动边距(如果您的终端有)。有时它可能会使用控制序列显式地重新定位光标。
它这样做的事实就是造成诸如在https://superuser.com/questions/695338/。如果提示字符串中的控制序列的分隔不正确,人们可能会搞乱光标在哪里,以及需要发出什么光标运动才能写入屏幕上的特定位置的想法。
您的终端模拟器不处理命令行或行编辑的概念。它不是这些层的一部分。它看到一个简单的字符流和控制序列,它必须渲染它们。您的终端仿真器有责任实现在其 termcap/terminfo 条目中为其通告的控制序列。 GNU readline、libedit、ZLE、、、vim
和screen
其他将使用他们发现的广告内容。例如,如果您在 termcap/terminfo 中声明您的终端具有自动边距,则当在右边距打印字符时,模拟器必须进行换行。如果您声明您的终端可以上下移动光标,那么当它收到适当的控制序列时,它确实必须这样做。
顺便说一句:如果 GNU readline 发现它无法向上移动光标,因为 termcap/terminfo 条目没有说明这样做的方法,那么实际上根本看不到换行。 readline 退回到一种模式,在该模式中,它横向滚动输入行,全部在一行上。
答案2
终端[模拟器]负责此操作。移动到下一行的第一列正是终端在填充一行上的最后一个位置后所做的操作。
cat
您可以通过输入并键入一些长行来轻松看出这不是 shell 执行的操作。 Shell 喜欢bash
并且zsh
实际上确实跟踪它们认为终端具有的光标位置和列数,并在行尾输出各种终端控制序列,但这只是为了它们可以实现一些更高级的行编辑功能(例如右手提示、水平滚动、显示和擦除选项卡完成菜单、重写/刷新当前行等...)。如果他们不这样做,换行仍然会发生。
tty 层也可能了解屏幕尺寸,但同样,它不用于确保发生换行。
如果您的终端不执行此操作,则说明您的终端存在错误。