Open10

Vim8 + vim-jetpack + vim-lsp + ddc.vim

heavenshellheavenshell

前提

現状 Vim8 で 魔改造 neocomplete と vim-lsp、魔改造 tsuquyomi という構成で普段コードを書いていて困ってない(たまに tsuquyomi が爆発するくらい)。
流石に古い環境なので最新のプラグインが自分の実用に耐えられるか素振りをする。

今の環境を汚したく無いので Docker で環境構築をしてすぐ捨てられるように。

  • LSP クライアントはvim-lsp(と vim-lsp-settings)
  • 補完は ddc.vim
  • パッケージマネージャーはなんでも良いので jetpack を試す
heavenshellheavenshell

まずは Vim8 をビルド。
適当にシェルスクリプトをでっち上げ、実行。

#!/bin/sh

git clone --depth 1 https://github.com/vim/vim  $HOME/src/vim
cd $HOME/src/vim
mkdir $HOME/src/build

./configure \
  --prefix=$HOME/src/build \
  --with-features=huge \
  --enable-multibyte \
  --enable-terminal \
  --enable-cscope \
  --enable-fail-if-missing \
  --enable-python3interp=dynamic \
  --enable-luainterp \
  --with-luajit \
  --with-tlib=ncurses
make
make install
heavenshellheavenshell

jetpack とか deno とかを入れるため適当なシェルスクリプを作成

curl -fLo ~/.vim/autoload/jetpack.vim --create-dirs \
    https://raw.githubusercontent.com/tani/vim-jetpack/master/autoload/jetpack.vim

curl -fsSL https://deno.land/x/install/install.sh | sh
echo 'export DENO_INSTALL="${HOME}/.deno"' >> ~/.bash_profile
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bash_profile

curl -L git.io/nodebrew | perl - setup
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
echo 'export PATH=$PATH:./node_modules/.bin' >> ~/.bash_profile

echo 'export PATH=/$HOME/src/build/bin:$PATH' >> ~/.bash_profile

. ~/.bash_profile

nodebrew install-binary v16.15.0
nodebrew use v16.15.0

nodebrew を入れてるのは Ubuntu の apt で入るのが v10.x だっため、nodebrew で適当に入れる。
(pyright とかが Node が必要)

heavenshellheavenshell

vimrc を作成

autocmd!
set nocompatible

call jetpack#begin()

Jetpack 'vim-denops/denops.vim'
Jetpack 'Shougo/ddc.vim'

" sources
Jetpack 'Shougo/ddc-around'
Jetpack 'Shougo/ddc-omni'
Jetpack 'matsui54/ddc-buffer'
Jetpack 'LumaKernel/ddc-file'

" filters
Jetpack 'Shougo/ddc-matcher_head'
Jetpack 'Shougo/ddc-sorter_rank'

call jetpack#end()
let s:sources = [
  \  'omni',
  \  'around',
  \  'buffer',
  \  'file',
  \ ]
let s:sourceOptions = {
  \ '_': {
  \   'matchers': ['matcher_head'],
  \   'sorters': ['sorter_rank'],
  \ },
  \ 'omni': {
  \   'mark': 'O',
  \   'forceCompletionPattern': '\.\w*|:\w*|->\w*',
  \   'minAutoCompleteLength': 1,
  \ },
  \ 'buffer': {'mark': 'B'},
  \ 'around': {'mark': 'A'},
  \ 'file': {
  \   'mark': 'F',
  \   'isVolatile': v:true,
  \   'forceCompletionPattern': '\S/\S*',
  \ }}
call ddc#custom#patch_global('sources', s:sources)
call ddc#custom#patch_global('sourceOptions', s:sourceOptions)

call ddc#custom#patch_global('sourceParams', {
    \ 'buffer': {
    \   'requireSameFiletype': v:false,
    \   'limitBytes': 5000000,
    \   'fromAltBuf': v:true,
    \   'forceCollect': v:true,
    \ },
    \ })
call ddc#enable()
function! s:on_lsp_buffer_enabled() abort
  setlocal omnifunc=lsp#complete
  setlocal signcolumn=no
  if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif
endfunction

augroup lsp_install
  autocmd!
  autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END

let g:lsp_async_completion = 1
let g:lsp_use_event_queue = 1

let g:lsp_settings_filetype_typescript = ['deno', 'typescript-language-server']

let g:lsp_settings = {}
let g:lsp_settings['pyright-langserver'] = {
\ 'allowlist': ['python'],
\ 'workspace_config': {
\   'python': {
\     'analysis': {
\       'useLibraryCodeForTypes': v:true,
\       'typeCheckingMode': 'off',
\     },
\   },
\  }}

ddc.vim は neocomplete と同等の環境を目指すのでとりあえず omni, file, buffer, around あたりを。
vim-lsp は pyright ととりあえず typescript-language-server を入れる。

heavenshellheavenshell

omni が補完の途中で消える。

deno を補完

補完の元になるソースごとに違うのか、挙動が怪しい。
consoleと入力し . を打った時点で補完は出て期待通りだが、補完ウィンドウを消して、もう一度 . を打っても補完ウインドウが表示されない。

vim-lsp の omni 補完で pyright を補完

pyright は . を打てば出てくるが、__ と絞り込んだら around とかで omni のが補完消えてしまう。

heavenshellheavenshell

これはどうしたもんかと思い、ふと pum.vim を入れたら良いのかなと思い導入してみる。

Jetpack 'Shougo/pum.vim'

call ddc#custom#patch_global('completionMenu', 'pum.vim')
inoremap <C-n> <Cmd>call pum#map#select_relative(+1)<CR>
inoremap <C-p> <Cmd>call pum#map#select_relative(-1)<CR>
inoremap <C-y> <Cmd>call pum#map#confirm()<CR>
inoremap <C-e> <Cmd>call pum#map#cancel()<CR>

を追加。

heavenshellheavenshell

vim-lsp(pyright) + ddc.vim + pum.vim

vim-lsp(deno) + ddc.vim + pum.vim

期待通りになった 🎉

heavenshellheavenshell

これで乗り換えられると思い、typescript-language-server を試してみたが、tsserver と比べて微妙に機能が足りんかなぁと思うところがあった。

vim-lsp(typescript-language-server)

tsuquyomi(tsserver)

出てくる補完の量が全然違う。

heavenshellheavenshell

tsserver は LSP を使わず tsuquyomi のままでいくかと思い、jetpack でインストールしても非常に遅い(遅延にならない)。
そこだけ今まで通り秘伝のタレ(遅延ロード)を使ってロードするのもなぁと思い、tsserver が真に LS 化するまで、とりあえずは今まで通りでいいやとなった。

heavenshellheavenshell

ddc.vim とネィティブの omni 補完は微妙な感じだったけど pum.vim を使えば特に困ることもなさそう。
asynccomplete.vim が omni 補完を使ったときに buffer とか around の補完で上書きされて、自分にはあってないと思ったので、乗り換えるのなら ddc.vim + pum.vim が良さそう。
また ddc-vim-lsp とか asyncomplete-vim-lsp とか常に LS と通信して補完候補を表示するのは好きじゃ無いので使わない。

手動で C-x C-o とかその他の Vim の補完を使うスタイルなので、手動で補完を実行したらそっちを優先して出してほしいなどの使い方をしていて ddc.vim + pum.vim は邪魔をしないので良さそう。