Sphinx-1.3 に numfig っぽい機能を付けた話

このブログでは numfig の闇と向き合う の記事から numfig との取っ組み合いをしていましたが、
ひょんなことから Sphinx 本体の改修を手伝うことになり、
つい先日 Assign numbers to figures, tables and code-blocks というプルリクが本体に取り込まれました。
また、別のプルリクとして Add :numref: role to refer figures, tables and code-blocks by its fignum が送られていて、
ふたつを合わせると numfig の図表番号という考え方が Sphinx 本体にマージされることになります。

Sphinx 拡張を書くのと比べると Sphinx 本体をいじるのはできることが多くなるかわりに、
奔放なコードを書くと禍根を残すことになるので三倍ぐらい丁寧にコードを読むことになりました。


また、他にも code-block にキャプションを振る機能graphviz 拡張のキャプションまわりの改善など、
toctree や参照まわりに関する改善を積み重ねてきました。
詳しい日付はまだ出ていませんが、Sphinx 1.3のβ版は近日リリースされるとのことです。

論文や書籍を書くなど、numfig に興味を持っているひとは Sphinx 1.3β にチャレンジしてみてください。
conf.py に numfig = True と書くだけで図表番号が採番されるようになります。


リリースを目前にして、マージされたプルリクのリストを見て、頑張ったなあという感慨を抱いたので記録代わりに記事を書いておきます。

visio2img と sphinxcontrib-visio のメンテナーになりました

少し前、インターン生として @yassu がうちの会社に来ていたので、
その際にドキュメント作成に使うツールを作ってもらいました。

visio2imgsphinxcontrib-visio の 2パッケージです。
それぞれ、visio2img は Visio ファイルから画像ファイルを抽出するコマンドラインツール
sphinxcontrib-visioSphinx 文書の中に Visio 画像を埋め込む Sphinx 拡張です。

ネットワークエンジニアを筆頭に Visio を使って画像を作っている方は多いと思いますので、
これらのツールを使ってよりより便利にドキュメントをつくって貰えればと思います。

なお、visio2img は内部で Visio コンポーネントを呼び出しているため、
実行環境には Visio がインストールされている必要があります。

visio2img は Microsoft さんの提供でメンテナンスされています

これらのパッケージのメンテナンスには Visio のライセンスが必要となるため、
ライセンスを持っている僕がパッケージのメンテナとして活動しています。

さて、この僕の持つ Visio のライセンスですが、実は Microsoft さんによって提供されています。
去年の 5月に開催されたカンファレンスカンファレンスMicrosoft さんから頂いたものを使っています。
おかげさまで visio2img のメンテナンスに役立てることができました。

改めて Microsoft さんには感謝したいと思います。

今後の予定

とりあえず、自分が思いつく一通りの機能は実装して一段落したところです。
使っていただいて、気になる点があればレポートをお願いします。

SphinxCon JP を開催することにしました

すでに渋谷では SphinxCon 開催の話題でもちきり状態で、
ご存じない方はもういらっしゃらないとは思いますが、今年も SphinxCon JP 2014 を開催します。

ノリと勢いで 2012, 2013 とやってきていましたが、なんと 3年目を迎えることになりました。
参加者も発表者も募集しているので、興味がある方はお誘い合わせの上登録をお願いします。
今年の状況によっては、2015 の開催につながるかもしれないので、ちょっとでも興味があれば飛び込んでみてください*1


さて、この SphinxCon JP の開催までは精鋭スタッフの努力によって成り立っています。
今年はそのリーダーとして @usaturn 氏が先頭に立ち、来るイベント当日に向けて準備を進めています。
そこで、今回はリーダー @usaturn 氏のために、新たに Sphinx 拡張を作ってみました*2
それが sphinxjp.usaturn です。

sphinxjp.usaturn は warningnote などの、admonition と呼ばれるテキストブロックの記述に用います。
sphinxjp.usaturn の設定を行うと usaturn ディレティブが追加され、
reST の中でうさたーんに注意書きをしゃべってもらうことができます。
たとえば

.. usaturn:: こんにちは、私はうさたーんです。

マークアップを行うと、次のように変換されます。
f:id:tk0miya:20140907111027p:plain

また、sphinxjp.usaturn は add_character_admonition という API を提供しているため、
conf.py で設定を書き加えることでうさたーん以外にも喋らせることができます。

この機能を用いると、キャラクターの対話形式の記事も簡単に作ることができます。

.. usaturn:: こんにちは、私はうさたーんです。

.. shimizukawa:: こんにちは、私はペンです。
   :align: right

.. usaturn:: いいえ、それはペンではありません。久美です。

.. shimizukawa:: ケン、座ってください。
   :align: right

.. usaturn:: 私も寿司が好きです。

f:id:tk0miya:20140907111545p:plain

とっても便利ですね。

まとめ

  • SphinxCon JP 2014 が開催されます。スピーカーも参加者も大募集中です。
  • sphinxjp.usaturn というモジュールを作りました
  • 犯人はこいつです

*1:Sphinx だけではテーマが限られてしまうので、どうせなら次は他のドキュメンテーションツールを混ぜつつ、DocTool Conf みたいに昇華できるといいのではないかとか、妄想はいろいろありますね。他のツールの状況とかも聞いてみたいし!

*2:sphinx-users.jp 界隈では敬意や感謝を表すために Sphinx 拡張を贈り合う習慣があるとかないとか... 参考: sphinxjp.shibukawa, sphinxjp-tk0miya

YAPC::Asia 2014 に行ってきた #yapcasia

相変わらず perl を書いてはいないのだけど、あのお祭り感が大好きなので
今年も YAPC::Asia に行ってきました。

帰り際に HUB で飲んでた時にスポンサーの人に煽られたのでなるはやで書いてます。


いつもは話半分、コード書き半分ぐらいの感じで過ごすのですが、
今回はわりかしまじめに(?)話を聞いて回ってました。

特に興味深かったのがこの辺り。

誰かが楽しそうに発表したり、面白いことをやってたりすると、すごく刺激されますね。
なにか人に話せる面白いことやりたいですね。

ちょうど JSON Schema を触るのを放置していたので、このあたりのことをやれという天啓だったのかもしれません。
ツッコミも飛んできたのでぼちぼち再開しようと思います。


毎回のことながら、YAPC はやる気を充電してくれるすごいイベントですね。
次回にはなにかネタを持っていけるよう精進していこうと思います。


最後に、今回の YAPC で聞いた中で、声に出して読みたいいい言葉をメモっておきます。



only ディレクティブの微妙なうごき

only ディレクティブを組み合わせるとあれこれ微妙な挙動が発生するようです。

最初は toctree と only ディレクティブの組み合わせについて悩んでいたのですが、
他にも only ディレクティブに関わる動きを @shimizukawa に教えてもらったので
合わせて紹介します。


toctree が 2重登録される

only ディレクティブの下に toctree ディレクティブを配置すると、
その toctree が 2重登録されてしまいます。

例えば、次のような reST を書いてみます。

.. index.rst

heading
========

.. toctree::

   sub
.. sub.rst
続きを読む

astah の画像を Sphinx に埋め込む拡張を作ってみた: sphinxcontrib-astah

先々週に cacoo の拡張をつくってそのあとパッケージングもしたのですが、
それに味をしめて(?) UML 系のツールとして名高い astah 向けの拡張もつくってみました。
sphinxcontrib-astah です。

やっていることは超シンプルで、内部で astah-command.sh を呼び出して いるだけです。


この間 cacoo 向けの拡張をつくった時に気づいたのですが、
API やコマンド経由で画像を生成するツールで、
なおかつ画像のフォーマットが常に PNGJPEG などのラスター形式のものについては、
sphinxcontrib-cacoo の実装がほぼそのまま使えるのではないかと思います。

astah 拡張を作るときは cacoo の API を呼び出している部分を
astah-command.sh の呼び出しに置き換えるぐらいの作業で対応することができました。

cacoo 拡張では次のことをしています。

  1. image ディレクティブを拡張して cacoo-image ディレクティブを作成 (オプションも継承)
  2. cacoo-image ディレクティブでは image ノードを cacoo_image ノードに置き換える (このとき、image ノードのオプションは引き継ぐ)
  3. doctree-resolved イベントで cacoo_image ノードから画像を生成し、image ノードに置き換える

こうすることで、出力形式ごとの(HTML, LaTeX 用などの) visitor 関数を書く必要がなくなるため、
image ディレクティブ(や figure ディレクティブ)の豊富なオプションをサポートしつつ、
なおかつツールが生成した画像を読み込むことができるようになります。


もしドキュメントの出力に合わせて画像の形式を変更したいなどの要望が出てくると、
実装はもう少し面倒なことになりそうな気がします。
blockdiag や graphviz などでは、画像フォーマットを切り替えたり、
ベクタ形式の画像を生成したりと割と細かいことをしているのでこういった方法は使えないのですが、
新しいツールをサポートするときにお手軽に拡張を作るときは便利かもしれません。



こうしたサードパーティツールを使う場合、テストを書くのが面倒なのが玉に瑕ですね。
mock を介したりしつつテストを書くと良いのでしょうが、
このふたつの拡張に関してはテストコードがない状態です。

テストがないコードに嫌悪感のある方、すっきりするチャンスです。
当方プルリクをお待ちしております:-)

あなたの知らない toctree の世界

numfig を実装してやらぁ!と息巻いてコードを書き始めたところ、
シンプルだと思っていた toctree の裏に思わぬ魔境が広がっていて
思わず部屋の隅っこで震えてしまった @tk0miya です。

Sphinx のリファレンスを舐めるように読み尽くした toctree マニアには常識かもしれませんが、
さっと読み飛ばした人々には toctree は謎機能の山に見えてくるはずです。

URL が指定できる

リファレンスの一節にそっとこんなことが書かれています。

また、ドキュメント名の代わりに、HTTPのURLを指定することで外部へのリンクを追加することもできます。

toctree って他の reST ファイルをリンクするためにだけあるんじゃなかったんですね。
早速使ってみましょう。

.. toctree::

   http://www.google.co.jp/

そしてこれをビルドしてみるとこんなふうになります。
f:id:tk0miya:20140819175541p:plain

どうやら URL を指定するとリンクテキストが None になってしまうようです。
この動作についてリファレンスには説明がありませんが、
toctree にはタイトルを付ける記法があるのでそれで回避するとよいでしょう。

.. toctree::

   Google <http://www.google.co.jp/>

いまいち使い所がつかめていないのですが、
目次に URL を入れたくなったときに使ってみてください。

ちなみに LaTeX の目次には効果がありません。

:numbered: オプションが引数を取るようになった

Sphinx 1.1 から numbered オプションが引数を取るようになっています。

特定の深さまでのナンバリングだけを行うこともできます。
numbered 引数に対して、数値で深さを指定してください。

というわけで、このオプションを指定してみます。
まず深さを指定しない場合の例。
f:id:tk0miya:20140819181106p:plain
続いて :numbered: 2 を指定した場合。
f:id:tk0miya:20140819181127p:plain
そして :numbered: 1 を指定した場合。
f:id:tk0miya:20140819181139p:plain

番号を振る階層が変化していますね。

なお、このオプションは LaTeX 経由で PDF を出力した場合は効力がありません。
そもそも LaTeX 経由ででは :numbered: 指定なしでも章番号が割り振られますし、
他のフォーマットでは :numbered: の指定は効果がないので、
HTML 専用オプションとして割り切って考えるのが良さそうです。

謎の self 指定

リファレンスを読み進めていくと、こんな記述もあります。

self は特別なエントリー名として扱われます。toctreeディレクティブを含むドキュメント自身を表します。これは、toctreeを使用して、”サイトマップ”を作成したい場合に便利です。

どうやら self という文字列を toctree に指定することができるようです。
試してみましょう。先ほどのドキュメントに加筆してみます。

.. toctree::
   :numbered:

   sub
   self

するとこんな出力になります。
f:id:tk0miya:20140819185229p:plain

何に使えるのか、いまいちよくわかりませんね。


ちなみに、self という名前は予約されているので self.rst というファイルを作っても
toctree で指定することはできません。ご注意ください。
subdir/self は問題ないので、self.rst を作れと遺言を受け取った方はディレクトリを掘るとよいでしょう。

toctree で循環参照をすると warning で注意される

toctree は名前の通りツリー構造を期待しているので、循環参照が起きることは想定していません。そのため、循環参照が起きるような指定をすると warning が出てきます。

例えば、自分自身のファイル名を指定すると…

.. toctree::

   index

こんなふうに注意されます。

/Users/tkomiya/work/tmp/foo/index.rst:: WARNING: circular toctree references detected, ignoring: index <- index

複数のファイルをまたがって参照しても注意されます。
次の例は index -> sub -> subsub1 -> index という循環がある場合の warning です。

/Users/tkomiya/work/tmp/foo/sub.rst:: WARNING: circular toctree references detected, ignoring: sub <- index <- subsub1 <- sub
/Users/tkomiya/work/tmp/foo/subsub1.rst:: WARNING: circular toctree references detected, ignoring: subsub1 <- sub <- index <- subsub1
/Users/tkomiya/work/tmp/foo/index.rst:: WARNING: circular toctree references detected, ignoring: index <- subsub1 <- sub <- index

なお、循環参照と :numbered: オプションを組み合わせると Sphinx ごと死ぬというバグを見つけたので、
循環参照マニアの人はこのバグが直るのを待つと良さそうです。


また、toctree はツリーにせよ、というコンセプトを無視して、
複数のファイルに特定のファイルをつなげて、ひし形に toctree を組むこともできます。
そうすると、navigation link が壊れたり*1、:numbered: による採番が狂ったりします。

まとめ

toctree は徐々に機能が追加されてきているものの、何に使うのかよくわからないものもあり、
アンバランスかつバギーな状態のようです。

せっかくですのでバグハンターの方々は、この辺りで楽しまれると良いのではないでしょうか。


あ、循環参照してる文書で make latex したら死んだ。
終わる。

*1:次へ、前への繰り返しで文書を辿れなくなる