Tab 宽度自适应以对齐的效果是怎么回事?


#1

Tab 这个字符显示一直困扰着我。

\t 在 Termainl 和 Emacs 里是自适应的,宽度不固定,会自动对齐,比如:

echo -e "a\tb\ncccc\td\n12345678"

iTerm2 + Fish (其实跟 Shell 没关系)的效果如下,可以看到第一个 Tab 显示 6 个字符宽度,第二个 Tab 显示成了 3 个字符宽度

Emacs 中也类似(开启了 whitespace-mode, » 提示 Tab 字符),第一个 Tab 显示 7 个字符宽度,第二个 Tab 显示成了 4 个字符宽度

这么做得到了对齐的效果,很好,但这个效果是哪来的(iTerm2、Emacs 的?)?有什么规定的文档吗?其它的 App 也会这么做吗?


#2

可能没这么复杂,tab原本的作用就是在打字机上快速输入表格,tabstop可以手动调整。emacs和iterm里跳转到下个tabstop是正常行为。之后在电子设备上保留这个功能(用来输入表格)是挺符合直觉的选择。最新世代的程序员倒有可能以为tab纯粹是用来缩进或者跳转按钮。


#3

首先这个显示 tab 的功能应该是 terminal (及对应的 emulator) 的事实标准的一部分的。

VT100 终端就有手动 set tab 功能,

Just like a typewriter, the VT100 can jump or tab to preselected points on a line. These tab stops may be individually changed, or totally cleared and then set.

手册上也说了这个也可以通过电脑发送 escape sequence 控制。支持摸拟 VT100 的 term emulator 自然至少要支持这些 escape sequence。

Set tab at current column    ESC H
Clear tab at current column  ESC [ g or ESC [ 0 g
Clear all tabs               ESC [ 3 g

POSIX 的 tabs(1) 可以调节对 tab 字符的显示规则。就是利用发送上面提到的 escape sequence。当然实际上一般是调用 termcap(5) 这个库根据 terminal 的具体种类发 escape sequence。这个只会影响 cat 之类 stdout 输出,对 vim top 这种直接 ncurse 的程序不会有影响

If no tab stops are specified, the ``standard’’ UNIX tab width of 8 is used.

-f FORTRAN format (columns 1, 7, 11, 15, 19, 23).

-s SNOBOL format (columns 1, 10, 55).

expand(1) 实现了 tab 到 space 的转換。具体算法 POSIX 不会规定,不过可以看 BSD 或 GNU 的实现。注意和这终端显示不一样。从终端复制出的文本在不同 tabs 设定下都是一样的,因为都还是 \t 字符沒做转換。

Emacs 用于控制的 tab-stop-list 实际上不太一样,Emacs 不能让 tab 显示成不同的寛度,所以设了 tab-stop-list 以后是混和了 tab 和 space 的。05

https://www.gnu.org/software/emacs/manual/html_node/emacs/Tab-Stops.html


#4

哦,Emacs 里 Tab 的显示的位置总是 8 的整数倍,为了达到这个目的,Tab 的显示宽度不固定。