Vim 模式
Zed 包含稱為「vim 模式」的 vim 模擬層。此文件旨在說明其運作方式,以及如何充分利用它。
理念
Zed 中的 Vim 模式應該主要是「做你預期的事」:它大多試圖完全複製 vim,但在可用的時候將使用 Zed 特定功能來使事情更順暢。
這表示 Zed 永遠不會 100% 相容於 Vim,但應該是 100% 熟悉 Vim!我們預期我們的 Vim 模式已經應付您 90% 的工作流程,而且我們希望能繼續加以改進。如果您發現自己在 Vim 模式中尚無法執行的事項,但您的現有工作流程依賴這些事項,請提出問題。
Zed 特定功能
Zed 建構於一個現代化的基礎之上,其中(除其他事項外)使用 tree-sitter 和語言伺服器來了解您正在編輯的檔案內容,並支援多個游標。
Vim 模式有幾個「Zed 核心」快捷鍵將有助於您充分利用 Zed 的特定功能組。
# Language server
g d Go to definition
g D Go to type definition
g cmd-d Go to implementation
c d Rename (change definition)
g A Go to All references to the current word
g s Find symbol in current file
g S Find symbol in entire project
g ] Go to next diagnostic
g [ Go to previous diagnostic
] d Go to next diagnostic
[ d Go to previous diagnostic
g h Show inline error (hover)
g . Open the code actions menu
# Git
] c Go to next git change
[ c Go to previous git change
# Treesitter
] x Select a smaller syntax node
[ x Select a larger syntax node
# Multi cursor
g l Add a visual selection for the next copy of the current word
g L The same, but backwards
g > Skip latest word selection, and add next.
g < The same, but backwards
g a Add a visual selection for every copy of the current word
# Pane management
g / Open a project-wide search
g <space> Open the current search excerpt
<ctrl-w> <space> Open the current search excerpt in a split
<ctrl-w> g d Go to definition in a split
<ctrl-w> g D Go to type definition in a split
# Insert mode
i a / a a Select the function argument the cursor is in
ctrl-x ctrl-o Open the completion menu
ctrl-x ctrl-c Request GitHub Copilot suggestion (if configured)
ctrl-x ctrl-a Open the inline AI assistant (if configured)
ctrl-x ctrl-l Open the code actions menu
ctrl-x ctrl-z Hides all suggestions
# Ex commands
:E[xplore] Open the project panel
:C[ollab] Open the collaboration panel
:Ch[at] Open the chat panel
:A[I] Open the AI panel
:No[tif] Open the notifications panel
:fe[edback] Open the feedback window
:cl[ist] Open the diagnostics window
:te[rm] Open the terminal
:Ext[ensions] Open the extensions window
Vim 模式使用 Zed 來定義概念,例如「括號」(適用於 %
鍵)和「字詞」(適用於動作,例如 w
和 e
)。這確實會產生一些差異,但這些差異大多是正面的。例如,在 Rust 等語言中,%
將 |
視為括號;在 Javascript 等語言中,w
將 $
視為字詞字元。
Vim 模式使用 Zed 的多重游標支援模擬視覺化區塊模式。這再次導致了一些差異,但功能強大得多。
Vim 巨集支援(q
及 @
)是使用 Zed 動作實作。這讓我們能夠支援自動完成碼的錄製及重播等。跟 Vim 不同,Zed 沒有重複使用 yank 暫存器來錄製巨集,而是使用兩個不同的名稱空間。
最後,Vim 模式的搜尋和替換功能是由 Zed 的功能做為後盾。這表示模式語法會稍微不同,詳情請參閱 正規表示式差異 段落。
自訂按鍵繫結
您可以使用 :keymap
編輯個人的按鍵繫結。對於特定於 vim 的捷徑,您可能會發現下列範本是很好的起點。
注意:我們在 Zed 版本
0.145.0
中進行了一些重大的變更。對於舊有的版本,請參閱 本文檔的舊版本。
[
{
"context": "VimControl && !menu",
"bindings": {
// put key-bindings here if you want them to work in normal & visual mode
}
},
{
"context": "vim_mode == insert",
"bindings": {
// "j k": "vim::NormalBefore" // remap jk in insert mode to escape.
}
},
{
"context": "EmptyPane || SharedScreen",
"bindings": {
// put key-bindings here (in addition to above) if you want them to
// work when no editor exists
// "space f": "file_finder::Toggle"
}
}
]
如果您想模擬 vim 的 map
(nmap
等)指令,您可以繫結到 workspace::SendKeystrokes
動作在正確的內容中。
可以在 這裡 看到 vim 模式中預設開啟的繫結。
內容
Zed 的鍵盤繫結僅在 "context"
與您在螢幕上的位置相符時才會進行評估。位置會巢狀,所以當您在編輯時,您會在頂端的 "Workspace"
位置,其中包含一個包含 "Editor"
的 "Pane"
。內容一次只能在一個層級中相符。因此可以結合 Editor && vim_mode == normal
,但 Workspace && vim_mode == normal
因為我們在 Editor
層級設定 vim 內容,所以永遠不會相符。
Vim 模式會為 Editor
新增幾個內容
vim_mode
類似於目前的模式,但並非完全相同。它會從normal
、visual
、insert
或replace
(依據您的模式)之一開始。如果您在輸入順序的過程中,vim_mode
會在等待任意鍵(例如,在輸入f
或t
之後)時為waiting
,或是在等待另一個繫結觸發時(例如,在輸入c
或d
之後)為operator
。- 除非
vim_mode == operator
,vim_operator
會設定為none
,此時它會設定為目前的運算子預設按鍵繫結(例如,在輸入d
之後,vim_operator == d
)。 "VimControl"
表示 vim 按鍵繫結應該起作用。它目前為vim_mode == normal || vim_mode == visual || vim_mode == operator
的別名,但定義可能會隨時間而改變。
回復一些常態感受
如果您在 Linux 或 Windows 上使用 Vim 模式,您可能會發現它覆寫了您不能沒有的按鍵繫結。您可以透過將這些複製到按鍵繫結中回復它們的預設值
{
"context": "Editor && !menu",
"bindings": {
"ctrl-c": "editor::Copy", // vim default: return to normal mode
"ctrl-x": "editor::Cut", // vim default: increment
"ctrl-v": "editor::Paste", // vim default: visual block mode
"ctrl-y": "editor::Undo", // vim default: line up
"ctrl-f": "buffer_search::Deploy", // vim default: page down
"ctrl-o": "workspace::Open", // vim default: go back
"ctrl-a": "editor::SelectAll", // vim default: increment
}
},
指令盤
Vim 模式可讓你使用 :
開啟 Zed 的指令面板。這表示你可以使用 Vim 的指令面板運行 Zed 支援的任何操作。
此外,Vim 模式包含許多熱門 Vim 指令的別名,以確保肌肉記憶有效運作。例如,:w<enter>
會儲存檔案。
我們(目前)不會模擬 Vim 指令列的全部功能,特別是,我們會針對特定模式進行特殊處理,而不是使用 Vim 的範圍選取語法,而且我們還不支援指令參數。在指令面板中找不到你所需的功能時,請在 GitHub 上提出意見。
如上所述,需要注意的一件事是,在 :%s/a/b
中,正規表示式引擎與 Vim 的引擎略有不同。
目前支援的 Vim 專用指令
# window management
:w[rite][!], :wq[!], :q[uit][!], :wa[ll][!], :wqa[ll][!], :qa[ll][!], :[e]x[it][!], :up[date]
to save/close tab(s) and pane(s) (no filename is supported yet)
:cq
to quit completely.
:vs[plit], :sp[lit]
to split vertically/horizontally (no filename is supported yet)
:new, :vne[w]
to create a new file in a new pane above or to the left
:tabedit, :tabnew
to create a new file in a new tab.
:tabn[ext], :tabp[rev]
to go to previous/next tabs
:tabc[lose]
to close the current tab
# navigating diagnostics
:cn[ext], :cp[rev], :ln[ext], :lp[rev]
to go to the next/prev diagnostics
:cc, :ll
to open the errors page
# jump to position
:<number>
to jump to a line number
:$
to jump to the end of the file
:/foo and :?foo
to jump to next/prev line matching foo
# replacement (/g is always assumed and Zed uses different regex syntax to vim)
:%s/foo/bar/
to replace instances of foo with bar
:X,Ys/foo/bar/
to limit replacement between line X and Y
other ranges are not yet implemented
# editing
:j[oin]
to join the current line (no range is yet supported)
:d[elete][l][p]
to delete the current line (no range is yet supported)
:s[ort] [i]
to sort the current selection (with i, case-insensitively)
由於任何 Zed 指令都可用,因此你可能會發現記得可執行正確指令的記憶策略很有幫助。例如
:diff Toggle Hunk [Diff]
:diffs Toggle all Hunk [Diffs]
:revert Revert Selected Hunks
:cpp [C]o[p]y [P]ath to file
:crp [C]opy [r]elative [P]ath
:reveal [Reveal] in finder
:zlog Open [Z]ed Log
設定
Vim 模式未在預設情況下啟用。如要啟用 Vim 模式,你需要將以下設定新增至設定檔
{
"vim_mode": true
}
或者,你可以從指令面板執行 toggle vim mode
指令來啟用 Vim 模式。
有些 Vim 設定可修改預設的 Vim 行為
{
"vim": {
// "always": use system clipboard when no register is specified
// "never": don't use system clipboard unless "+ or "* is specified
// "on_yank": use system clipboard for yank operations when no register is specified
"use_system_clipboard": "always",
// Lets `f` and `t` motions extend across multiple lines
"use_multiline_find": true
}
}
此外,如果你使用 Vim 模式,你可能還會喜歡以下幾個 Zed 設定
{
// disable cursor blink
"cursor_blink": false,
// use relative line numbers
"relative_line_numbers": true,
// hide the scroll bar
"scrollbar": { "show": "never" },
// allow cursor to reach edges of screen
"vertical_scroll_margin": 0,
"gutter": {
// disable line numbers completely:
"line_numbers": false
},
"command_aliases": {
"W": "w",
"Wq": "wq",
"Q": "q"
}
}
如果你想要在編輯器與停駐區(終端機、專案面板、AI 助理,......)之間進行導覽,就像在分割之間導覽一樣,你可以使用以下按鍵組合
{
"context": "Dock",
"bindings": {
"ctrl-w h": ["workspace::ActivatePaneInDirection", "Left"],
"ctrl-w l": ["workspace::ActivatePaneInDirection", "Right"],
"ctrl-w k": ["workspace::ActivatePaneInDirection", "Up"],
"ctrl-w j": ["workspace::ActivatePaneInDirection", "Down"]
// ... or other keybindings
}
}
預設情況下不會啟用詞元內的移動。如要啟用,請將這些組合新增至你的按鍵對應。
{
"context": "VimControl && !menu",
"bindings": {
"w": "vim::NextSubwordStart",
"b": "vim::PreviousSubwordStart",
"e": "vim::NextSubwordEnd",
"g e": "vim::PreviousSubwordEnd"
}
},
預設情況下也不會啟用圍繞選取範圍的視覺模式(shift-s
通常會像 c
一樣運作)。如要啟用,請將以下內容新增至你的按鍵對應。
{
"context": "vim_mode == visual",
"bindings": {
"shift-s": [
"vim::PushOperator",
{
"AddSurrounds": {}
}
]
}
}
支援的外掛程式
Zed 對一些 Vim 外掛程式提供初階支援
- 從
vim-surround
,ys
、cs
和ds
可以運作。不過你還不能新增新的 HTML 標籤。 - 從
vim-commentary
,gc
在視覺模式,以及gcc
在一般模式。不過你還不能運作在任意物件上。 - 從
netrw
,大多數的按鍵組合都支援於專案面板中。 - 從
vim-spider
/CamelCaseMotion
,你可以使用如上所述的詞元內移動。
正規表示式差異
Zed 使用與 Vim 不同的正規表示式引擎。這表示你必須為某些事項使用不同的語法。
值得注意的是
- Vim 使用
\(
和\)
表示擷取群組,在 Zed 中,這些是(
和)
。 - 另一方面,
(
和)
表示字面上的括號,但是在 Zed 中,這些必須轉譯為\(
和\)
。 - 在取代時,Vim 使用
\0
表示整個比對,在 Zed 中,這是$0
,編號擷取群組\1
->$1
的處理方式相同。 - Vim 使用
/g
表示「列中的所有配對」,在 Zed 中,這是默認的 - Vim 使用
/i
表示「不區分大小寫」,在 Zed 中,你可以在模式的開頭使用(?i)
或是使用cmd-option-c
切換大小寫敏感度。
為了協助轉換,當你執行 :%s//
時,命令面板會修復括號並替換群組。因此,%s:/\(a\)(b)/\1/
將會轉換為搜尋 "(a)(b)" 和替換為 "$1"。
有關 Zed 正規表示式引擎支援的完整語法,請參閱 正則表示式 Crate 文件。