Vimのキーマッピングに迷わないための俺々キーマッピングルールをご紹介します

# tl;dr

- キーマッピングはぶっちゃけ好み
- 私好みのキーマッピングはこうですよという話
- お前のキーマッピングは間違っている的なレスお待ちしております

## おしながき

| キー                   | マッピング対象                                                                                                            |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `<Space>`              | 標準コマンドのPrefix                                                                                                      |
| `,`(カンマ)            | `<Leader>`割当用かつ言語系以外の共通プラグインのPrefix                                                                    |
| `\\`(バックスラッシュ) | `<LocalReader>`割当用かつ言語別プラグインのPrefix                                                                         |
| `<C-j>`                | FuzzyFinder([denite.nvim](https://github.com/Shougo/denite.nvim), [fzf.vim](https://github.com/junegunn/fzf.vim))のPrefix |
| `<C-n>`, `<C-p>`       | QuickFixの移動(`:cnext`, `:cprevious`)を割当                                                                              |
| `H`, `L`               | `^`をマップ                                                                                                               |
| `K`                    | 言語毎のドキュメント参照コマンド割当                                                                                      |
| `s`                    | [vim-sandwich](https://github.com/machakann/vim-sandwich)用                                                               |

上記表がすべてなのですが、
一応解説を以下に記載しました。暇つぶしにどうぞ

### <Space>

- デフォルトキーマップ解説
    - 1文字右へ移動
- ルール
    - プラグインのコマンドを割当しない
    - 標準コマンドのショートカットを割当する
    - 標準キーバンドの打ちづらいキーを割当する
    - 自作関数の割当する
- 例

    ```vim
    # .vimrcのリロード
    nnoremap <Space>s :source $HOME/.vimrc<CR>
    # ファイル保存のショートカット
    nnoremap <silent> <Space>w :<C-u>w<CR>
    # <c-^>のショートカット
    nnoremap <Space><Space> <c-^>

    # QuickFixのトグル
    function! ToggleQuickfix()
        let l:nr = winnr('$')
        cwindow
        let l:nr2 = winnr('$')
        if l:nr == l:nr2
            cclose
        endif
    endfunction
    nnoremap <script> <silent> <Space>f :call ToggleQuickfix()<CR>
    ```

### ,(カンマ)

- デフォルトキーマップ解説
    - `f*`と押した場合にカーソル位置から右の`*`に移動するが、`,(カンマ)`はそれを左方向に繰り返す
- ルール
    - `<Leader>`として扱う
    - 上記`<Space>`に該当するコマンドは割当しない
    - プラグインのコマンドのPrefixとして用いる
    - プラグラミング言語毎のプラグインのコマンドを割当しない
- 例
    - [vim-quickrun](https://github.com/thinca/vim-quickrun)

        ```vim
        nnoremap <Leader>r :<C-U>QuickRun<CR>
        xnoremap <Leader>r gv:<C-U>QuickRun<CR>
        ```
    - [nerdtree](https://github.com/scrooloose/nerdtree)

        ```vim
        nnoremap <silent> <Leader>t :<C-u>NERDTreeToggle<CR>
        nnoremap <silent> <Leader>f :<C-u>NERDTreeFind %<CR>
        ```
    - [tagbar](https://github.com/majutsushi/tagbar)

        ```vim
        nnoremap <Leader>o :<C-u>TagbarToggle<CR>
        ```
    - [caw.vim](https://github.com/tyru/caw.vim)

        ```vim
        " Add comment to beginning line(consider whitespace)
        nnoremap <Leader>c <Plug>(caw:hatpos:toggle)
        vnoremap <Leader>c <Plug>(caw:hatpos:toggle)
        " Add comment to beginning line(ignore whitespace)
        nnoremap <Leader>, <Plug>(caw:zeropos:toggle)
        vnoremap <Leader>, <Plug>(caw:zeropos:toggle)
        ```
    - [open-browser.vim](https://github.com/tyru/open-browser.vim)

        ```vim
        nnoremap <Leader>b <Plug>(openbrowser-smart-search)
        vnoremap <Leader>b <Plug>(openbrowser-smart-search)
        ```

### \(バックスラッシュ)

- デフォルトキーマップ解説
    - キーマップ拡張のために空けてある
- ルール
    - `<LocalLeader>`として扱う
    - 上記`,(カンマ)`に該当するコマンドは割当しない
    - プラグラミング言語毎のプラグインのコマンドを割当する
    - autocmdを用いて、各言語毎にキーマップが切り替わるようにする
- 例
    - [vim-go](https://github.com/fatih/vim-go)

        ```vim
        augroup GoCommands
            autocmd!
            autocmd FileType go nnoremap <silent><LocalLeader>r  <Plug>(go-run)
            autocmd FileType go nnoremap <silent><LocalLeader>b  <Plug>(go-build)
            autocmd FileType go nnoremap <silent><LocalLeader>tt <Plug>(go-test)
            autocmd FileType go nnoremap <silent><LocalLeader>tf <Plug>(go-test-func)
            autocmd FileType go nnoremap <silent><LocalLeader>ts :<C-u>GoTests
            autocmd FileType go nnoremap <silent><LocalLeader>ta :<C-u>GoTestsAll
            autocmd FileType go nnoremap <silent><LocalLeader>m  <Plug>(go-imports)
            autocmd FileType go nnoremap <silent><LocalLeader>i  <Plug>(go-install)
            autocmd FileType go nnoremap <silent>K               <Plug>(go-doc)
            autocmd FileType go nnoremap <silent><LocalLeader>d  <Plug>(go-doc-browser)
            autocmd FileType go nnoremap <silent><LocalLeader>R  <Plug>(go-rename)
            autocmd FileType go nnoremap <silent><LocalLeader>c  <Plug>(go-coverage-toggle)
            autocmd FileType go nnoremap <silent><LocalLeader>n  <Plug>(go-referrers)
            autocmd FileType go nnoremap <silent><LocalLeader>a  <Plug>(go-alternate-edit)
            autocmd FileType go nnoremap <silent><LocalLeader>e  <Plug>(go-iferr)
            autocmd FileType go nnoremap <silent><LocalLeader>p  <Plug>(go-implements)
        augroup END
        ```
    - [jedi-vim](https://github.com/davidhalter/jedi-vim)

        ```vim
        let g:jedi#goto_command = "<C-]>"
        let g:jedi#goto_assignments_command = "<Localleader>g"
        let g:jedi#goto_definitions_command = ""
        let g:jedi#documentation_command = "K"
        let g:jedi#usages_command = "<Localleader>n"
        let g:jedi#rename_command = "<Localleader>R"
        ```
    - [vim-lsp](https://github.com/prabirshrestha/vim-lsp)

        ```vim
        augroup PylsCommands
            autocmd!
            autocmd FileType python nnoremap <C-]> :<C-u>LspDefinition<CR>
            autocmd FileType python nnoremap K :<C-u>LspHover<CR>
            autocmd FileType python nnoremap <LocalLeader>R :<C-u>LspRename<CR>
            autocmd FileType python nnoremap <LocalLeader>n :<C-u>LspReferences<CR>
        augroup END
        ```

### <C-j>

- デフォルトキーマップ解説
    - 1行下へ移動
- ルール
    - FuzzyFinderプラグインのPrefix
    - `<C-j>`の後続のキーはCtrlとの同時押しキー(`<C-某>`)とする
- 例
    - [denite.nvim](https://github.com/Shougo/denite.nvim)

        ```vim
        " Current direcotry files
        nnoremap <silent> <C-j><C-p> :<C-u>Denite file/rec/git -highlight-mode-insert=Search<CR>
        " Buffer files
        nnoremap <silent> <C-j><C-b> :<C-u>Denite buffer -highlight-mode-insert=Search<CR>
        " Outline current file
        nnoremap <silent> <C-j><C-o> :<C-u>Denite outline -highlight-mode-insert=Search<CR>
        " Reccent file
        nnoremap <silent> <C-j><C-r> :<C-u>Denite file_old -highlight-mode-insert=Search<CR>
        " Help tag
        nnoremap <silent> <C-j><C-h> :<C-u>Denite help -highlight-mode-insert=Search<CR>
        ```
    - [fzf.vim](https://github.com/junegunn/fzf.vim)

        ```vim
        " Gather files recursive and nominates all file names under the search directory
        nnoremap <silent> <C-j><C-j> :<C-u>Files<CR>
        " Git Status
        nnoremap <silent> <C-j><C-g> :<C-u>GFiles?<CR>
        " Ctags index project
        nnoremap <silent> <C-j><C-]> :<C-u>Tags<CR>
        " My cli setting
        nnoremap <silent> <C-j><C-v> :<C-u>Files ~/.dotfiles<CR>
        ```

### <C-n>,<C-p>

- デフォルトキーマップ解説
    - `<C-n>`のデフォルトは1行下へ移動
    - `<C-p>`のデフォルトは1行上へ移動
- 例

    ```vim
    nnoremap <silent> <C-p> :<C-u>cp<CR>
    nnoremap <silent> <C-n> :<C-u>cn<CR>
    ```

QuickFixの上下移動はかなり使用頻度が高いのに`:cn`と`:cp`は3打と長い。長過ぎる。
そこへいくと`<C-n>`のデフォルトは下移動`<C-p>`のデフォルトは上移動と`j`,`k`の動作ともろかぶりである。
こんなにうちごろなキーを重複した操作にしておくなんてとんでもない。

### H,L

- デフォルトキーマップ解説
    - `H`はスクリーン上端に移動
    - `L`はスクリーン下端に移動
- 例

    ```vim
    noremap H ^
    noremap L $
    ```

デフォルトは使えるっちゃ使えるのですが
行頭、行末移動に比べたら使用頻度は雲泥の差なのでいいかなと。

本来の行頭移動(先頭の非空白文字列へ移動)の`^`(ハット)と行末移動の`$`(ダラー)はどうにも押しづらいのです。
できるだけデフォルトに慣れたほうがいいのですが、SHIFT+数字キーって指辛い。

ですが、
左に移動するのを強化する的な意味で`H`が行頭移動、
右に移動するのを強化する的な意味で`L`が行末移動、
は意味的にもしっくりくる気がしている。

しかし、このキーバインドに慣れるとサーバのVimで誤爆しまくること請け合いです。

### K

- デフォルトキーマップ解説
    - カーソル下のワードに対して`man`コマンド実行し、Vim上に表示する
    - 今回記事書いてて初めて知った
- ルール
    - 上記デフォルトの拡張を言語毎に最適なコマンドに割当する
- 例
    - vim-go

        ```vim
        augroup GoCommands
            autocmd!
            ...
            autocmd FileType go nnoremap <silent>K               <Plug>(go-doc)
            ...
        augroup END
        ```

### s

- デフォルトキーマップ解説
    - カーソル下1文字を削除してインサートモードへ

[vim-sandwich](https://github.com/machakann/vim-sandwich)のREADMEに書いてある割当が`s`なので従っています。それだけです。はい。

# ものすごく参考になる記事

- [vimでキーマッピングする際に考えたほうがいいこと](http://deris.hatenablog.jp/entry/2013/05/02/192415)