- 开发工具
- 代码编辑器
- 桌面应用
【免费下载链接】oni2
Native, lightweight modal code editor
2021 年 1 月发布的 Onivim 2 0.5.2(连同 2020 年 12 月未正式公告的 0.5.1)是该项目迈向 0.6.0 里程碑的关键月度版本,集中交付了 Vim 风格跨面板导航、:!命令输出 UI、自动换行、自动更新、基于 fzy 的模糊匹配、可定制行高与 Windows ANGLE 渲染兼容等能力。本文以该版本公告为主体,结合当前仓库的配置与源码实现,逐项拆解这些功能的配置方式、操作方法与底层原理,帮助读者理解并直接上手验证。
版本发布概览
Onivim 2 是一个原生、轻量的模态(modal)代码编辑器,其核心卖点是把 Vim 的操作模型与现代编辑器的 UI、VSCode 扩展生态结合起来。0.5.2 与 0.5.1 作为连续的两个月度版本,功能亮点覆盖了日常编辑体验的多个维度:
- Vim 风格导航(文件浏览器、搜索侧栏、符号大纲视图)
:!外 shell 命令输出在编辑器内的展示- 自动换行(word-wrap)支持
- Windows / OSX 自动更新基础设施
- fzy 模糊匹配算法集成
- 全文件类型关键字补全
- 可定制编辑器行高
- Windows 上基于 ANGLE 的渲染兼容
- OSX 首次运行体验优化
- VSCode 扩展宿主与 Vim 内核的系列修复
下文按功能逐节展开,并在每节给出仓库中对应的配置项与源码位置,便于读者按图索骥。
Vim 风格跨面板导航
0.5.2 为多个 UI 元素接入了 Vim 风格的导航模型,包括:
- 文件浏览器(file explorer)
- 搜索侧栏(search sidebar)
- 符号大纲视图(symbol outline):在普通模式下通过
gO打开(前提是当前语言扩展提供了文档符号 DocumentSymbols 数据)
这些面板统一支持CTRL-W+h/j/k/l的方向键绑定在面板间移动焦点,并支持大量 Vim 惯用的导航与滚动命令,如gg、G、zz、zb、zt等。
从源码看,这套交互由统一的树形组件驱动:在 src/Feature/Explorer/Feature_Explorer.re 中,symbolOutline字段就是一个Component_VimTree(~rowHeight=20),而focusOutline函数会切换焦点并置isSymbolOutlineExpanded为implicitlyOpen;面板收到按键事件后直接调用Component_VimTree.keyPress(key, model.symbolOutline)完成导航,符号选中则派发SymbolSelected(DocumentSymbols.symbol)消息。也就是说,gg/G/zz这类动作并不是为某个面板单独实现的,而是树组件提供的通用能力,文件浏览器、搜索结果与符号大纲因此获得一致的键盘体验。
符号大纲的数据来源是扩展宿主(Extension Host)的provideDocumentSymbols请求,实现在 src/Exthost/Request.re,其返回的DocumentSymbols.symbol结构直接喂给大纲树。这解释了公告中"当语言扩展提供该能力时可用"的前提。
:!命令输出 UI
本次版本为 bang 命令:!增加了输出展示支持:执行外部 shell 命令后,其标准输出不再只落在终端日志里,而是可以在编辑器 UI 中查看。对于依赖:!跑构建、格式化或临时命令的 Vim 用户,这一改动让 Onivim 2 在 Ex 命令行为上更贴近原生 Vim 的交互预期。
自动换行(Word-wrap)支持
自动换行是本次公告明确标注"Finally"的功能,配置方式有二:
- 配置项方式:
"editor.wordWrap": true(布尔值) - Vim 命令方式:
:set wrap与:set nowrap
在仓库中该配置的实现位于 src/Feature/Editor/EditorConfiguration.re:
let wordWrap = setting("editor.wordWrap", ~vim=VimSettings.wrap, wordWrap, ~default=`On); let wordWrapColumn = setting("editor.wordWrapColumn", int, ~default=80);几点值得注意的细节:
- 默认值为
On(与公告示例中"设置为 true"的提法一致,布尔true解码为On)。 - 配置键通过
~vim=VimSettings.wrap与 Vim 的wrap设置双向绑定,因此:set wrap/:set nowrap与配置文件中的editor.wordWrap是同一状态的两种表达。 - 解码器
wordWrapDecode(同文件第 42–65 行)同时接受布尔值与字符串值:true/false,以及"on"/"off"(其他字符串一律按Off处理),保证配置文件的书写宽容度。 - 配套的
editor.wordWrapColumn默认 80,用于控制换行列位置。 - 渲染端在 src/Feature/Editor/Editor.re 与 L577 处根据
EditorConfiguration.wordWrap.get(config) == \On` 决定是否进入换行布局路径,实现层面由编辑器视图的换行排版逻辑承担。
自动更新(Auto-update)
0.5.2 通过 Sparkle Framework 为Windows 与 OSX接入了自动更新能力,公告将其描述为基础设施级别的进展,更新界面会提示用户下载新版本。Linux 侧的方案仍在调研中,公告提到了 AppImageUpdate 与 Snap store 两条候选路线,属于当时未定的开放事项。
值得注意的是,本仓库内确实保留了 Sparkle 相关的桥接代码:目录 src/oni2-sparkle 包含.c/.h与 Reason 绑定文件,用于在 Onivim 2 中调用 Sparkle 的更新检查与安装流程,这与公告所述"OSX 上通过 Sparkle 集成自动更新"相互印证。
模糊匹配改进:集成 fzy
此前 Onivim 2 的模糊匹配算法在匹配精度与性能上都有瓶颈。0.5.x 系列通过为fzy编写 ReasonML / OCaml 包装库(reason-fzy),将 fzy 的评分与命中位置算法引入编辑器,显著改善了两方面:
- 匹配准确度:对子序列命中、连续命中、首字母命中等的打分更合理;
- 性能:搜索响应更快,适合在键入过程中实时过滤大量候选。
模糊匹配在 Onivim 2 中的三个典型应用场景为:
- QuickOpen 快速打开(
Control+P/Command+P) - 命令面板 Command Palette(
Control+Shift+P/Command+Shift+P) - 补全项的模糊匹配
仓库中该集成的核心在 src/Core/Filter.re:rank函数对候选列表逐项格式化后调用Fzy.fzySearchList(searchStrings, query, ()),再按result.original_index还原到原始条目,并通过match.positions生成高亮区间、match.score保留评分。返回结果{item, highlight, score}被 QuickOpen 与补全列表共用,这也解释了公告中"既用于 QuickOpen 又用于补全"的描述。score同时被作为排序依据,确保最相关的候选排在最前。
关键字补全(Keyword completion)
在 0.5.1 之前,Onivim 2 只支持来自语言扩展的补全;0.5.1 起,所有文件类型都获得了基于缓冲区内容的关键字补全。也就是说,即使没有安装对应语言的补全提供方,用户依然可以基于当前打开文件的词汇获得基础补全提示,这大幅降低了日常编辑对扩展的依赖。
可定制的编辑器行高
行高此前是写死的,0.5.x 将其开放为配置项:
- 配置项方式:
"editor.lineHeight" - Vim 命令方式:
:set linespace
实现上,该配置位于 src/Feature/Configuration/GlobalConfiguration.re,通过~vim=VimSettings.lineSpace与 Vim 的linespace关联;而VimSettings.lineSpace(同文件第 225–231 行)把 Vim 的整数值linespace映射为LineHeight.padding,默认值为LineHeight.default。
行高类型定义在 src/Core/LineHeight.re 中,支持三种取值形态:
| 形态 | 含义 | 示例 |
|---|---|---|
Proportional(float) | 按字体测量高度的倍数计算,lineHeight = 字体高度 × size | { "proportional": 1.2 } |
Absolute(float) | 固定像素高度 | { "absolute": 24 } |
Padding(int) | 在字体高度之上增加像素内边距,lineHeight = 字体高度 + padding | { "padding": 4 } |
值得注意的默认与解码细节:
- 默认值
LineHeight.default = proportional(1.2),即 1.2 倍字体行高; - 配置解码器支持直接写一个浮点数:
justFloat规定数值 ≥ 5 时按Absolute(绝对像素)解释,否则回退到Proportional(1.2)默认值,兼顾了"直接写像素"与"防呆回退"两种需求; - 渲染侧通过
LineHeight.calculate(~measuredFontHeight)将三种形态统一换算为像素,并广泛用于 src/Feature/Editor/Draw.re 的绘制逻辑(光标、选区、装饰等均以行高为基准布局),因此行高的变化会整体影响编辑器的垂直排版。
:set linespace与editor.lineHeight的桥接意味着两种写法最终落到同一个行高模型上,用户按习惯选择即可。
Windows 渲染兼容:ANGLE
公告指出一个 Windows 上的实际问题:OpenGL 在 Windows(尤其是虚拟机)中的驱动支持远不如 DirectX 成熟,部分环境只有 OpenGL 1.0,而 Onivim 2 需要 3.0+,导致启动崩溃或黑屏。为此 0.5.x 引入了ANGLE——一个以 DirectX 为后端实现的 OpenGL API 层。通过 ANGLE,Onivim 2 在不改上层渲染代码的前提下,借用 DirectX 更完善的驱动、硬件与平台支持,显著改善了 Windows 兼容性。这一改动是渲染管线的底层替换,用户无需任何配置即可受益。
OSX 首次运行体验
此前 OSX 用户首次启动 Onivim 2 会连续遭遇两个不必要的权限弹窗:一是通知权限,二是"访问 Documents 文件夹"的授权请求——后者源于旧逻辑默认自动打开 Documents 目录。0.5.x 移除了"启动即打开 Documents"的行为,改为默认不打开任何文件夹,从而消除了这条令人困惑的权限链路,让首次启动直接进入干净的编辑界面。
VSCode 扩展宿主修复
0.5.1 与 0.5.2 延续了对 VSCode 插件兼容性的持续投入,公告列出的代表性改进包括:
- 新增 XML 语言扩展支持;
- 扩展宿主(vscode-exthost)多次升级:1.46.0 → 1.47.1 → 1.50.1;
- 修复 vscode-spell-checker 的阻塞问题;
- 修复扩展搜索 / 下载过程中的多类错误;
- 修复补全详情出错时的崩溃;
- 为补全提供方增加
additionalTextEdits(自动导入)支持。
这些改动共同指向一个目标:让越来越多依赖语言服务器与扩展 API 的 VSCode 插件在 Onivim 2 中开箱即用。扩展宿主相关的实现集中在 src/Exthost 目录(消息传输、请求/响应编解码与扩展 API 桥接都在此),测试用例则位于 test/Exthost。
Vim 修复与 VimL 插件进展
公告特别强调,Vim 侧的工作重点是为 VimL 插件(如 vim-surround)铺路,这暴露了底层 libvim 的一系列缺陷并逐一修复。0.5.x 中值得关注的修复包括:
- 修复
:enew崩溃; - 状态栏增加宏录制指示器;
- 状态栏显示待处理的操作符(pending operator);
- 修复可视模式内部运动(
viw/vi")命令; - 修复退出插入模式后光标定位的抖动问题;
- 实现
getchar()处理器(VimL 插件支持的前提); - 接通
:messages与:messages clearEx 命令; - 为插入模式命令处理计数(count)。
公告同时注明:getchar()的按键显示功能当时仍有一个已知 bug(按键序列cs(}能正确执行,但按键可视化无法捕获),插件支持"尚未到生产可用阶段",属于持续前进中的工作。
0.6.0 路线图与月度发布策略
公告披露了 0.6.0 里程碑的目标清单与计划调整:
- 0.6.0 目标:VimL 插件集成、Snippet(代码片段)支持、Vim 代码折叠集成、Code Lens、Code Actions;
- 计划调整:原定 2020 年 12 月底的 0.6.0 被推迟,改为"完成即发布"(When It's Done),期间以 0.5.x 月度版本持续迭代;
- 优先级模型:0.6.0 之后,后续里程碑(0.7.0+)将依据社区投票最高的 issue 确定,日常开发则需要在里程碑目标、每日阻塞/崩溃、高票 issue、Vim 工作流、VSCode 扩展宿主工作流之间权衡。
对读者而言,这意味着 0.5.x 系列是通往完整插件生态的过渡版本,其每月的修复与基础设施(如自动更新、扩展宿主升级)都在为 0.6.0 铺路。完整的逐项变更记录可查阅仓库根目录的 CHANGES_CURRENT.md(对应发布时点的快照版本)。
总结
0.5.2 / 0.5.1 是一个典型的"体验完善型"月度版本:Vim 风格导航把键盘操作模型统一扩展到文件浏览器、搜索与符号大纲;自动换行与可定制行高补齐了编辑器排版的基础配置(对应editor.wordWrap/editor.lineHeight,并分别与:set wrap、:set linespace双向绑定);fzy 的引入从算法层面提升了 QuickOpen、命令面板与补全的匹配质量;ANGLE 与 Sparkle 则分别解决 Windows 渲染兼容与更新分发两个平台级问题。结合本仓库源码(EditorConfiguration.re、LineHeight.re、Filter.re、Feature_Explorer.re)可以确认,这些能力在代码中均有对应的配置定义、解码逻辑与调用链支撑,读者可按本文给出的键位与配置项直接上手验证。
- 开发工具
- 代码编辑器
- 桌面应用
【免费下载链接】oni2
Native, lightweight modal code editor
相关推荐
深度解析gh_mirrors/raft/raft:Go语言实现的Raft分布式共识协议完全指南
深度解析gh_mirrors/raft/raft:Go语言实现的Raft分布式共识协议完全指南 gh_mirrors/raft/raft是一个基于Go语言实现的
后端LogicFlow 节点体系与自定义节点开发:从内置基础图形到 model / view 双层定制
LogicFlow 节点体系与自定义节点开发:从内置基础图形到 model / view 双层定制 LogicFlow 是一款专注于业务自定义的流程图编辑框架,
物联网消息队列后端Grok Build 界面导航实战指南:掌握焦点切换、滚动回溯、面板与 Vim 模式的完整用法
Grok Build 界面导航实战指南:掌握焦点切换、滚动回溯、面板与 Vim 模式的完整用法 导读 Grok Build(本仓库 crates/codegen
人工智能大模型AI Agent代码智能体CLI工具调用MCP Clients
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考