ゴリゴリのVimmerがVSCodeに移行して、本当にマウスを使わなくてよくなる設定を考えた

## この記事の対象者
・VSCodeでマウスを使わずスマートに開発したい方
・Neovim/vimを使っているがVSCodeの操作感が気に入らない方
・絶対にマウスを使いたくない方

## はじめに

みなさまVim使ってますか！？ はじめまして、Vimmerです。
Neovimで数年開発をしつづけているのですが、最近React, Vueを書く機会が多く、あんまりVimプラグインと相性よくないなと感じていて、VSCodeでも開発できるように設定を考えました。
Neovimフォークする拡張機能もありますが、プラグインがちゃんと機能しなかったりとたびたび不安定なことがあり、実務で使うには頼りない感じでした。なので、Vim拡張機能+VSCodeの設定で、まったくマウスを触らずに開発できるようなNeovimライクな操作感を実現できればなぁという構想からいろいろディグり、3か月ほど操作をためして８割くらい完成したので共有したいと思います。

## 設定
コピペすればとりあえず使えます。有識者はいい感じにアジャストしてください。

`keybindings.json`
```
[
    // file explorerにfocusしているとき
    {
        "key": "a",
        "command": "explorer.newFile",
        "when": "filesExplorerFocus && !inputFocus"
    },
    {
        "key": "shift+a",
        "command": "explorer.newFolder",
        "when": "filesExplorerFocus && !inputFocus"
    },
    {
        "key": "shift+d",
        "command": "deleteFile",
        "when": "filesExplorerFocus && !inputFocus"
    },
    {
        "key": "r",
        "command": "renameFile",
        "when": "filesExplorerFocus && !inputFocus"
    },
    {
        "key": "y",
        "command": "filesExplorer.copy",
        "when": "filesExplorerFocus && !inputFocus"
    },
    {
        "key": "p",
        "command": "filesExplorer.paste",
        "when": "filesExplorerFocus && !inputFocus"
    },

    // when filesExploreFocus
    // file treeにfocusしている状態
    // file treeが常に左想定
    //ctrl + l (→)でfileにfocus
    {
        "key": "ctrl+l",
        "command": "workbench.action.focusActiveEditorGroup",
        "when": "filesExplorerFocus"
    },
    // when terminal focus
    // terminalにfocusしている状態
    // terminalが常に下想定
    //ctrl + k (↑)でfileにfocus
    {
        "key": "ctrl+k",
        "command": "workbench.action.focusActiveEditorGroup",
        "when": "terminalFocus"
    },
    // ctrl shift tでterminal内にいるとき新規作成
    {
        "key": "ctrl+shift+t",
        "command": "workbench.action.terminal.new",
        "when": "terminalFocus"
    },
    // ctrl shift wでterminal内にいるとき閉じる
    {
        "key": "ctrl+shift+w",
        "command": "workbench.action.terminal.kill",
        "when": "terminalFocus"
    },
    // ctrl tabでterminal移動
    {
        "key": "ctrl+tab",
        "command": "workbench.action.terminal.focusNext",
        "when": "terminalFocus"
    },
    // ctrl shift tabでterminal逆移動
    {
        "key": "ctrl+shift+tab",
        "command": "workbench.action.terminal.focusPrevious",
        "when": "terminalFocus"
    },
    // file explorerを開閉
    {
        "key": "ctrl+e",
        "command": "-workbench.view.explorer"
    },
    {
        "key": "ctrl+e",
        "command": "workbench.view.explorer",
        "when": "!explorerViewletVisible"
    },
    {
        "key": "ctrl+e",
        "command": "workbench.action.toggleSidebarVisibility",
        "when": "explorerViewletVisible"
    },
    // ctrl + bでサイドバーを開閉
    {
        "key": "ctrl+b",
        "command": "workbench.action.toggleSidebarVisibility"
    },
    // ctrl + tでターミナルを開閉
    {
        "key": "ctrl+t",
        "command": "workbench.action.terminal.toggleTerminal"
    },
    // ctrl+pで検索したパレット内で、ctrl+nで下に移動
    {
        "key": "ctrl+n",
        "command": "workbench.action.quickOpenNavigateNext",
        "when": "inQuickOpen"
    },
    // ctrl+pで検索したパレット内で、ctrl+pで上に移動
    {
        "key": "ctrl+p",
        "command": "workbench.action.quickOpenNavigatePrevious",
        "when": "inQuickOpen"
    },
    // ctrl + shift + f を ctrl + f に変更
    {
        "key": "ctrl+f",
        "command": "workbench.action.findInFiles"
    },
    // grep検索したあと、検索候補リストにctrl + nで移動
    {
        "key": "ctrl+n",
        "command": "search.action.focusSearchList",
        "when": "searchViewletVisible && searchViewletFocus && inputFocus"
    },
    // grep検索したあと、検索候補リストにいるときに検索ボックスに移動
    {
        "key": "ctrl+n",
        "command": "workbench.action.findInFiles",
        "when": "searchViewletVisible && searchViewletFocus && !inputFocus"
    },
    // shift kでマウスホバーで見られる情報（型定義など）を見る
    {
        "key": "Shift+K",
        "command": "editor.action.showHover",
        "when": "editorTextFocus && vim.active && vim.mode == 'Normal'"
    }
]

```
`settings.json`
```
{
  // ... 
  // vim
  // 行を折り返しする(マウスを使わないため)
  "editor.wordWrap": "on",
  // sync os clipboard
  "vim.useSystemClipboard": true,
  "vim.leader": "<space>",
  "vim.easymotion": true,
  "vim.sneak": true,
  "vim.incsearch": true,
  "vim.useCtrlKeys": true,
  "vim.hlsearch": true,
  // c-p vdcode file検索を優先
  // c-f vdcode grepを優先(ctrl+fをgrepにしているため)
  "vim.handleKeys": {
    "<C-p>": false,
    "<C-f>": false,
  },
  "vim.normalModeKeyBindings": [],
  "vim.normalModeKeyBindingsNonRecursive": [
    // ctrl + jkhl で window focus移動
    {
      "before": ["<C-h>"],
      "after": ["<C-w>", "h"]
    },
    {
      "before": ["<C-j>"],
      "after": ["<C-w>", "j"]
    },
    {
      "before": ["<C-k>"],
      "after": ["<C-w>", "k"]
    },
    {
      "before": ["<C-l>"],
      "after": ["<C-w>", "l"]
    },
    // shift + HL(左右) で buffer(file) 移動
    {
      "before": ["H"],
      "after": ["g", "T"]
    },
    {
      "before": ["L"],
      "after": ["g", "t"]
    },
    // vscode undo redoにvim undo redoをbind
    {
        "before" : ["u"],
        "commands" : ["undo"]
    },
    {
        "before" : ["<C-r>"],
        "commands" : ["redo"]
    },
    {
      "before": ["<C-n>"],
      "after": ["g", "b"]
    },
  ],
  // jk で insertを抜ける jjは邪道
  "vim.insertModeKeyBindings": [
    {
        "before": [
            "j",
            "k"
        ],
        "after": [
            "<Esc>"
        ]
    }
  ],
  "vim.visualModeKeyBindingsNonRecursive": [
    {
        "before": [
            "p",
        ],
        "after": [
            "\"",
            "_",
            "d",
            "P",
        ]
    },
    {
      "before": ["<C-n>"],
      "after": ["g", "b"]
    },
  ],
  // minimarp 非表示(スプリットしたとき邪魔)
  "editor.minimap.renderCharacters": false,
  "editor.minimap.enabled": false,
  // relative number表示
  "editor.lineNumbers": "relative",
  "window.titleBarStyle": "custom",
  // scrollbar非表示（マウス使わないため）
  "editor.scrollbar.vertical": "hidden",
  "editor.scrollbar.horizontal": "hidden",
  "workbench.editor.scrollbar.vertical": "hidden",
  "workbench.editor.scrollbar.horizontal": "hidden",
  "workbench.editor.enablePreview": false,
  "workbench.editor.editorActionsLocation": "titleBar",
  "workbench.editor.wrapTabs": true,
  // ...
}
  ```
## 何がうれしいのか

### ファイル検索 grep
  pointとして、Vimmerのみなさんはわりかしディレクトリ構成を把握して頻繁にファイル検索、grep(Telescope的な）を使いこなしていると思いますので、`ctrl + p`, `ctrl + f` でファイル検索・grepできるようにコマンドを上書きしています。ポイントとして、`ctrl + p`で検索したあとは`ctrl + p`(prev), `ctrl + n`(next)でファイル前後できますし、`ctrl + f`で検索した場合は`ctrl + n` でファイル一覧と検索ボックス内を往来できるようにしています。これがかなり便利です。

### ターミナル操作
  ターミナル・ファイルツリーについては、`ctrl + t`, `ctrl + e`でToggleできるようにしています。
  ターミナル内部で、webブラウザのような操作感でターミナル追加（`ctrl + shift + t`)、ターミナルを閉じる（`ctrl + shift + w`)、ターミナルを移動(`ctrl + tab` ( + `shift`で逆移動))を実現しています。ターミナルは常に下にある前提として `ctrl + j or k` でBuffer（ファイル）との往来を実現しています。

### ファイル操作
  ファイルツリーについては、`ctrl + e`でToggleできるようにしています。
  ファイルツリーも同様に、左にある前提として`ctrl + h or l` で往来を実現しています。みなさまの定位置によってお好きに変更してください。ファイルツリー上にいるとき、`a`でファイル追加(/を最後につけるとdirectory追加）、`shift + d`でファイル/ディレクトリ削除, `r`でrename, `y`でコピー、`p`でペーストといった、Vimのファイルツリーライブラリでは基本的にできそうな動作を追加しました。これによってファイル操作もマウスいらずです！
  ちなみに、サイドバーは`ctrl + b`で何を開いていても開閉をToggleできます。これが地味に便利です。

  ## まとめ
  `ctrl + p`で検索としてしまったせいでコーディング中の候補選択で`ctrl + n`しか使えない、`ctrl + f`でgrepとしたことでターミナル内検索ができないといった弊害がありますが、いまのところ私のスタイルでは満足して開発できています。ぜひ参考にしてください。不明点やご意見があればぜひともお気軽にコメントください。
  
  わたしがはたらく[株式会社Vitalize](https://recruit.vitalize.co.jp/)では未経験の方からGeekな皆さまでエンジニアを大募集しています。全国の各地方に支社を複数展開しており、希望のブランチで勤務が可能です。ご興味がございましたらお気軽にご応募くださいませ。