プラグインを入れる以外のVim強化Tips

この記事は [iRidge Advent Calendar 2018](https://qiita.com/advent-calendar/2018/iridge) の一日目です。
念の為言っておくと [Vim Advent Calendar 2018](https://qiita.com/advent-calendar/2018/vim)ではありませんよ。

# ti;dr

Vimには多くの便利プラグインがあります。
ですがVimを強化する手段はそれだけではありません。
いくつかの設定を入れるだけであなたのVimは、いとも簡単にモダンで便利な機能を追加することができるのです。
今回はそんないくつかのTipsをご紹介します。

## 以前開いたファイルのカーソル位置を保持する

私はターミナル上でVim(Neovim)を使っているので、
つい手癖で`:q`を叩いて、Vimを終了させてしまうことがよくあります。
そんなとき、見ていたファイルの位置が失われてしまい、開いてまた所定の位置に移動している。
なんてことありませんか？

以下のautocmdを追加することで、カーソル位置を復元することができるのです。モダンな感じですね。

```vim
augroup KeepLastPosition
  au BufRead * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g`\"" | endif
augroup END
```


## 以前のアンドゥを保存する

上と同じように、編集していてつい手癖で`:wq`を押してVimを終了してしまった。
がしかし、保存前の編集状態に戻したいことありませんか？

以下のautocmdを追加することで、Vimのアンドウ履歴を保存することができるのです。これまたモダンな感じですね。

```vim
if has('persistent_undo')
  set undodir=./.vimundo,~/.vimundo
  augroup SaveUndoFile
    autocmd!
    autocmd BufReadPre ~/* setlocal undofile
  augroup END
endif
```

- 参考
    - [Hack #162: Vimを終了しても undo 履歴を復元する](https://vim-jp.org/vim-users-jp/2010/07/19/Hack-162.html)


## Grepしたら即座にQuickFixする

VimにはいくつかのGrep用プラグインがあるわけですが、
VimにはもともとGrep機能が備わっているのです。`:vim`や`:grep`がそれなんですけど、詳細は以下の記事なんかがよくまとまっています。

[vimgrepとQuickfix知らないVimmerはちょっとこっち来い](https://qiita.com/yuku_t/items/0c1aff03949cb1b8fe6b)

で、grepするときの話なんですが、grepしたらQuickFixに出したいのがVimmerの性なわけです。
がしかし、`:vim {pattern} {file} | cw`の`| cw`っていちいちうつのめんどくさくないですか？
どうせgrepしたらQuickFixに出すじゃないかと。

そんなあなたには以下の設定がおすすめです。
`:vim {pattern} {file}`まで打ち込めば、なんと勝手にQuickFixに流してくれます。これでもっとGrepできますね。

```vim
augroup GrepCmd
    autocmd!
    autocmd QuickFixCmdPost vim,grep,make if len(getqflist()) != 0 | cwindow | endif
augroup END
```

あとついでに、以下のキーバインドを登録しておくと`Ctrl+n,p`でサクサク移動できるのでおすすめです。
ただ`Ctrl+n,p`は超打ちやすい優良キーなので、コレに使うかどうかは熟考すべき項目ですね。

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

## システムGrepを変更する

Grepは超重たい処理なので、もっと早くしたい。
あとGitのリポジトリにいるとき`.gitignore`を読み取りしてくれたら便利なのに...
なんてタイミングがありますよね？

ええできますとも、Vimには外部Grep(`:grep`)の実行プログラムを変更することができるので、
デフォルトのシステムGrepを差し替えて、便利機能付きのGrepにしてやればよいのです。
じつはGNU Grepも進化してるから、速度ついてはアップグレードすればよくね説はありますけども。

私は[ripgrep](https://github.com/BurntSushi/ripgrep)を使っています。
rust実装で高速かつ`.gitignore`を勝手に無視してくれる。
しかも、vimからコールするためのオプション(`--vimgrep`)とか用意してくれてるんですよ！
なんていい子なのかしら。

というわけで以下の設定で`:grep`実行時にripgrepをコールしにいってくれます。

```vim
if executable('rg')
    let &grepprg = 'rg --vimgrep --hidden'
    set grepformat=%f:%l:%c:%m
endif
```

ちなみに`--hidden`は`.gitignore`を見てくれるオプション

## QuickFixをトグル

QuickFixがちょいと邪魔なのってタイミングは割とあって、
そういうときは`:cclose, :ccl`すればいいんですが、再度見たいときに`:copen, :cope`する必要があります。

ちょっとコマンドとしては長いので、キーマップしたいけど、2種類もキーマップ消費するのはちょっと...
というときはないですかね？

そんなときはトグルする用の関数つくればいいんですよ。

```vim
" Toggle quickfix
if exists('g:__QUICKFIX_TOGGLE__')
    finish
endif
let g:__QUICKFIX_TOGGLE__ = 1

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>
```

## Vimの起動時間を測る

Vimの一つの大きなメリットとして、起動速度の速さがありますね。
けどプラグインを入れすぎて、鈍重なVimになっていることもあるわけです。
体感ではなく、ちゃんと測定するのがすごく重要になってくるわけですね。体感も重要だけど。
Vimには当然そのためのオプション(`--startuptime`)があるわけなんですけど、
つどつどコレを実行するのはだるいですよね。

そんなときは以下のオプションをつけてやれば、Vimの起動毎に起動時間を表示してくれるので、
気軽に起動時間をチェックすることが出来ます。
これでなんとなーく見ていて、遅いからどうにかしたい。というときに`--startuptime`でしっかり解析しましょう。

```vim
augroup VimrCheckTime
    autocmd!
    autocmd InsertEnter,WinEnter * checktime
augroup END
```

## 直近にヤンクしたレジスタ(0レジスタ)をペースト

他のエディタからVimに移って来たときに困ることの一つがヤンクレジスタであると思います。
削除操作とかしたときに、無名レジスタが書き換わってしまって、これはヤンクしたくないの...
ってときありますよね？

Vimの削除操作はレジスタを書き換えてしまうのが原因です。
ですがヤンクした内容と、削除操作とかでレジスタ登録された内容は分けて考えたいところです。
まあ明示的に`0レジスタ`をペーストすればいいんですが`"0p`はそこそこ打ちづらいです。

なので打ちやすいキーバインドにしておくのがおすすめ。

```vim
nnoremap <Space>p "0p
vnoremap <Space>p "0p
```

ついでに、明らかにレジスタ登録が不要な操作(一文字だけ消すとか)を`_レジスタ`に飛ばしとくと、無名レジスタが汚れないのでおすすめ。

```vim
nnoremap x "_x
```

レジスタについては詳しくまとめてくれているひとがいらっしゃるので貼っときます

- 参考
    - [Vim備忘録 コピペとレジスタ](https://oplern.hatenablog.com/entry/2017/04/16/174653)

## 現在開いているファイルと以前開いているファイルをトグル

`<C-^>`(直前に開いたファイルと今開いているファイルをトグルする)って超便利だけど、
打ちづらくないですか？右手がものすごいホームポジションからズレません？
というわけでキーマップ。

```vim
nnoremap <Space><Space> <C-^>
```

## ファイル行の絶対行と相対行をトグル

`{count}j,k`で指定数の上下移動するために`:set relativenumber`しているんですけど、
人に見せるときとか、行数わからんって言われたりするんですよね。
そんなときはトグルですよトグル。

```vim
function! ToggleRelativenumber() abort
  if &relativenumber == 1
     setlocal norelativenumber
  else
     setlocal relativenumber
  endif
endfunction
nnoremap <silent> <Space>n :call ToggleRelativenumber()<cr>
```

## GitCommitのスペルチェック自動有効化

Gitのcommitメッセージ書くときに勝手にスペルチェックONにしてくれるよ！

```
augroup GitSpellCheck
    autocmd!
    autocmd FileType gitcommit setlocal spell
augroup END
```

# 宣伝

ちなみにここでご紹介しているTipsの多くは、[vimrc読書会](https://vim-jp.org/reading-vimrc/)で教えてもらいました。
もっと知りたいひとは是非参加しましょう！！！