错位时空

生活由一个个选择构成但不是所有的选择都只有做出选择这一种选择

在做完 typst-concealer 这个插件的 MVP 之后我深感 Neovim 作为终端编辑器来自其底层抽象对图片渲染能力支持的薄弱最大的问题是合理的行内公式渲染需要支持可变行高以支持高度略大于行高的公式的美观渲染然而终端模拟器的行高模型是固定行高因此对于一些较高的公式我们必须要在字体与编辑器统一显示完整公式之间做取舍做到后者意味着将公式缩放到行高尺寸这会导致人眼不断在不同字体大小间对焦长期导致用眼疲劳做到前者则不可避免遇到对 𝐴=1𝑧𝑤 这种公式的裁剪行为这两者都并不完美

因此我在想既然我已经为网页实现了 Typst SVG Embedded 数学公式的基线对齐逻辑 (正如你所见上面的数学公式正确地撑开了行高并且基线基本与原文对齐)为何不在其他 GUI 编辑器中实现这个功能呢基本的需求便是在不打断日常笔记流程的前提下实现 Obsidian 的 Typst 预览体验

首先我尝试的是与 Obsidian 相同的技术路径即通过 Tauri 后端桥接 Typst Crate 来实现语法树分析提取数学公式位置并在前端使用 CodeMirror 6 来实现美观的公式渲染其中

  • 我在网页端实现的基线对齐逻辑可以被替换为 CodeMirror 中的 decoration SVG embedding
  • 我在 math-conceal.nvim 中实现的细粒度 conceal (即光标移动到被折叠的字段上再展开) 逻辑也可以被直接复用

因此伴随着这些经验积累以及 coding agents初稿只用了一个下午便进入了可用阶段

image
这是初稿的效果
image
这是初稿的效果

如你所见这个实现已经做到了美观的公式渲染比在 Neovim 中与 kitty 图像协议大战三百回合要好很多并且也能自然表达行内高公式的可变行高行为

然而问题也便从中出现功能性可用初稿到一个真正可以在生产环境中被复用的编辑器产品存在比想象中更多的 Gap

  • Typst 的多文件编辑补全体验强依赖于 LSP
  • 作为 Neovim 重度用户我的工作流已经强烈地绑定给了一系列 LSP 和 formatters 以及一些基于 Tree-sitter 实现的小但常用工具 (比如数学区域自动切换中英文输入法使用 textobjecttextobject 编辑数学公式节点等)当这些工具不被支持我感到原有的很符合直觉的工作流被强行打断
  • 基于 Web 前端技术构建的编辑器在大文件项目下卡顿明显

当然一开始我还是很期待这些问题能被妥善解决的但是伴随着时间的推进我逐渐意识到在这样一个完全从零开始的架构上构建大量的插件化定制化逻辑并不是一件很聪明的事情我要重复造轮子自动补全做完是多 LSP server 支持LSP 做完是 TextMate 高亮还有 Vim 模拟器的集成做完这些还需要将它们移动到统一的 CodeMirror 插件兼容层上保证它们在实际工作的时候不会打架固然每个任务都可以被解决但这种长期实现我已有工具能力的过程 (关键是甚至连可用层次都做不到) 很快便消耗掉了我的耐心

后来我也尝试了其他不同的方案比如写 Emacs 插件深度修改 VSCodium 的源码来实现可变行高支持这些工作都各有千秋但总存在不足最重要的是在这些编辑器的实践过程中我发现我陷入了一个标准的循环

  • 利用 GUI 编辑器的特定机制快速实现了 Neovim 所难以实现的可变行高机制以及其相对应的预览机制
  • 在公式预览机制稳定之后便开始寻求对 Neovim 日常工作流的复刻

前者通常能成功是因为 GUI 编辑器比 Neovim 天然便多了很多排版上的优势后者通常不能成功因为 Neovim 有与自身终端设计抽象绑定的各类编辑工作流现代 GUI 虽然本质上可以继承但通常不会作为这些 GUI 编辑器的首要实现目标

很显然这不是简单的选型失误而是一次对需求的误判

当我试图用一个 GUI 编辑器去替代 TUI 框架下的 Neovim 时我实际上在做的是为了一个只占整体体验 10% 的渲染改进去撬动另外 90% 早已成熟的快捷键配置脚本与工作流问题不在于这 10% 不诱人而在于它根本不足以构成一次整体迁移的理由可一旦选择已经做出人就会很自然地把 100% 的精力投向这 10%仿佛只要把它做得足够漂亮这次选择就会自动变得正确可等到尘埃落定真正决定工具是否可用的仍然是那迟迟没有被补回来的 90%于是最后得到的往往不是一个新的生产工具而只是一个完成得很精致的玩具

比起匆匆做出一个选择并立马付诸实践之外更重要的或许是去询问自己为何会在此刻被置身于一个选择的环境之中

回过头看在我的实际工作流里高公式在固定行高中被截断从来都不是一个真正困扰我的问题这样的公式本来就不常出现即使出现因为公式本身就是我亲手输入的我也完全可以凭上下文和记忆把它补全出来Preview 插件的价值不过是在降低这种模式匹配的成本而不是替代一项原本无法完成的工作

那么既然本质上不存在需求那为什么我会在这些方案的实现中花费了极长时间遍历了三个方案才最终意识到这个浅显的道理呢

其实真正让我投入如此多时间的是这样的一个事实一个局部上更美观更先进的原型太容易让人误以为自己抓住了真正的问题可原型的成功只证明了局部机制可以成立它从来不等于这套东西能接入我已有的生活也正是在这里决策与执行开始错位做决定时我看到的是那 10% 的收益真正开始做时支付的却是重建整个工作流的代价

当念头出现在脑海里并以诸多好处诱惑前行时真正的智慧或许不是直接向前走向某一个岔路口而是后退后退以审视诱惑背后的代价审视自身真实的处境审视那些日用不知视而不见的浅显道理

人们常说后退其实是向前确实是这样选择引导人向左或向右给予人行路便必然前进的幻觉但有时后退审视往往会找到左右之外的第三个方向这个方向不通往任何可以预见的终点却因为持有前所未有的澄明觉知通往一个更高远的未来

Back to all articles

Loading comments...