ddc.vim 使わない奴いる！？いねえよなぁ！？

何故か「日和ってるやついる！？」が頭に浮かんだんでタイトルにw (東リべ観てないんだけどね...w)

前回に引き続きdotfile の整理でいざneovim の番になったが乱雑にプラグインがインストールされてるしイマイチ設定されてないしで酷かったからいい感じに自分好みにしてくぞ〜
で, 今回はddc.vim！

# ddc.vim とは

https://github.com/Shougo/ddc.vim

彼の有名なShouugoさんが開発された自動補完プラグイン！
プラグインを導入しただけだと何も機能しないけど自分好みにカスタマイズできる！とのことでこれを使う
coc.nvim を使おうか迷ったけど, 巨大すぎて何ができるか理解するのに時間がかかりそうだったから...

# 必要なものがあるお

実際にddc.vim を入れる前に必要なものを入れるお
ddc.vim はDeno 依存なのでインストールが必須！
てことで〜, やってくぞ！

## Deno のインストール

https://deno.com/

Deno の公式を見てみると

```bash
curl -fsSL https://deno.land/install.sh | sh
```

これを実行すると`~/.deno`にインストールされる
そしてあとはパスを通すと使えるようになる！

```zsh
echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.zshrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```

僕はzsh を使ってますが, 適宜修正してね
で, 再読込まで終わったら一応バージョン確認

```zsh
deno --version
deno 1.43.3 (release, x86_64-unknown-linux-gnu)
v8 12.4.254.13
typescript 5.4.5
```

はい！こんな感じで表示されればOK！

## denops.vim の導入

https://github.com/vim-denops/denops.vim

まずdenops.vim ってなんぞやだけど,
> JavaScript/TypeScript のランタイムであるDeno を利用してVim/Neovim 双方で動作するプラグインを作るためのエコシステム
> - Vim / Neovim で同一コードを利用可能
> - Vim プラグインとしてインストールが可能
> - Vim script と比較してエンジンが爆速なのでゴリ押しが可能
> - ユーザーによるライブラリの依存管理が不要
> - プラグインが別プロセスとして動作するため Vim が固まりにくい
> - プラグイン毎にスレッドが分かれているため相互干渉が起こりにくい

引用 [denops.vim とは](https://zenn.dev/lambdalisue/articles/b4a31fba0b1ce95104c9#denops.vim-%E3%81%A8%E3%81%AF)

denops.vim の解説はこんなもんにして[README](https://github.com/vim-denops/denops.vim#for-users
) 通りに導入するお


まずdeno のパスを`g:denops#deno`に代入してあげるので`~/.config/nvim/init.nvim`を開いて

```vim
:echo exepath('deno')
/home/macha/.deno/bin/deno
```

これでパスが確認できたので

```vim:init.vim
let g:denops#deno = '/home/macha/.deno/bin/deno
```

そしてプラグインをインストール！
僕は新規プラグインがあれば自動でインストールしてくれるdein を使ってるので`dein.toml` に

```toml:dein.toml
[[plugins]]
repo = 'vim-denops/denops.vim'
```

を追記して再起動すると無事インストールされるね！

denops が動くか確認するのに`vim-denops/denops-helloworld.vim`をインストールして`:DenopsHello`を実行すると分かるみたい！

```toml:dein.toml
[[plugins]]
repo = 'vim-denops/denops-helloworld.vim'
```

`dein.toml` に追記してコマンドを実行すると〜

```vim
:DenopsHello
Hello, Denops!
```

OK!
今後は使わないから削除してOKだよ〜

donops のプラグインの起動が遅い場合, 共有サーバーを使うと早くなるみたい
僕は使わないけど使う人はどうぞ！

```vim:init.vim
let g:denops_server_addr = '127.0.0.1:32123'
```

```toml:dein.toml
[[plugins]]
repo = 'vim-denops/denops-shared-server.vim'
```

```vim
:call denops_shared_server#install()
```

これでオッケ！

# ddc.vim を導入

事前準備が終わったらddc.vim をインストールしよう！
一旦[Shougo さんの紹介](https://zenn.dev/shougo/articles/ddc-vim-beta#ddc.vim-%E3%81%AE%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95)を忠実に追ってくよ

```toml: dein.toml
# ddc 本体
[[plugins]]
repo = 'Shougo/ddc.vim'
hook_add = '/path/your/config.d/ddc.vim'

# ddc の補完を表示させるやつ
[[plugins]]
repo = 'Shougo/ddc-ui-native'
```

ん？`ddc-ui-native`？
何だお前？と思ったそこのあなた！
コメントに書いたとおり補完を表示してくれるやつ
ddc 自体は補完機能を提供してるだけで表示は別でやらなきゃいけない！(それに気づくまで時間かかった...)

https://github.com/Shougo/ddc-ui-native

で, 補完機能と表示ができるようになっても補完内容が無いので追加！

https://github.com/Shougo/ddc-source-around

https://github.com/Shougo/ddc-filter-matcher_head

https://github.com/Shougo/ddc-filter-sorter_rank

```toml: dein.toml
# バッファー内の情報を補完
[[plugins]]
repo = 'Shougo/ddc-source-around'

# ヘッダーのマッチを
[[plugins]]
repo = 'Shougo/ddc-filter-matcher_head'

# 補完を現在の入力に応じて変化させる
[[plugins]]
repo = 'Shougo/ddc-filter-sorter_rank'
```

一旦これらをインストールして次にddc.vim の設定するお

```vim:config.d/ddc.vim
" ui で何を使用するか指定
call ddc#custom#patch_global('ui', 'native')

" 補完内容を管理
call ddc#custom#patch_global('sources', ['around'])

" 保管時のオプションを管理
call ddc#custom#patch_global('sourceOptions', {
      \ '_': {
      \   'matchers': ['matcher_head'],
      \   'sorters': ['sorter_rank']},
      \ })

" ddc を有効化！
call ddc#enable()
```

これでvim を再起動すると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/ae8db8a0-e91e-b455-0b2a-4febd4522e8f.png)

スクショが見づらいけど〜YES！！！！
補完が動いた〜

次はファイルの補完を！

https://github.com/LumaKernel/ddc-source-file

```toml:dein.toml
[[plugins]]
repo = 'LumaKernel/ddc-source-file'
```

```vim:config.d/ddc.vim
call ddc#custom#patch_global('ui', 'native')

" file を補完候補に追加する
call ddc#custom#patch_global('sources', ['around', 'file'])

" 前の設定だとどっちがaround かfile かわからないのでmark を設定
call ddc#custom#patch_global('sourceOptions', {
      \ '_': {
      \   'matchers': ['matcher_head'],
      \   'sorters': ['sorter_rank']
      \ },
      \ 'around': {
      \   'mark': 'A'
      \ },
      \ 'file': {
      \   'mark': 'F',
      \   'isVolatile': v:true,
      \   'forceCompletionPattern': '\S/\S*',
      \ }})
call ddc#custom#patch_filetype(
    \ ['ps1', 'dosbatch', 'autohotkey', 'registry'], {
    \ 'sourceOptions': {
    \   'file': {
    \     'forceCompletionPattern': '\S\/\S*',
    \   },
    \ },
    \ 'sourceParams': {
    \   'file': {
    \     'mode': 'unix',
    \   },
    \ }})
call ddc#enable()
```

またまた見づらいけどできた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/5369f1a6-a852-f61a-4488-cd7f6fc38fa5.png)

file は違うけどShougo さんの後を追ってきたからここからは僕が好きなようにイジっていくぜ〜 :thumbsup: 

# TABで補完したくないやついる！？いねえよなぁ！？

またまた擦ってTAB 補完！
デフォルトだとTABがそのままになってるので補完できるように
[ddcのdoc](https://github.com/Shougo/ddc.vim/blob/main/doc/ddc.txt#L633) を見ると`ddc-ui-native`用の設定が書いてある！
ありがたや〜

```vim:init.vim
" <TAB>: completion.
inoremap <expr> <TAB>
    \ pumvisible() ? '<C-n>' :
    \ (col('.') <= 1 <Bar><Bar> getline('.')[col('.') - 2] =~# '\s') ?
    \ '<TAB>' : ddc#map#manual_complete()

" <S-TAB>: completion back.
inoremap <expr> <S-TAB>  pumvisible() ? '<C-p>' : '<C-h>'
```

でもTAB いっぱい押すの嫌だから<C-j>, <C-k>も使えるようにしよう！

```vim:init.vim
" <C-j>: completion.
inoremap <expr> <C-j>
    \ pumvisible() ? '<space>' :
    \ (col('.') <= 1 <Bar><Bar> getline('.')[col('.') - 2] =~# '\s') ?
    \ '<TAB>' : ddc#map#manual_complete()
" <C-k>: completion back.
inoremap <expr> <C-k>  pumvisible() ? '<C-p>' : ''
```

# source を更に追加していくぞ〜

TAB 補完とかを有効にしたらsource (補完候補) を増やして便利にするぜ :sunglasses: 
ddc のsource は[Topics](https://github.com/topics/ddc-source) にまとめてあるから自分で好きなのを選ぼう！

## ddc-source-vim-lsp

https://github.com/shun/ddc-source-vim-lsp

やっぱコードを書くなら[LSP](https://e-words.jp/w/LSP-2.html) (Language Server Protocol) は欲しいでしょってことで`ddc-source-vim-lsp`！

この子は`vim-lsp`も必要とのことなのでこれの設定ができる`vim-lsp-settings`もついでに

```toml:dein.toml
[[plugins]]
repo = 'prabirshrestha/vim-lsp'

[[plugins]]
repo = 'mattn/vim-lsp-settings'
hook_add = '''
execute 'source ' . g:plugin_config_dir . '/hook/vim-lsp-settings.vim'
'''

[[plugins]]
repo = 'shun/ddc-source-vim-lsp'
```

```vim:config.d/ddc.vim
call ddc#custom#patch_global('sources', [
    \ 'around',
    \ 'file',
    \ 'vim-lsp',
    \ ])

call ddc#custom#patch_global('sourceOptions', {
    \   '_': {
    \     'matchers': ['matcher_head'],
    \     'sorters': ['sorter_rank']
    \   },
    \   'around': {
    \     'mark': 'A'
    \   },
    \   'file': {
    \     'mark': 'F',
    \     'isVolatile': v:true,
    \     'forceCompletionPattern': '\S/\S*',
    \   },
    \   'vim-lsp': {
    \     'mark': 'lsp',
    \     'forceCompletionPattern': '\.\w*|:\w*|->\w*',
    \   },
    \ })
```

vim-lsp-settings の設定は別の記事で！(今後追加予定)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/987f4110-e601-8e94-b449-df8181bc1fb1.png)

とりあえずおっけ〜

## ddc-tabnine

AI がいい感じにコードを提案してくれるやつ！
github Copilot に似たサービスで無料でも使える :thumbsup: 

```toml:dein.toml
[[plugins]]
repo = 'LumaKernel/ddc-tabnine'
```

```vim:config.d/ddc.vim
call ddc#custom#patch_global('sources', [
    \ 'around',
    \ 'file',
    \ 'vim-lsp',
    \ 'tabnine',
    \ ])

call ddc#custom#patch_global('sourceOptions', {
    \   '_': {
    \     'matchers': ['matcher_fuzzy'],
    \     'sorters': ['sorter_fuzzy'],
    \     'converters': ['converter_fuzzy'],
    \     'minAutoCompleteLength': 1,
    \   },
    \   'around': {
    \     'mark': 'A'
    \   },
    \   'file': {
    \     'mark': 'F',
    \     'isVolatile': v:true,
    \     'forceCompletionPattern': '\S/\S*',
    \   },
    \   'vim-lsp': {
    \     'mark': 'lsp',
    \     'forceCompletionPattern': '\.\w*|:\w*|->\w*',
    \   },
    \   'tabnine': {
    \     'mark': 'TN',
    \     'maxItems': 5,
    \   },
    \ })
```

これでできたと思ったけど

```vim
[denops] [ddc-tabnine] Failed to install TabNine cli version 4.160.0.
```

インストールが失敗してるけどなぜだ？

### ddc-tanine でTabNine のインストールが失敗するぞ...

どうにかして使えるようにしたいのでとりあえずファイルがあるかわからないから確認を
デフォルトで`Default: <XDG Cache Dir>/ddc-tabnine/binaries`にインストールされるらしいので確認すると

```zsh
ls <XDG Cache Dir>/ddc-tabnine/binaries/4.160.0

```

何も見つからず
`ddc_tabnine#reinstall()`という関数があるらしいので実行してみると

```
function ddc_tabnine#reinstall[1]..denops#request[1]..denops#_internal#server#chan#request[6]..denops#_internal#rpc#nvi
m#request の処理中にエラーが検出されました:
```

まだだめだぁ
もう一度ディレクトリを確認してみると

```zsh
ls <XDG Cache Dir>/ddc-tabnine/binaries/4.160.0
x86_64-unknown-linux-musl
```

お！
ディレクトリが増えてる！
中を見てみると

```zsh
ls <XDG Cache Dir>/ddc-tabnine/binaries/4.160.0/x86_64-unknown-linux-musl
TabNine.zip
```

Zip ファイルがある！
これを解答してみると

```zsh
unzip TabNine.zip
Archive:  TabNine.zip
  inflating: TabNine
  inflating: TabNine-deep-cloud
  inflating: TabNine-deep-local
  inflating: TabNine-server-runner
  inflating: WD-TabNine
ls
TabNine  TabNine-deep-cloud  TabNine-deep-local  TabNine-server-runner  TabNine.zip  WD-TabNine
```

色々出てきた
一旦vim を再起動してみると

```vim
:messages
[ddc] PermissionDenied: Failed to spawn '<XDG Cache Dir>/ddc-tabnine/binaries/4.160.0/x86_64-unknown-linux-musl/TabN
ine': Permission denied (os error 13)
```

権限が無いと
確認してみると

```zsh
ls -l
合計 125M
-rw-r--r-- 1 macha macha  44M  5月  6 17:48 TabNine
-rw-r--r-- 1 macha macha  13M  5月  6 17:48 TabNine-deep-cloud
-rw-r--r-- 1 macha macha  15M  5月  6 17:48 TabNine-deep-local
-rw-r--r-- 1 macha macha 6.3M  5月  6 17:48 TabNine-server-runner
-rw-rw-r-- 1 macha macha  40M  5月 19 01:43 TabNine.zip
-rw-r--r-- 1 macha macha 8.8M  5月  6 17:48 WD-TabNine
```

実行権限が無いからだ
`chmod +x`で与えてあげると

```zsh
chmod +x TabNine TabNine-deep-cloud TabNine-deep-local TabNine-server-runner WD-TabNine
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/f017a5d0-8a2b-6416-8b59-7b11a9fc3581.png)

お！無事使えるようになった！

# filter も追加だ！

source の追加が終わったら次はfilter を追加するぞ〜

## ddc-fuzzy

人間と同じようにvim にも曖昧でいて欲しいからフィルターをfuzzy に！
その関係で初めに入れた`ddc-filter-sorter_rank`と`ddc-filtermatcher_head`は削除するよ〜

```toml:dein.toml
[[plugins]]
repo = 'tani/ddc-fuzzy'
```

```vim:config.d/ddc.vim
call ddc#custom#patch_global('sourceOptions', {
    \   '_': {
    \     'matchers': ['matcher_fuzzy'],
    \     'sorters': ['sorter_fuzzy'],
    \     'converters': ['converter_fuzzy'],
    \     'minAutoCompleteLength': 1,
    \   },
    \   'around': {
    \     'mark': 'A'
    \   },
    \   'file': {
    \     'mark': 'F',
    \     'isVolatile': v:true,
    \     'forceCompletionPattern': '\S/\S*',
    \   },
    \   'vim-lsp': {
    \     'mark': 'lsp',
    \     'forceCompletionPattern': '\.\w*|:\w*|->\w*',
    \   },
    \ })
    
call ddc#custom#patch_global('filterParams', {
    \   'matcher_fuzzy': {
    \     'splitMode': 'word'
    \   }
    \ })
```

何がどう変わったかわ分かんないけどOK！

# 補完候補多すぎでは？？

特に何もイジってないと`lsp`がめっっっっちゃ出てきちゃう...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/823bc22f-a2c0-4c4c-e904-27bf13c21be3.png)


こんなにあっても困るので表示数を少なくしちゃう！
ついでにTabNine の候補をデフォルトの5から10にするよ〜

`maxItems`を指定してあげると調整できる〜

:::note warn
2022.02.22 にmaxCandidates からmaxItems にリネームされてるから注意！
https://github.com/Shougo/ddc.vim/blob/main/doc/ddc.txt#L1752
:::


```vim:config.d/ddc.vim
call ddc#custom#patch_global('sourceOptions', {
    \   '_': {
    \     'matchers': ['matcher_fuzzy'],
    \     'sorters': ['sorter_fuzzy'],
    \     'converters': ['converter_fuzzy'],
    \     'minAutoCompleteLength': 1,
    \   },
    \   'around': {
    \     'mark': 'A'
    \   },
    \   'file': {
    \     'mark': 'F',
    \     'isVolatile': v:true,
    \     'forceCompletionPattern': '\S/\S*',
    \   },
    \   'vim-lsp': {
    \     'mark': 'lsp',
    \     'maxItems': 15,
    \   },
    \   'tabnine': {
    \     'mark': 'TN',
    \     'maxItems': 10,
    \   },
    \ })
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/39f6049b-e0f4-70b4-3e06-695e7245e857.png)

おけおけ

# 補完候補の順番を変えたい...

今は
1. around
1. file
1. lsp
1. tabnine

の順になってるけどaround は下でいいし, tabnine は上にいて欲しいので`ddc#custom#patch_global('sources'`の順番をイジるお

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/2b484564-8ec0-445d-06a9-cf8164ed7212.png)

```vim:config.d/ddc.vim
call ddc#custom#patch_global('sources', [
    \ 'tabnine',
    \ 'file',
    \ 'vim-lsp',
    \ 'around',
    \ ])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199251/ff05632e-98c0-74ca-544c-4af41df6865b.png)

おっけ〜

# こんな感じかな〜

いい感じに補完ができるようになったぜ〜
まだプラグインとか見直し中だからもしかしたらもうちょっと変わるかもしれないけど今回はここまで！

次は`vim-lsp-settings` で :hand_splayed: 

# 参考文献

https://zenn.dev/shougo/articles/ddc-vim-beta

https://github.com/Shougo/ddc.vim/tree/main

https://qiita.com/t7u-ito/items/e43cbb8597ffa21835a6