見出し画像

Vimの新しい自動補完プラグイン「ddc.vim」を使ってみた

電通デジタルでデータサイエンティストを務める吉田です。
これはDentsu Digital Advent Calendar 2021の3日目の記事です。

今回の記事では、今年出てきたばかりのddc.vimというVimの自動補完プラグインを試しに使ってみたので、基本的な実装例と使用感について紹介したいと思います。執筆時点ではまだBeta版とのことですが、動作は安定していて個人的にかなり使用感がよかったので紹介します。

エディタの自動補完について

この記事での「自動補完」とは、入力中のテキストに応じてそのバッファでの既出単語やプログラミング言語の文法に沿った単語の入力候補を自動で表示し、選択できるようにする入力補助機能のことです。これがあるとコーディングスピードが上がったり、型や文法のヒントが表示されるので便利ですね。最近の高級エディタではデフォルトの状態でも自動補完機能が付いているものもあります。

私はローカル/リモート問わずコードを書くときのエディタはVimを使うことが多いのですが、Vimmerの方はご存じの通りVimにはデフォルトでは自動補完などの機能は備わっていないため専用のプラグインを追加して使っていた時期がありました。

「使っていた時期があった」ということで、最近では自動補完機能はずっとオフにしていました。理由はいくつかあるのですが主にはプラグインを追加することによってVimの動作が著しく重くなったり、入力候補の切り替えで編集中の画面がチラつくのが煩わしいと感じることが多かったためです。個々の環境によって差はあると思いますが、自動補完という機能は比較的重いもので、Vimというソフトウェアの性質やプラグインの実装仕様上そういった不便な点が生じるという指摘がされていたのを何度も目にしました。

ddc.vimについて

今年に入ってからddc.vimというVim/Neovim用の新しい自動補完プラグインが出ているのを目にし、かなり軽快に動くとの声が多く上がっていたため試しに使ってみることにしました。

ddc.vimは環境依存の問題が生じにくいDeno(JavaScript/TypeScriptのランタイム環境)で開発されているためインストールが比較的容易でVim8/neovim両方に互換性があるということと、プラグイン内部で非同期処理をすることで高速な処理を実現している点などを特徴に持つようです。
詳しくは作者のShougoさんご自身の記事の中で説明されています。

ddc.vim自体の開発効率とユーザーの設定の自由度を向上させるために、補完に必要な単語や文法の情報を収集する「source」と、表示する補完候補のフィルタリングや優先順位付けを行う「filter」が本体と切り離して開発されており、ユーザーはこのsourceとfilterを好みに合わせてインストールしたり独自に開発したりすることができます。

導入方法と使用感

ddc.vimを利用するにはVim 8.2.0662以上またはneovim 0.5.0以上である必要があるので、これより低いバージョンを使っている場合はアップデートが必要です。また、Deno環境が必要になるので先にインストールしておきます。

Denoの公式ドキュメントに環境ごとのインストール方法の記載がありますが、Windows環境であればScoopやChocolateyなどのパッケージマネージャーに対応しているので容易にインストールできます。

ddc.vim本体と併せてDenoでVimプラグインを開発する環境であるdenops.vimとVim標準の補完を用いずにポップアップウィンドウを表示するpum.vim、そして先に記載したsourceとfilterをインストールします。
個人的に「これは標準的な補完機能を実現するために必要そうだ」と考えてピックアップした下記のsource, filterとともにすべて一緒にインストールします。
記載しているのはvim-plugを使ってインストールする例です。

call plug#begin()
" ddc.vim本体
Plug 'Shougo/ddc.vim'
" DenoでVimプラグインを開発するためのプラグイン
Plug 'vim-denops/denops.vim'
" ポップアップウィンドウを表示するプラグイン
Plug 'Shougo/pum.vim'
" カーソル周辺の既出単語を補完するsource
Plug 'Shougo/ddc-around'
" ファイル名を補完するsource
Plug 'LumaKernel/ddc-file'
" 入力中の単語を補完の対象にするfilter
Plug 'Shougo/ddc-matcher_head'
" 補完候補を適切にソートするfilter
Plug 'Shougo/ddc-sorter_rank'
" 補完候補の重複を防ぐためのfilter
Plug 'Shougo/ddc-converter_remove_overlap'
call plug#end()

LSP(Language Server Protocol)を使うことでプログラミング言語の文法に応じて単語の補完や文法ヒントを表示することができますが、vim-lspvim-lsp-settingsが必要なのでインストールされていない場合はインストールします。vim-lspの使い方については公式のドキュメントに従ってください。

Plug 'mattn/vim-lsp-settings'
Plug 'prabirshrestha/vim-lsp'

インストールしただけではddc.vimは使えず、sourceやfilterの設定をする必要があります。これが少々手間に感じますが、この仕様が補完設定の自由度の高さを支えています。

とりあえず基本的な動きを実現する設定を作成したので、下記の設定を.vimrcに書き込めば一通り動きを確認することができます。

call plug#('Shougo/ddc.vim')
call plug#('vim-denops/denops.vim')
call plug#('Shougo/pum.vim')
call plug#('Shougo/ddc-around')
call plug#('LumaKernel/ddc-file')
call plug#('Shougo/ddc-matcher_head')
call plug#('Shougo/ddc-sorter_rank')
call plug#('Shougo/ddc-converter_remove_overlap')
call plug#('prabirshrestha/vim-lsp')
call plug#('mattn/vim-lsp-settings')

call ddc#custom#patch_global('completionMenu', 'pum.vim')
call ddc#custom#patch_global('sources', [
 \ 'around',
 \ 'vim-lsp',
 \ 'file'
 \ ])
call ddc#custom#patch_global('sourceOptions', {
 \ '_': {
 \   'matchers': ['matcher_head'],
 \   'sorters': ['sorter_rank'],
 \   'converters': ['converter_remove_overlap'],
 \ },
 \ 'around': {'mark': 'Around'},
 \ 'vim-lsp': {
 \   'mark': 'LSP', 
 \   'matchers': ['matcher_head'],
 \   'forceCompletionPattern': '\.|:|->|"\w+/*'
 \ },
 \ 'file': {
 \   'mark': 'file',
 \   'isVolatile': v:true, 
 \   'forceCompletionPattern': '\S/\S*'
 \ }})
call ddc#enable()
inoremap <Tab> <Cmd>call pum#map#insert_relative(+1)<CR>
inoremap <S-Tab> <Cmd>call pum#map#insert_relative(-1)<CR>

ドキュメントにより細かい設定事項についての記載があります。補完を表示し始める最低文字数を設定するminAutoCompleteLength、表示する補完候補の上限数を設定するmaxCandidatesなどを指定できるようになっています。
設定の仕方など仕組みを理解するのに少し時間を要しましたが、環境構築とインストールが容易なのでリモートサーバーにVim環境を整える際にも導入しやすそうです。

以下はPythonコードを例にした動作の様子です。
上記の設定では表示された補完候補に対してTabで選択できるようにしていますが、非常にサクサク動きます。LSPの連携による文法のサポートもしっかり動いています。

画像1

画像2

[Ctrl+N, P]や[Ctrl+X, F]でのVim標準の手動補完機能でも慣れてしまえば大して不自由はないのですが、自動で候補が表示されてTabでサクサク入力していけるのはやはり気持ちがいいです。個人的にはコーディング内容に応じて自動補完のON/OFFを使い分けるのが合っていると思いました。

この記事の執筆時点ではまだddc.vimの導入手順などについて日本語で書かれた記事はあまり多くないので、これから試してみる方の参考になれば嬉しいです。

参考にしたページ

ddc.vim - GitHub
pum.vim - GitHub
denops.vim - GitHub
新世代の自動補完プラグイン ddc.vim - Zenn
自動補完プラグイン ddc.vim + pum.vim - Zenn
Deno - A modern runtime for JavaScript and TypeScript