- 开发工具
- 代码编辑器
- 桌面应用
【免费下载链接】oni2
Native, lightweight modal code editor
导读
本文是 vim-tips.md 的深度展开,面向从 Vim/Neovim 迁移到 Onivim 2 的开发者,系统讲解三个最常遇到的"水土不服"问题:如何让布局标签页恢复 Vim 的切换习惯、如何用experimental.viml复刻.vimrc、以及如何用 Onivim 2 的原生键位绑定配置执行 Ex 命令与 Vim 动作。读完本文你将掌握对应的配置项取值、默认值与底层实现原理,并能在configuration.json中直接落地使用。
一、让标签页像 Vim 一样工作:singleTabMode与layoutTabPosition
Onivim 2 的界面引入了"编辑器组(editor groups)"概念,每个组可以容纳多个编辑器并在顶部显示标签页(tabs),这与 Vim 默认"一个窗口只显示一个缓冲区、通过:buffer/gt切换"的心智模型不同。文档给出的第一个迁移诉求正是:"如何让 tabs 的行为像 Vim 一样?"
解决方案只需在configuration.json中加入两项设置:
{ "oni.layout.singleTabMode": true, "oni.layout.layoutTabPosition": "top" }配置项详解与默认值
这两个配置项的完整定义位于 src/Feature/Layout/Configuration.re:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
oni.layout.singleTabMode | bool | false | 为true时,每个编辑器组只容纳一个编辑器,关闭编辑器即关闭整个组,同时隐藏编辑器标签页,从而"几乎抹掉编辑器组的概念" |
oni.layout.layoutTabPosition | "top"/"bottom" | "bottom" | 控制布局标签页的位置,"top"时标签在上、编辑器在下(接近 Vim 的习惯视图) |
从源码看,layoutTabPosition使用自定义编解码器(Configuration.re#L30-L48)把字符串严格映射为\top或`bottom两个变体,解析到未知值时回退到bottom;singleTabMode则是标准布尔设置([Configuration.re#L61](https://link.gitcode.com/i/98c623f5c0bbe2a511722404c49c90f4#L61))。这两项与oni.layout.showLayoutTabs(取值"always" | "smart" | "off",默认"smart"`,即只有多个标签时才显示)共同构成了 Layout 功能模块的对外配置面(Configuration.re#L51-L59)。
底层实现:源码级印证
- 打开编辑器时的分流:在 Feature_Layout.re#L7-L12 的
openEditor中,当singleTabMode.get(config)为真时调用Group.replaceAllWith(editor),即新打开的编辑器直接替换组内全部内容;否则调用Group.openEditor(editor)追加为新标签。 - 标签页渲染的隐藏逻辑:在 View.re#L296 中,
showTabs && !singleTabMode才渲染编辑器的Tabs组件;标签栏整体仅在showLayoutTabs非off时出现。 - 标签位置的分支渲染:在 View.re#L639-L642,按
layoutTabPosition的值决定tabs与activeLayout的先后顺序——top时标签在上,bottom时编辑器在上。
由此可以推断:打开singleTabMode后,<C-w>系列窗口操作与:split仍然可用(它们作用于编辑器组本身),但同一组内不会再累积多个标签页,行为上更贴近 Vim 的"单窗口单缓冲区"直觉。
二、用experimental.viml复刻你的.vimrc
第二个高频诉求是"如何复刻我的 .vimrc?"。Onivim 2 通过experimental.viml设置在启动时执行一段 VimL 命令,从而把nnoremap、set等命令"搬"进 Onivim 2。
配置方式
按 settings.md 的说明,该配置接受字符串或字符串数组,默认值为[]:
{ "experimental.viml": ["nnoremap ; :", "set smartcase", "set ignorecase"] }等价于把每条字符串当作 VimL 逐行执行。文档中的经典示例"experimental.viml": ["nnoremap ; :"]可把;映射为进入命令行模式,找回 Vim 的输入习惯。
源码实现
在 Feature_Vim.re#L109-L110 中,该设置被声明为setting("experimental.viml", list(string), ~default=[]),并作为模型字段experimentalViml: list(string)保存(Feature_Vim.re#L21),随后通过Configuration.[experimentalViml.spec]注册进配置系统(Feature_Vim.re#L464),随编辑器启动加载一次。
集成测试佐证
仓库中的 VimExperimentalVimlTest.re 直接验证了这一机制:它把"experimental.viml": ["set smartcase", "set ignorecase", "echo 'hello-world'"]作为集成测试配置注入,随后断言:
- 初始模式为 Normal;
- 出现消息为
hello-world的通知; - 该通知只出现一次(对应 issue #3196 的回归测试,确保
experimental.viml命令不会被反复执行)。
类似的 VimL 映射行为还可参考 InputRemapMotionTest.re(通过nnoremap j h等命令做方向键重映射)与 VimlRemapCmdlineTest.re(nnoremap ö :)。
重要限制:为什么它叫 "experimental"
文档与源码都明确强调该机制的实验性边界:
- 命令支持面有限:很多 VimL 命令不生效,且官方目前没有一份"哪些支持、哪些不支持"的完整清单;
- 兼容性未全面测试:settings.md 的 Experimental 一节特别注明 VimL 的完整支持范围尚未经过系统测试,官方仍在推进 libvim 侧的测试用例,使用需自担风险;
- 未来会被替换:该机制最终将被一个支持更大、定义更明确的 VimL 子集的机制取代(对应 upstream issue #150)。
因此建议:把experimental.viml当作"启动期的一次性 VimL 注入"来用,优先放键位映射与简单的set选项;复杂的插件逻辑(Vimscript 函数、<Plug>映射等)不要依赖它。仓库中 VimScriptLocalFunctionTest.re 与 PlugScriptLocal.vim 展示了 Vimscript 本地函数与<Plug>映射在测试中的用法,可作为探索边界时的参考。
三、用原生键位绑定执行 Ex 命令与 Vim 动作
Onivim 2 的键位绑定文件与 VSCode 的 Key Bindings 高度兼容(详见 key-bindings.md),规则定义为 JSON 数组,位于键位绑定文件(而非configuration.json):
[ { "key": "<C-P>", "command": "workbench.action.quickOpen", "when": "editorTextFocus" } ]通过:前缀执行 Ex 命令
Vim 用户最关心的问题——"能否用原生键位配置绑定 Vim 的 motions 和命令"——文档给出了明确答案:
Ex 命令支持在 Normal 模式下把命令前加上
:前缀来绑定,就像在 Normal 模式下敲入该命令一样。
文档示例:
[ { "key": "kk", "command": ":split", "when": "editorTextFocus" }, { "key": "<C-D>", "command": ":d 2", "when": "insertMode" } ]逐条解读:
| 规则 | key | command | when | 效果 |
|---|---|---|---|---|
| 1 | kk(键序列) | :split | editorTextFocus | 连续按k、k执行水平分割,等价于 Normal 模式输入:split<CR> |
| 2 | <C-D> | :d 2 | insertMode | 插入模式下按Ctrl+D执行:d 2(删除当前行及其后 1 行,共 2 行) |
两个值得注意的细节:
command中写的是完整 Ex 命令文本(含参数),因此:d 2这类带计数的命令可以原样工作;绑定执行时等价于在命令行中输入并回车。when子句控制生效上下文,例如insertMode确保规则只在插入模式生效,避免与 Vim 的默认<C-D>(向下滚动半屏)冲突——这也是 Onivim 2 原生键位系统相对"盲目 remap"的优势。
键位格式与when上下文
为了让上面的示例可扩展,这里补充 key-bindings.md 的键位格式要点:
- Vim 风格:
<C-P>、<S-P>、<A-P>、<D-P>分别对应 Control、Shift、Alt、Command(Linux/Windows 上D-同时处理 Meta/Win 键),可组合如<C-S-P>; - 键序列:
"key": "jk"表示依次按下j、k; - VSCode 风格:
Ctrl+、Shift+、Alt+、Meta+/Cmd+/Win+同样受支持; when表达式:支持&&(与)、||(或)、!(非)与括号分组,例如(editorTextFocus && !insertMode) || suggestWidgetVisible;- 常用上下文:
editorTextFocus(编辑器聚焦)、insertMode(插入模式)、suggestWidgetVisible(补全浮窗可见)、terminalFocus(终端聚焦)等。
when表达式在引擎层由Oni2.core.whenExpr模块解析与求值,其语法树类型(Defined、Eq、Neq、Regex、And、Or、Not、Value)定义于 WhenExpr.rei,ContextKeys负责从编辑器状态模型中提取上下文键值。也就是说,所有when子句最终都由这一套统一表达式引擎计算,规则评估顺序为自底向上、首个完全匹配者胜出,用户自定义规则追加在底部、因而优先执行。
尚不支持的:Vim motions 的原生绑定
需要明确的是:目前没有为 Vim motions(如w、b、gg等移动命令)创建原生键位绑定的支持。如果你要重映射 motion,必须走 VimL 路线,即结合第二节的experimental.viml,例如:
{ "experimental.viml": [ "nnoremap j h", "nnoremap k j", "nnoremap ; :" ] }(第一、二条来自 InputRemapMotionTest.re 的测试映射,表示把j映射为h、把k映射为j。)这正是 Onivim 2 目前的分工:Ex 命令走原生键位(性能好、可配when),motion 重映射走 VimL(兼容 Vim 肌肉记忆)。
四、整合示例:一份面向 Vim 迁移者的配置
把以上三部分整合进configuration.json与键位绑定文件,可以得到一份可直接试用的迁移配置:
configuration.json:
{ "oni.layout.singleTabMode": true, "oni.layout.layoutTabPosition": "top", "experimental.viml": ["nnoremap ; :", "set smartcase", "set ignorecase"] }键位绑定文件:
[ { "key": "kk", "command": ":split", "when": "editorTextFocus" }, { "key": "<C-D>", "command": ":d 2", "when": "insertMode" }, { "key": "jk", "command": "vim.esc", "when": "insertMode" } ]其中jk键序列绑定vim.esc是 key-bindings.md 中演示的经典"插入模式逃生键",用来替代 Vim 里常见的:inoremap jk <ESC>。
五、总结与迁移路径建议
回到 vim-tips.md 的三个问题,迁移路径可以归纳为:
- 标签页行为:打开
oni.layout.singleTabMode(配合oni.layout.layoutTabPosition调整标签位置),即可获得接近 Vim 的"单编辑器组"体验;如需保留多标签但只在必要时显示,保持showLayoutTabs为默认的"smart"即可。 .vimrc复刻:把键位映射与set选项写入experimental.viml(字符串或数组),但要接受其实验性边界——命令支持面有限、无官方清单、未来会被更完善的 VimL 子集机制替代,复杂脚本不要依赖它。- Ex 命令绑定:使用原生键位配置,以
:前缀的 Ex 命令为command,配合when子句精确控制生效模式;motion 重映射暂不支持原生绑定,请走experimental.viml的 VimL 映射。
这套组合可以覆盖绝大多数 Vim 迁移者的日常操作习惯,同时保留 Onivim 2 原生渲染与 VSCode 风格扩展生态的优势。
延伸阅读:settings.md(全部配置项与默认值)、key-bindings.md(键位格式、remap、leader key 与when上下文全集)、modal-editing-101.md(模式编辑基础)。
- 开发工具
- 代码编辑器
- 桌面应用
【免费下载链接】oni2
Native, lightweight modal code editor
相关推荐
终极指南:如何将小爱音箱改造成你的专属AI语音助手
终极指南:如何将小爱音箱改造成你的专属AI语音助手 想让家中的小爱音箱真正听懂你的需求,从"人工智障"升级为"智能学霸"吗?MiGPT项目为你提供了完美解决方案
人工智能AI 应用语音智能家居交互助手猫抓插件快速上手:浏览器资源嗅探与网页视频下载指南
猫抓插件快速上手:浏览器资源嗅探与网页视频下载指南 做运营的小周要剪一段官网首页的宣传片片段,可网页播放器上找不到"另存为",右键被禁用,F12 里翻半天只看到
音视频终极Alacritty终端键位绑定迁移指南:从入门到精通的完整方案
终极Alacritty终端键位绑定迁移指南:从入门到精通的完整方案 Alacritty是一款跨平台的OpenGL终端模拟器,以其极致性能和高度可定制性深受开发者
桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考