fish-shell で Makefile のヘルプを自動生成する

開発で Makefile を使うとき、どんなターゲットが定義されているか確認したくなることがある。
これまでは、この記事で紹介されているワンライナーを使ってヘルプを表示するというのをよくやっていた。

postd.cc

しかし、この方法だと Makefile を作るたびにスクリプトを仕込む必要があり、イマイチな感じがしていた。
また人によって好みが分かれそうなので、他の人と共有している Makefile に気軽に導入しずらいという問題もある。

そこで、fish-shell の function で make コマンドを上書きして、make help でヘルプを表示できるようにしてみた。
これなら自分の環境にしか影響しないし、Makefileスクリプトを書く必要もない。

function make
    # Makefileがないか、help以外のターゲットが指定されている場合はmakeに処理を委ねる
    if test ! -f Makefile -o "$argv" != 'help'
        command make $argv
        return
    end

    set -l targets (command grep -E '^[a-zA-Z_-]+:.*$' Makefile)

    # 既にhelpターゲットが定義されている場合はそちらを優先する
    if string match -q -r '^help:.*$' $targets
        command make help
        return
    end

    echo 'Targets:'
    for target in $targets
        set -l matches (string match -r '^([a-zA-Z_-]+):.*?(?:## (.*))?$' $target)
        set_color cyan; printf '  %-18s %s' $matches[2]
        test -n $matches[3] && set_color normal && echo $matches[3]
    end
end

例えば、こんな風に Makefile を書いておくと、

.PHONY: build
build: ## Build app
  ...

.PHONY: test
test: ## Run test
  ...

...

こんな感じでヘルプを表示できる。

f:id:questbeat:20200802024500p:plain:w500

余談 : fish-shell の make 補完機能

実は fish-shell は標準で make の補完に対応していて、Tab キーを押すとターゲットの候補を表示してくれる。
ターゲットを確認したいだけならこれでもいいかもしれない。

f:id:questbeat:20200802024503p:plain:w600

補完処理の実装は https://github.com/fish-shell/fish-shell/blob/master/share/completions/make.fish にある。
__fish_print_make_targets という便利関数が定義されているので、これを使って make ヘルパーを作るのもよさそう。