Vimにcoc.nvimを入れたら便利すぎて感動したっていう話


ぼくはパソコンは実家にしか無く、開発系は全てAndroidの[Termux](https://play.google.com/store/apps/details?id=com.termux)で済ませなくてはなりません。
(Termuxを使えば結構色々なLinux系のコマンド、ソフトを使えるのでたいへん助かってます)
よって、ぼくの開発環境は"ポケットIDE"。そう、(neo)Vimです。

こういうわけで、開発毎に、それぞれの言語の補完プラグイン、Linter(これはうまく動かなかったのだが)を入れ、またファイラを入れ、がんばっていた訳です。

#プロローグ
数年前、ネットをVimについてググりサーフィンしていると、"LSP"という単語が目に入りました。"Language Server Protocol"。どうやら、コーディング補助系について規格化したものであるようなのです。
(参考:https://langserver.org/)

Vimに対応させるプラグインも出てきたと聞いて、すぐ飛びついた訳ですが、当時、ぼくは英語力も拙く、READMEさえも読めずにうまく設定すらもできないで諦めてしまいました。

受験を経て、ある程度英語力もついたことだし、または、LSP界隈も活発になっているかも？と期待して、調べてみると、実装も複数なされていて、どうやら聞き覚えのないものも出てきているようです。その一つが[coc.nvim](https://github.com/neoclide/coc.nvim)でした。

#coc.nvimの導入
Vim(8.0.1453以上) || Neovim(0.3.1以上)が必要です。

まず、Node.jsとyarnを入れましょう。

```bash:install.sh
apt install nodejs
npm install -g yarn
```

あとはcoc.nvim自体をいつものパッケージマネージャなどの方法で加えるだけです。

###vim-plugを導入済みの場合
ぼくはvim-plugなので、以下をinit.vim(vimrc)に書き加えます。

```vimscript:init.vim
Plug 'neoclide/coc.nvim', {'branch': 'release'}
```

そして `:PlugInstall` をノーマルモードでEnter。
インストール時に色々足りないって注意されたのですが、その都度指摘してくれ、選択すれば自動でそれらをインストールしてくれました。


これで終わりです。[このページ](https://github.com/neoclide/coc.nvim)も参照してみてください。

#各種設定など
`:help coc-nvim.txt`でヘルプが見れます。

coc.nvimの設定ファイルはコマンド`:CocConfig`で開くことができます。ただ、デフォルトでも使いにくいわけではないです。

また、coc.nvimのExtension、というものがあり、機能追加・拡張ができます。各言語のlanguageserverもあります。
coc.nvimの拡張専用のパッケージマネージャがあり、それでExtensionを管理してくれます。

試しにtypescript/javascriptのサーバーであるcoc-tsserverを入れてみます。コマンドモードで以下をEnter:

```vim:cocinst.vim
:CocInstall coc-tsserver
```

また、設定すれば、Extensionにないサーバーも使えます。

(2021/01/03追記：現在はC言語のcocエクステンションも存在するようですが、エクステンションにないLSPサーバーの設定方法の例示として以下を残しておきます)

例えば、C系のサーバーのclangdだと、coc.nvimの設定ファイルに、

```json:coc-settings.json
{
  "languageserver": {
    "clangd": {
      "command": "clangd",
      "filetypes": ["c", "cpp", "objc", "objcpp"]
    }
  }
}
```

このように書けば使えるようになります。
[ここ](https://github.com/neoclide/coc.nvim/wiki/Language-servers)に、各種言語について設定方法などをまとめて下さっているので参照してみてください。

#coc.nvimの機能
coc.nvimで対応が実装されている各機能を調べてみました。
##AutoCompletion
デフォルトでリアルタイムの補完が効きました。
![cmpl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/e8d2b087-3634-73bf-799f-e9c0c3e2d667.gif)
また、何もサーバーなどを登録せずとも、Vimでデフォルトで使える補完の、ファイル、バッファ、aroundの補完候補は一覧で出てきます。

##Diagnostics
エラー、警告、インフォメーションが表示されます。その場所にカーソルを合わせるとメッセージが見れます。
![Screenshot_20190625-205610_Termux.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/195eaee5-b8ed-15dc-bb20-191d6b199445.jpeg)
画面左端のアイコンの背景色・文字色の設定をするには、init.vim(vimrc)に、例えば以下のようにして書き加えます。

```vimscript:init.vim
highlight CocErrorSign ctermfg=15 ctermbg=196
highlight CocWarningSign ctermfg=0 ctermbg=172
```

15、196、0、172が色です。[このサイト](https://jonasjacek.github.io/colors/)の"Xterm Number"を参照してみてください。

##CocList
多機能セレクタと呼ばれるものです。かなり便利です。CtrlPに類似しています。
デフォルトでもextentionのトグル、diagnosticsのリスト表示とジャンプ、symbolの検索まで色々できます。
さらに、拡張`coc-lists`を入れると、ファイル検索、grep検索、buffer移動など、もう何でもできます…
何でも突っ込んだ感じになる機能ですが、あいまい検索ができるので割とスムーズに操作できます。

![recording_20190625_203809.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/ac83a16d-b8f2-acd6-c193-a681aefaac7d.gif)

Vimプラグイン(cocの拡張ではない)の `coc-fzf`([リンク](https://github.com/antoinemadec/coc-fzf))を入れると候補の検索に[FZF](https://github.com/junegunn/fzf)を使うようになり、軽快な動作になります。
詳しくは [こちら](https://qiita.com/Amadeus_vn/items/4be5fbfda38fddd765ff) で別に扱っているので興味があれば御覧ください。

##Hover
ヒント(ホバー)を読むことができます。
2019/06/25の時点では、NeoVimのnightlyビルドではfloating windowが使えるようですが、これはそれにも対応しています。
残念ながら、Termux版はstableのみなのでpreview windowにヒントが表示されています。
![Screenshot_20190625-220825_Termux.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/d11ebc83-92e4-99dc-5dd0-38cec33dd3c9.jpeg)

【2019年9月27日追記】
Termux版のNeoVimでfloating windowが有効になったようです。
![20190927_133652.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/6e9fd837-a39c-c902-2953-def569afbd3f.jpeg)

##References
参照先を一覧にして見ることができます。
![Screenshot_20190625-220646_Termux.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/6524de40-99d9-4162-d242-afb113a9df57.jpeg)

##Definition
定義にジャンプします。
![recording_20190625_215859.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/3449e47d-eb93-7db6-8d28-606d5d35ee6b.gif)

別ファイルに定義が書いてある場合、別ファイルのバッファを開き、ジャンプしてくれます。

##Rename
変数名などを一括リネームします
![recording_20190710_012858.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/9ce72731-3a03-655d-2cb8-87682c2e880d.gif)

##Format
ソースコードを綺麗に整えます。
![recording_20190806_143408.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229154/d55226e4-0cbf-f67a-efb2-4570956bb20a.gif)


#機能の呼び出し方
多数の機能がある！と言うことは調べてみて割とすぐにわかったのですが、呼び出し方がちょっと引っかかったのでメモしておきます。

| 機能 | 呼び出し方 |
|:---:|:---|
|AutoCompletion|insertモードで既に有効 |
|Diagnostics|画面左端にマーク表示されている<br>CocList内にリスト有|
|CocList|:CocListコマンドで呼び出し|
|Hover|:call CocAction('doHover')で呼び出し|
|References|\<Plug\>(coc-references)で呼び出し|
|Definition|\<Plug\>(coc-definition)で呼び出し|
|Rename|\<Plug\>(coc-rename)で呼び出し|
|Format|\<Plug\>(coc-format)で呼び出し|
これらをそれぞれショートカット設定などして呼び出す感じかな。
少しバラバラに思えるのですが、多分本当はもっと奥深く体系だった構成なのでしょう。
coc.txtをもっと読み解かなくては……。

#init.vim(vimrc)の例
自分のinit.vimからcoc.nvim周りのものを抜粋・コメントしました。
もしよかったら参考にどぞ。

```vimscript:init.vim
﻿call plug#begin('~/.vim/vim-plug')
  Plug 'itchyny/lightline.vim'
  Plug 'neoclide/coc.nvim', {'branch': 'release'}
call plug#end()

"LightLineにcoc.nvimのステータスを載せます
let g:lightline = {
  \'active': {
    \'right': [
      \['coc']
    \]
  \},
  \'component_function': {
    \'coc': 'coc#status'
  \}
\}

"Diagnosticsの、左横のアイコンの色設定
highlight CocErrorSign ctermfg=15 ctermbg=196
highlight CocWarningSign ctermfg=0 ctermbg=172

"以下ショートカット

"ノーマルモードで
"スペース2回でCocList
nmap <silent> <space><space> :<C-u>CocList<cr>
"スペースhでHover
nmap <silent> <space>h :<C-u>call CocAction('doHover')<cr>
"スペースdfでDefinition
nmap <silent> <space>df <Plug>(coc-definition)
"スペースrfでReferences
nmap <silent> <space>rf <Plug>(coc-references)
"スペースrnでRename
nmap <silent> <space>rn <Plug>(coc-rename)
"スペースfmtでFormat
nmap <silent> <space>fmt <Plug>(coc-format)
```


#まとめや追伸
使ってみた感じですが、Androidスマホでもヌルヌルでサクサク動いて快適です。
これでまたvimが真のideに近づいていけます。
嬉しい限りですね。

この先、新たな発見等をしたら追記していこうと思います。