akimo.dev

パッケージマネージャーのラッパーを作った

僕は現在Macを使っているので、Homebrewで入れられるものはHomebrewで入れることが多い。しかし、何でもかんでもHomebrewで入れられるわけではないので、Go製ツールのインストールにgo installを使うこともあるし、npm系のツールをpnpmで入れたりもする。複数のパッケージマネージャーを使うこと自体は別に構わないのだが、インストール関連ならまだしも、使用頻度の低いコマンドをパッケージマネージャーごとに覚えるのは難しい。また、Goはパッケージマネージャーとして貧弱である。こういった問題を解決するために、pacxというパッケージマネージャーのラッパーを作った。

akimon658/pacx: Wrapper for package managers, allowing you to define and configure your package managers in Lua
github.com

類似のツールはちょっと調べただけでもhkdb/apprami3l/pacaptrなどなどいくらでも出てくるが、ツール側でサポートされたパッケージマネージャーのみ使えるというものが主流で拡張性に欠ける。そこでpacxでは、自分でパッケージマネージャーを定義し、その挙動をLuaで記述できるようにした。例えば、

return {
  install = function(pkg)
    os.execute("brew install " .. pkg)
  end,
}

このコードを$XDG_CONFIG_HOME/pacx/brew.luaとして保存した状態でpacx install brew:ghを実行すると、brew install ghが実行される。

Luaなので、パッケージマネージャーにない機能も自分で実装すれば使えるようになる。例えば、$XDG_CONFIG_HOME/pacx/go.lua

local function install(pkg)
  os.execute("go install -ldflags='-s -w' -trimpath " .. pkgName)
end

local function upgrade(pkg)
  local pkginfo = io.popen("go version -m $(go env GOPATH)/bin/" .. pkg)
  if not pkginfo then
    error("failed to execute go version -m " .. pkg)
  end

  _ = pkginfo:read()
  local pkgpath = string.match(pkginfo:read(), "path%s+(%S+)")
  install(pkgpath)
end

return {
  install = install,
  upgrade = upgrade,
}

と書いたとしよう。この状態で何かインストールするときにはpacx install go:golang.org/x/tools/goplsのようにパッケージ名を指定する必要があるが、アップグレードはpacx upgrade go:goplsのようにバイナリ名だけで行えるようになる。

pacx側でサポートしているパッケージマネージャーなんてものはないので設定を書かなければ使えないが、その代わりLuaでできることは大体できる。とはいえ、自力で0から設定を書かなければいけないのも面倒なので、wikiにはいくつかのパッケージマネージャーについて設定例を載せている。

また、自動で作られる$XDG_CONFIG_HOME/pacx/pacx.luaというファイルにはサブコマンドの名前やエイリアスが書かれているので、これを編集することでサブコマンド名も自分が使いやすいように変更できる。