造轮子工程 · 第 5 章 造文本编辑器 章节摘要:文本编辑器是最「老牌」的造轮子项目之一——Vim、Emacs、VS Code 背后都是几十年打磨的编辑器内核。造一个编辑器能教会你「交互式程序」的全部核心:你要管理一块不断变化的文本(缓冲区)、在终端的任意位置渲染字符(光标)、响应用户的每一次按键、把改动安全地落盘。本章导读编辑器的五个核心子系统:缓冲区模型(为什么不是「一个字符串」那么简单)、光标移动与模式(致敬 Vim 的 normal/insert 双模式)、文件 I/O(读取、保存、编码处理)、终端渲染(termios 原始模式、VT100 转义码、增量重绘)、撤销与重做(命令模式的应用)。我们以「造一个能用箭头键移动、能输入、能保存退出的小编辑器」为目标。
章节摘要:文本编辑器是最「老牌」的造轮子项目之一——Vim、Emacs、VS Code 背后都是几十年打磨的编辑器内核。造一个编辑器能教会你「交互式程序」的全部核心:你要管理一块不断变化的文本(缓冲区)、在终端的任意位置渲染字符(光标)、响应用户的每一次按键、把改动安全地落盘。本章导读编辑器的五个核心子系统:缓冲区模型(为什么不是「一个字符串」那么简单)、光标移动与模式(致敬 Vim 的 normal/insert 双模式)、文件 I/O(读取、保存、编码处理)、终端渲染(termios 原始模式、VT100 转义码、增量重绘)、撤销与重做(命令模式的应用)。我们以「造一个能用箭头键移动、能输入、能保存退出的小编辑器」为目标。读完本章,你不仅拥有一个自己的编辑器,更理解了 Vim/Emacs 的设计哲学——为什么 Vim 要分模式,为什么 Emacs 是「伪装成编辑器的操作系统」。
阅读完本章,你应当能够:
编辑器的内核是一个「缓冲区 + 命令 + 渲染」的三角:缓冲区是文本的内部表示、命令是用户意图的可逆封装、渲染是缓冲区到屏幕的增量投影。三者解耦,是 Vim/Emacs 能稳定运行几十年的工程根基。
朴素做法「整个文件存成一个字符串」在小文件上够用,但插入删除要搬移大量字符。讲清三种专业缓冲区结构:行数组(数组每元素一行)、gap buffer(留一个空隙在光标处)、piece table(原文 + 增量片段表)。Vim/Emacs/VS Code 各有取舍。
光标的「逻辑位置」(第几行第几列)与「物理位置」(终端坐标)的换算。重点讲 Vim 风格的模式:normal(导航/删除/粘贴)、insert(输入文字)、command(保存退出等命令)。理解模式为什么是「效率神器」——手不离开主键区。
读取要处理编码(UTF-8)与行尾(CRLF/LF),保存要保证「原子性」——先写临时文件,写成功后 rename 覆盖原文件,这样即使中途崩溃也不会损坏原文件。这是「数据安全」的基本素养。
让程序「接管终端」:termios 切原始模式(关回显、关行缓冲、捕获每次按键),VT100 转义码控制光标移动(\033[H)、清屏(\033[2J)、上色(\033[31m)。这是编辑器、Shell、TUI 程序共通的底层技能。
朴素做法「每按一键全屏重绘」在大文件上会闪。讲清增量重绘的思路:记录上次渲染状态、只重绘变化的行、用转义码定位到变化位置。这是编辑器性能的关键。
撤销的本质是「把每次编辑封装成一个可逆命令」(插入的反向是删除、删除的反向是重新插入)。讲清命令模式(command pattern)与撤销栈/重做栈的双栈模型。呼应「设计模式」的实战应用。
把前六节串起来,目标是造一个:能打开文件、用箭头键或 hjkl 移动、输入文字、Ctrl+S 保存、Ctrl+Q 退出的小编辑器。这是本章的最小可用目标,也是后续扩展(搜索替换、多缓冲、语法高亮)的起点。
本章遵循「数据 → 控制 → 渲染 → 综合」的递进路径,先内部表示,再用户交互,最后屏幕呈现:
缓冲区模型 (01) ── 文本的内部表示 │ ▼ 光标与模式 (02) ── 用户怎么操作文本 │ ▼ 文件 IO (03) ── 怎么进出文件 │ ▼ 终端渲染 (04) ── 怎么把缓冲区画到屏幕 │ ▼ 增量重绘 (05) ── 怎么画得不闪 │ ▼ 撤销重做 (06) ── 怎么让操作可逆 │ ▼ 综合小编辑器 (07) ── 全章综合应用 │ ▼ 第 6 章:从"编辑文本"到"管理文本的历史"——造 Git
01 是内部地基(选对缓冲区结构,后续都顺);02-03 是「用户与文件的桥梁」;04-05 是「屏幕呈现」(termios 是底层,增量重绘是优化);06 是「可逆性」的工程实现;07 是综合。这条路线也是 Vim/Emacs 这类编辑器的真实演进路径——从「能编辑」到「编辑得好用」。
前置知识:
本章为后续章节奠定的基础: