ZedでVimの設定を再現する 
ZedのVim Modeが思ったより充実していた。
https://zed.dev/docs/vim
zed.dev充実しているだけじゃ移行しようとは思わなかったが、Claude CodeをACP経由で使えるのが決め手で一旦使ってみることにした。
具体は下記参照。
https://zed.dev/blog/claude-code-via-acp
zed.dev使ってみたらVim Modeの体験も、ACPの体験もよかったのでkeymapを設定してみた。
設定の全体は下記。
json
// Zed keymap
//
// For information on binding keys, see the Zed
// documentation: https://zed.dev/docs/key-bindings
//
// To see the default key bindings run `zed: open default keymap`
// from the command palette.
[
  {
    "bindings": {
      "cmd-m": ["agent::NewExternalAgentThread", { "agent": "claude_code" }],
      "cmd-l": "agent::ToggleFocus"
    }
  },
  // Insert mode cursor movement (vim style hjkl)
  {
    "context": "Editor && vim_mode == insert",
    "bindings": {
      "ctrl-h": "vim::Left",
      "ctrl-j": "vim::Down",
      "ctrl-k": "vim::Up",
      "ctrl-l": "vim::Right"
    }
  },
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "shift-h": "vim::StartOfLine",
      "shift-l": "vim::EndOfLine",
      "ctrl-j": "editor::JoinLines",
      "shift-j": [ "editor::MoveDownByLines", { "lines": 6 } ],
      "shift-k": [ "editor::MoveUpByLines", { "lines": 6 } ]
    }
  },
  {
    "context": "Editor && vim_mode == visual",
    "bindings": {
      "shift-h": "vim::StartOfLine",
      "shift-l": "vim::EndOfLine",
      "ctrl-j": "editor::JoinLines"
    }
  },
  // Window pane management
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "ctrl-w -": "pane::SplitDown",
      "ctrl-w \\": "pane::SplitRight",
      "ctrl-w c": "pane::CloseActiveItem",
      "ctrl-w j": "workspace::ActivatePaneDown",
      "ctrl-w k": "workspace::ActivatePaneUp",
      "ctrl-w h": "workspace::ActivatePaneLeft",
      "ctrl-w l": "workspace::ActivatePaneRight"
    }
  },
  // Project panel navigation
  {
    "context": "ProjectPanel",
    "bindings": {
      "m r": "project_panel::Rename",
      "m c": "project_panel::Copy",
      "m p": "project_panel::Paste",
      "m a": "project_panel::NewFile",
      "m d": "project_panel::Delete",
      "m f": "project_panel::NewDirectory",
      "enter": "project_panel::ExpandSelectedEntry"
    }
  },
  // Vim-style line navigation and LSP
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "g d": "editor::GoToDefinitionSplit",
      "g f": "editor::GoToDeclaration",
      "g r": "editor::FindAllReferences",
      "g i": "editor::GoToImplementation",
      "g a": "editor::ToggleCodeActions"
    }
  },
  // Terminal toggle
  {
    "bindings": {
      "cmd-j": "workspace::ToggleBottomDock"
    }
  },
  // File navigation
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "space e": "file_finder::Toggle",
      "space p": "pane::DeploySearch"
    }
  }
]詳細 
External Agentの設定 
ACP経由でAI Agent呼ぶときのコマンド。
新規スレッドを作成するケースとFocus のトグルを定義している。
json
  {
    "bindings": {
      "cmd-m": ["agent::NewExternalAgentThread", { "agent": "claude_code" }],
      "cmd-l": "agent::ToggleFocus"
    }
  },ウィンドウのペーン操作 
Vim内でウィンドウ操作するときに使っているkeymap
json
  // Window pane management
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "ctrl-w -": "pane::SplitDown",
      "ctrl-w \\": "pane::SplitRight",
      "ctrl-w c": "pane::CloseActiveItem",
      "ctrl-w j": "workspace::ActivatePaneDown",
      "ctrl-w k": "workspace::ActivatePaneUp",
      "ctrl-w h": "workspace::ActivatePaneLeft",
      "ctrl-w l": "workspace::ActivatePaneRight"
    }
  },ファイル操作 
ファイル操作もhjlk移動しているのでそのままKeymapでファイル操作を対応させたくて適用した。
ここはVimで設定してなかったので使ったり使ってなかったり。
json
  // Project panel navigation
  {
    "context": "ProjectPanel",
    "bindings": {
      "m r": "project_panel::Rename",
      "m c": "project_panel::Copy",
      "m p": "project_panel::Paste",
      "m a": "project_panel::NewFile",
      "m d": "project_panel::Delete",
      "m f": "project_panel::NewDirectory",
      "enter": "project_panel::ExpandSelectedEntry"
    }
  },LSP 
lsp関連はほとんどデフォルトのKeybindだが、editor::GoToDefinitionSplit, editor::GoToImplementationSplitのような、splitして開くActionがあって便利なのでこれを採用している。
json
  // Vim-style line navigation and LSP
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "g d": "editor::GoToDefinitionSplit",
      "g f": "editor::GoToDeclaration",
      "g r": "editor::FindAllReferences",
      "g i": "editor::GoToImplementationSplit",
      "g a": "editor::ToggleCodeActions"
    }
  },Terminal 
下のペーンにTerminalを配置しており、邪魔なときは消したいのでToggleするようにしている。
json
  // Terminal toggle
  {
    "bindings": {
      "cmd-j": "workspace::ToggleBottomDock"
    }
  },File finder & File search 
もともとtelescopeでfinder をspace e, searchをspace pで設定していたので適用した。
json
  // File navigation
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "space e": "file_finder::Toggle",
      "space p": "pane::DeploySearch"
    }
  }
]邪道キーバインド 
文頭、文末に移動する0, $が遠かったのでshift-h, shift-lにマッピングしている。
改行がなくて{, }で移動できないときにshift-j, shift-kで6行移動する。
このあたりはかなり邪道で近いうちにやめたいので参考にしないでください
json
  {
    "context": "Editor && vim_mode == normal",
    "bindings": {
      "shift-h": "vim::StartOfLine",
      "shift-l": "vim::EndOfLine",
      "ctrl-j": "editor::JoinLines",
      "shift-j": [ "editor::MoveDownByLines", { "lines": 6 } ],
      "shift-k": [ "editor::MoveUpByLines", { "lines": 6 } ]
    }
  },
  {
    "context": "Editor && vim_mode == visual",
    "bindings": {
      "shift-h": "vim::StartOfLine",
      "shift-l": "vim::EndOfLine",
      "ctrl-j": "editor::JoinLines"
    }
  },Insert中にVimのキーバインドで移動する 
これも邪道。
ecsするほどではないときにこれ使ってしまっている。
json
  // Insert mode cursor movement (vim style hjkl)
  {
    "context": "Editor && vim_mode == insert",
    "bindings": {
      "ctrl-h": "vim::Left",
      "ctrl-j": "vim::Down",
      "ctrl-k": "vim::Up",
      "ctrl-l": "vim::Right"
    }
  },