ddc.vimを使ってmakeやGinなどのExコマンドの補完を実現する

by
カテゴリ:

ddc.vimは自動補完プラグインの1つです。
Denoをバックエンドにすることで、ユーザーにとっては軽快な挙動を、開発者にとっては高いメンテナンス性を享受できます。

新世代の自動補完プラグイン ddc.vim

コマンドライン補完にも対応しており、組込みの補完よりも補完候補のソースやマッチング、ソーティングにおいて、高い柔軟性を持ちます。

[gin.vim] :https://github.com/lambdalisue/gin.vim

たとえばExコマンドのmakeはターゲットの補完に対応していません。
VimでGitを使うための[gin.vim]が提供するGinコマンドもサブコマンド(commitcherry-pickなど)を補完できません。

Exコマンドの引数の補完をしようと思うと、Exコマンドを定義するタイミングで補完の動作も定義する必要があります(:h command-complete
ユーザーサイドで定義するのは中々厳しいものがありそうですし、本家へのPRも簡単ではなさそうですね……。

でも大丈夫。ddc.vimならできます!

Vimでは:!git switch -c hogeといった具合に、:!から始まるコマンドをシェルで実行する機能があります。
そして、ddc.vim向けには、シェルスクリプト向けの補完候補を提供するddc-source-shell-nativeがあります。

これらをうまく使ってあげると、Exコマンドをあたかもシェルのコマンドのように扱って補完できます。

設定方法

準備するもの

fishの設定

fishはエイリアスを作った場合に、補完定義を大元のコマンドから継承できて便利です。

~/.config/fish/config.fishに以下のように補完したいExコマンドのaliasを書いておきます。

たとえばGinGinBufferは実質的にgitコマンドのラッパーなので、gitへのaliasとして書きます。

alias Gin=git
alias GinBuffer=git

Vimの設定

……と言いつつNeovim向けのLuaになってます。うまく読み替えてください。

最小設定なので補完候補の表示しかできません。
候補選択などをするにはマッピングを設定してください。

-- プラグイン読み込み
vim.opt.runtimepath:prepend("path/to/pum.vim")
vim.opt.runtimepath:prepend("path/to/denops.vim")
vim.opt.runtimepath:prepend("path/to/ddc.vim")
vim.opt.runtimepath:prepend("path/to/ddc-ui-pum")
vim.opt.runtimepath:prepend("path/to/ddc-source-shell-native")
vim.opt.runtimepath:prepend("path/to/ddc-matcher_head")

-- コマンドライン補完の設定
vim.fn["ddc#custom#patch_global"]({
  ui = "pum",
  autoCompleteEvents = { "CmdlineChanged" },
  cmdlineSources = { [":"] = { "shell-native" } },
  sourceOptions = {
    ["shell-native"] = {
      mark = "FISH",
      matchers = { "matcher_head" },
      isVolatile = true,
      minAutoCompleteLength = 0,
      minKeywordLength = 0,
      -- コマンドラインが `!`、`Make `、`Gin `、`GinBuffer `のいずれかで始まる場合のみ有効
      enabledIf = string.format(
        [[getcmdline() =~# "^\\(%s\\)" ? v:true : v:false]],
        table.concat({ "!", "Make ", "Gin ", "GinBuffer " }, [[\\|]])
      ),
    },
  },
  sourceParams = { ["shell-native"] = { shell = "fish" } },
})

function CommandlinePre()
  vim.fn["ddc#enable_cmdline_completion"]()
end

vim.keymap.set("n", ":", "<Cmd>lua CommandlinePre()<CR>:")

おまけ

Gitのコマンド補完と一口に言っても、実装依存でshellによって様々だったりします。
Zshの設定は骨が折れますが、やっておくと、cherry-pickの対象コミットを補完したり、コミットメッセージを見れたりして便利。

ENJOY