NimでAPIドキュメントを書く

# まえがき

* [Nimの標準ライブラリのドキュメント整備のissues](https://github.com/nim-lang/Nim/issues/10330)に参加したときに、Nimのドキュメントを書く方法についていろいろ知見を得ました
* NimでAPIドキュメント書いてドキュメント生成する方法について書きます。

# APIドキュメントの書き方

## Nimのドキュメンテーションコメント

Nimではコメントを書く時に`#`と書きますが、ドキュメンテーションコメントを書く時は`##`と書きます。

以下のように書きます。

```sample.nim
## sample.nim はAPIドキュメントのサンプルです。
##
## これはトップレベルのドキュメンテーションコメント。

var v1* = 1
  ## v1 は1が入っています。
  ## 複数行のテキストも表現できます。

const
  v2* = 2
    ## v2 は2です。
    ## こちらも複数行のテキストを表現できます。
  v3 = 3
    ## v3 は非公開なのでドキュメントが生成されない。

type
  SampleObject* = object
    ## SampleObject はサンプルオブジェクトです。
    v: int

proc sampleProc*(n: int) =
  ## サンプルプロシージャです。
  echo "Sample"
```

このコードからドキュメントを生成してみます。
以下のように実行します。実行するとsample.htmlが生成されます。

```bash
$ nim doc sample.nim
```

生成されたドキュメントは以下です。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69665/f7a281da-d4f0-454b-c058-8c9c079690f4.png)

## ドキュメント記法(reStructuredText)について

Nimでのドキュメント記法は**reStructuredText**です。
reStructuredTextの書き方については以下の記事がとても参考になります。

* [ふだん Markdown を書く技術者のための reStructuredText 文法まとめ](https://gotohayato.com/content/464)

## サンプルコードの書き方(runnableExamples)

サンプルコードの書き方ですが、`runnableExamples`というNimの組み込みプロシージャを使います。
以下に使用例を示します。

```sample.nim
## sample.nim はAPIドキュメントのサンプルです。
##
## これはトップレベルのドキュメンテーションコメント。
##
## 使用例
## ------
##
runnableExamples:
  import sample

  echo 1.add1()
  ## Output:
  ##   2

proc add1*(n: int): int =
  ## add1 は ``n`` に1加算する。
  runnableExamples:
    doAssert 1.add1() == 2
    doAssert 10.add1() == 11
  return n + 1
```

このコードから以下のAPIドキュメントが生成されます。

![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69665/710cb74e-4ddb-7078-1470-695eeee1edc4.png)

`runnableExamples`のブロックのコードが、HTMLでコードブロックとして表現されています。

`runnableExamples`でサンプルコードを実装すると以下のメリットを得られるので、積極的にこちらを使うべきです。

* エディタのオートコンプリートやシンタックスハイライトが効く
* コンパイルが通ることを検証できる
* サンプルコードが実際に動作することを検証できる

`runnableExamples`のコードはデバッグビルドとリリースビルドからは無視されるので、実行時の無駄な負荷も発生しません。

reStructuredTextでもコードブロック記法があるので、以下のようにサンプルコードを書くこともできます。

```rst
## .. code-block:: Nim
##    echo "Hello"
```

こちらはコンパイルが通ることの検証ができないのでrunnableExamplesが使えるときはそちらを使うと良いと思います。

runnableExamplesでは、実際にコンパイルしてバイナリを生成してサンプルコードを実行して正常終了することでサンプルコードを検証するような作りになっています。

サンプルコードのコンパイルが通らなかったり、サンプルコード内でエラーが発生したらドキュメントの生成はそこで停止します。

# 複数モジュールのドキュメント生成

以下のように、複数のモジュールをimportしているNimコードのドキュメントを生成したい場合があります。

```
src/
  +- sample/
  |   +- module1.nim
  |   `- module2.nim
  `- sample.nim
```

```sample.nim
import sample/[module1, module2]
```

単純に`nim doc`だけでドキュメントを生成すると、import先まではドキュメントを生成してくれません。

この場合は`--project`と`--index:on`と`--out`オプションを使用します。
以下のように実行することでドキュメントを生成できます。

```bash
$ nimble doc --project --index:on -o:docs src/sample.nim
```

これで`docs`ディレクトリ配下にAPIドキュメントのhtmlが生成されます。
上記の例だと、sample.nimからimportしているサブモジュールの`module1`、`module2`のドキュメントも生成されます。

# 実際にやってみた

迷路を生成するコマンド兼ライブラリのハイブリッドなモジュールを作成しました。

* [GitHub - jiro4989/maze](https://github.com/jiro4989/maze)

こちらのモジュールでも前述と同様に`nimble doc --project --index:on -o:docs`でドキュメントを生成しています。

生成されたドキュメントはGitHub Pagesで公開しています。
以下がそのページです。

* [maze/maze.html](https://jiro4989.github.io/maze/maze.html)

こちらはGitHub ActionsをCIに使用しています。
masterブランチが更新されると自動でGitHub Pagesに公開されるようにしています。

以前僕が書いた[Qiita - Nim用のGitHub Actionsを作ってみた](https://qiita.com/jiro4989/items/809f2a520c2e40d65bd3)で作成した自作のGitHub Actionも使用しています。

# まとめ

以下の内容について書きました。

* APIドキュメントの書き方
* ドキュメント生成コマンド
* サンプルコードの書き方
* 実際にやってみた例の紹介

APIドキュメントの書き方としては公式の`lib/pure`配下のドキュメンテーションコメントが参考になります。
困った時は標準ライブラリのドキュメンテーションコメントを読むのもありですね。

以上です。