VSCodeでいい感じにVimを使うための設定

VSCodeでいい感じにVimを使うための設定

VSCodeを2年ほど使った後、私は同僚のVimmerに出会いました。
Vimmerと知るまでは、「手元がゆっくりで落ち着いて開発してる人だなー」という印象でしたが、全く違いました。
ホームポジションから動かさずに無駄なくコーディングするため、忙しく手元を動かす必要がなかったのです。

なんでわざわざVSCodeでVimなの?

本家のVimから出てくんなとか言われそうですが、Vimを知らずにVSCodeを使っていた私の視点からの所見では、VSCodeが人気だからです。

人気なので、拡張機能が充実しており、新しいものに対応した拡張機能もすぐに出てきます。

クロスプラットフォームでWindows、Mac、Linux、(そのうちWeb上でも)と、どこでも動作します。
Vimも大概OKですが、VSCodeは加えて様々な言語に対応します。
C#, Java, PHP, Python, Ruby, Go, JavaScript, TypeScript, Angular, Vue.js, React…上げればキリないぐらい、LanguageServerのおかげでIDEさながらの充実した支援が受けられます。

設定かんたん!(←大事)
Vimは自分色に染められるのが良いところですが、設定にとんでもなく時間が掛かります。というか、終りがありません。
VSCodeなら言語周りの設定は拡張機能入れれば完了します。
古参のVimmerには無縁でしょうが、肥大化したVimの設定に新規ユーザーはこれから足を踏み入れるでしょうか?

いろいろありますが、強いもの(VSCode)に乗っかってVimの操作性の恩恵だけ受けるのが、良い方法ではないかと思います。

Vim拡張機能をインストールしよう!

こいつです。黙ってインストールです。
https://marketplace.visualstudio.com/items?itemName=vscodevim.vim

設定しないと始まらない!

私の今のsetting.jsonに記載されているvim関連の設定値です。
細かい説明はしません。意味あっての設定値なので気になるものは調べてください。

    // vim
    "vim.useSystemClipboard": true, // クリップボードを使用
    "vim.easymotion": true, // 文字列カーソルジャンプ拡張機能
    "vim.sneak": true, // s[S]から二文字で該当箇所へジャンプ
    "vim.sneakUseIgnorecaseAndSmartcase": true, // sneak時にignorecase, smartcase設定を使用
    "vim.useCtrlKeys": true, // Ctrlキー拡張を有効化
    "vim.easymotionMarkerFontFamily": "Myrica M", // easymotionのフォントを変更
    "vim.incsearch": true, // incsearchを有効化
    "vim.ignorecase": true, // ignorecaseを有効化
    "vim.visualstar": true, // visualstarを有効化
    "vim.leader": "<space>", // <leader>キーを変更
    "vim.foldfix": true, // 折りたたみ箇所を開かないように変更
    "vim.hlsearch": true, // 検索マッチ箇所をハイライト
    "vim.highlightedyank.enable": true, // yank範囲をハイライト
    "vim.camelCaseMotion.enable": true, // camelCaseMotionを有効化
    "vim.insertModeKeyBindings": [
        { "before": ["j", "k"], "commands": ["extension.vim_escape"]}, // normalモードへ戻る
        { "before": ["<C-k>"], "commands": ["acceptSelectedSuggestion"]} // サジェストを選択
    ],
    "vim.normalModeKeyBindingsNonRecursive": [
        { "before": ["J"], "after": ["2", "j"]}, // カーソル移動を高速化
        { "before": ["K"], "after": ["2", "k"]}, // カーソル移動を高速化
        { "before": ["<leader>", "j"], "after": ["J"]}, // 行を結合
        { "before": ["<C-n>"], "after": ["g", "b"]}, // カーソル位置の単語をマルチカーソルで選択
        { "before": ["<leader>", "\/"], "commands": [":noh"]}, // ハイライトクリア
        { "before": ["<leader>", "w"], "commands": [":w"]}, // ファイル保存
        { "before": ["Z", "Z"], "commands": [":wq"]}, // 保存して閉じる
        { "before": ["<leader>", "a"], "after": ["g", "g", "V", "G"]}, // 全選択する
        { "before": ["<leader>", "k"], "commands": ["workbench.action.keepEditor"]},  // プレビュー表示を開いたままにする
        { "before": ["<leader>", "b"], "commands": ["workbench.action.toggleSidebarVisibility"]},  // サイドバーの開閉
        { "before": ["<leader>", "n"], "commands": ["workbench.action.files.newUntitledFile"]},  // 新規ファイル
        { "before": ["<leader>", "p"], "commands": ["workbench.action.quickOpen"]}, // クイックオープンを開く
        { "before": ["<leader>", "o"], "commands": ["workbench.action.gotoSymbol"]},  // ファイル内シンボル検索
        { "before": ["<leader>", "t"], "commands": ["workbench.action.showAllSymbols"]},  // ワークスペース内シンボル検索
        { "before": ["<C-w>", "<C-o>"], "commands": [":tabo"]},  // 現在のタブ以外を閉じる
    ],
    "vim.visualModeKeyBindingsNonRecursive": [
        { "before": ["J"], "after": ["2", "j"]}, // カーソル移動を高速化
        { "before": ["K"], "after": ["2", "k"]}, // カーソル移動を高速化
        { "before": ["<C-n>"], "after": ["g", "b"]}, // カーソル位置の単語をマルチカーソルで選択
    ],

キーボードショートカットの変更

こちらはキーバインドの変更です。
setting.jsonに記載するvim用のキーバインディングではなく、VSCodeのキーボードショートカットの変更です。

// 既定値を上書きするには、このファイル内にキー バインドを挿入します
[
    {
        "key": "ctrl+oem_comma", // setting.jsonを開く
        "command": "workbench.action.openSettingsJson"
    },
    {
        "key": "f6", // デバッグをカーソル位置まで進めて止める
        "command": "-workbench.action.debug.pause",
        "when": "inDebugMode"
    },
    {
        "key": "f6", // デバッグをカーソル位置まで進めて止める
        "command": "editor.debug.action.runToCursor"
    },
    {
        "key": "ctrl+h", // 左のエディタに移動
        "command": "workbench.action.previousEditor",
        "when": "editorFocus && vim.mode == 'Normal'"
    },
    {
        "key": "ctrl+l", // 右のエディタに移動
        "command": "workbench.action.nextEditor",
        "when": "editorFocus && vim.mode == 'Normal'"
    },
    {
        "key": "ctrl+p", // クイックオープン時の上移動
        "command": "workbench.action.quickOpenNavigatePreviousInFilePicker",
        "when": "inQuickOpen"
    },
    {
        "key": "ctrl+n", // クイックオープン時の下移動
        "command": "workbench.action.quickOpenNavigateNextInFilePicker",
        "when": "inQuickOpen"
    },
    {
        "key": "ctrl+w l", // サイドバーからの移動
        "command": "workbench.action.focusFirstEditorGroup",
        "when": "!editorFocus"
    },
    {
        "key": "ctrl+w l", // サイドバーからの移動
        "command": "workbench.action.navigateEditorGroups",
        "when": "!editorFocus"
    },
    {
        "key": "ctrl+n", // 検索画面の選択のフォーカスを下へ移動
        "command": "search.focus.nextInputBox",
        "when": "inputBoxFocus && searchViewletVisible"
    },
    {
        "key": "ctrl+n", // ファイルエクスプローラー上で新規ファイル作成
        "command": "explorer.newFile",
        "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
    },
    {
        "key": "ctrl+shift+n", // ファイルエクスプローラー上で新規ディレクトリ作成
        "command": "explorer.newFolder",
        "when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
    },
    {
        "key": "alt+k", // 現在行を上に移動
        "command": "editor.action.moveLinesUpAction",
        "when": "editorTextFocus && !editorReadonly && vim.active"
    },
    {
        "key": "alt+j", // 現在行を下に移動
        "command": "editor.action.moveLinesDownAction",
        "when": "editorTextFocus && !editorReadonly && vim.active"
    },
    {
        "key": "alt+h", // 前に戻る
        "command": "workbench.action.navigateBack"
    },
    {
        "key": "alt+l", // 先に進む
        "command": "workbench.action.navigateForward"
    },
    {
        "key": "shift+alt+k", // 行を上へコピー
        "command": "editor.action.copyLinesUpAction",
        "when": "editorTextFocus && !editorReadonly && vim.active"
    },
    {
        "key": "shift+alt+j", // 行を下へコピー
        "command": "editor.action.copyLinesDownAction",
        "when": "editorTextFocus && !editorReadonly && vim.active"
    },
]

サイドバー間を移動するためのショートカットの追加と、
タブの切り替え(Ctrl+w, Ctrl+l)で行えるショートカットを追加します。
分割タブ間の移動は、VSCodeデフォルトのCtrl+1,2,3…で行います。
クイックオープン時のファイル展開やシンボル参照の候補をCtrl+P, Nで選択できるようにします。
確定はVSCode標準の動作で、ショートカットキーを離せば自動で確定されます。
検索画面の選択フォーカスを下へ移動するのは、Grep検索(Ctrl+Shift+G)を押した際、デフォルトでカーソルが検索フォームにセットされるので、それを検索結果にCtrl+nで移動できるようにします。
移動後は、jkで上下に移動します。

結局、使いやすいの?

ショートカット等は同じ操作に対してVSCode標準とVimのショートカットがそれぞれあったりして、正直わかりにくいところもあります。

ですが、便利なところも多くあります。
VSCodeは色々なエディタのいいとこ取りをしている感じで、ショートカットの動作が洗練されている印象があります。
マルチカーソル等も、Ctrl+Alt+{Up} or {Down}で行単位でカーソルを増やした後、その状態を維持したまま自由自在に動き回れます。
この辺りはVimでも似たような事は出来ますが、手数は多くなりがちで、直感的ではありません。

VSCode + Vimなので、VSCodeで洗練された操作のいくつかは、Vim拡張機能を入れていても動作します。
煩わしさを感じることもありますが、慣れで解決する範囲と見ました。
それ以上の拡張機能や言語を含めたメリットが上回ると判断しました。
生粋のVimmerの方にもVSCodeを少し使いこなしてから判断しても遅くはないはずです。

私は最初にVSCodeから入ったので、VSCode + Vimは使いやすいと思います。
VSCode単体でも困らない程度に使いやすいんですが、マスターしたときのスキルの上限でみたら、間違いなくVSCode + Vimです。

一緒に試してみませんか。
褒めてばかりですが、私自身4回ぐらいVim拡張機能をアンインストールしています。
乗り換えてすぐは間違いなくパフォーマンスガタ落ちです。
脳トレやってる気分になります。

確かに慣れないうちはVimなしでコーディングした方が早いんですが、
「Vimなら今の操作はもっと簡単だよな…」と悪魔の声が聞こえるようになってきます。

そのうち、無意識にciwとか押し始めます。
そうなれば、貴方もVimmerの仲間入りです。

Vimカテゴリの最新記事