n度目の正直でVSCodeからVim(拡張)に乗り換えた話

ジョブカン事業部のアドベントカレンダー3日目です。

この度、Vimへの乗り換えを決行してから数ヶ月経ちましたので、布教を兼ねてどこに魅力を感じたのかなどを書きたいと思います。

# 現在の構成
Vimに乗り換えたと書いていますが、実際にはVSCodeに拡張を入れて使っています。
* 仕事ではMac/プライベートではWindows
* HHKB(US配列)
* Visual Studio Code
* VSCode Neovim 拡張

# 今までのエディタ遍歴
#### 学生時代
* Visual Studio
* Sublime Text

C/C++を使うことが多かったのでVisual Sutdioを使っていました。
gccを使う時やLinuxで開発をするときはSublime Textを使うことが多かったです。

#### 前職
* Visual Studio
* 秀丸

前職もC/C++や.NETが多かったのでVisual Studioを使っていました。
ベテランの方も多かったので流れで秀丸も使っていました。（grep検索が優秀だったのを覚えています）

#### 現職(Vimにする前)
* Visual Studio Code

私はRuby on Railsでの開発をずっと行っているので、VSCodeを使っています。
先輩はRubyMineだったりしたのですが、タイミングを逃し続けてVSCodeになっています。

# なぜVimに乗り換えようと思ったのか

### 「かっこいい」、「早そう」
以前から「かっこいい」「使いこなしたら早くなるんだろうな」とは思っていたので、何度かVSCodeにVim拡張を入れて移行を試みました。
最初のうちは良いのですが、しばらくすると「普通に書いたほうが早い」となってVimをOFFにしてしまうというのを繰り返していました。
（急ぎの案件が振ってくる → 一旦拡張をOFF → 二度とONにならない というのが王道パターンです）

### あるコマンドに一目惚れした
ある時YouTubeを見ていると爆速でVimを操っている人を見つけました。
その方のVim解説動画で紹介されていた`ct)`というコマンドになぜか一目惚れしてしまい、移行を決めました。

# 一目惚れしたコマンドたちの紹介

## `ct)`
Vimに乗り換えたきっかけでもあるこのコマンドは、カーソルがある場所から`)`の手前までを削除して、INSERTモードに入るというコマンドです。
![ct_brackets.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621534/7ae63d8c-da4e-7fc1-e03f-92d8ec50be8f.gif)
`ct)options:`+Escで`flag_a`より後ろの引数をすべて消して、optionsに置き換えています。

![ct_under.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621534/034d7e76-5a8c-12f1-aec7-552648c1ec31.gif)
`)`の部分は好きな文字に置き換えられるため、例えば`create_user`の先頭で`ct_update`+Escと入力すれば`_`の手前を`update`に書き換える操作も可能です。

## `ciw`
もう一つ、Vim乗り換えを後押しをしたコマンドです。
これも文字を消して、INSERTモードに入るというコマンドの一つで、現在カーソルがある単語を削除してINSERTモードに入るコマンドです。

![ciw.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621534/10695130-3ed7-930b-d233-4445e412c68f.gif)
`options`を消して`flags`に置き換える操作を`ciwflags`と打つことで実現できます。

# 乗り換え先の選定
Vimに乗り換える際、候補としては純粋なVimやNeovim、VSCodeに拡張を入れるなどいくつかの選択肢がありますが、私はVSCode拡張の恩恵を捨てる覚悟が決められなかったため、拡張を入れることにしました。（いずれはtmuxとか使ってみたいです）

最初は`VSCode Vim`を入れて使っていたのですが、WindowsのWSL2上のLinuxで開発するときに、後述するIME OFF周りの動作に不都合があったため、`VSCode Neovim`に乗り換えました。
それぞれの違いは下記のイメージです。

#### VSCode Vim
* VSCode内のjsでVimの動作をエミュレートしている
* vimrc相当の設定もVSCodeのSettings.jsonに記載する
* コアな機能は未実装だったりする
#### VSCode Neovim
* バックエンドでNeovimを使用する
* 別途Neovimのインストールが必要
* 実際のNeovim上で動作するため、多くの機能がinit.vim(.vimrc)そのままで動く

# Vimの設定など
具体的にどのような設定で使っているのかを共有したいと思います。

方針として、できるだけデフォルトの動作からカスタマイズしすぎないようにしているのですが、肌にどうしても合わない設定などは追加したりしています。

#### neovimの設定
<details><summary>init.vim</summary>

```init.vim
" クリップボード共有
set clipboard=unnamedplus

" 削除系のコマンドでレジスタが上書きされないようにする
nnoremap d "_d
nnoremap D "_D
xnoremap d "_d
nnoremap c "_c
nnoremap C "_C
nnoremap s "_s
nnoremap S "_S
xnoremap c "_c
xnoremap C "_C

" xをdに置き換え
nnoremap x d
nnoremap xx dd
nnoremap X D
xnoremap x d

" IME OFF設定
if executable('im-select')
  autocmd InsertLeave * :call system('im-select com.apple.keylayout.ABC')
  autocmd CmdlineLeave * :call system('im-select com.apple.keylayout.ABC')
endif
```
</details>

* OS側のクリップボードとレジスタを共有する設定を追加しています
* 削除系のコマンドでレジスタが上書きされないようにしています
  * なにかをyankした状態で削除してからペーストしたいことが多々あったため、削除系のコマンドのyank先をブラックホールレジスタに変えてしまっています。
  * その代わり`x`を通常の`d`として定義することで削除しながらのyankを切り取りとして定義しています。
* Escでノーマルモードに抜けたときにIMEをOFFにする
  * 直前まで日本語を打っていた場合、Escでインサートモードを抜けて`hjkl`などで移動しようとしても全角が入力されてしまいます。それを避けるために自動でIMEがOFFになるように設定しています。

#### VSCodeのキーバインド
<details><summary>keybindings.json</summary>

```keybindings.json
[
  {
    "key": "space d",
    "command": "editor.action.goToDeclaration",
    "when": "neovim.mode == normal && editorTextFocus",
  },
  {
    "key": "space b",
    "command": "workbench.action.navigateBack",
    "when": "neovim.mode == normal && editorTextFocus",
  },
]
```
</details>

* space+dで定義ジャンプができるようにしています。（space+bで元いたところに戻る）


# まとめ
今回はVimに乗り換えた理由や設定を軽く紹介しました。この記事を見てVimに興味を持つ人がいたら嬉しいです。
まだまだ使いこなすというレベルには達していないので、今後も修行を積んでいきたいと思います。

# おわりに
DONUTSでは新卒中途問わず積極的に採用活動を行っています。
詳細はこちらをご確認ください。

https://www.donuts.ne.jp/recruit/

https://recruit.jobcan.jp/donuts/show/B001/1396297