ここぽんのーと

コードとデザインの境界に生きるエンジニアの、雑多な記録帳。

自作Dash docsetの作り方 — Alfred + Dashの爆速リファレンス引き環境を拡張する

2015/01/12, cocopon

OS Xをメインでお使いの開発者な皆さま、Alfred + Dashのコンボで爆速リファレンス引きライフを満喫していますでしょうか。今回はこの快適環境を拡張するべく、自分でDash用のドキュメント(= docset)を作ってみました。

「Alfred、Dashって何?」な方のために

それぞれどういうアプリなのか知らない方のために、簡単に解説しておきますね。

まず、「Dash」は高速なドキュメントブラウザです。iOSやJava、Ruby、Processing、…ありとあらゆる言語のリファレンスが「docset」として用意されており、1クリックでインストールできます。自分の使う言語分をすべてインストールすれば、すべてのリファレンスが一所から引けるようになるのです。無料でお試しできるので、使ったことがないなら今すぐインストールすべし。

もう一方の「Alfred」は、高機能なランチャーアプリ。Spotlightのもっとすごいやつです。

それで、このAlfredの「Powerpack」という有料機能を購入してDashと連携させることで、わずか数タイプによる「ランチャー起動→リファレンス引き」が実現するわけです。

2015-01-11 02.16.16

連携の手順については、こちらのスライドがよくまとまっています。13ページ目から。

よく使うライブラリ用のdocsetがない!

前述のとおり、ほとんどの言語・ライブラリは既にdocsetが用意されていて、1クリックでインストールできます。

2015-01-11 01.06.08

上図はDashの公式サイトにあるリストの一部。聞いたこともないマイナーそうなものもたくさんあるし、自分の使いたいものもきっとあるよね!と思うのですが、意外と見つからないものです。

自分の場合だと…最近ビジュアルコーディングを勉強していまして、Processingで作ったスケッチをWebで公開する際に「EaselJS」や「Paper.js」で書き直しているのですが、どちらもdocsetはありませんでした。

うーん。せっかくスバラシイ環境を整えたのに、使えないなんてもったいない。ないなら自分で作ってしまおうか!

Paper.jsのdocsetを自作する

今回は、ブラウザでフニフニ動くアートが作れるライブラリ「Paper.js」を例に、docsetができるまでを解説していきます。作ってみたいけど躊躇している人の背中をドンッと押せればいいなぁと思っております!

ちなみに、これから解説する諸々の手順をRubyで自動化したものがこちらの「paperjs-docset」。Paper.jsのdocsetをコマンド1発で生成してくれます!

0. docsetの作り方を調べる

まずは公式ドキュメントを読んで、docsetの作り方を調べます。「Generating Docsets」が該当ページですね。

2015-01-11 01.21.02

たくさん方法があるようですが、今回のお題であるPaper.jsのリファレンスはWeb上にあるのみ。1〜6番は該当しないので、最後の7番「HTMLから生成する」になりそうです。

1. docsetのフォルダを作成する

公式の手順に従い、docsetのフォルダを作成します。

mkdir -p Paperjs.docset/Contents/Resources/Documents/

この「Documents」フォルダ以下に、必要なファイルたちを突っ込んでいくようです。

2. リファレンスのHTMLを丸ごと取得する

では、リファレンスのHTMLを取得しましょう。幸いにもPaper.jsのWebサイトのデータはGitHubで公開されているので、git cloneすれば手元に持ってくることができます。感謝。

cloneしてきた中身を見てみると…。

2015-01-11 01.45.25

ふむふむ。中身を調べてみたところ、「reference」フォルダ下にリファレンスのHTMLが、「assets」フォルダ下に必要なリソースが置かれているようです。この2つのディレクトリを、docsetの「Documents」フォルダにコピーしました。

2015-01-11 11.43.20

3. docsetの構成に合わせて修正する

さて、コピーしてきたHTMLのソースを見てみると、絶対パス(/から始まるパス)が含まれていたり、リファレンスにするには不要なメニューが含まれていたりと、このまま使うのは厳しそうです。docsetの構成に合わせて修正しましょう。

絶対パスはテキストの置換で相対パスに直し、不要なメニューはCSSのdisplay: none;を追記して非表示にしました。

(ここでは解説しませんが、「paperjs-docset」では他にも細かな表示調整のための処理を加えています。興味があればソースコードをどうぞ)

4. Info.plistを作成する

公式サイトの例にならいInfo.plistを作成、「Paperjs.docset/Contents」フォルダに置きます。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleIdentifier</key>
  <string>paperjs</string>
  <key>CFBundleName</key>
  <string>Paper.js</string>
  <key>DocSetPlatformFamily</key>
  <string>paperjs</string>
  <key>isDashDocset</key>
  <true/>
  <key>isJavaScriptEnabled</key>
  <true/>
</dict>
</plist>

ここで重要なのが、isJavaScriptEnabledフラグ。HTML内でJavaScriptを使う場合は、このフラグをtrueにしておく必要があります。小一時間はまりました…。

5. SQLiteで索引用のファイルを作る

表示するコンテンツが用意できたら、それらを引くための索引を作成してあげましょう。Dashの索引はSQLiteのDBファイル形式です。「Paperjs.docset/Contents/Resources/docSet.dsidx」として配置します。

用意するテーブルの名前は「searchIndex」。ここに「(Dashで検索するときの)名前」「タイプ」「HTMLのパス」を1組としたレコードをずらっと並べます。「タイプ」は、クラスやメソッド、名前空間のような種類のこと。公式サイトにリストがあります。

2015-01-11 11.49.50

テーブルは、公式サイトにあるとおりのSQL文で作成できます。

CREATE TABLE searchIndex(
  id INTEGER PRIMARY KEY,
  name TEXT,
  type TEXT,
  path TEXT);

レコードを追加するときの文は、例えばこんな感じ。

INSERT OR IGNORE INTO
  searchIndex(name, type, path)
  VALUES ('Color', 'Class', 'reference/color/index.html');

数百あるであろうレコードを手入力するのは現実的でないので、お好きなプログラミング言語でさくっと自動化するのがよいでしょう。「paperjs-docset」では、RubyでHTMLを解析してメソッドを抽出し、レコードとして追加しています。

6. 完成!

以上で完成です!完成したdocsetをDashに追加しましょう。設定画面の「Docsets」タブをクリックし、ウィンドウ下方の「+」ボタンで追加できます。

2015-01-11 11.52.43

ジャーン!! 追加された!

2015-01-11 11.55.26

エラーが出る場合は、足りないファイルがないか、設定ファイルの値が正しいかなどなど確認してみてください。

最後にTIPS: インポート済みのdocsetを更新(再読み込み)する

Dashにインポート済みのdocsetは、表示中にCommand + Rで更新(再読み込み)できます。この機能を駆使することで、「docsetのファイル更新→Dashでの表示確認」の一連の作業が捗ります。自分はこれに気づくまで「docsetを一度削除→再度インポート」を繰り返して消耗していました…(x_x)