PkgTemplates による Julia パッケージの作り方（前半）

# Notification

- GitHub Actions と連携した方法を書きました． [-> こちらをどうぞ <-](https://qiita.com/SatoshiTerasaki/items/88ff6a1e9351cec6aafe)

# 本日は

最近はJuliaの環境構築に慣れてきたので野良パッケージを作ることをしていました。
作成にあたって PkgTemplates.jl が便利です。

パッケージの作り方は公式ドキュメントの [5. Creating Packages](https://julialang.github.io/Pkg.jl/v1/creating-packages/) のページにもあるように

```
pkg> generate HelloWorld
```

のようにすることでできます。この場合、必要最低限のものしか得られません。
将来スゴイJuliaなパッケージをGitHubで公開するにはGitHubにリポジトリを登録して、Travis CIによるCIを回したりと様々な準備が必要です。ナニカスゴイパッケージが作られてもそれの使い方、関数の仕様が明記されているドキュメントがないと寂しい物があります。こういったことを手軽に、ドキュメントの生成・管理もしやすい仕組みがJuliaにはあります。ここでは、PkgTemplatesから雛形をつくって、(または既存のパッケージ追加し）にDocumenter.jlによるドキュメントを自動生成し、それをGitHubPagesから閲覧できるようにする手順を紹介します。`Julia` は `1.1.1`、OS は Ubuntu16.04 で行っています。

思ったより量が多くなってしまったので、前半と後半に分けたいと思います。前半は主にローカルでの作業になります。

# Packageを作ろう

冒頭で述べたように

```julia
pkg> generate HelloWorld
```

でもいいですが、ここでは [PkgTemplates.jl](https://github.com/invenia/PkgTemplates.jl) の力を借ります。インストールしましょう。

```julia
julia> using Pkg
julia> pkg"add PkgTemplates"
# 次の方法でも良い
pkg> add PkgTemplates
```

インストールしたらパッケージの雛形を作りましょう。

- `ssh=true` をしているのは、GitHub二段階認証をしている関係で git push につかうremoteが `git@github.com:ユーザ名/リポジトリ名.git` にしているからです。必要に応じて `false` に変更などをしてください。
- 最終的にはみなさんのGitHubにリポジトリを作成してGitHubPageにドキュメントをアップすることになりますので、`git` の設定に GitHub のアカウント名をひもづけておく必要があります。これを設定しておかないとパッケージ生成に失敗します。

```
$ git config --global github.user あなたのGitHubのアカウント名
```

```julia
julia> using PkgTemplates
julia> t = Template(;
           ssh=true,
           plugins=[
               TravisCI(),
               GitHubPages(),
           ]
           ,
       )
```


- `plugins` には `TravisCI` と `GitHubPages` のものだけを加えておきました。`PkgTemplates.jl` のREADME を参照し必要に応じて追加してください。
- ここでは `HelloWorld` という名前でパッケージ名を作ります。ちょこっと時間かかります。

```julia
julia> generate("Helloworld", t)
```

`generate` は PkgTemplate が提供している関数です。引数を `(t, "HelloWorld")` にしても同じです。内部で引数の順番を調節してくれます。（お、Juliaのマルチディスパッチですねー）

そうするとデフォルト環境では `~/.julia/dev/` 直下に `HelloWorld` パッケージが生成されます。

```console
$ tree ~/.julia/dev/HelloWorld
HelloWorld/
├── docs
│   ├── make.jl
│   ├── Manifest.toml
│   ├── Project.toml
│   └── src
│       └── index.md
├── LICENSE
├── Manifest.toml
├── Project.toml
├── README.md
├── src
│   └── HelloWorld.jl
└── test
    └── runtests.jl

4 directories, 10 files
```

`docs` 以下に ドキュメントを書くための `make.jl` および、それを実行するための環境を作るための設定ファイル `Project.toml` が得られます。

# Document を生成しよう。

将来的にはGitHubPagesでドキュメントを閲覧できるようにしたいですね。どういうものができるのか確認してみましょう。`~/.julia/dev/HelloWorld` に作業ディレクトリを移動して次を実行します。

```
$ julia --project=docs -e '
          using Pkg;
          Pkg.develop(PackageSpec(path=pwd()));
          Pkg.instantiate();
          include("docs/make.jl");
'
```

これはPkgTemplatesによって自動生成された `.travis.yml` にあるドキュメントを生成する命令そのものです。

`make.jl` が実行され doc/build 以下にウェブページが作られます。

```
├── docs
│   ├── build
│   │   ├── assets
│   │   │   ├── arrow.svg
│   │   │   ├── documenter.css
│   │   │   ├── documenter.js
│   │   │   └── search.js
│   │   ├── index.html
│   │   ├── search
│   │   │   └── index.html
│   │   └── search_index.js
```

`make.jl` の中身を見るとわかりますが、`Documenter` パッケージに依存しています。`PkgTemplates.jl` はdocs以下の `make.jl` などの__ファイルを作るだけに過ぎず__、Webページ生成は`Documenter.jl`の仕事です。実際、[Documenter.jlのドキュメント](https://juliadocs.github.io/Documenter.jl/stable/man/guide/)をみると `docs` 以下に作るファイルを手動で作る方法が書いてあります。すでに作成したパッケージにドキュメントを追加したい場合はPkgTemplateで生成された `docs` 以下をコピーすると可能です。ただし、後で述べるように__パッケージ名を変更__ や `.travis.yml` の__編集__が必要です。

## 生成された結果をローカルで閲覧


[Documenter.jlのドキュメント](https://juliadocs.github.io/Documenter.jl/stable/man/guide/)

にあるように `docs/build` に移動後、下記を実行しHTTPサーバーを立ち上げます。

```console
$ python3 -m http.server --bind localhost
```

下記のような結果が得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/278f48dc-f28e-575d-f357-363973a6da8e.png)

え？なにかへんなコメントが書かれてるって？そうですね。`src/HelloWorld.jl` にある関数にdocを追加しました。doc/以下の中身をいじらなくても、ソースコードにコメントを書いておくことでそれがドキュメントとして反映されます。

## 既存のパッケージにドキュメントを追加する場合

### 雛形 `docs` をコピー

例えば `~/.julia/dev` 以下で `Gomah` というパッケージを作っているとします。docs を作るには次の選択肢があります。

- `Documenter.jl` のチュートリアルに従って `docs` にしたがって作る
- `PkgTemplates.jl` で生成した`HelloWorld` で生成された `docs` を `Gomah` 以下にコピーする

後者の場合、パッケージ名HelloWorldに依存している部分を加える対象のパッケージ名に変更（ここでは `Gomah`) に変更します。具体的には 

- `make.jl` と `docs/src/index.md` にある `HelloWorld` を `Gomah` 置換する
- docs/Project.toml にある `HelloWorld` の行を `Gomah` と対応するUUIDに置換する

の二つあります.

### .travis.yml の編集

`.travis.yml` に次のジョブを追加します。`PkgTemplates.jl` で生成されたパッケージを開発で続ける場合はこの操作は不要です。（すでに定義されているため）。


```yml

jobs:
  include:
    - stage: Documentation
      julia: 1.0
      script: julia --project=docs -e '
          using Pkg;
          Pkg.develop(PackageSpec(path=pwd()));
          Pkg.instantiate();
          include("docs/make.jl");'
      after_success: skip
```

たとえば、次のような形になります。


```yml:.travis.yml
# Documentation: http://docs.travis-ci.com/user/languages/julia/
language: julia
os:
  - linux
  - osx
julia:
  - 1.1
  - nightly
matrix:
  allow_failures:
    - julia: nightly
  fast_finish: true
notifications:
  email: false
after_success:
  - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder())'
  - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder())'
jobs:
  include:
    - stage: Documentation
      julia: 1.1
      script: julia --project=docs -e '
          using Pkg;
          Pkg.develop(PackageSpec(path=pwd()));
          Pkg.instantiate();
          include("docs/make.jl");'
      after_success: skip

```

# GitHub にパッケージをリポジトリとしてpush

GitHubPagesにドキュメントを公開するのでリポジトリにプッシュする必要があります。お？ `git init` しないといけないのか？心配いりません。`PkgTemplates.jl` で生成したパッケージをGitHubに登録する方法を紹介します。`PkgTemplates.jl` の便利機能ですでにパッケージがリポジトリとして `git init` されており自動生成されたファイルがすでにコミットしている状態になっています。`.gitignore` などもよしなに作られイタレリツクセリです。

下図は `tig` で git のコミットログを表示した様子を表しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/62fb42bd-a912-ecf4-b634-e7eb7f0989fd.png)

これから、この状態のをみなさんのGitHubにプッシュします。その準備のためにGitHubに受け皿としてからのリポジトリを作っておく必要があります。

## `HelloWorld.jl` の生成

`HelloWorld.jl` という名前でリポジトリを作ります。__`Repository name` だけを編集してそのまま何もせずに、そう何も考えずに、 `Create Repository`ボタンをおします。__

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/bd28cb42-0c69-662f-4973-a3cb96c965e3.png)

ページが遷移した後どうすればいいのかの指示が来ますので、下記の図を参考につぎを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/7631f82b-316b-a825-2a60-7e34bfe73126.png)

```
$ cd ~/.julia/dev/HelloWorld
$ git push -u origin master
```

`git remote -v` するとわかりますが、すでに push 先が登録されていますので `git remote add origin ...` は不要です。



## すでに作成したパッケージに対して docs を追加したい場合

すでにGitHubでリポジトリをつくってバージョン管理していると思うのでそのリポジトリの `.gitignore`ファイルに 

```
/docs/build/
/docs/site/
```

を追加します。

この後は `.gitignore`, `docs`, `.travis.yml` を `git add` してコミットをします（ブランチは適当に作成してください)。

前半戦は以上です。

# 後半戦 ですること

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/b753b928-3b40-73a9-c46a-65e42973b439.png)

リポジトリを見るとプッシュされた変更が反映されているのがわかります。README.mdをみると `docs` のバッジがでていますね。これは将来あなたのパッケージを使う場合にユーザーが参照するドキュメントになります。ボタンを押してもこの時点では４０４です。後半戦ではローカルで閲覧したHTMLを見られるようにしていきます。

[後半につづく](https://qiita.com/SatoshiTerasaki/items/f43a7730bcf57f4b9572)