奇怪的 Vim
2023年8月5号,vim 的作者 Bram Moolenaar 去世了。NeoVim 的作者专门写了一片悼文放在了 NeoVim 的官网上,大家可以看一看。他在里面说他在做什么事情之前都先想一想“如果是 Bram 的话,它会怎么做?”,我觉得这是个相当高的评价了,就是我想活成他的样子,按他的思维方式去思考问题。
关于 Bram,大家可以自行搜索去了解,它不光是个伟大的程序员而且还是个慈善家。
但我们今天不谈论他这个人,我想谈一谈 Vim 本身。
Vim 其实是个挺奇怪的软件的,现在我们想到文本编辑器,一般都是一个白板,上面有一条竖线不停的闪。想输入什么就直接敲下对应的按键。非常的简单。
但如果是 Vim 的话,就会变的很复杂,比如你需要用 hjkl 移动光标,按 i 键进入插入模式才能输入。按 v 键进入选择模式才能选中的操作。
等等。
我第一次接触到 Vim 的时候,感觉这真是太反人类了,为什么要搞的这么复杂?这难道不是把简单的问题复杂化了么?而且还这么多人用他?
我觉得想回答这个问题,就要看看 Vim 是如何发展而来的,所以我们今天来探究一下 Vim 的历史,看看他是怎么来的。
人口普查与打孔卡
我们要从 1890 年美国人口普查开始讲。自 1790 年以来,美国宪法要求美国宪法要求每 10 年进行一次人口普查,然后根据人口普查的结果决定各州在众议院所在席位的比例。他们专门有个人口普查局负责这个事。
那个时候的人口普查是个相当困难的事情,一次人口普查关收集收据就要几年,统计数据又要几年时间。1880 年的人口普查就花了 8 年多时间才完成。
他们意识到随着人口的增长,人口普查花费时间能会越来越多,下一次人口普查很可能没法在 10 年内完成了。
于是他们举行了一个比赛,看谁有更好的方法统计数据。
一个叫 Herman Hollerith(赫尔曼·霍利里思) 的员工发明的制表机赢得了比赛。
Hollerith 1890 Census Tabulator
他这个机器是这样运作的,首先你拿到一大堆调查问卷。你拿出其中一张,通过一个类似于比例绘图仪的东西,把上面的信息录入到一张打孔卡上
然后你就把调查问卷上的信息转换为了一堆打孔卡,之后你拿着打孔卡,把它放入制表机中。制表机会根据打孔卡上面的孔形成不同的电路,然后做出运算,最后把结果显示出来。
最后你把刚才的打孔卡,放入制表机旁边的分类机中,就可以了。
The 1890 US Census and the history of punchcard computing [feat. Grant of 3blue1brown fame]
它不仅自动完成了数据统计的工作,而且更重要的是,使用这个机器并不需要专业知识。只要稍加培训就可以了。
这个机器大大提高了数据统计的效率,1890 年的人口普查仅仅用了 6 年就完成了,尽管这次的人口比 10 年前多了 1600 万。
完成这次的人口普查之后,也就是 1896 年 Herman Hollerith 自己给自己的机器申请了专利,创立了专门的制表机公司,Tabulating Machine Company,主营制表机的业务。
1911 年 Hollerith 联合其他三家公司成立了Computing-Tabulating-Recording Company(CTR),这家公司在 1924 年改名为 International Business Machines Corporation 也就是今天的 IBM。
后来的打孔卡作为一种廉价的且易得的储存介质被广泛的使用,发展出了很多种类型的打孔卡,但最常用的还是 IBM 出的 IBM CARD 成为了后来的标准。
这种打孔卡有 12 行,80 列。每一列通过在不同的位置打孔来代表一个字符,如果不打孔就是空格,最多通过两个孔表示一个字符。所以这一张最多能表示 80 个字符。
为什么是两个孔表示一个字符呢?其实完全可以用三个孔来表示一个字符对吧,这样就不用那么多的行数了。但其实不行,因为打孔卡毕竟是一张纸,如果打了太多的孔,可能导致纸的强度下降。所以 12 行两个孔就是个比较合适的规格。
至于为什么是 80 列,就是历史原因了。最开始的打孔卡其实用的是 Hollerith Card,他当时只有 45 列,然后打得孔都是圆的。储存信息更少,后来人们希望能储存更多信息,于是 IBM 公司就改进了 Hollerith Card 推出了 IBM Card,它把孔改成了长方形,让整个卡片更紧凑,列数增加到了 80 列,基本上是原来的两倍了。
这种打孔卡也成了最流行的打孔卡,12 行 80 列成了一种标准。大家平时如果用格式化软件 prettier 的话,可以看到它默认的 printWidth 参数就是 80。很可能就是从这来的。
直到 1980 年代磁盘和磁带出现之前,打孔卡一直是主流的储存介质。不管是公司的报表还是一个计算机程序,都被写在一叠叠的打孔卡上。
不用电脑的程序员
所以那个时候的程序员是怎么工作的呢?
那时的程序员是这样工作的,你需要先在纸上写好你的程序。你要仔细检查你的程序,你要在脑海中运行这个程序,而不是在电脑上 debug。除此之外你一定要检查是否有语法错误。
但确认无误后,就可以把程序通过打孔机转换成打孔卡,一张卡就是一行代码。
最后你就能得到厚厚一叠打孔卡,所以这叠卡的顺序就很重要,如果你的顺序错了,或者丢了一张,那就完蛋了。
所以有一些高端的打孔机,可以在打孔卡的最后四列打上一个行号,然后有专门的分拣机根据这个行号自动给你排序。但这个分拣机又是个挺贵的机器,不是随时都能用的,所以那会儿通常的做法是,在你录入好所有的打孔卡之后,用笔在这叠卡的侧面,斜着给它画一道,这样如果有卡被放在错误的位置就能一眼看出来。另外打孔卡会切掉一个角,省着你把它防反。
然后你拿着你这叠卡去机房,把它交给操作员。如果人多的话,你可能还要排队。通常有一个专门的大屋子放电脑,有点像今天的机房,然后旁边一个小屋子专门用来提交作业,像前台一样。然后再旁边的一个屋,就全是打孔机。
你的卡交给计算机的操作员,让他把打孔卡喂给计算机。计算机会读取的你的程序然后运行,你可以在这等着它出结果,也可以等第二天再来取。
The 1890 US Census and the history of punchcard computing [feat. Grant of 3blue1brown fame]
这有点像现在去银行或者其他地方办事的感觉,就你把你的材料都准备好了,然后跑去机房,把你的卡交给操作员,然后他特别熟练的开始各种操作,办各种手续,然后告诉你“行了,回去吧,明天这个时候再来取结果吧”。然后你第二天又来,他把打印的出来的结果交给你,你拿过来一看,程序运行失败,你少写两个分号,你就傻逼了。
所以那会儿的程序员很可能都见不到电脑,可能全程都是那个“操作员”在操作电脑。
因为那时候使用计算机是非常昂贵而且复杂的,按分钟计费,不可能像今天一样,咱们一人一台电脑,那会儿可能一个学校或者公司一台电脑,然后大家一起用。储存空间也是非常昂贵且有限的,不可能专门给你分配一点空间储存你的数据,所以都是使用打孔卡作为储存媒介,毕竟这玩意儿很便宜。
这就跟今天的情况很不一样,那会儿是没有个人电脑的,都是大家一起用一台电脑。没有一个所谓的终端可以用。
但如何做到大家一起用一台电脑呢?那会儿主流的操作系统都是批处理式的,它能自动的执行任务,不用人看着,自己就在那跑。但是一次只能执行一个用户的任务,下一个人来就得等上一个人的任务处理完毕才行。所以你没法做到“实时”,所以也就谈不上“交互”了。
其实那个时候已经有显示设备了,键盘也是有的。但交互式的文字编辑程序还没有出现,我相信以那个时候的技术,写出一个文本编辑器是完全没有问题的。但问题不在“文本编辑”,问题在“交互”。你能想象一个不是实时的文本编辑器么?
直到分时操作系统被发明出来,他让计算机能同时处理多个用户的任务。这样“实时的交互”才变成可能。
很快一个叫 Ken Thompson 的年轻人在贝尔实验室中开发了一个不需要 Unix 系统,并且根据早期的文本编辑器 QED 的基础上开发了 新的编辑器 ed,当作 Unix 的默认文本编辑器。我们今天在 mac os 的终端中依然可以使用它。