FIVETEESIXONE

Crystal の Dash Docset を作る


この記事は Crystal Advent Calendar 2015 の3日目の記事です。

昨日は、kfly8 さんによる Hello, Crystal でした。Crystal アプリケーションを Heroku にデプロイして動かすという内容で、自分も書いてある通りにやってみたんですが、buildpack もあるのでサクっと動かせて素敵でした!しかし、ここはリスペクトを込めて一言言っておくべきでしょう。「このぱくり記事め! (ごめんなさい)」

TL;DR

Crystal の API リファレンスの Dash Docset を作りました。

2015-12-03-crystal-dash-docset-1.png

使ってみたい方はここからダウンロードして、crystal.docset を Dash に読み込んでください。

Dash Docset

さて、タイトルにある通り、この記事では Crystal の Dash Docset を作ります。

Dash というのは OS X 用の API ドキュメントブラウザーで、もうこの時点で OS X ユーザーじゃなかったり Dash 使ってない方は回れ右して帰っていただくしかない残念な感じなんですが、僕はとても愛用しているので、そんな僕のために作りたいと思います。それで、Docset というのは、その Dash で利用するための API ドキュメントのセットのことです。それの Crystal 版を作ろうという話です。

ただ、ここでちょっとどうしてもお話ししておきたいのはですね。実は昨日から熱がすげーあってあれなんですね。もう体調が激ヤバなんですね。だからそんな状態であることがきっと内容にも反映されてくると思います。皆さんの優しさを期待します。

よし作ってみよう

Dash の Docset というのは HTML ファイル群によって構成されます。だから、基本的には API リファレンスをまるっとダウンロードしてきてそれを Docset 用に構成すれば OK です。

ただ、Dash でちゃんと利用できるようにするためには、

  • インデックスの構築
  • 見た目の整形

などを行う必要があります。

インデックスの構築

Dash が便利な点は、クラスやメソッドなどにインデックスを張って一発で該当のドキュメントを絞り込める点です。このおかげで、Alfred や Emacs などの外部ツールと連携することで、かなりシームレスに見たい場所に直接ジャンプすることができるようになっています。したがって、Docset を構成する際にはそれらの場所を指示してインデックスを構築しておく必要があります。

嬉しいことに、世の中には Dashing という Docset の生成ツールがあるので、これを使えば、CSS セレクタで DOM を指定することにより簡単にインデックスを構築することができます。

見た目の整形

Dash のブラウザーは HTML をそのまま表示できますが、何も加工しない状態ではかなり微妙な表示になってしまいます。例えば Crystal の API リファレンスで言うと、サイドバーは Dash のサイドメニューが担うために不要です。また、JavaScript なども不要ですし、綺麗に表示するためには CSS をちょいちょい修正する必要もあるでしょう。

これらに関してはそれぞれの HTML の内容に依存して必要となることが違うので、オールマイティに加工するツールなどはなく地道に修正するしかありません。幸い Crystal の場合は元からナイスな HTML になっていたので、修正が必要な箇所はそれほど多くはありませんでした。

crystal-dash-docset-generator

ということで、上記した「インデックスの構築」と「見た目の整形」をワンストップで自動的にやってくれる crystal-dash-docset-generator というやつを作りました。これを実行すると、公式の API リファレンスから HTML をばーっとダウンロードしてきて、必要な整形処理を施した上で Dashing を使って Docset を作ってくれます。

なんと素晴らしいことに、この crystal-dash-docset-generator には Crystal は1行も使われておらず、Ruby で実装されています。だって加工が Nokogiri とか使った方が楽で…それと、中のコードを見たらあまりの酷さに眩暈がすると思うので絶対に見てはいけません。全部風邪が悪いのです。

えーと、気を取り直して、この crystal-dash-docset-generator を使うと、カレントディレクトリに crystal というディレクトリが作られて、その中に crystal.docset という名前で Docset が生成されます。後は、Dash の Preferences から読み込んでやるだけで使う準備は完了です。

CI で最新の Docset を生成する

これでコマンド一発で Docset を生成することができるようになりましたが、API リファレンスは更新されることが前提なので、最新の Docset がいつも手に入るようにしておきたいです。ただ何度も手動で生成するのはやってられない感 max ですので、CI を使うようにします。

とりあえずよくあるパターンの Travis と Heroku の合わせ技で CI を構成しましょうか。

TravisCI で Docset をビルドする

crystal-dash-docset というリポジトリを用意して、ビルド用のスクリプトが Travis で実行されるようにしました。CI が走るたびに Docset の生成を行い、生成した Docset をリポジトリに push するだけの簡単なお仕事です。

このように、生成した Docset 自体もこのリポジトリに保存されるため、生成されたら適当に pull してくればその時点で最新の Docset が手に入ります。

Heroku Scheduler で TravisCI をキックする

わざわざここで説明するほどのことじゃない気がするので流していきます。Heroku Scheduler に Travis のビルドをキックするジョブを設定しておいて、毎日1回実行されるようにしています。

課題

こんな感じで、Dash 愛好家としてはわりと悪くない Crystal の API リファレンス参照環境ができたのですが、

  • インデックスがいまいち (クラスとモジュールが区別されてない、表示が崩れるところがある、など)
  • Docset Feed を用意していないので最後はやっぱり手動で更新しないといけない
  • docrystal のドキュメントにも対応したい
  • 体調管理 (昼間暖かくても、夜中まで飲む日はアウターを着て出かけましょう)

など、まだ微妙なところは色々あるので、どうにか改善していきたいところです。

さて、明日は

Crystal Advent Calendar 2015、明日は tbpgr さんです!なんと、もう記事は下書きまで準備できているらしい…すげえ…さすが、絶対に真似できないようなことをサラッとやってくれる!