VimをVSCodeライクにする

本記事は [Classi Advent Calendar 2020](https://qiita.com/advent-calendar/2020/classi) 14日目の記事です。

こんにちは。今年Classiに新卒入社した@youichiroです。
皆さんはエディタは何を使っていますか？
自分は普段VSCodeを使って開発を行なっていますが、vimをVSCodeのように使いたいと思いました。
ということで、vimをカスタマイズして見た目や機能をVSCodeライクにしていきます。

## Before / After
vimの初期状態(何も設定していない状態)から、以下の変更を加えていきます

- プラグインを管理する (vim-plug)
- ステータスバーを表示する (vim-airline)
- カラースキームをVSCodeライクにする (vim-code-dark)
- ファイルツリーを表示する (fern.vim)
- gitの差分を表示する (vim-gitgutter)
- ファイル検索する (fzf.vim)
              
Before
![スクリーンショット 2020-12-11 15.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/bc491f48-8b6d-cfef-f6be-825717092dac.png)

After
![vim5.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/613aa205-b99f-32c2-4bc3-18b9622ab1af.gif)



## プラグインを管理する
VSCodeには拡張機能をインストール・管理する仕組みがありますが、vimでも[vim-plug](https://github.com/junegunn/vim-plug)を使ってvimプラグインを管理することができます
次のコマンドを実行してインストールします

```sh
$ curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```

vimの設定ファイルである`~/.vimrc`に以下の記述を追加します

```vim
call plug#begin()

" ここにインストールしたいプラグインを列挙する
" Plug 'hoge/huga'

call plug#end()
```

`plug#begin()`と`plug#end()`の間にインストールしたいプラグインを記述し、vim上で`:PlugInstall`コマンドを実行するとそのプラグインがインストールされます
プラグインを削除したい場合は、.vimrcから記述を削除して`:PlugClean`コマンドを実行します


## ステータスバーを表示する
初期のステータスバーは簡素すぎるので、いい感じのステータスバーを表示するために[vim-airline](https://github.com/vim-airline/vim-airline)をインストールします

```vim
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
```

タブラインも表示するために、.vimrcに次の設定を追加します

```vim
let g:airline#extensions#tabline#enabled = 1
```

変更後
![スクリーンショット 2020-12-10 7.25.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/ae5ebbe3-e51c-e198-66da-286331b01f20.png)

ステータスラインとタブラインの余計な項目を除きたかったので、以下の設定を追加しました
例えば右下の表示項目を行数のみにしています

```vim
"" vim-airline
" ステータスラインに表示する項目を変更する
let g:airline#extensions#default#layout = [
  \ [ 'a', 'b', 'c' ],
  \ ['z']
  \ ]
let g:airline_section_c = '%t %M'
let g:airline_section_z = get(g:, 'airline_linecolumn_prefix', '').'%3l:%-2v'
" 変更がなければdiffの行数を表示しない
let g:airline#extensions#hunks#non_zero_only = 1 

" タブラインの表示を変更する
let g:airline#extensions#tabline#fnamemod = ':t'
let g:airline#extensions#tabline#show_buffers = 1
let g:airline#extensions#tabline#show_splits = 0
let g:airline#extensions#tabline#show_tabs = 1
let g:airline#extensions#tabline#show_tab_nr = 0
let g:airline#extensions#tabline#show_tab_type = 1
let g:airline#extensions#tabline#show_close_button = 0
```

ステータスラインの設定については [vim-airlineの使い方と設定方法。Vimのステータスバーを最強に！](https://original-game.com/vim-airline/) 、タブラインの設定については [Best airline settings](https://www.reddit.com/r/vim/comments/crs61u/best_airline_settings/) が参考になりました

変更後
![スクリーンショット 2020-12-10 9.21.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/ed7ad0bd-e780-9c72-bee2-2c8aed330d03.png)


## カラースキームをVSCodeライクにする
vimの色の付け方をVSCodeライクにするために、[vim-code-dark](https://github.com/tomasiser/vim-code-dark)をダウンロードします

```sh
$ git clone https://github.com/tomasiser/vim-code-dark.git ~/.vim/bundle/vim-code-dark.git
$ ln -s ~/.vim/bundle/vim-code-dark.git/colors/codedark.vim ~/.vim/colors/codedark.vim
```

.vimrcに次の設定を追加すると、VSCodeライクのカラースキームが適用されます

```vim
colorscheme codedark
```

`vim-airline`も同じカラースキームのテーマを適用するために、プラグインをインストールし、テーマを指定します

```vim
Plug 'tomasiser/vim-code-dark'
```

```vim
let g:airline_theme = 'codedark'
```

変更後
![スクリーンショット 2020-12-11 17.36.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/6577d05d-b9b3-057d-49ad-02bd17ebbf03.png)



## ファイルツリーを表示する
vimのファイルツリーを表示するためのプラグインは[NERDTree](https://github.com/preservim/nerdtree)が有名ですが、それよりもパフォーマンスが良いらしい[fern.vim](https://github.com/lambdalisue/fern.vim)を使いました
[2020秋 Vim のファイラー系プラグイン比較](https://zenn.dev/lambdalisue/articles/3deb92360546d526381f)にプラグインの比較がまとめられています

```vim
Plug 'lambdalisue/fern.vim'
```

`:Fern .` でウィンドウにファイルツリーを表示します
`:Fern . -drawer` でサイドバーのように左側にファイルツリーを表示します

次のように設定し、`Ctrl+n`で左側にファイルツリーを開くようにしました

```vim
" Ctrl+nでファイルツリーを表示/非表示する
nnoremap <C-n> :Fern . -reveal=% -drawer -toggle -width=40<CR>
```

`-reveal=%`で現在開いているファイルにフォーカスし、`-toggle`で表示/非表示を切り替えられるようにし、`-width`で横幅を指定しています

ファイルツリー上でファイルの作成や削除などの操作が可能です

|コマンド|説明|
|:---:|---|
|j, k|上下に移動する|
|l|フォルダを展開する、ファイルを開く|
|h|フォルダを閉じる|
|e|ファイルを開く|
|E|垂直分割してファイルを開く|
|t|新規タブでファイルを開く|
|Ctrl+m|フォルダを開く|
|Ctrl+h|親ディレクトリに移動する|
|N|ファイルを新規作成する|
|K|ディレクトリを新規作成する|
|D|ファイルを削除する|
|m|ファイルを移動する|
|R|ファイル名を変更する|
|-|ファイルを選択する|
|C|ファイルをコピーする|
|P|ペーストする|
|M|ファイルをコピーし、ペーストした時に元のファイルを削除する|
|y|ファイルパスをコピーする|
|z|ファイル名に合わせてウィンドウ幅を広げる|
|!|隠しファイルを表示/非表示する|


### ファイルツリーにgitの差分を表示する

[fern-git-status.vim](https://github.com/lambdalisue/fern-git-status.vim)をインストールすることで、ファイルツリーにgitの差分が表示されます

```vim
Plug 'lambdalisue/fern-git-status.vim'
```

変更後
![スクリーンショット 2020-12-11 18.40.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/12e2dda1-9a99-7593-d889-78934520e7fd.png)


### ファイルツリーにファイルのアイコンを表示する
アイコンを表示するためには必要なフォントをインストールする必要があります
[Nerd Fonts](https://github.com/ryanoasis/nerd-fonts)をインストールすれば良いのですが、今回は自分がVSCodeのフォントに設定していた`Menlo`フォントを使いたかったので、[font-menlo-extra](https://github.com/yumitsu/font-menlo-extra)からフォントをダウンロードします

- https://github.com/yumitsu/font-menlo-extra/blob/master/Menlo-Regular-Normal.ttf をダウンロード
- ダウンロードしたファイルを開き、フォントをインストール

![スクリーンショット 2020-12-11 22.47.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/e825dfbb-b6c6-c80d-37c7-0fc32eba9dfd.png)

- ターミナルのフォントを`Menlo Nerd Font`に変更

![スクリーンショット 2020-12-11 22.49.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/e2963ed7-4fe3-fd0d-44de-5ecc35e572c3.png)

これでフォントの用意はできました
ファイルツリーにフォントを表示するために[nerdfont.vim](https://github.com/lambdalisue/nerdfont.vim)と[fern-renderer-nerdfont.vim](https://github.com/lambdalisue/fern-renderer-nerdfont.vim)をインストールします

```vim
Plug 'lambdalisue/nerdfont.vim'
Plug 'lambdalisue/fern-renderer-nerdfont.vim'
```

次の設定を追加してアイコン表示を有効化します

```vim
let g:fern#renderer = 'nerdfont'
```


### ファイルツリーのアイコンに色をつける
アイコンの表示はできたのですが全てのファイルで同じ色だったので、色を変えます
[glyph-palette.vim](https://github.com/lambdalisue/glyph-palette.vim)をインストールし、設定を追加します

```vim
Plug 'lambdalisue/glyph-palette.vim'
```

```vim
" アイコンに色をつける
augroup my-glyph-palette
  autocmd! *
  autocmd FileType fern call glyph_palette#apply()
  autocmd FileType nerdtree,startify call glyph_palette#apply()
augroup END
```

変更後
![スクリーンショット 2020-12-11 2.53.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/193b6914-6810-a1de-2be3-43910fabc686.png)


## gitの差分を表示する
VSCodeだと変更がある行に印が表示され、差分を確認することができます。vimでもできます。
[vim-gitgutter](https://github.com/airblade/vim-gitgutter)をインストールすると差分のある行に印が表示されるようになります

```vim
Plug 'airblade/vim-gitgutter'
```

印を表示する以外にも変更箇所へ移動したり差分をハイライトしたりすることができます
以下の設定とキーマップの追加して使いやすくしました

```vim
"" git操作
" g]で前の変更箇所へ移動する
nnoremap g[ :GitGutterPrevHunk<CR>
" g[で次の変更箇所へ移動する
nnoremap g] :GitGutterNextHunk<CR>
" ghでdiffをハイライトする
nnoremap gh :GitGutterLineHighlightsToggle<CR>
" gpでカーソル行のdiffを表示する
nnoremap gp :GitGutterPreviewHunk<CR>
" 記号の色を変更する
highlight GitGutterAdd ctermfg=green
highlight GitGutterChange ctermfg=blue
highlight GitGutterDelete ctermfg=red

"" 反映時間を短くする(デフォルトは4000ms)
set updatetime=250
```

変更後
![スクリーンショット 2020-12-11 3.25.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/53b3fc48-8346-161f-a908-9285f58574b6.png)

この他にも[vim-fugitive](https://github.com/tpope/vim-fugitive)をインストールするとvimからgit操作を行えたり、[vim-rhubarb](https://github.com/tpope/vim-rhubarb)をインストールすると対象のファイル/行をGitHubで開けたりすることができます


## ファイル検索する
自分はVSCodeでファイル名によるファイルを検索するときは`Command+p`、文字列によるファイルを検索するときは`Command+Shift+f`をよく使います。vimでもできます。
[fzf.vim](https://github.com/junegunn/fzf.vim)をインストールすると便利な検索機能を使うことができます

```vim
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
```

次のパッケージを使うのでインストールしておきます

```sh
$ brew install bat
$ brew install ripgrep
```

[こちら](https://github.com/junegunn/fzf.vim#commands)にあるように、`:GFiles`でgit管理されているファイルのファイル名であいまい検索ができ、`:Rg`でファイルの文字列でのあいまい検索ができるようになります
使いやすくなるように以下のキーマップを設定しました
`Ctrl+p`を押すと検索プレビューが表示され、ファイル名によるファイルのあいまい検索を行うことができ、また`Ctrl+g`で文字列によるファイルのあいまい検索ができます

```vim
"" fzf.vim
" Ctrl+pでファイル検索を開く
" git管理されていれば:GFiles、そうでなければ:Filesを実行する
fun! FzfOmniFiles()
  let is_git = system('git status')
  if v:shell_error
    :Files
  else
    :GFiles
  endif
endfun
nnoremap <C-p> :call FzfOmniFiles()<CR>

" Ctrl+gで文字列検索を開く
" <S-?>でプレビューを表示/非表示する
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ 'rg --column --line-number --hidden --ignore-case --no-heading --color=always '.shellescape(<q-args>), 1,
\ <bang>0 ? fzf#vim#with_preview({'options': '--delimiter : --nth 3..'}, 'up:60%')
\ : fzf#vim#with_preview({'options': '--exact --delimiter : --nth 3..'}, 'right:50%:hidden', '?'),
\ <bang>0)
nnoremap <C-g> :Rg<CR>

" frでカーソル位置の単語をファイル検索する
nnoremap fr vawy:Rg <C-R>"<CR>
" frで選択した単語をファイル検索する
xnoremap fr y:Rg <C-R>"<CR>

" fbでバッファ検索を開く
nnoremap fb :Buffers<CR>
" fpでバッファの中で1つ前に開いたファイルを開く
nnoremap fp :Buffers<CR><CR>
" flで開いているファイルの文字列検索を開く
nnoremap fl :BLines<CR>
" fmでマーク検索を開く
nnoremap fm :Marks<CR>
" fhでファイル閲覧履歴検索を開く
nnoremap fh :History<CR>
" fcでコミット履歴検索を開く
nnoremap fc :Commits<CR>
```

文字列検索(`Ctrl+g`)の様子
![rg.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145075/b545ddb2-31a9-2953-fb25-333d24196d4d.gif)

検索してファイルを選択した状態で、次のキーでファイルを開くことができます

|キー|動作|
|---|---|
|Enter|今のウィンドウで開く|
|Ctrl+v|垂直分割で開く|
|Ctrl+x|水平分割で開く|
|Ctrl+t|新規タブで開く|

## おわりに
vimの初期状態からカスタマイズしていき、見た目や機能をVSCodeライクにしてみました。
最終的な.vimrcは[こちら](https://github.com/youichiro/vscode-like-vimrc/blob/master/.vimrc)にあります。

明日は@tomoyanamekawaさんです！