Sphinxを便利にして、みんなに使ってもらいたい

[Sphinx](http://sphinx-users.jp/)は非常に素晴らしいドキュメント生成ツールです。
この素晴らしいツールを社内で流行らせようと頑張ったのですが、誰も使ってくれません。

みんながどんなタイミングで、Sphinxを諦めてしまうのか振り返ってみました。

- `reStructuredText`がわからないし、覚えたくもない
- デフォルトのテーマが見にくいからやめる
- sphinx-quickstartの設問が多すぎて途中でやめる
- ドキュメント作成のたびに`conf.py`を編集するのが面倒なので使わなくなる
- ドキュメント確認のたびに`make html`が面倒なので使わなくなる
- 最近はJupyterでドキュメント書くので・・・

こんなところでしょうか。
たぶん、Sphinxがいまいち流行らないのも、ここら辺が理由が大きいんじゃないかと思います。

# Markdownを使う
残念ながらマークアップ言語の主流は`reStructuredText`ではなく`Markdown`です。`Markdown`ならみんなに使ってもらえるんじゃないでしょうか。

Sphinxは`recommonmark`で`Markdown`を使えるようになります。
`recommonmark`の設定方法は、たくさんの方が記事を書いています、以下の記事などを参考にしてください。

[MarkdownでSphinxできるようになったので試してみた（後編）](http://tech.3rd-p-zombie.net/entry/2015/12/02/023732)

`recommonmark`はpipでインストール可能です。

```
pip install commonmark recommonmark
```

`conf.py`を以下のように編集します。

```python:conf.py
source_suffix = ['.rst', '.md']

from recommonmark.parser import CommonMarkParser

source_parsers = {
    '.md': CommonMarkParser,
}
```

さらに`recommonmark`を拡張する`AutoStructify`コンポーネントについて説明します。

### AutoStructifyコンポーネント
`AutoStructify`コンポーネントをセットアップすると、マークダウンから`reStructuredText`の様々な拡張が使えるようになります。
`AutoStructify`コンポーネントを有効にするには`conf.py`を編集します。

```python:conf.py
from recommonmark.transform import AutoStructify

github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
def setup(app):
    app.add_config_value('recommonmark_config', {
            'url_resolver': lambda url: github_doc_root + url,
            'auto_toc_tree_section': 'Contents',
            }, True)
    app.add_transform(AutoStructify)
```

マークダウン上で、以下のことができるようになります。

- toctree生成
- 他文書のリンク
- 数式 / インライン数式[^1]
- `reStructuredText`の埋め込み

[^1]: 数式を使うには`sphinx.ext.mathjax`などの拡張を有効にする必要があります

#### toctree生成
```:マークダウン記法
* [Title1](doc1.md)
* [Title2](doc2.md)
```
#### 他文書のリンク
```:マークダウン記法
[API Reference](api_ref.md)
```
#### 数式 / インライン数式
````:マークダウン記法
```math
E = m c^2
``` ``
````

インライン数式も使えます。

```:マークダウン記法
This formula `$ y=\sum_{i=1}^n g(x_i) $`
```

参考
http://recommonmark.readthedocs.io/en/latest/auto_structify.html


### Commonmarkの「表組み」が使えない問題

`recommonmark`でマークダウンが書けるのは良いのですが、表組み(テーブル)が使えません。
これは`CommonMark`が表組みはサポートしていないためで、近い未来に表組みがサポートされる事はなさそうです。

`recommonmark`のGitHubでもイシューが上がっていましたが「`eval_rst`使えばいいんじゃね？」という事になっています。

https://github.com/rtfd/recommonmark/issues/3

表組みに関して言えば`reStructuredText`の方が表現力が高いですし、`eval_rst`であればマークダウンの記述を崩さないので、ひとまずはこれで良いかなと思っています。

`eval_rst`で表組みは以下のようにします。

`````
```eval_rst
=====  =====  =======
A      B      A and B
=====  =====  =======
False  False  False
True   False  False
False  True   False
True   True   True
=====  =====  =======
``` ``
`````


# 見やすいテーマを設定する
とりあえず`Markdown`、およびその拡張が使えるようになったので、結構便利になってきました。
あとは見やすいテーマの設定です。

いくつかのテーマを試ましたが、やはり[Read The Docsテーマ](http://docs.readthedocs.io/en/latest/theme.html)が一番見やすいと思います。

インストールpipで簡単に行えます。
```
pip install sphinx_rtd_theme
```

後は`conf.py`を編集します。

```python:conf.py
import sphinx_rtd_theme

html_theme = "sphinx_rtd_theme"

html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
```

かなり見やすくなりましたね！！

![rtd.png](https://qiita-image-store.s3.amazonaws.com/0/140075/1432f909-24ed-dd5d-ee0e-b448b6a9ca39.png)

# ドキュメント生成を簡単にする

テーマも見やすくなって、かなり便利になってきましたね。

さて、いままで`Markdown`の設定して、テーマを設定して、結構な量の`conf.py`を編集してきました。
この作業は**ドキュメントを作る度に毎回行う必要があります**、不便すぎるわ、なんだそれ。

さすがに毎回`conf.py`を編集は辛すぎます、テンプレート機能を使いましょう。

** 注意 **
現状、conf.pyのテンプレートを使用するにはSphinxのバージョン(1.5.2)のソースファイルを編集します。
行う場合は自己責任でおねがいします。

## テンプレート機能を使う

`sphinx-quickstart`には`--templatedir`というオプションが用意されています。
`sphinx-quickstart`は`jinja2`を使って、`conf.py`や`Makefile`などのもろもろのファイルをテンプレートから生成しています。

ここで散々いじった`conf.py`を雛形としたテンプレートファイルを用意すれば良いのです！

テンプレートファイルの雛形は以下の場所にあるはずです、各環境にあわせて適宜読み替えてください。

`Pythonのパス/site-packages/Sphinx-x.x.x-pyx.x.egg/sphinx/templates/quickstart`

ファイルが見つからない場合は`conf.py_t`というファイルを検索して見つけてください。
`recommonmark`と`rtd_theme`の設定をした`conf.py_t`をgistに乗せておきます。

https://gist.github.com/pashango2/399010efaa546a47db5c82c72e4f3b5e

`conf.py_t`をどこか適当なディレクトリに置いてください。
なお、テンプレートディレクトリにファイルがいくつかありますが、`sphinx-quickstart`のソースを読む限り、存在しないテンプレートファイルはシステムのテンプレートファイルを見るようなので、すべてのファイルをコピーする必要はありません。

| テンプレートファイル名 | 説明 |
|:-:|:--|
| conf.py_t  | conf.pyのテンプレート  |
| Makefile.new_t  | シンプル版Makefileのテンプレート  |
| Makefinle_t  |Makefileのテンプレート  |
|  make.bat.new_t | シンプル版make.batのテンプレート  |
|  make.bat_t | make.batのテンプレート  | 
|  master_doc.rst_t | 最初に生成される.rstのテンプレート  |

### しかし、conf.pyが書き換わらない！
テンプレートファイルを格納したディレクトリを指定して`sphinx-quickstart`を実行します。

```
sphinx-quickstart --templatedir=my_sphinx_template
```

しかし、何回コマンドを実行しても`conf.py`が書き換わりません。
`Makefile`など他のファイルは書き換わるのに`conf.py`はどうしても書き換わらないのでソースを読みます。

[`sphinx/quickstart.py`](https://github.com/sphinx-doc/sphinx/blob/master/sphinx/quickstart.py)の442行目でコードが以下のようになっています。

```python:quickstart.py
    with open(os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')) as f:
       conf_text = convert_python_source(f.read())
```

`conf.py_t`だけ直接パッケージ配下のファイルを直指定しています。

```python:quickstart.py
    # with open(os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')) as f:
    conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None
    if not conf_path or not path.isfile(conf_path):
        conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')
    with open(conf_path) as f:
        conf_text = convert_python_source(f.read())
```
※ template_dirがNoneの場合にエラーが出ていました、修正いたします(2017/02/05)

`conf.py`でテンプレートが使えないのは不便すぎるので、ソースを書き換えてしまいます。

### Sphinxのソース書き換えについて(2017-02-08追記)

現状で`conf.py`にテンプレート機能が効かないのはバグとなります。

上記の変更をプルリクエストしてマージされましたので、３月中頃にリリース予定の1.5.3では修正される予定です。
初めてGithubでプルリクエストを出したのですが色々失敗をしました、付き合ってくださったSphinxコントリビュータの方に感謝いたします。

# sphinx-quickstartを便利にする
テンプレートの件は少しモヤモヤしますが、毎回の`conf.py`編集から解放されて、だんだん便利になってきました。
`sphinx-quickstart`は、バージョンを重ねるごとに項目が増えてきて、もはやクイックではない問題です。

`sphinx-quickstart`は色々なオプションが用意されているので、すべてのオプションを適用したバッチファイルを作れば良いのですが、オプション数が多いので非常に面倒です。

そこでクイックスタートをクイックにするPythonスクリプトを書こうと思います。

```python:my-sphinx-quickstart.py
#! codig:utf-8
import sys
from sphinx.quickstart import ask_user, generate, DEFAULT_VALUE

d = DEFAULT_VALUE.copy()

d["path"] = sys.argv[1]
d["project"] = sys.argv[2]
d["author"] = sys.argv[3]

# 決め打ちの設定
d["version"] = "1.0"
d["language"] = "ja"

# シンプルなMakefile
d["make_mode"] = True

# エクステンションの設定
d["ext_mathjax"] = True

template_dir = "テンプレートパスまたはNone"

# 不足パラメータがあった場合の質問（無くてもよい、お好みで）
ask_user(d)

# ドキュメント生成
generate(d, templatedir=template_dir)
```

内容は各自で書き換えてください。
上の例ではプロジェクトパス、プロジェクト名、作者名を引数にして実行すると、後はすべてデフォルト設定でドキュメントを作成してくれます。

基本的に`sphinx.quickstart.generate`メソッドにパラメータ辞書とテンプレートディレクトリを渡す事でドキュメントを作成しています。
Jsonで設定を外部ファイルに移したり、GUIで設定するスクリプトとかを書くと便利かもしれません。

このスクリプトとテンプレートディレクトリを社内で共有すれば、カスタムされたドキュメント生成が一瞬で作れるようになります。
これは便利に違いない。

#### 2017-03-06追記
[Sphinxのドキュメント作成を便利にする「sphinx-quickstart-plus」を作りました](http://qiita.com/pashango2/items/512e567b328058d4107a)を書きました、この記事のconf.pyの設定が自動生成されるツールです。

# sphinx-autobuildを使って自動ビルドをする

これでドキュメント作成時に、わずらわしい`sphinx-quickstart`と`conf.py`の編集から解放されました。
この時点で、かなり便利になったかと思います。

ドキュメントを更新＆確認するごとに、いちいち`make html`を打たなくてはいけないのですが、`sphinx-autobuild`を使うと自動でビルドされるようになります。

pipでインストール可能です。

```
pip install sphinx-autobuild
```

インストール後に以下のコマンドでファイル監視が始まり、更新と同時にビルドされます。

```
sphinx-autobuild  <ソースディレクトリ> <ビルド成果物出力ディレクトリ>
```

このコマンドは長くなるので毎回入力するのは面倒です、なので生成された`Makefile`に次のコードを付け足すと便利です。

```:Makefileの場合
livehtml:
	sphinx-autobuild -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
```


```:NewMakefileの場合
livehtml:
	sphinx-autobuild -b html $(SOURCEDIR) $(BUILDDIR)/html
```

※Makefileの仕様としてインデントはTABにしないとエラーになります、注意してください

以下のコマンドで自動ビルド監視が始まります。

```
make livehtml
```

`localhost:8000`でドキュメントにアクセスします。
ちなみに先に話したテンプレート機能で`Makefile_t`と`Makefile.new_t`に、それぞれのコードを追加しておくと便利です。

gistに`Makefile_t`と`Makefile.new_t`のテンプレートを乗せておきます。

https://gist.github.com/pashango2/399010efaa546a47db5c82c72e4f3b5e

# Jupyterのノートブックを取り込む(2017-02-06追加)

最近はJupyterを使ってドキュメントを書く人も増えてきたと思います。
Sphinxの拡張に[nbsphinx](https://nbsphinx.readthedocs.io/en/0.2.12/)というものがあり、この拡張でJupyterノートブックを取り込むことができます。

インストールは`pip`で簡単に行えます。

```
pip install nbsphinx
```

例によって`conf.py`を編集します。

```python:conf.py
extensions = [
    'nbsphinx',
    'sphinx.ext.mathjax',
]
exclude_patterns = ['_build', '**.ipynb_checkpoints']
```

`nbsphinx`拡張と無視パターンに`**.ipynb_checkpoints`が入っている事を確認してください。

次に`toctree`にノートブックを追加します、拡張子`.ipynb`を除去したファイル名を書いてください。
なお、ノートブックの1行目に見出し（`# タイトル`)を入れないと、認識されないので注意してください。

下の例では`jupyter.ipynb`というファイルを文書として追加している例です。

```
Welcome to test's documentation!
================================

.. toctree::
   :maxdepth: 2
   :caption: Contents:

   jupyter
```

Jupyterノートブックが追加されました！
`nbsphinx`も`conf.py_t`のテンプレートに追加しておくと便利でしょう。

![jupyter.png](https://qiita-image-store.s3.amazonaws.com/0/140075/5f4be02d-2569-f626-155b-e9dc1c901aff.png)

# <i class="fa fa-flag" aria-hidden="true"></i>Font Awesomeを使う(2017-02-11追加)

[Font Awesome](http://fontawesome.io/)は様々なフォントアイコンでドキュメントの表現力を上げてくれます。
QiitaもFont Awesomeに対応しています。

SphinxでFont Awesomeを使うには[sphinx_fontawesome](https://github.com/fraoustin/sphinx_fontawesome)を使います、インストールは例により`pip`で簡単に行なえます。

```
pip install sphinx_fontawesome
```

`conf.py`を編集します。

```python
import sphinx_fontawesome
extensions = ['sphinx_fontawesome']
```

マークダウンから使いたい場合は普通にHTMLを打ちます。

```HTML
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
```

このようにSphinxのマークダウンからFont Awesomeが使えます。

![fontawesome.png](https://qiita-image-store.s3.amazonaws.com/0/140075/759f2cc9-5193-af33-f418-71987155f0bf.png)


`reStructuredText`からの使い方は[sphinx_fontawesome](https://github.com/fraoustin/sphinx_fontawesome)のReadmeで参照してください。

# AtomでreStructuredTextをプレビューする

`reStructuredText`で頑張りたい人は、[Atom](https://atom.io/)に`reStructuredText`をプレビューするプラグインがあります。

rst-preview: https://atom.io/packages/rst-preview

`ctrl-shift-r`でプレビューを表示できます、`pandoc`を使うので先にインストールしておいてください。

![005.png](https://qiita-image-store.s3.amazonaws.com/0/140075/3cd8eb19-8add-23df-837a-1284d5af3a59.png)

# あとがき

Sphinxは様々なところで不便なところがありましたが、環境さえ整備すれば、かなり便利になります。

- `Markdown`でドキュメントが書ける
- いざとなったら`reStructuredText`も混ぜて書くことができる
- Jupyterノートブックも取り込める
- 自動ビルドもしてくれる
- 拡張も豊富
- Pythonとの高い親和性
- ドキュメント生成もスクリプトで一発

最強のドキュメント環境に近づいたんじゃないかと思います。

~~最後に、テンプレート機能で`conf.py`を書き換えるソース改造は自己責任で、またはSphinxのバージョン1.5.3を待ってください。~~
テンプレートに関しては最新版のSphinx 1.5.3で修正されています。

#### 2017-03-06追記

[Sphinxのドキュメント作成を便利にする「sphinx-quickstart-plus」を作りました](http://qiita.com/pashango2/items/512e567b328058d4107a)を書きました、この記事のconf.pyの設定が自動生成されるツールです。