行吧,我自己写一个文本编辑器
文章摘要
英国 Web 开发者 David Bushell 在 2026 年 9 月 1 日写下这篇实验记录。起因是此前那篇引起广泛共鸣的《他们不再像做 Sublime Text 那样做软件了》。他的心路历程很实诚:”现在的软件都是垃圾。这让我想到:我很擅长做垃圾啊!那我为什么不能自己写个文本编辑器?”他给自己定的基准线也很低——VS Code 建在 Monaco Editor 之上,那是一坨 div 汤地狱,”如果那就是标准,我犯错的余地大得很”。
第一次尝试:canvas。 他把所有内容都渲染到 canvas 元素上,实现了最小可用特性集:按下指针定位光标、方向键移动光标、高亮当前行、输入文字、花哨的光标动画。但 canvas 什么都不白送:文本选择、撤销/重做历史、多行粘贴、溢出滚动全都得自己做。滚动是最要命的——他不想自己实现弹性滚动条,于是作弊:用一个隐藏的 div 撑到与 canvas 文本等高,借浏览器原生 overflow 产生滚动位置,再据此计算 canvas 的渲染偏移。做到这里他反而泄气了,因为 canvas 完全没有可访问性,继续往上堆特性并不能解决这个根本问题。
第二次尝试:contenteditable。 既然那个 div 已经在了,不如直接把文本原生渲染在里面,加上 contenteditable 属性。他用的是 plaintext-only 取值,非常适合代码,所有内容保持在单个文本节点里;同时关掉 autocapitalize、autocorrect、spellcheck、translate。这里有个血泪教训:spellcheck 之类属性必须关掉,否则会出现输入延迟尖峰——他花了好几天才发现这个修复。这条路的收益是巨大的:原生文本选择、撤销历史、以及浏览器免费接好的一大堆可访问性。他用 Selection API 拿到度量信息继续绘制自定义光标,用 ::selection 做选中样式,把原生 caret-color 设为透明(他自己也承认这大概是不该做的事)。但超过一定字符数后会出现奇怪的性能问题,Chromium 比 WebKit 和 Firefox 更糟,而且不可预测。
第三次尝试:textarea。 结论出人意料地简单——对长文本,textarea 的性能远好于 contenteditable。最终 demo 里他还加上了语法高亮。原计划是在 contenteditable 上用 CSS 自定义 ::highlight,但 textarea 用不了 CSS Highlights,于是不得不加第三层:给可见行铺一层 div 汤,套上 MicroLighter 做高亮。他随后补记了两条读者反馈:新的 OpaqueRange API 让 textarea 也能用自定义 highlight,EditContext API 则改善了 canvas 的输入处理。太多 CSS highlight 又是另一个性能瓶颈;更稳健的方案是用 Tree-sitter 生成语法树、只为可见行生成高亮。
他给这个项目的自评是”看起来像 90% 的文本编辑器,功能只有 1%”,剩下的就是”把猫头鹰的其余部分画完”那个梗。他想继续画,但一想到 tab 缩进这种小事就打退堂鼓——现在他只是劫持 tab 键插入两个空格。项目就此归档,留待某个下雨天。文末他留了个坑给人上钩:JavaScript 的字符串和文本范围按 UTF-16 code unit 工作,很容易天真地引入 bug——同一个”绿柠檬”emoji,.length 是 5,展开成数组是 3,用 Intl.Segmenter 按字素簇切是 1。
HN 评论精华
“文本编辑是已解决的问题”引发了本贴最大的辩论。 anon291 打头炮:团队在推他用 VS Code,但我们已经有 emacs 这个完全可编程可脚本化、好一万倍的编辑器了,”文本编辑是已解决的问题,这些工具号称的优势大多只是 vim 或 emacs 的一种配置”。xedrac 虽然每天用 emacs(当然配 vim 键位),却完全理解 VS Code 为何流行:极易上手、功能繁多、默认值合理。cosmic_cheese 由此引出一个被低估的观点:”在 FOSS 世界里,好的默认值被严重低估。可配置性很棒,但没有好默认值时它也是负债——潜在用户在喜欢上软件之前早就跑了。” kstenerud 指出 emacs 和 Lisp 有同一个毛病:无限可配置加上缺少一套”钦定的、大家真心愿意开箱即用的”标准,导致每个人的环境互不兼容。iLemming 的长篇反驳很有代表性:Emacs 根本不是传统意义上的文本编辑器,而是”文本编排器”(text orchestrator)——他一边打字一边可以读浏览器页面上的链接列表、检查哪些链接指向 HN 讨论、跨所有标签页搜索、控制 YouTube 视频的快退和倍速、把屏幕任意区域 OCR 成 buffer,这些应用之间没有任何兼容层或 RPC,唯一的共同属性就是文本。他的结论是:”厂商的设计就是要把你的文本扣为人质”,所以文本编辑远不是已解决的问题。
rfgplk 从另一个角度否定”已解决”:超过 90% 的编辑器在输入或修改文本时有肉眼可见的延迟(emacs、某些配置的 nvim、VS Code、Sublime 都算),”今天的文本编辑器应该跑在 DRAM 读写速度上”。self_awareness 附议并甩出了那篇经典的《Typing with Pleasure》,说这只说明 90% 的编辑器选错了 UI 工具包,”我们在 Amiga 500 上就有过比现在更快的编辑器(CygnusEd)。我们退步了。我们曾经拥有然后弄丢了——这和不知道怎么做完全是两码事。”他还认为真正没解决的是远程编辑和 LSP 支持,而且”LSP 支持”远不止”把 HTTP 请求发给某个 server 再解释返回”那么简单——jdtls 经常坏,clangd 时灵时不灵,Ruby 的语言服务器难配到痛苦,同一个 Dart LSP 在 VS Code 能用在 Vim 不能用。
vibe coding 写编辑器成了本贴的时代切片。 stillpointlab 说他刚让 Fable 给他写了个编辑器——准确讲是包了一层 KDE 的 KTextEditor 库(那本身就是 90% 的编辑器),用 Rust 包装并接上 LSP,花了两天,得到一个又小又快的编辑器;tab 交给 Sway 管、模糊查找交给 fuzzel、文件树交给 broot。他强调这是 100% vibe code、一行代码没读、全部直接合并,”它靠泡泡糖和透明胶带粘在一起,但它正好做我想要的事,而且到目前为止一个 bug、一次崩溃都没有”(他也诚实地披露:用了不到一周)。他解释动机时说了一句很多人会共鸣的话:我现在写的代码不多了,主要是读、搜索、导航,所以那些强大的编辑功能对我是浪费。boxed 也贴出了让 Claude 写的 IDE(TurboKod),说本来是个玩笑想法、现在成了日常主力,尤其是 review 模式在大量工作经由 LLM 的今天特别有用。
反对的声音也不客气。brettermeier:”为什么要为一个外面已经有一千个的东西烧掉这么多 token 和能源?我不认为这是未来,那会是个愚蠢的未来。” wolletd 阴阳道:”必须把所有 vibe code 的软件都分享出去,好污染未来的 LLM 训练!” brailsafe 说他打算这样”利用这个时代”:继续用这些年一直在用的工具,如果哪天不够用了,就花钱买那些以做编辑器为业的公司做的高质量产品,而不是再花更多钱给那些试图说服他”这些产品已经过时”的公司。dwedge 捕捉到一个时代症候:stillpointlab 说”特性很少,是刻意的”,在 vibe coding 之前这句话的含义从上下文一望即知(刻意极简),”现在它同样可能意味着 Fable 没问你就自己实现了一些功能”。
最好的一条是 tzs 的历史故事。 1980-81 年他在加州理工高能物理系做兼职系统程序员,前任是研究生时期的 Rob Pike。某天他和另一个学生 Karl Heuer 一起干程序员的经典消遣——吐槽当时的全屏编辑器有多烂、说自己能写得更好。结果这演变成一场比赛,两人通宵各写各的编辑器,全程只有打字声,偶尔有人宣布某个功能跑通了以扰乱对手心态。第二天早上另一位管理员 Norman Wilson 看到了,在给 Rob Pike 的邮件里提了一嘴,Pike 的回复大意是:”每个人都写全屏编辑器,这很容易做,还能让他们感觉自己很重要。让他们去做点有用的事。”tzs 的结尾很妙:”才过了两年左右,Rob Pike 自己就写了个全屏编辑器。不知道有没有让他感觉很重要?”(bruckie 和 solarexplorer 分别贴出了 Acme 和 Sam。)他还补了细节:Karl 的编辑器叫 ted,他自己那个叫 smegma。这条线随后跑题到 Rob Pike 和 Go 的设计动机,有人贴出那段著名的”我们的程序员是 Googler 不是研究者”的演讲原文,speed_spread 则为 Java 辩护:Java 的问题从来不是语言,而是互联网泡沫时代那些为了卖”企业级方案”而把一切复杂化的工具厂商。
bitwize 贴了 ESR《无根之根》里的那则公案:小和尚抱怨没有一个编辑器能满足他全部需求,于是宣布”我要写出史上最好的编辑器”,话没说完就被 Foo 大师一棍敲在后脑勺上——”蠢材!你以为我想再学一个编辑器?”sph 提炼出两条可能矛盾的教训:(a)世界不需要又一个编辑器;(b)如果你要写编辑器,它的目标受众应该只有一个人——你自己。
akersten 的评论则精准戳中了文章本身的悖论:谁能想到呢,那个专门为这个用例设计、内建于浏览器三十年的 textarea 元素,居然是性能最好、行为最一致的实现方式。”但我有点遗憾作者在这里就停止削减不必要的复杂度了……我们其实还没在造文本编辑器,我们在造一个有花哨输入框的网站。如果要造真正的文本编辑器,我们还得把浏览器这坨臃肿也一并抛弃。” samus 则给了作者一句公道话:每次有人冒出这个想法,都会发现文本编辑很难;难得的是这位作者还考虑了可访问性。