文本编辑器的核心难点是什么?
电脑办公时,经常要对一个文本格式的文件进行编辑,那就离开不文本编辑器。或许有人会对文本编辑器的内部构造和原理感兴趣,作为一名长期开发文本编辑器的老师傅,笔者简单介绍下文本编辑器做的事情,和它背后的核心难点。
简单来说,其实文本文件分两种,一种是纯文本,另外一种是带格式的文本。前者以各种txt 文件和编程代码文件居多,内部存放的是纯粹的文字,而不包括渲染该文字时的格式说明。后者以html/markdown/pdf 等常见格式居多,内部存放不仅包含文字本身,还包括显示该文字时的格式,比如字体大小,颜色,段距等。这种带格式的文本,还有一个专业的名称——富文本,顾名思义,不仅包含文本,还富含对文本的格式属性描述。
拿笔者开发的Ndd 编辑器而言,它是一款纯粹的纯文本编辑器,只提供对纯文本文件的编辑,而无法提供对富文本的编辑或渲染。实际上,富文本有许多不同的常见格式,包括公开格式或私有格式。常见的富文本格式有html、markdown、docx、pdf等,比较冷门的有tex 格式。如果要对富文本进行显示,一般而言,需要使用支持对应格式的对应软件。
有了这些前提知识后,可以简单回答文本编辑器在做什么——本质就是提供对文档格式的解析、数字存储,格式渲染显示。每种文本编辑器,无论是纯文本的,还是富文本的,它都需要对文档进行显示。差异点在于,对于富文本的渲染,其需要遵循富文本格式的定义,要能在格式规定的前提下显示出文本。
知道文本编辑器所做的工作后,介绍其核心技术难点——高效美观渲染显示。具体来说,其核心难点有如下2点。
1 高效的文本定位+实际内容修改管理
试想一下,看到一篇文章后,鼠标只要动一下,就要把鼠标所在的屏幕逻辑位置,换算到当前文字的排版显示位置,同时后台要计算出实际存储在内存或硬盘中的字节位置,三个位置三位一体,不能有一个字符的偏差,而且要快速。
文本的存储格式至关重要。试想如果在一段文字中,插入一个新文字,那么直观来说,在插入的这个鼠标位置,要立刻腾出一个空位,把新文字塞进去,然后把本来这个位置后面的所有内容,都立刻往后移动一个位置。如何选择一种高效的数据结构,对是否能快速做完该流程至关重要。
常见的文本组织管理数据结构有列表、分块、gap、piecetable,树形节点等,并没有一种放之四海而皆准的数据结构,取决于具体编辑器需要实现的功能和需求复杂度。
2 高效美观的渲染
直白说即良好的排版。富文本的格式琳琅满目,细节锱铢必较,是对文本渲染的一大挑战。从文字渲染的角度而言,浏览器从本质而言也算高级的文本编辑器,无非是在做html/css等富文本的渲染,全球能做好的目前也就2到3家,其中谷歌以遥遥领先的趋势排第一。
每时每刻,编辑器需要在后台计算好每一段文字的显示宽度、高度,字体大小、颜色、段字距离等排版细节,然后快速的呈现在用户面前。这里面每一个细节,都够一个独立开发者喝一壶的。武断地说,99%的普通开发者,无论是从技术难度,还是工作量评估二个维度而言,都不足以独立开发一款文本编辑器。
ndd 是一款简单的文本编辑器,麻雀虽小五脏俱全,也需要面对几个难点。
第一个是巨长文本的渲染性能。如果一段文字很长,有几万个汉字,在显示的时候,屏幕宽度无法显示这么长的一行。要想看到长行的所有文字,需要自动换行的效果。即把一个很长的句子,掰断为屏幕宽度的多个小段,从而达到一个长句能够以多个“视图行”同时呈现给用户的方式。这里的难点在于,在后台实时动态计算每个“视图行”的宽度,单个视图行的宽度和屏幕可视宽度一样宽。这虽然是个粗活,因为工作量巨大,要做到实时计算很难。
简单举例来说,要把一根竹竿放进麻袋,需要把长竹竿砍成多个小段,每个小段要能整整齐齐的正好和麻袋的宽度一致,否则就会装不下,或者浪费麻袋空间。这里最大的麻烦在于性能,做这件事本身不难,最难的是能否快速去做。只要卡一秒,用户都会抱怨难用,卡3到5秒,用户就用脚投票,然后骂垃圾了。
具体来说长行可能很长,有几万个文字,每个文字可能是中英字符、标点字符、阿拉伯字符,其字符宽度各不相同,每一个“视图行”要和屏幕一样宽,单行包含的字符个数都可能不一样。这个动态计算的过程相对耗时,就会导致卡顿。
第二个是排版美观问题。就算解决了渲染的问题,还需要考虑美观问题。比如有时候英文最好不能把一个单词从中间切开显示,避免一个单词切断后出现在上一行行尾和下一行行首的情况,这种类似的特殊情况,也需要考虑在渲染的方案之中。
种种这些难点和性能要求加起来,直接劝退了大量想尝试“自己从0到1写编辑器”的开发者。据我不精确考证,开源gun项目的祖师爷理查德·斯托曼,他写出了世界上第一个gcc编译器,写出了第一个调试器gdb,为后续linux系统的编译和调试打下了基础。但是很少有人知道,这哥们在做第一个gcc编译器的时候,同时也做了一个文本编辑器,就是大名鼎鼎的emacs。可以武断的说,文本编辑器是和编译器一样的基础核心工具之一,虽然他们的难度和工程量有一些区别,但是重要性却是不相上下的。
IT界中有个搞笑的故事,tex的发明者高德纳,就是写《计算机程序设计的艺术》的大牛,本来准备写7本同类系列书籍。结果写到第2本的时候,因为没有一个好的文字排版工具,不得不中断10年,先去写了一个文字排版系统tex。由此可见,一种高效美观的排版显示系统,对高德纳这种级别的大牛也是一个颇为棘手的问题,以至于“十年磨一剑”,方才打磨出tex。
AI 对程序员的冲击
最后我想讨论下AI对程序员行业的冲击。对初学者的建议是,如果你想做真正厉害的程序员,真的建议从自己写一写文本编辑器,编译器,数据库等项目入手。不一定要做出真正流行可用的编辑器,编译器,或发明自己的语言,但是你要做这些有难度的事情。在做这些事情中,尝试去解决那些牛人遇到的同样问题,这样你才能成为和牛人比肩靠齐的人。
当然是从0到1的那种写,不是说在开源的基础上继续扩展,如果不是从0开始写,而是拿开源组件直接改,这样你就逃避了那些真正难搞,却让人成长的部分。
一个程序员,如果尝试自己开发文本编辑器,开发自己的编程语言,开发自己的操作系统,那么他才可能成长为真正的牛人。这部分人,无论如何也不需要担心“AI取代程序员”这类话题。
从纯粹的技术角度而言,我对AI没有太多担忧,唯一担忧是大量初级的程序员被淘汰,我的活反而更重了。因为我知道无论是从技术的难度,还是工程的复杂度而言,我所面临的一系列问题,远远不是目前AI所能掌控的。那种给一个提示词,AI就能给你推翻重来的糊弄,在面对文本编辑器,语言编译器这些需要精确控制的场景,是无论如何都无法令人接受的。
不过我是说目前的AI,如果未来十年AI还能继续保持进化,那就不好说了。今天的AI远不足以替换牛人,只会造成初级程序员的断层式淘汰。
夜雨聆风