2012-12-24 Start Sphinx Documentation

Sphinx Advent Calendar 2012 24日目担当の 波田野 ( @tcsh ) です。

今回は、Sphinxを使ってドキュメントを作るときに、自分がやっている手順を書いてみます。

Note

Sphinx環境の構築については今回は書きません。

自分は、下記を使って書いています。 (2012-12-24 時点)

  • Sphinx 1.1.3
  • Mercurial 2.4
  • vim 7.3.661

おおまかな流れとしては、

  1. リポジトリを作成する
  2. Sphinxドキュメントのセットアップをする。
  3. コンテンツのlocal公開
  4. .hgignore の作成
  5. Sphinxドキュメントの基本パーツ作成
  6. 最初のコミット
  7. ドキュメント本体を書き出す

という感じです。

Warning

ツッコミやアイデアがあれば、Sphinx-Users-jp ML や #sphinxjp で是非よろしくお願いします!

1. リポジトリの作成

まず、ドキュメント用のディレクトリを作成します。

command:

% setenv TARGET_DOC $HOME/work/hg/sample-sphinx
% mkdir ${TARGET_DOC}
% cd ${TARGET_DOC}

Mercurial のリポジトリを作成します。

command:

% hg init
% ls -a

result:

.     ..      .hg

2. Sphinxドキュメントのセットアップ

sphinx-quickstart の実行

sphinx-quickstartを実行します。

command:

% sphinx-quickstart

以下の3つ以外はデフォルト値を使っているので、エンター連打してます:-)

> Project name: Sphinx Sample Product document
> Author name(s): HATANO Hirokazu
> Project version: 1.0

Note

  • いつか使ってみたいもの
    • epub builder
    • intersphinx
    • todo
    • coverage
    • ifconfig
  • make.bat は、稀にWindowsでビルドすることがあるので、一応作っています。

result:

Finished: An initial directory structure has been created.

You should now populate your master file ./index.rst and create other documentation
source files. Use the Makefile to build the docs, like so:
   make builder
where "builder" is one of the supported builders, e.g. html, latex or linkcheck.

Makefile の編集

Sphinxのワーニングログをファイル(./_warn.log)に出力する設定を Makefile に記述します。

Makefile (diff):

- SPHINXOPTS    =
+ SPHINXOPTS    = -w _warn.log

conf.py の編集

オレオレテーマを _themes 下にシンボリックリンクで置いているので、それを使う設定をします。

conf.py (diff):

- html_theme = 'default'
+ #html_theme = 'default'
+ html_theme = 'tcsh'

- #html_theme_path = []
+ html_theme_path = ['_themes']

sphinx-quickstartが作ったタイトルでは長過ぎるので、書き換えます。

conf.py (diff):

- #html_title = None
+ html_title = project

smartpantsは手順書系の記述でわるさ(クォート系が自動置換される)するので False にします。

conf.py (diff):

- #html_use_smartypants = True
+ html_use_smartypants = False

Note

extensions は、ここでは省略します。 共通でインクルードする方法をさがし中。

リポジトリへの追加

この時点で、管理系ファイルをリポジトリに追加しておきます。

command:

% hg add Makefile conf.py index.rst make.bat

result:

Makefile を追加登録中
conf.py を追加登録中
index.rst を追加登録中
make.bat を追加登録中

3. コンテンツのlocal公開

ビルドしてローカルでコンテンツ(まだカラッポですが)を閲覧してみます。

コンテンツの初ビルド

コンテンツをビルドしてみます。

command:

make html

result:

(snip)

build succeeded.

Build finished. The HTML pages are in _build/html.

コンテンツのlocalhost公開

自分は Mac でのlocalコンテンツを ~/public_html で公開しているので、その下にコンテンツへのシンボリックを張ります。

Note

Mountain Lion のシステムプリファレンスから "Web共有" が消えたんですね、知らなかった... (UNIX系サーバと同じく apachectl 使うみたいです。)

command:

% pushd ~/public_html/
% ln -s ${TARGET_DOC}/_build/html sample-sphinx

ブラウザで http://localhost/sample-sphinx にアクセスすると、スケルトン状態のコンテンツが見えます。

確認できたら、ドキュメント作業ディレクトリに戻ります。

command:

% popd

4. .hgignore の作成

hg status を実行するとリポジトリに反映されていないファイルのリストが表示されます。

command:

% hg status

result:

A Makefile
A conf.py
A index.rst
A make.bat
? _build/doctrees/environment.pickle
(snip)
? _build/html/searchindex.js
? _themes/tcsh

リポジトリトップ直下に .hgignore を作成して、バージョン管理する必要がないファイルを登録しておきます。

.hgignore:

.sw.$
_build
_themes/tcsh
_warn.log

Note

.sw.$ は viなどが作成するスワップ系ファイルを除外するために記述します。

.hgignoreファイルもリポジトリで管理します。

command:

% hg add .hgignore

result:

.hgignore を追加登録中

この時点で、リポジトリ未反映ファイルは下記になります。

command:

% hg status

result:

A .hgignore
A Makefile
A conf.py
A index.rst
A make.bat

5. 基本パーツの作成

この段階で、reSTファイルを書いて、local Web で見た目を確認する環境は整いました。

が、Sphinxならではの機能を活かすため、追加で主に下記の作業をしています。

  1. 置換テーブルの作成/設定
  2. 用語集/用語一覧(Index)の作成
  3. 各ページへのリファレンス名の追加

上記以外の調整作業も含めて書いていきます。

5.1. タイトルの編集

sphinx-quickstartが作ったタイトルでは長過ぎるので、書き換えます。

index.rst (diff):

- .. Sphinx Sample Product document documentation master file, created by
-    sphinx-quickstart on Mon Dec 24 11:39:02 2012.
-    You can adapt this file completely to your liking, but it should at least
-    contain the root `toctree` directive.

- Welcome to Sphinx Sample Product document's documentation!
- ==========================================================

+ ==============================================================================
+ Sphinx Sample Product document
+ ==============================================================================

Note

自分は、最上位の Section Structure は = を 64もしくは78個上下に挟んでいます。

5.2. リファレンス名の追加

トップページへのリンクをどこにでも記述できるようにリファレンス名を追加します。

ファイルの1行目にリファレンス名 'top' を記述して、タイトルとの間に空行を追加します。

index.rst (add):

.. _top:

==============================================================================
Sphinx Sample Product document
==============================================================================

5.3. トップへのリンクの追加

今回はサンプルとして index.rst の末尾に top へのリンクを追加しておきます。

index.rst (add):

:ref:`TOPへ戻る <top>`

5.4. modindexの削除

Pythonistaじゃないので modindexは行削除しています。 (すいません、すいません)

index.rst (diff):

- * :ref:`modindex`

Note

  • Python以外のモジュールは genindex に入ります。
  • これが分けられると便利だと思ったり..

5.5. 置換テーブルの作成

Sphinxでは、手順テンプレートの特定文字列を置換して、特定作業の手順書を自動生成することなどが簡単にできます。

自分はこれを多用しているので、最初に置換定義を記述するためのファイルを作成しています。

今回は、とりあえず動作確認用の置換定義だけ入れておきます。

define/defines.txt:

.. |CURRENT_VERSION| replace:: 1.0.0
.. |NEXT_VERSION|    replace:: 1.0.1

ビルドするときに全rstファイルが置換テーブルを参照できるように conf.py に下記を追記します。

conf.py (add):

rst_prolog= u"""
.. include:: /define/defines.txt
"""

Note

conf.py で絶対パス指定すると、Sphinxドキュメントのルートからの相対指定になるようです。

5.6. 用語集の作成

ドキュメントで用語にゆらぎがあると後で保守が大変なので、最初に用語を書いておく場を用意しています。

今回は、上で作成した置換サンプルが表示されるか確認するための用語サンプルを入れておきます。

define/words.rst:

.. _words:

================================================================
用語の定義
================================================================

.. glossary::

  Hello
    挨拶の言葉

  Current Version
    |CURRENT_VERSION|

  Next Version
    |NEXT_VERSION|

:ref:`TOPへ戻る <top>`

インデックスファイルの toctree に define/words を追記します。

index.rst:

.. toctree::
   :maxdepth: 2

   ./define/words

Note

ここでは説明の簡略化のため、直接 define/words を記述していますが、大抵は各階層に index.rst ファイルを作成して、:glob: オプションで自動取得させています。

用語へは term ロールでリンクが作成可能です。

今回は index から 定義へのリンクを追記しておきます。 (ついでに 置換も使ってバージョン情報も表示してみました。)

index.rst (add):

----------------------------------------------------------------
hello documentation!
----------------------------------------------------------------

このドキュメントでは :term:`hello` についてドキュメントしていきます。

- :term:`Current Version`: |CURRENT_VERSION|
- :term:`Next Version`:    |NEXT_VERSION|

5.7. コンテンツをビルドしてみる

さて、ここまでのコンテンツをビルドしてみます。

command:

% make html

Warning

下記が使えるようになっていることを確認します。

置換
  • 置換文字列が、置換テーブルに従って置換されている。
用語一覧(Index)/用語へのリンク
  • termロールを記述した用語について、リンクが作成されている。
  • indexページの 'Indices and tables' にある Index リンクをクリックすると用語一覧が表示される。
  • 用語をクリックすると、用語集のページに遷移し、該当用語がハイライトされる。
リファレンス名/リファレンスリンク
  • 用語集の一番下に 'TOP' へのリンクが作成されている。
  • リンクをクリックすると、トップページに遷移する。
Search Page
  • indexページの 'Indices and tables' にある 'Search Page' リンクをクリックすると検索画面が表示される。
  • キーワード(英語のみ 例: Hello)を入力して、'Search'ボタンをクリックすると、キーワードが存在するページの一覧が表示される。

5.8. リポジトリへの登録

この時点で、リポジトリ未反映ファイルは下記になります。

command:

% hg status

result:

A .hgignore
A Makefile
A conf.py
A index.rst
A make.bat
? define/defines.txt
? define/words.rst

未登録ファイルを登録します。

command:

% hg add define/defines.txt define/words.rst

result:

define/defines.txt を追加登録中
define/words.rst を追加登録中

6. 最初のコミット

ここまでで、ひととおりSphinxドキュメントらしい体裁が整ったので、本格的にドキュメントを書き出す前に最初のコミットをしておきます。

command:

% hg commit -m 'created repository'

result:

.hgignore
Makefile
conf.py
define/defines.txt
define/words.rst
index.rst
make.bat
コミット対象リビジョン 0:22155cb1732d

さて、ここまででSphinxなドキュメントを書く準備は整いました。 あとは、がしがし書いていくだけですね。

7. ドキュメントの作成

では、具体的なドキュメントの作成について、、、書こうと思いましたが、ちょっと情報過多なので、今日はこれぐらいにしておきたいと思います。

今、自分が使っているディレクティブを中心に簡単に触れます。

7.1. プロダクトドキュメントの作成

literalinclude が非常に使い勝手良いです。

  • :language: オプションで言語を指定すると、言語に従ったハイライトがされる。(Pygments)

    • Rails では 'ruby' や 'erb' を指定することが多い。
    • VBA では 'vbnet' を使う。

    reSTソース (code 全体):

    .. literalinclude:: ./sample/hello_controller.rb
       :language: ruby
    

    HTML出力 (code 全体):

    # coding: utf-8
    
    class HelloController < ApplicationController
      def index
        render :text => 'こんにちは、世界!'
      end
    
      #ここから
      def view
        @msg = 'こんにちは、世界!'
        render 'hello/world'
      end
      #ここまで
    
      def about_author
        render :text => Hello::Application.config.author
      end
    end
    
  • :start-after: と :end-before: で特定ブロックだけ限定したインクルードができる。

    • 行番号指定に比べて、インクルード対象範囲がおかしくなりにくい。
    • 特定ブロックだけインクルードできるようにコメントに工夫が必要。
    • 少々邪魔でも、 start-xxx や end-xxx などのコメントをソースコードに入れておいた方がSphinxからのマッチングは確実。

    reSTソース (codeの一部):

    .. literalinclude:: ./sample/hello_controller.rb
       :language: ruby
       :start-after: #ここから
       :end-before: #ここまで
    

    HTML出力 (codeの一部):

      def view
        @msg = 'こんにちは、世界!'
        render 'hello/world'
      end
    
  • コードが更新された場合でも、buildしなおせば最新のコードに追随できる。

Note

仕様や要求を reST でまとめ、その仕様ドキュメントにソースコードをliteralincludeする、変更があった場合は Howをソースコードに Why を reSTファイルに残す、が理想なんじゃないかと思っています。

7.2. 運用ドキュメントの作成

include と replace の合わせ技が強力です。

  • define/work-manual/ などに、定型作業の手順テンプレートを作成し、変数部分に置換文字列( |HOGE| など)を記述しておく。

define/work-manual/hello.txt:

.. rubric:: 1. login

command:

  % ssh |TARGET_HOST|


.. rubric:: 2. ls

command:

  % ls


.. rubric:: 3. logout

command:

  % exit

Note

  • include先ファイルで Section Structure (見出し) を使うと、include元とコンフリクトするリスクが高いため、 rubric ディレクティブを使っています。
  • 置換文字列を使っているブロックで :: によるリテラル化をすると、置換文字列がそのまま表示されてしまうので注意が必要です。Admonitions系のディレクティブを活用するのが吉。
  • activity/2012/20121224-hello.rst などに、置換(replace)を定義し includeディレクティブでテンプレートを指定しておく。 (テンプレートの変数部分が置換された手順書が生成される。)

activity/2012/20121224-hello.rst:

==============================================================================
2012-12-24 Hello
==============================================================================

----------------------------------------------------------------
作業手順
----------------------------------------------------------------

.. |TARGET_HOST| replace:: svr1.example.co.jp

.. include:: ../define/hello.txt

Note

作業後にテンプレートが更新されてビルドされると、手順が最新のものになってしまうことには注意が必要です。 (make textなどでテキスト出力して、チケットに添付するなどがいいかも。)

make text の結果 (_build/text/activity/2012/20121224-hello.txt ):

2012-12-24 Hello
****************


作業手順
====

-[ 1. login ]-

command:

   % ssh svr1.example.co.jp

-[ 2. ls ]-

command:

   % ls

-[ 3. logout ]-

command:

   % exit

8. おわりに

はじめてアドベントカレンダーなるものに参加しましたが、つい書きたいことが多くなってしまって大変でした。 が、日頃まとめたいとおもっていて手つかずだったものについて、自分なりにまとめなおす時間が取れた、少しアウトプットできたという点でとても良い経験でした。

来年もより良いドキュメンテーションへの道を探りつつ、Sphinxコミュニティにも積極的に参加していきたいと考えています。

ということで、明日はアドベントカレンダー最終日、Sphinx開発者のGeorg Brandlさん です! Happy Sphinx!!