终端里的工具改了文件,砚不能还停在旧内容上
第 19 篇记过一个问题:编码工具就在砚的终端里跑,人没有切出窗口,磁盘上的文件已经变了,编辑器还会不会等着下次获得焦点才刷新?
后面的开发开始补这笔账。alpha.16 先加强保存和替换时的冲突检查,alpha.17 再接上文件变化通知,把打开的文档、文件树、快速打开和搜索连起来。
大小和时间都没变,内容也可能变了
以前判断外部修改,文件大小和修改时间是很方便的线索。但同步工具可能保留时间,替换的文字也可能恰好一样长。
这次把保存时的判断补到内容层:元数据相同,还要和上一次读写留下的磁盘内容基线比较。普通保存和自动保存都走这个检查,发现冲突先停下来,编辑区和磁盘两份内容各自保留。
明确选择覆盖,才是另一条动作。不能让自动保存替人做这个决定。
这也没有把整个文件系统变成事务数据库;其他进程仍可能继续写。这里只把"大小和时间没变就当作没改"的缺口补上。
收到变化后,先看编辑区有没有自己的修改
没有未保存内容,就读入磁盘的新版本,重载本身留在撤销历史里。想找回刚才那份文字,还能撤销一步。
如果编辑区也改了,就留住自己的草稿,显示冲突提示。磁盘文件被删除时,标签里的内容也先留着,接下来保存可以重新创建文件。
读取放在后台。读完回来时,要再确认还是原文件夹、原文档版本和原磁盘基线。人已经切项目或者继续输入了,旧结果就不能直接盖下来。
"我发起读取的时候是对的"只够说明开始那一刻,不能说明返回那一刻。
监听也要有个范围
这轮使用文件事件,把一阵创建、写入和删除合成批次,避免一次 checkout 触发一堆零碎刷新。
监听的是文件树已经读过的目录和打开文件所在目录,当前上限为 512 个目录。它没有一口气递归监听整个项目。某些平台的监听会占用不少文件描述符,无限制铺开并不划算。
这个范围也意味着:不能据此说任意深层目录的变化都能实时收到。没有文件事件、事件丢失等情况,仍靠重新获得焦点时的检查补一层。
树更新了,快速打开也要更新
目录新增或删除,除了刷新树,还要重建文件索引。索引在后台完整构建,再整体换进去;构建期间继续用旧列表,不把半份结果交给快速打开。
同一时刻只做一轮索引构建,期间又有变化就再补一轮。切走文件夹后,旧任务不能把结果交给新项目。
搜索也跟着变:磁盘文件改了,重查对应文件;编辑区有未保存修改,用缓冲区里的文本。对同一文件接连发出的搜索,只接收最新请求的结果,免得慢一点的旧搜索最后回来,把新结果顶掉。
替换之前,再确认眼前那一处还在
搜索结果留在屏幕上时,文件可能又被改过。单条替换要拒绝过期结果,整文件替换要重新读内容,写回前继续检查外部变化。
带 UTF-8 BOM 的文件也补了坐标处理:搜索看到的正文位置要和编辑器一致,保存时却仍保留编码标记和行尾格式。
这一轮里,测试专门覆盖了保留大小和时间的外部写入、删除再创建、迟到的读取和搜索结果。它们不太适合拿来做功能截图,却决定了能不能放心让另一个工具在同一目录里工作。
第 19 篇提出的问题,到这里有了具体实现。至于大型目录和持续写入下的表现,还得继续拿实际场景量,不能用"加了监听"替代后面的观察。
下载试用
保存与替换保护进入 alpha.16,文件刷新进入 alpha.17;下面提供包含两批改动的 alpha.17。
下载地址核对于 2026-10-19。安装包适用于 macOS 13+、Apple Silicon,目前尚未 Apple 公证,首次打开说明见发布页。
仓库留档
- 实现与设计:core/edit/edit.go、core/app/freshness.go、core/workspace/watch.go、core/app/search.go。
- 测试入口:core/app/freshness_test.go、core/app/safety_test.go、core/workspace/watch_test.go。本轮只核对源码、历史报告与发布信息,没有重跑产品测试或安装包。