3.5K Views
April 27, 23
スライド概要
ちょっとお洒落な ddu.vim plugin のつくりかた 2023/04/28 ゴリラ.vim #26 @tennashi (twitter: @tnnsh1, bluesky: tennashi.bsky.social)
ddu.vim って? Shougo/ddu.vim Dark deno-powered UI framework for neovim/Vim8 いわゆるファジーファインダやファイラなどを作るためのフレームワーク ui plugin: 実際に vim 上に描画する役割 source plugin: 画面に表示するアイテムを収集する役割 filter plugin: 収集したアイテムを加工する役割 matcher: 収集したアイテムを絞り込む sorter: 収集したアイテムをソートする converter: 収集したアイテムを変換する kind plugin: 各アイテムで実行できるアクションを定義する役割 cf. https://zenn.dev/shougo/articles/ddu-vim-beta source がコマンドや API などを叩いて列挙した候補を filter で加工/選択して kind に定義されたアクションを 実行する
基本的な ddu.vim plugin の作り方 denops.vim を利用しており、ddu.vim plugin も TypeScript (deno) で記述できる 例えば source plugin の場合 `BaseSource` abstruct class を継承して `Source` class を作る `gather()` method にアイテムの収集処理を実装する `params()` method に source の挙動を制御するためのデフォルト設定を返す処理を実装する cf. https://zenn.dev/shougo/articles/ddu-vim-make-plugins その他の plugin も `Base*` abstruct class を継承して実装を書けばよい
お洒落な? fzf には preview 機能があったり… ここでは 色が付いたり プレビューができたり するような ddu.vim plugin の作り方を紹介する
色を付ける
source の `gather()` method で返す `Item` 型の `highlights` フィールドを設定することで各アイテム
に色を付けることができる
item.highlights = [
{
name: "some name",
hl_group: "Identifier",
col: 1,
width: byteLength(item.display),
},
]
`name`: ハイライト名、被るとうまくハイライトが反映されない
`hl_group`: Vim 上のハイライトグループ `:h highlight-groups`
`col`: ハイライトの開始列 (1 始まり)
`width`: ハイライトする幅 (バイト数)
source plugin の中で実装するもよし、個人的には別に filter plugin を作ってハイライトさせるのが綺麗に見え
てハマっている
プレビューを実装する
kind plugin には `getPreviewer()` method が提供されており、これを実装するとプレビュー機能を提供で
きる
getPreviewer(args: GetPreviewerArguments): Promise<Previewer | undefined> {
const action args.item.action as ActionData;
}
return Promise.resolve({
kind: "terminal",
cmds: ["git", "show", action.commitHash],
});
上記の例だとアイテム上にカーソルがあるときに `git show <commit_hash>` を自動で実行して表示してく
れる
// `ddu-ui-ff` にて `preview` アクションを `autoAction` に設定している場合
`Previewer` 型 `Previewer` 型には `BufferPreviewer`: 存在しているバッファやファイルをプレビューとして表示したいとき `NoFilePreviewer`: 適当な文字列をプレビューとして表示したいとき `TerminalPreviewer`: コマンド実行結果をプレビューとして表示したいとき が用意されており、用途に合わせて使い分ける
おまけ 今回の話題と少しずれるが、ハマったところ denops plugin も ddu.vim plugin も dynamic import を利用しており、deno の `npm:` import は dynamic import に対応していない https://github.com/denoland/deno/issues/17579 多分…仕様って言われそう… アクション実行中にウィンドウのフォーカスが移動できない https://github.com/Shougo/ddu.vim/issues/47 `ActionFlags.RestoreCursor` を用意してもらって `return ActionFlags.RefreshItems | ActionFlags.RestoreCursor` みたいに返せるようになった
最近の悩み 今書いている ddu.vim plugin で困ってるところ Git の remote branch の情報のような取得に時間がかかる情報をアイテムに付与したいときにキャッシュを実 装したくなった キャッシュ自体は denops plugin を別に書くことで簡単に実装できるが、キャッシュが更新されたことを ddu.vim 側に伝える綺麗な方法はないかなーと試行錯誤中
あとは時間の許す限りコードを見るのとデモ