Note
この記事はVim 駅伝の 10/16 の記事です。
TL;DR
- CLI ツールを管理する方法として、Vim/Neovimのプラグインマネージャーを使うと意外と便利
はじめに
皆さんはCLI ツールをどのように管理していますか?
私はmacOSで使うツールの管理に以下のパッケージマネージャーたちを使っています。
- 汎用的なパッケージマネージャー
- 言語ごとのパッケージマネージャー
- ツールごとのパッケージマネージャー
結構多いですね。 ツールは多岐にわたるので、それぞれのツールに合ったパッケージマネージャーを使っています。
理想のパッケージマネージャー
私は複数マシンを使っているので、マシン間の設定をdotfilesとして管理しています。
https://github.com/ryoppippi/dotfiles
自分がdotfilesで使用するパッケージマネージャーに求める条件は以下の通りです。
- パッケージマネージャーのインストール、アンインストールが簡単
- パッケージマネージャーの設定をDeclarativeに記述できる
- パッケージマネージャがー管理するツールの設定やバージョンをDeclarativeに記述できる
- Lockfileでバージョン、差分を管理できる
- パッケージマネージャーが管理するツールのバージョンを切り替えることができる/簡単に戻すことができる
- 設定量は多過ぎず少な過ぎず
- 暗黙の動作が少ない
これらを満たしていると、Github上で差分も簡単に確認でき、またマシン間でもgit pullして簡単なコマンドを打つだけで環境を再現できるので、とても便利です。
Aqua
これらを条件を考えた時に、汎用のパッケージマネージャーにおいては、Aquaが一番条件を満たしていると思います。
AquaはYAMLでDeclarativeにツールを管理でき、またRenovateを併用すれば最新版の確認、更新も簡単にできます。 また、設定もプリセットのものが多く、もし欲しいツールがなかった場合も本家のRegistryにPull Requestを送ることで追加できます。 そのため、自分の使用するCLI ツールは極力Aquaで管理したいと思っています。
しかし、AquaはGo言語以外のビルドをサポートしていないので、Go言語以外で書かれていて尚且つバイナリが提供されていないツールを管理することができません。 また、特定の場所にインストールが必要なもの(gh extension)も管理できません。
追記: CargoによるInstallにも対応しているようです!
afx
自分は使用していないのですが、afxというパッケージマネージャーもあります。
https://github.com/babarot/afx
このパッケージマネージャーはAquaと同じくYAMLでDeclarativeにツールを管理できます。 AquaのようなRegistryは存在しないので、自分でビルドスクリプトを書く必要がありますが、その分ビルドスクリプトを定義したり、gh extensionを管理したりと、より柔軟な管理ができます。 とても魅力的なパッケージマネージャーですが、以下の理由で自分は使用していません。
- 更新時、Releaseにあるものは最新版をチェックして落とすことができるが、例えばmain ブランチのHEADを落としてきてビルドするようなことはできない
- Lockfileを採用していないので、ツールのバージョン一覧を1箇所で確認することができない
- (これはAquaも同じであるが) YAMLで設定を記述するので、設定量が多いとYAMLの記述が煩雑になる
- (これはafxは何も悪くないのですが)これ以上パッケージマネージャーを増やしたくない
とても良いパッケージマネージャーではあるので、ぜひ皆さんチェックしてみてください。
解: lazy.nvimを悪用する
というわけで、自分が求める条件を満たすパッケージマネージャーがなかなか見つかりません。
これは自分で作るしかないのかなと思いつつ、なかなか手がつけられない中数ヶ月が経ちました。
そんな中、先日の駅伝でslinさんがvim/neovimのパッケージマネージャーであるdeinを悪用して、IMEの辞書を管理する方法を紹介していました。
https://github.com/Shougo/dein.vim
https://zenn.dev/slin/articles/2023-10-02-skktips#辞書をdeinで管理する
またこれについて楽園で盛り上がっていたところ、CLI ツールを管理するのにも使えるんじゃないかという話になりました。
これについて考えてみると、vim/neovimのパッケージマネージャー、特に自分の使っているlazy.nvimは以下のような特徴があります。
- パッケージマネージャーのインストール、アンインストールが簡単 → vimの設定の一部なのですでにある
- パッケージマネージャーの設定をDeclarativeに記述できる → lua で記述できる
- パッケージマネージャーが管理するツールの設定やバージョンをDeclarativeに記述できる → lua で記述できる
- Lockfileでバージョン、差分を管理できる →
lazy-lock.jsonが生成されるので、差分が取れる - 設定量は多過ぎず少な過ぎず → お作法に乗っ取れば、設定量は少ない。独自のビルドの設定も記述できる
https://github.com/folke/lazy.nvim
というわけで、1からパッケージマネージャーを作るよりも、vim/neovimのパッケージマネージャーを悪用する方が簡単そうだなと思い、実際に設定を書いてみました。
以下に自分がAqua/Homebrew管理外だったツールをいかにして管理したかを書いていきます(da-ja-re)。
gh extensionの管理
gh extensionは、ghコマンドの拡張機能です。 自分もいくつか愛用しているものがあります。
https://github.com/ryoppippi/gh-cr https://github.com/yusukebe/gh-markdown-preview https://github.com/actions/gh-actions-cache https://github.com/seachicken/gh-poi
これらのコマンドはghコマンドと一緒に使うことで、githubにまつわる便利な機能を提供してくれます。 しかし、これらのツールを管理するツールは(現時点ではafxをのぞいて)存在しません。
これをlazy.nvimで管理してみましょう。
この設定ファイルの中でやっていることは以下の通りです。
- 指定したレポジトリの最新版を落としてくる
- go build する
- ビルドされたバイナリをgh extensionのディレクトリ(macOSでは
~/.local/share/gh/extensions/)に配置する
これで、gh extensionをlazy.nvimで管理することができました。
新しいgh extensionを追加したい場合は、この設定ファイルに追記するだけで、lazy.nvimのアップデートをすると、自動的に最新版が落とされます。
別のマシンを使う時にも、dotfilesをpullしてNeovimを起動するだけで、最新版のgh extensionが自動的にインストールされます。
lazy-lock.jsonにバージョンが記述されるので、差分も確認できて嬉しいですね。
追記: gh extension install .でローカルのレポジトリをインストールできることを知り、設定を簡素化しました。 https://github.com/ryoppippi/dotfiles/blob/b0a7e71f797259847106786a1fce7eefef4b18b3/nvim/lua/cli/gh.lua
zlsの管理
zlsはzigのLanguage Serverです。 https://github.com/zigtools/zls
自分はzigのHEADを使っているので、zlsを使用するにはmasterをcloneして最新版のzigでビルドする必要があります。
今までは毎日手動でzlsからgit pull、ビルドしていましたが、これもlazy.nvimで管理することにしました。
これもやっていることは簡単で、lazy.nvimでアップデートをすると、zlsのレポジトリをgit pullして勝手にビルドしてくれます。 あとはビルドされたバイナリをnvim-lspconfigで指定するだけで、zlsを使うことができます。
これで、zlsをlazy.nvimで管理することができました。
まとめ
この記事では、vim/neovimのプラグインマネージャーを悪用してCLI ツールを管理する方法、そしてlazy.nvimを使用した具体的な設定を紹介しました。 推奨されている方法ではないので、自己責任でお願いします。
これまで、Vimはエディタとして、単なる便利なCLI ツールの一つでしかありませんでした。 しかし、他のCLI ツールの管理をしたり、またGitを拡張するツールとしてVim使ったりしていると、VimがTerminalの環境を全て飲み込んでいくような、そんな感覚になります。
/blog/2023-08-16-zenn-3b5125f9e06bf9-ja
これからもVim/Neovimと仲良くしていきたいですね。