Zed 内置 Vim 模式实战指南:从模式设计、命令映射到 Zed 原生扩展与配置调优
Zed 并不是简单地做“键位仿真”,而是把 Vim 的模态操作模型嫁接到自身基于 Tree-sitter、语言服务器与多光标的高性能编辑内核上。这篇指南以 Zed 官方 Vim 模式文档为主线(仓库 docs/src/vim.md),完整覆盖模式的启用/关闭、motion 与 text object 快捷键、: 命令面板、AnyQuotes/AnyBrackets 文本对象、键位上下文定制与全部相关设置项,并结合 crates 源码给出实现层证据。读完你可以在 Zed 中真正配置出一套既保留 Vim 肌肉记忆、又能享用语义导航、多光标、内联 AI 等 Zed 原生能力的日常编辑环境。
Zed vim mode 的设计理念
Vim 模式的目标是“在合理之处复刻 Vim 的 motions 与命令行为,在 Zed 更强的地方使用 Zed 自己的实现”,力求开箱即用、无需配置即可获得熟悉的体验。它并非 Vim 的一比一克隆,而是把 Vim 的模态设计与 Zed 的现代能力融合,并保持高度可配置(可以添加自己的键位或覆盖默认值)。
Zed 官方文档将 vim mode 中复用 Zed 核心功能、从而在行为上产生差异的特性归纳为四类:
- Motions(动作):vim mode 使用 Zed 的语义解析按语言微调 motion 行为。例如在 Rust 中,用
%跳转匹配括号时也能与管道符|配对;在 JavaScript 中,w会把$当作单词字符。 - Visual block 选择:vim mode 用 Zed 的多光标来模拟块选择,这让块选择灵活得多。例如块选择后输入的任何内容都会实时同步到每一行,并且你可以随时增删光标。
- Macros(宏):vim mode 用 Zed 的录制系统承载 Vim 宏,因此可以录制与回放更复杂的操作,例如自动补全。
- Search 与 replace:vim mode 复用 Zed 的搜索系统,因此正则语法与 Vim 略有差异,详见下文 正则差异 一节。
从源码结构看,这套体系在 crates/vim/src/ 中按职责拆分为多个模块:motion.rs(动作)、object.rs(文本对象)、visual.rs(可视模式)、normal.rs / insert.rs / replace.rs(各模式)、surrounds.rs(包围与去包围)、command.rs(Ex 命令解析与 :set 选项)、digraph.rs(二合字 digraph)、rewrap.rs 与 indent.rs,另有 helix.rs 提供 Helix 风格的模式支持,可以顺着这些文件深入阅读各功能的实现细节。
启用与禁用 vim mode
首次启动 Zed 时,欢迎屏上会有一个复选框让你选择是否启用 vim mode。如果错过了这一步,随时可以通过命令面板执行工作区命令 workspace::ToggleVimMode 来开关该模式。
注意:该命令实际切换的是用户设置中的如下属性:
{ "vim_mode": true }
对应地,在 assets/settings/default.json 中该值默认为 false。设置项的读取逻辑独立成 crate:crates/vim_mode_setting/src/vim_mode_setting.rs 中定义了 VimModeSetting 与 HelixModeSetting 两个 bool 型设置,其注释说明将其独立拆分,是为了让其他 crate 在不整体依赖 vim crate 的前提下也能开关 Vim/Helix 模式。
Zed 专属功能
Zed 构建在现代基础之上:使用 Tree-sitter 与语言服务器理解正在编辑的文件内容,并原生支持多光标。Vim 模式为此内置了一批 “core Zed” 键位,帮助你最大化利用 Zed 的独有能力。平台间键位略有差异,仓库中存放了 default-linux.json、default-macos.json 与 default-windows.json 三份默认键位表,下面各表以文档原文为准。
语言服务器(Language server)
以下命令借助语言服务器完成代码跳转与重构,默认快捷键:
| Command | Default Shortcut |
|---|---|
| Go to definition | g d |
| Go to declaration | g D |
| Go to type definition | g y |
| Go to implementation | g I |
| Rename (change definition) | c d |
| Go to All references to the current word | g A |
| Find symbol in current file | g s |
| Find symbol in entire project | g S |
| Go to next diagnostic | g ] 或 ] d |
| Go to previous diagnostic | g [ 或 [ d |
| Show inline error (hover) | g h |
| Open the code actions menu | g . |
Git
| Command | Default Shortcut |
|---|---|
| Go to next git change | ] c |
| Go to previous git change | [ c |
| Expand diff hunk | d o |
| Toggle staged | d O |
| Stage and next (in diff view) | d u |
| Unstage and next (in diff view) | d U |
| Restore change | d p |
Tree-sitter
Tree-sitter 是 Zed 用来理解代码结构的解析器。Zed 提供了两类基于语法树的能力:改变光标位置的 motions,以及可作为操作目标的 text objects。
| Command | Default Shortcut |
|---|---|
| Go to next/previous method | ] m / [ m |
| Go to next/previous method end | ] M / [ M |
| Go to next/previous section | ] ] / [ [ |
| Go to next/previous section end | ] [ / [ ] |
| Go to next/previous comment | ] /, ] * / [ /, [ * |
| Select a larger syntax node | [ x |
| Select a smaller syntax node | ] x |
| Text Objects | Default Shortcut |
|---|---|
| Around a class, definition, etc. | a c |
| Inside a class, definition, etc. | i c |
| Around a function, method etc. | a f |
| Inside a function, method, etc. | i f |
| A comment | g c |
| An argument, or list item, etc. | i a |
| An argument, or list item, etc. (including trailing comma) | a a |
| Around an HTML-like tag | a t |
| Inside an HTML-like tag | i t |
| The current indent level, and one line before and after | a I |
| The current indent level, and one line before | a i |
| The current indent level | i i |
需要说明的是各 motion/text object 目标的一致性:[m 系列 motion 的目标定义与 af 的边界一致;[[ 系列的目标与 ac 相同,且在没有类时退而使用函数;gc 用于定位 [ / 与 g c 对应的注释。函数、类、注释的“边界定义”是语言相关的,扩展可通过添加 textobjects.scm 查询文件来补充支持(例如 crates/grammars/src/c/textobjects.scm、crates/grammars/src/go/textobjects.scm 等都是这类查询文件)。而参数与标签的定义运行在 Tree-sitter 层面、按解析树中的特定模式匹配,目前不支持按语言配置。
多光标(Multi cursor)
以下命令用于管理 Zed 中的多个光标:
| Command | Default Shortcut |
|---|---|
| Add a cursor selecting the next copy of the current word | g l |
| Add a cursor selecting the previous copy of the current word | g L |
| Add a cursor at the end of every line in the current visual selection | g A |
| Add a cursor at the first character of every line in the current visual selection | g I |
| Add a visual selection for every copy of the current word | g a |
| Skip latest word selection, and add next | g > |
| Skip latest word selection, and add previous | g < |
面板管理(Pane management)
| Command | Default Shortcut |
|---|---|
| Open a project-wide search | g / |
| Open the current search excerpt | g <space> |
| Open the current search excerpt in a split | <ctrl-w> <space> |
| Go to definition in a split | <ctrl-w> g d |
| Go to type definition in a split | <ctrl-w> g D |
插入模式(In insert mode)
以下命令让你无需退出插入模式即可唤起 Zed 的补全菜单、向 GitHub Copilot 请求建议,或打开内联 AI 助手:
| Command | Default Shortcut |
|---|---|
| Open the completion menu | ctrl-x ctrl-o |
| Request GitHub Copilot suggestion (requires GitHub Copilot to be configured) | ctrl-x ctrl-c |
| Open the inline AI assistant (requires a configured assistant) | ctrl-x ctrl-a |
| Open the code actions menu | ctrl-x ctrl-l |
| Hides all suggestions | ctrl-x ctrl-z |
内置插件功能(Supported plugins)
Zed 的 vim mode 直接内置了 Vim 生态中常由插件提供的功能:
- 用
ys(yank surround)给文本对象加包围、cs改包围、ds删包围; - 可视模式下用
gc、普通模式下用gcc注释/取消注释选区; - 项目面板支持大量仿照 Vim 插件 netrw 的快捷键:用
hjkl导航、o打开文件、t在新标签页打开文件等; - 可以自行添加键位在
camelCase名称内按“子词”导航,见下文可选键位绑定; - 用
gR实现 ReplaceWithRegister 式功能; - 用
cx实现 vim-exchange 式功能(注意可视模式默认无绑定,可在可选键位绑定中自行添加); - 用
[-、]-、[+、]+、[=、]=相对光标进行 indent-wise 式导航; - 用 AnyQuotes/AnyBrackets 选中引号/括号文本,并额外提供基于 Neovim mini.ai 插件的 MiniQuotes/MiniBrackets 备选选择策略,详见下节。
这些绑定的默认实现都体现在默认键位表 assets/keymaps/vim.json 中,可作为对照自定义的起点。
Any Bracket 功能:引号与括号文本对象的两种策略
Zed 提供两种选中被引号/括号包围文本的策略。这些文本对象默认不启用,需要在 keymap 中配置后才可用。
支持的字符集
每种文本对象作用于固定字符:
| Text Object | Characters |
|---|---|
| AnyQuotes/MiniQuotes | 单引号(')、双引号(")、反引号(`) |
| AnyBrackets/MiniBrackets | 圆括号(())、方括号([])、花括号({})、尖括号(<>) |
“Any”与“Mini”两种变体作用于相同字符集,区别在于选择策略。
AnyQuotes / AnyBrackets:传统 Vim 行为
- 选择优先级:优先找到最内层(最近的)引号或括号;
- 回退机制:如果找不到则回退到当前行;
- 基于字符匹配:只关注开/闭字符本身,不考虑语法语义;
- 贴近原版 Vim:AnyBrackets 与原版 Vim 中
ci<、ci(等命令行为一致,包括一些边界情形(例如把=>中的>视为闭括号)。
MiniQuotes / MiniBrackets:mini.ai 行为
- 选择优先级:先搜索当前行,再向外扩展;
- Tree-sitter 集成:使用 Tree-sitter 查询实现更上下文相关的选区;
- 语法感知匹配:能区分真正的括号与类似字符的其他语境(例如
=>中的>)。
如何选择
- 若你偏好传统 Vim 行为、想要“优先最内层分隔符”的稳定字符级选择、需要与原版 Vim 文本对象行为高度一致,选 AnyQuotes/AnyBrackets;
- 若你偏好 mini.ai 插件行为、想要基于 Tree-sitter 的更上下文相关的选择、搜索时优先当前行,选 MiniQuotes/MiniBrackets。
配置示例
使用这些文本对象需要向 keymap 添加绑定。下面示例让它们在文本对象操作符(i 与 a)或改包围(cs)语境下可用:
{
"context": "vim_operator == a || vim_operator == i || vim_operator == cs",
"bindings": {
// Traditional Vim behavior
"q": "vim::AnyQuotes",
"b": "vim::AnyBrackets",
// mini.ai plugin behavior
"Q": "vim::MiniQuotes",
"B": "vim::MiniBrackets"
}
}
配置完成后即可使用类似命令:
cib- 用 AnyBrackets 行为修改括号内内容ciB- 用 MiniBrackets 行为修改括号内内容ciq- 用 AnyQuotes 行为修改引号内内容ciQ- 用 MiniQuotes 行为修改引号内内容
对照默认键位表 assets/keymaps/vim.json 可以看到:在 vim_operator 语境下,默认把 q 绑到了 vim::MiniQuotes,而 AnyQuotes、AnyBrackets、MiniBrackets 等均以注释形式保留,说明这正是文档所述“默认不启用、需自行配置”的能力入口,直接编辑你的用户 keymap 覆盖即可。
命令面板(: 命令)
Vim 模式允许你用 : 打开 Zed 的命令面板,随后输入任意常规 Zed 命令;同时为流行的 Vim 命令提供别名,保证肌肉记忆可以迁移。例如输入 :w 或 :write 都可以保存文件。
以下表格列出可在命令面板使用的命令,方括号内为可省略的字符。
注意:目前并不完整模拟 Vim 命令行的全部能力,命令暂不支持参数。官方欢迎用户在缺少所需功能时提交 issue 反馈。
文件与窗口管理
因为命令暂不支持参数,保存或新建文件时无法指定文件名。
| Command | Description |
|---|---|
:w[rite][!] |
Save the current file |
:wq[!] |
Save the file and close the buffer |
:q[uit][!] |
Close the buffer |
:wa[ll][!] |
Save all open files |
:wqa[ll][!] |
Save all open files and close all buffers |
:qa[ll][!] |
Close all buffers |
:[e]x[it][!] |
Close the buffer |
:up[date] |
Save the current file |
:cq |
Quit completely (close all running instances of Zed) |
:bd[elete][!] |
Close the active file in all panes |
:vs[plit] |
Split the pane vertically |
:sp[lit] |
Split the pane horizontally |
:new |
Create a new file in a horizontal split |
:vne[w] |
Create a new file in a vertical split |
:tabedit |
Create a new file in a new tab |
:tabnew |
Create a new file in a new tab |
:tabn[ext] |
Go to the next tab |
:tabp[rev] |
Go to previous tab |
:tabc[lose] |
Close the current tab |
:ls |
Show all buffers |
注意:
!用于强制执行命令,即不保存更改即执行、或在覆盖文件前不提示。
Ex 命令
这些命令打开 Zed 的各类面板与窗口:
| Command | Default Shortcut |
|---|---|
| Open the project panel | :E[xplore] |
| Open the collaboration panel | :C[ollab] |
| Open the chat panel | :Ch[at] |
| Open the AI panel | :A[I] |
| Open the git panel | :G[it] |
| Open the debug panel | :D[ebug] |
| Open the notifications panel | :No[tif] |
| Open the feedback window | :fe[edback] |
| Open the diagnostics window | :cl[ist] |
| Open the terminal | :te[rm] |
| Open the extensions window | :Ext[ensions] |
诊断导航
| Command | Description |
|---|---|
:cn[ext] or :ln[ext] |
Go to the next diagnostic |
:cp[rev] or :lp[rev] |
Go to the previous diagnostic |
:cc or :ll |
Open the errors page |
Git
| Command | Description |
|---|---|
:dif[fupdate] |
View the diff under the cursor (d o in normal mode) |
:rev[ert] |
Revert the diff under the cursor (d p in normal mode) |
跳转
| Command | Description |
|---|---|
:<number> |
Jump to a line number |
:$ |
Jump to the end of the file |
:/foo and :?foo |
Jump to next/prev line matching foo |
替换
该命令模拟 Vim 的 substitute 命令。它使用正则表达式,而 Zed 的语法与 Vim 略有不同(详见下文正则差异)。Zed 默认只替换当前行搜索模式的首个匹配;要替换全部匹配需追加 g 标志。
| Command | Description |
|---|---|
:[range]s/foo/bar/[g] |
Replace instances of foo with bar |
编辑
| Command | Description |
|---|---|
:j[oin] |
Join the current line |
:d[elete][l][p] |
Delete the current line |
:s[ort] [i] |
Sort the current selection (with i, case-insensitively) |
:y[ank] |
Yank (copy) the current selection or line |
Set
以下命令针对当前 buffer 局部修改编辑器选项:
| Command | Description |
|---|---|
:se[t] [no]wrap |
Lines longer than the width of the window will wrap and displaying continues on the next line |
:se[t] [no]nu[mber] |
Print the line number in front of each line |
:se[t] [no]r[elative]nu[mber] |
Changes the displayed number to be relative to the cursor |
:se[t] [no]i[gnore]c[ase] |
Controls whether the buffer and project search use case-sensitive matching |
从源码看,Ex 命令的解析集中在 crates/vim/src/command.rs:例如 gdefault/nogdefault 在 command.rs 中被解析为 VimOption::GDefault,并在执行时写回全局设置(command.rs);而在 crates/vim/src/normal/search.rs 的替换逻辑中,gdefault 会反转 g 标志的含义,其行为由测试用例 test_replace_gdefault(search.rs)对照 Neovim 行为验证:开启 gdefault 后 :s/// 默认替换全部匹配,而加 g 反而只替换首个匹配。
命令助记符(Command mnemonics)
Zed 默认不预置任何命令助记符,但你可以在设置文件的 command_aliases 字段定义指向 Zed 命令的短别名。在命令面板输入该映射中的别名时,会自动解析为对应命令。
配置示例
{
"command_aliases": {
"zlog": "zed::OpenLog",
"newf": "workspace::NewFile",
"diffs": "editor::ToggleSelectedDiffHunks",
"crp": "workspace::CopyRelativePath",
"cpp": "workspace::CopyPath",
"reveal": "editor::RevealInFileManager",
"clank": "editor::CancelLanguageServerWork"
}
}
配置后即可使用:
:zlog- 打开 Zed 日志:newf- 新建文件:diffs- 切换选中 diff hunk:crp- 复制当前文件相对路径:cpp- 复制当前文件完整路径:reveal- 在文件管理器中显示当前文件:clank- 取消语言服务器工作
自定义键位绑定
选择正确的 context
Zed 的键位只有在 "context" 属性与编辑器中当前位置匹配时才生效。例如把键位放进 "Editor" context,只在编辑文件时生效;放进 "Workspace" context,则在 Zed 任意位置都生效。示例——编辑文件时保存:
{
"context": "Editor",
"bindings": {
"ctrl-s": "workspace::Save"
}
}
Context 是嵌套的:编辑文件时你处于 "Editor" context,它位于 "Pane" context 之内,而 "Pane" 又在 "Workspace" context 之内。因此放在 "Workspace" 的键位在编辑文件时同样生效。示例(该绑定是 Zed 内置默认 workspace 保存命令,仅供说明):
// This key binding will work when you're editing a file. It comes built into Zed by default as the workspace: save command.
{
"context": "Workspace",
"bindings": {
"ctrl-s": "workspace::Save"
}
}
Context 本质是表达式,支持 &&(与)与 ||(或)布尔运算符。例如用 "Editor && vim_mode == normal" 让键位只在编辑文件且处于 vim 普通模式时生效。
Vim 模式向 "Editor" context 添加了以下子 context:
| Operator | Description |
|---|---|
| VimControl | Indicates that vim keybindings should work. Currently an alias for vim_mode == normal || vim_mode == visual || vim_mode == operator, but the definition may change over time |
| vim_mode == normal | Normal mode |
| vim_mode == visual | Visual mode |
| vim_mode == insert | Insert mode |
| vim_mode == replace | Replace mode |
| vim_mode == waiting | Waiting for an arbitrary key (e.g., after typing f or t) |
| vim_mode == operator | Waiting for another binding to trigger (e.g., after typing c or d) |
| vim_operator | Set to none unless vim_mode == operator, in which case it is set to the current operator's default keybinding (e.g., after typing d, vim_operator == d) |
| helix_mode | Set when the current mode is a Helix mode (helix_normal or helix_select), including while an operator is pending and vim_mode reports operator or waiting |
注意:Context 每次只在一层上匹配。因此
"Editor && vim_mode == normal"是可行的,而"Workspace && vim_mode == normal"永远不会匹配,因为 vim context 是在"Editor"层设置的。
常用 vim context 模板
下面的模板覆盖了常用的 vim context,可直接复制整合进你的用户 keymap:
[
{
"context": "VimControl && !menu",
"bindings": {
// Put key bindings here if you want them to work in normal & visual mode.
}
},
{
"context": "vim_mode == normal && !menu",
"bindings": {
// "shift-y": ["workspace::SendKeystrokes", "y $"] // Use neovim's yank behavior: yank to end of line.
}
},
{
"context": "vim_mode == insert",
"bindings": {
// "j k": "vim::NormalBefore" // In insert mode, make jk escape to normal mode.
}
},
{
"context": "EmptyPane || SharedScreen",
"bindings": {
// Put key bindings here (in addition to the context above) if you want them to
// work when no editor exists.
// "space f": "file_finder::Toggle"
}
}
]
注意:如需模拟 Vim 的
map类命令(nmap等),可以在正确 context 下使用workspace::SendKeystrokes动作实现。
可选键位绑定
跨 dock 导航:默认你只能用 ctrl+w 加 hjkl 在编辑器各面板(pane)之间移动,但这些快捷键不适用于终端、项目面板、agent 面板等 dock。若想让同样的快捷键作用于 dock,把下面键位加入用户 keymap:
{
"context": "Dock",
"bindings": {
"ctrl-w h": "workspace::ActivatePaneLeft",
"ctrl-w l": "workspace::ActivatePaneRight",
"ctrl-w k": "workspace::ActivatePaneUp",
"ctrl-w j": "workspace::ActivatePaneDown"
// ... or other keybindings
}
}
子词导航(Subword motion):默认不启用,它允许在 camelCase 或 snake_case 内按单词导航和选择。启用方式:
{
"context": "VimControl && !menu && vim_mode != operator",
"bindings": {
"w": "vim::NextSubwordStart",
"b": "vim::PreviousSubwordStart",
"e": "vim::NextSubwordEnd",
"g e": "vim::PreviousSubwordEnd"
}
}
注意:
dw等操作不受影响。如果希望操作也使用子词 motion,请把 context 中的vim_mode != operator去掉。
对照默认键位表 assets/keymaps/vim.json 可见,这些子词 motion 绑定在默认配置中同样以注释形式存在,静待启用。
可视模式包围:vim mode 在普通模式下用 ys 添加包围,但没有可视模式下的添加包围快捷键。默认 shift-s 是替换选区(删除文本并进入插入模式)。若想在可视模式下用 shift-s 添加包围:
{
"context": "vim_mode == visual",
"bindings": {
"shift-s": "vim::PushAddSurrounds"
}
}
光标行尾回绕(whichwrap):非模态编辑器通常在越过行尾时光标自动回绕,而 Zed 与 Vim 一致,默认让光标停在各行边界。若希望回绕,覆盖以下键位(等价于 VimScript 的 set whichwrap+=<,>,[,],h,l):
// In VimScript, this would look like this:
// set whichwrap+=<,>,[,],h,l
{
"context": "VimControl && !menu",
"bindings": {
"left": "vim::WrappingLeft",
"right": "vim::WrappingRight",
"h": "vim::WrappingLeft",
"l": "vim::WrappingRight"
}
}
Sneak 快速跳转:可跳转到文本中任意两字符序列。默认 s 映射为 vim::Substitute,添加以下绑定会覆盖它,请确认符合你的工作流:
{
"context": "vim_mode == normal || vim_mode == visual",
"bindings": {
"s": "vim::PushSneak",
"shift-s": "vim::PushSneakBackward"
}
}
Helix 风格跳词标签:在可见的单词开头显示跳转标签。vim 模式默认无绑定,示例使用 g w(与 Helix 默认绑定一致,但会覆盖 vim 默认的 rewrap 绑定):
{
"context": "vim_mode == normal || vim_mode == visual",
"bindings": {
"g w": "vim::HelixJumpToWord"
}
}
vim-exchange 可视模式绑定:因 shift-x 与可视模式默认的 vim::VisualDeleteLine 冲突,需要时手动绑定:
{
"context": "vim_mode == visual",
"bindings": {
"shift-x": "vim::Exchange"
}
}
恢复常用文本编辑与 Zed 键位
在 Linux 或 Windows 上使用 vim 模式时,可能会发现它覆盖了你离不开的快捷键:ctrl+v 粘贴、ctrl+f 搜索等。把下面的数据复制进 keymap 即可恢复:
{
"context": "Editor && !menu",
"bindings": {
"ctrl-f": "buffer_search::Deploy", // vim default: page down
"ctrl-c": "editor::Copy", // vim default: return to normal mode
"ctrl-x": "editor::Cut", // vim default: decrement
"ctrl-v": "editor::Paste", // vim default: visual block mode
"ctrl-a": "editor::SelectAll", // vim default: increment
"ctrl-y": "editor::Undo", // vim default: line up
"ctrl-t": "project_symbols::Toggle", // vim default: go to older tag
"ctrl-o": "workspace::Open", // vim default: go back
"ctrl-s": "workspace::Save", // vim default: show signature
"ctrl-b": "workspace::ToggleLeftDock" // vim default: down
}
},
修改 vim 模式设置
以下是可改变 vim 模式行为的设置项:
| Property | Description | Default Value |
|---|---|---|
| default_mode | The default mode to start in. One of "normal", "insert", "replace", "visual", "visual_line", "visual_block", "helix_normal". | "normal" |
| use_system_clipboard | Determines how system clipboard is used:
|
"always" |
| use_multiline_find | deprecated | |
| use_smartcase_find | If true, f and t motions are case-insensitive when the target letter is lowercase. |
false |
| use_regex_search | If true, then vim search will use regex mode |
true |
| gdefault | If true, the :substitute command replaces all matches in a line by default (as if g flag was given). The g flag then toggles this, replacing only the first match. |
false |
| toggle_relative_line_numbers | If true, line numbers are relative in normal mode and absolute in insert mode, giving you the best of both options. |
false |
| custom_digraphs | An object that allows you to add custom digraphs. Read below for an example. | {} |
| highlight_on_yank_duration | The duration of the highlight animation(in ms). Set to 0 to disable |
200 |
添加一个“僵尸 emoji”二合字的示例——之后输入 ctrl-k f z 即可插入一个僵尸 emoji,可按需添加任意多个:
{
"vim": {
"custom_digraphs": {
"fz": "🧟♀️"
}
}
}
把这些设置组合使用的完整示例:
{
"vim": {
"default_mode": "insert",
"use_system_clipboard": "never",
"use_smartcase_find": true,
"use_regex_search": true,
"gdefault": true,
"toggle_relative_line_numbers": true,
"highlight_on_yank_duration": 50,
"custom_digraphs": {
"fz": "🧟♀️"
}
}
}
从源码看,上述设置项的 schema 定义在 crates/settings_content/src/settings_content.rs 的 VimSettingsContent(含 gdefault 的语义注释、cursor_shape、show_edit_predictions_in_normal_mode 等),取值类型如 ModeContent(normal/insert,见 settings_content.rs)与 UseSystemClipboard(never/always/on_yank,见 settings_content.rs)。它们最终汇入 crates/vim/src/vim.rs 中标记 RegisterSetting 的 VimSettings 结构体,并在 vim.rs 的 Settings trait 实现里统一 unwrap() 为具体运行时值;assets/settings/default.json 中 vim 配置段 给出了与上表一致的默认值。关键行为都有对应源码落点,例如:yank 高亮时长在 crates/vim/src/normal/yank.rs 中读取并决定高亮动画;剪贴板策略在 crates/vim/src/state.rs 与 crates/vim/src/state.rs 中被查询,用于决定是否写系统剪贴板;digraph 在 crates/vim/src/digraph.rs 中先查用户自定义映射再查内置表,其测试用例(digraph.rs)也直接演示了插入自定义 digraph 的写法。
对 vim 模式有用的核心 Zed 设置
以下通用 Zed 设置能帮你进一步打磨 Vim 体验:
| Property | Description | Default Value |
|---|---|---|
| cursor_blink | If true, the cursor blinks. |
true |
| relative_line_numbers | If "enabled", line numbers in the left gutter are relative to the cursor. If "wrapped", they also display for wrapped lines. |
"disabled" |
| scrollbar | Object that controls the scrollbar display. Set to { "show": "never" } to hide the scroll bar. |
{ "show": "auto" } |
| scroll_beyond_last_line | If set to "one_page", allows scrolling up to one page beyond the last line. Set to "off" to prevent this behavior. |
"one_page" |
| vertical_scroll_margin | The number of lines to keep above or below the cursor when scrolling. Set to 0 to allow the cursor to go up to the edges of the screen vertically. |
3 |
| gutter.line_numbers | Controls the display of line numbers in the gutter. Set the "line_numbers" property to false to hide line numbers. |
true |
| command_aliases | Object that defines aliases for commands in the command palette. You can use it to define shortcut names for commands you use often. Read below for examples. | {} |
综合调整示例:
{
// Disable cursor blink
"cursor_blink": false,
// Use relative line numbers
"relative_line_numbers": "enabled",
// Hide the scroll bar
"scrollbar": { "show": "never" },
// Prevent the buffer from scrolling beyond the last line
"scroll_beyond_last_line": "off",
// Allow the cursor to reach the edges of the screen
"vertical_scroll_margin": 0,
"gutter": {
// Disable line numbers completely
"line_numbers": false
},
"command_aliases": {
"W": "w",
"Wq": "wq",
"Q": "q"
}
}
command_aliases 是一个把键或键序列映射到 vim 模式命令的对象。上例定义了多个别名:W 对应 w、Wq 对应 wq、Q 对应 q。它与普通 Zed 设置(如 assets/settings/default.json)平级存放,用户在用户设置文件中覆盖即可。
另外,vim 模式还支持各模式独立光标形状(vim.cursor_shape,含 normal/replace/visual/insert,值可为 block、bar、underline、hollow,插入模式还可设 inherit 继承编辑器主光标),以及控制普通模式下是否显示 edit predictions 的 show_edit_predictions_in_normal_mode,这两项同样定义在 settings_content.rs 与 default.json 中,属于文档默认配置之外值得了解的高级选项。
正则差异(Regex differences)
Zed 使用与 Vim 不同的正则引擎,因此部分场景需要换用不同的语法。最常见的差异如下:
- 捕获组:Vim 用
\(与\)表示捕获组,Zed 中为(与)。反过来,Vim 中(与)表示字面括号,Zed 中必须转义为\(与\)。 - 匹配引用:替换时 Vim 用反斜杠加数字表示已匹配的捕获组(如
\1),Zed 用美元符:Vim 中\0表示整个匹配,Zed 里是$0;编号捕获组同理,Vim 的\1对应 Zed 的$1。 - 全局选项:Vim 默认只匹配每行首个出现、在末尾加
/g找全部;Zed 中正则搜索默认全局。 - 大小写敏感:Vim 用
/i表示不区分大小写搜索;Zed 中可在模式开头写(?i),或用快捷键search::ToggleCaseSensitive切换大小写敏感。
注意:为帮助过渡,当你编写 Vim 风格替换命令
:%s//时,命令面板会替你修复括号与替换组。例如 Zed 会把%s:/\(a\)(b)/\1/转换为搜索 "(a)(b)"、替换为 "$1"。
Zed 正则引擎的完整语法以 Rust regex crate 支持为准(对应 Cargo.lock 中所锁定版本的 regex 依赖),其替换语义($1、$0 等)也直接体现在 crates/vim/src/normal/search.rs 的 substitute 实现中。
小结
Zed 的 vim 模式是一套“语义化”而非“键位化”的模态编辑实现:%、w 等 motion 感知语言结构,visual block 建立于实时多光标之上,宏可以录制补全等复合操作,gc/af 等文本对象由 Tree-sitter 查询驱动,而语言服务器、Git 与内联 AI 也被映射成顺手的 vim 风格快捷键。配合 vim_* 系列 context 表达式、command_aliases、Any/Mini 系列引号括号文本对象与 vim 设置段,几乎每个行为都可按需覆盖。若想深入了解实现,建议从 crates/vim/src 入手,尤其关注 vim.rs(模式状态与设置装配)、normal/search.rs(查找替换)、object.rs(文本对象)与 visual.rs(可视模式),再对照 assets/keymaps/vim.json 理解默认键位的组织方式。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00