この記事は、 Crystal Advent Calendar 2017 の13日目の記事です。
crystalのcliには便利なサブコマンドやオプションがあります。コーディングを支えるものだったり、build時の細かな設定だったりします。知っていると得をする、だけど知らない人も多いかもしれない。そんなサブコマンドやオプションを紹介します。
今回は、 $ crystal tool expand を紹介します。
tool expand
まずはcliのhelpを見てみましょう。
$ crystal tool --help
Usage: crystal tool [tool] [switches] [program file] [--] [arguments]
Tool:
context show context for given location
expand show macro expansion for given location
format format project, directories and/or files
hierarchy show type hierarchy
implementations show implementations for given call in location
types show type of main variables
--help, -h show this help
expand があります。
show macro expansion for given location
macroを展開してくれるコマンドです。expandのhelpも見てみましょう。
$ crystal tool expand --help
Usage: crystal tool expand [options] [programfile] [--] [arguments]
Options:
-D FLAG, --define FLAG Define a compile-time flag
-c LOC, --cursor LOC Cursor location with LOC as path/to/file.cr:line:column
-f text|json, --format text|json Output format text (default) or json
--error-trace Show full error trace
-h, --help Show this message
--no-color Disable colored output
--prelude Use given file as prelude
-s, --stats Enable statistics output
-p, --progress Enable progress output
-t, --time Enable execution time output
よく使うのは-cオプションです。カーソルの位置をファイルパス:行数:列数と指定することで、その位置のmacroを展開してくれます。
例を見てみましょう。ちょうど先週のアドベント・カレンダーでmacroを取り扱ったので、そのコードで試してみます。
class User def initialize(@name : String, @age : Int32) end def_equals @name, @age end
このファイルに対して以下のコマンドを打つと、macro部分が展開されます。(5行7列はdef_equalsのeの位置です)
$ crystal tool expand -c src/def_equals_expand.cr:5:7 src/def_equals_expand.cr
1 expansion found
expansion 1:
def_equals(@name, @age)
~> def ==(other : self)
if @name == (other.@name)
else
return false
end
if @age == (other.@age)
else
return false
end
true
end
カーソル位置でmacroが発見され、それが展開されました。既存のmacroの実装を確認することができます。
とはいえ、このexpand の活躍する場は、何と言っても「macroを書いているとき」です。このコマンドが無かった時は、展開後のmacroがどうなるかを知る術はありませんでした。build時に出るエラーだけが頼りでした。
実はこのexpandは、渋谷で開かれたCrystal勉強会が発端です。「macro書きづらいよね」という話を懇親会で行っていたところ、Crystalのハードコアなコントリビューターである make_now_justさんが後日実装されたのです。それがすぐに本家に取り込まれ、正式なtoolとなりました。toolの生まれる瞬間を目の当たりにしていたので、自分もexpandはなんだか好きです。
通常はエディタから叩くことが多いでしょう。ファイルパス:行数:列数 というインターフェースになっているので、設定はし易いと思います。
「macroのハードル高い...」と思っている方は、ぜひ使ってみてください。