neovimでLSP(LanguageServerProtocol)を使ってみる

今までずっとALEっていう非同期コードチェックプラグインを使ってましたが,少し挙動が遅いと思ってました.

先日この記事を見て,

kutimoti.hatenablog.com

LSPを使うと早くなるっぽい??って思って導入してみました.

結果として,コードチェックは爆速になりました.

LSPとは

この記事に詳細があります.

language server protocolについて (前編)

要約するとLSPを使うことで,

  • 自動補完
  • ヒント(ホバー)の表示
  • シンボルの定義の位置を取得
  • コードの整形
  • エラー分析,修正案の提示

等が利用できるようになります.

neovimでLSPを導入する

LanguageClient-neovimを使います.

上記プラグインを入れる前はvim-lspを入れたのですが,コードチェックの挙動がおかしかったのでやめました.

プラグイン構成

  • LanguageClient-neovim
  • deoplete
  • neosnippet

dein.toml

[[plugins]]
repo = 'autozimu/LanguageClient-neovim'
rev = 'next'
build = 'bash install.sh'
hook_add = '''
source ~/.config/nvim/plugins/LanguageClient-neovim.rc.vim
'''

dein_lazy.toml

[[plugins]]
repo = 'Shougo/context_filetype.vim'

[[plugins]]
repo = 'Shougo/neosnippet.vim'
on_event = 'InsertCharPre'
on_ft = 'snippet'
depends = 'context_filetype.vim'
hook_source = '''
source ~/.config/nvim/plugins/neosnippet.rc.vim
'''

[[plugins]]
repo = 'Shougo/deoplete.nvim'
depends = 'context_filetype.vim'
on_event = 'InsertEnter'
hook_source = '''
source ~/.config/nvim/plugins/deoplete.rc.vim
'''

~/.config/nvim/plugins/LanguageClient-neovim.rc.vim

set hidden

let g:LanguageClient_serverCommands = {}

" 言語ごとに設定する
if executable('clangd')
    let g:LanguageClient_serverCommands = {
        \ 'cpp': ['clangd']
        \ }
endif

augroup LanguageClient_config
    autocmd!
    autocmd User LanguageClientStarted setlocal signcolumn=yes
    autocmd User LanguageClientStopped setlocal signcolumn=auto
augroup END

let g:LanguageClient_autoStart = 1
nnoremap <Leader>lh :call LanguageClient_textDocument_hover()<CR>
nnoremap <Leader>ld :call LanguageClient_textDocument_definition()<CR>
nnoremap <Leader>lr :call LanguageClient_textDocument_rename()<CR>
nnoremap <Leader>lf :call LanguageClient_textDocument_formatting()<CR>

~/.config/nvim/plugins/neosnippet.rc.vim

let g:neosnippet#snippets_directory = '~/.config/nvim/snippets'
imap <C-k> <Plug>(neosnippet_expand_or_jump)
smap <C-k> <Plug>(neosnippet_expand_or_jump)
xmap <C-k> <Plug>(neosnippet_expand_target)
if has('conceal')
    set conceallevel=2 concealcursor=niv
endif

~/.config/nvim/plugins/deoplete.rc.vim

" deoplete options
let g:deoplete#enable_at_startup = 1
let g:deoplete#auto_complete_delay = 0
let g:deoplete#auto_complete_start_length = 1
let g:deoplete#enable_camel_case = 0
let g:deoplete#enable_ignore_case = 0
let g:deoplete#enable_refresh_always = 0
let g:deoplete#enable_smart_case = 1
let g:deoplete#file#enable_buffer_path = 1
let g:deoplete#max_list = 10000

言語ごとのLanguageServerを導入する

https://langserver.org

上記サイトから自身が使う言語のLanguageServerを導入してPATHを通してください.

一例としてclangdをmacで導入する流れを紹介します.

clangdを導入

  • Homebrewでllvmをインストールする

$ brew install llvm

  • PATHを通す

brew install llvmで出力された最後の方に現在のshellでの通し方が書いてあるのでそれを見てください.

  • $ clangd --versionでPATHが通ってることを確認する.

使用感

コードチェックが爆速すぎて気持ちがいい.

今まで:%s/hoge/huga/gで置換をしてたけど,それが変数であれ,コメントであれ全てのhogeが置き換わって不便だった.

LSPの機能のRenameを使うと変数のhogeだけを置き換えるということが出来るので凄くいい.

気になったこと

  • LanguageServerから取得される補完リストを出力するのが少し遅い
  • nvim newfile.*で新たにファイルを作成しつつneovimを起動すると,LanguageServer-neovimが起動しない.手動で:LanguageClientStartとすると起動する.

参考サイト

github.com

github.com

http://langserver.org