Vim-Modus
Zed enthält eine Vim-Emulationsebene, die als „Vim-Modus“ bekannt ist. Dieses Dokument soll beschreiben, wie es funktioniert und wie man das Beste daraus macht.
Philosophie
Der Vim-Modus in Zed soll in erster Linie „tun, was Sie erwarten“: Er versucht größtenteils, Vim exakt zu kopieren, wird aber Zed-spezifische Funktionen nutzen, wenn diese verfügbar sind, um die Dinge reibungsloser zu gestalten.
Das bedeutet, dass Zed niemals zu 100 % Vim-kompatibel sein wird, aber zu 100 % Vim-vertraut sein sollte! Wir gehen davon aus, dass unser Vim-Modus bereits 90 % Ihres Workflows abdeckt, und wir möchten ihn weiter verbessern. Wenn Sie Dinge finden, die Sie im Vim-Modus noch nicht tun können, auf die Sie sich aber in Ihrem aktuellen Workflow verlassen, reichen Sie bitte einen Fehlerbericht ein.
Zed-spezifische Funktionen
Zed basiert auf einer modernen Grundlage, die (unter anderem) Tree-Sitter und Sprachserver verwendet, um den Inhalt der Datei zu verstehen, die Sie bearbeiten, und die standardmäßig mehrere Cursor unterstützt.
Der Vim-Modus hat mehrere „Kern-Zed“-Tastenkombinationen, die Ihnen dabei helfen werden, den spezifischen Funktionsumfang von Zed optimal zu nutzen.
# 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
Der Vim-Modus verwendet Zed, um Konzepte wie „Klammern“ (für die Taste %
) und „Wörter“ (für Bewegungen wie w
und e
) zu definieren. Dies führt zwar zu einigen Unterschieden, die meisten davon sind jedoch positiv. Beispielsweise betrachtet %
in Sprachen wie Rust |
als Klammer und w
betrachtet $
in Sprachen wie JavaScript als Wortzeichen.
Der Vim-Modus emuliert die visuelle Blockauswahl mit der Multiple-Cursor-Unterstützung von Zed. Auch dies führt zwar zu einigen Unterschieden, ist jedoch wesentlich leistungsfähiger.
Vims Makrounterstützung (q
und @
) wird mit den Aktionen von Zed implementiert. Auf diese Weise können wir die Aufzeichnung und Wiedergabe von automatisch vervollständigtem Code usw. unterstützen. Im Gegensatz zu Vim verwendet Zed nicht die Yank-Register zur Aufzeichnung von Makros, es handelt sich um zwei separate Namensräume.
Schließlich wird die Such- und Ersetzungsfunktion des Vim-Modus von Zed unterstützt. Dies bedeutet, dass die Mustersyntax etwas anders ist. Details finden Sie im Abschnitt Regex-Unterschiede.
Benutzerdefinierte Tastenkombinationen
: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"
位置が最上位にあり、"Pane"
が含まれ、さらに"Editor"
が含まれます。コンテキストは一度に1つのレベルでのみ一致します。そのため、Editor && vim_mode == normal
を組み合わせることは可能ですが、Workspace && vim_mode == normal
は決して一致しません。これは、vimコンテキストをEditor
レベルで設定するためです。
vimモードはEditor
にいくつかのコンテキストを追加します。
vim_mode
は現在のモードに似ていますが、完全に同じではありません。normal
、visual
、insert
、replace
のいずれかで開始されます(モードによって異なります)。シーケンスの途中で入力している場合は、任意のキーを待機している(たとえばf
やt
を入力した後)場合はvim_mode
がwaiting
になり、別のバインディングがトリガーされるのを待機している(たとえばc
やd
を入力した後)場合はoperator
になります。vim_operator
は、vim_mode == 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
を使用して「1行のすべての一致」を示しますが、Zedではこれは暗黙的です - Vimでは、
/i
を使用して「大文字と小文字を区別しない」を示しますが、Zedではパターンの最初に(?i)
を使用するか、cmd-option-c
を使用して大文字と小文字の区別を切り替えることができます。
移行を支援するために、:%s//
を実行するとコマンドパレットは括弧を修正し、グループを置き換えます。したがって、%s:/\(a\)(b)/\1/
は"(a)(b)"を検索し、"$1"を置換するように変換されます。
Zedの正規表現エンジンでサポートされる構文の詳細は、regex crateドキュメントを参照してください。