Satyrographos でパッケージの簡単インストール

この記事は [SATySFi Advent Calendar 2019](https://adventar.org/calendars/3929) 7日目の記事です。前日は @amutake さんの『[GitHub Actions を使った文書やパッケージの CI](http://amutake.hatenablog.com/entry/2019/12/06/103839)』です。次日は @abenori さんです。

本稿では [SATySFi](https://github.com/gfngfn/SATySFi) 用に開発しているパッケージマネージャー [Satyrographos](https://github.com/na4zagin3/satyrographos) を紹介します。

# 動機
SATySFi で何かイイ感じのパッケージを自作したり、また、配布されているものを使用したいとします。大抵のパッケージは `*.satyh` や `*.satyg` ファイルのみからなるために、適切な場所にコピーすれば事足りるわけですが、以下の問題点があります。

- SATySFi のバージョンを変えてコンパイルできるか試しているとき、一々 `~/.satysfi` を消去した上で SATySFi 標準ライブラリと各パッケージをインストールし直して試す必要があり、手間が掛かる。
    - 例：master 版から 0.0.3 版に切り替えたとき、単純に上書きするだけだと `dist/packages/annot.satyh` が残ったままになる。
- ハッシュファイルへの変更（例：『[SATySFiで素敵な文字を出力する　「番外編：好きなフォントを使いたい」節](https://qiita.com/zr_tex8r/items/56dee4364b05974d7a54#%E7%95%AA%E5%A4%96%E7%B7%A8%E5%A5%BD%E3%81%8D%E3%81%AA%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84)』）があるときにには、インストールし直した後、毎回ハッシュファイルへの変更を適用し直す必要がある。
    - フォントを含むパッケージのインストーラーはどう書けば良いのか？
    - 『[SATySFi 用のフォントライブラリを作ってみた](https://qiita.com/na4zagin3/items/627599ca746756e93bc1)』時に困ったのが Satyrographos 開発のきっかけである。
- 精力的な開発により、SATySFi 最新開発版 と最終リリース版である所の 0.0.3 版との間に[大きな差異](https://github.com/gfngfn/SATySFi/blob/69e62f66056b5644461f73c5fe841003602b0938/CHANGELOG.md#unreleased)が存在する。例えば SATySFi で（数式としてではなく文章として）ギリシャ文字を出力するパッケージ（[SATySFi-grcnum](https://qiita.com/na4zagin3/items/ae566b888f9a980fc34b)）は 0.0.3 版では動かないので対応バージョンから除外したい。

以上を解決するのが Satyrographos です。

# Satyrographos とは何なのか・何をするのか

一言で言えば、Satyrographos は `~/.satysfi` を消去して全てのパッケージを再インストールする操作を自動化するものです[^define-satyrographos]。

[^define-satyrographos]: 最終的には、バージョン制約解決やインターネットからのファイル取得を実装し、OPAM への依存を止め、完全なるパッケージマネージャにしたい。

以下のように Satyrographos ライブラリ置き場に `dist`、`fonts-theano`、`class-exdesign` が置かれているとき、

```
- Satyrographos ライブラリ置き場/
  - dist/ （SATySFi 標準ライブラリ）
    - fonts/
      - Junicode.ttf
    - hash/
      - fonts.satysfi-hash
    - packages/
      - List.satyh
  - fonts-theano/ （フォントライブラリ Theano）
    - fonts/
      - TheanoOldStyle-Regular.ttf
    - hash/
      - fonts.satysfi-hash
  - class-exdesign/ （puripuri氏作クラスライブラリ ExDesign）
    - packages/
      - exdesign.satyh
```

これを一まとめにして `~/.satysfi/dist` 以下に配置しなおします。

```
- ~/.satysfi/dist/
  - fonts/
    - Junicode.ttf  ← 標準ライブラリ
    - TheanoOldStyle-Regular.ttf  ← Theano
  - hash/
    - fonts.satysfi-hash  ← 標準ライブラリ & Theano
  - packages/
    - list.satyh  ← 標準ライブラリ
    - exdesign.satyh  ← ExDesign
```

要するにこれだけです。

Satyrographos ライブラリ置き場の管理、つまり、ライブラリのダウンロードやアップグレードは、今の所 [OPAM](https://opam.ocaml.org/)[^opam] にやってもらっています。（将来的にはパッケージ置き場の管理も提供したい）

[^opam]: OCaml Package Manager: SATySFi のビルドに必要なので、SATySFi 利用環境では使えることが多い。

# 基本的な使い方

## Satyrographos のインストール方法

### amutake/satysfi-docker 使用者
[amutake/satysfi-docker](https://github.com/amutake/satysfi-docker) を使っている場合には、既に入っています。

### SATySFi をこれから始めようとしている人
これから SATySFi をソースからビルドしようとしている人は、[SATySFi インストール手引き 2021年4月版](https://qiita.com/na4zagin3/items/a6e025c17ef991a4c923#%E5%A4%96%E9%83%A8%E3%83%AC%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%81%AE%E8%A8%AD%E5%AE%9A) に従ってください。

### SATySFi をビルドして使っている人（開発はしていない）
SATySFi 本体の開発はしていないけれども、SATySFi をビルドして使っている人は以下のコマンドを実行してください。ローカルの開発版の代わりに `satyrographos-repo` にある SATySFi 開発版のスナップショットを使うようになります。

```
$ opam repository add satyrographos-repo https://github.com/na4zagin3/satyrographos-repo.git
$ opam pin remove satysfi
$ opam install satysfi satysfi-dist satyrographos
$ sudo mv /usr/share/local/satysfi/dist /usr/share/local/satysfi/dist.old
```

### SATySFi 開発版を使って開発をしている人
`satysfi-dist.opam` を SATySFi に追加する PR ([#149](https://github.com/gfngfn/SATySFi/pull/149)) は 2019 年 12 月現在、マージされる見込みがありません。

Satyrographos は `dist` ライブラリが見つからない場合に `/usr/share/local/satysfi/dist` を利用しますので、適当にダミーの [`satysfi-dist.opam`](https://raw.githubusercontent.com/na4zagin3/satyrographos-repo/master/packages/satysfi-dist/satysfi-dist.0.0.3/opam) を SATySFi レポジトリに追加してください。

```
$ cd path/to/SATySFi
$ curl https://raw.githubusercontent.com/na4zagin3/satyrographos-repo/master/packages/satysfi-dist/satysfi-dist.0.0.3/opam > satysfi-dist.opam
$ opam pin -v "file://$PWD"
$ opam repository add satyrographos-repo https://github.com/na4zagin3/satyrographos-repo.git
$ opam install satysfi satysfi-dist satyrographos
```

### その他の人
上の条項に当てはまらない人は、README 等に反映させたいので、是非とも使用状況をコメントで教えてください！　お願いします m(_ _)m

## ライブラリのダウンロード・アップデート方法

ライブラリのダウンロードやアップデートは OPAM を用いて行います。

OCaml 用ライブラリと区別するために、SATySFi 用のライブラリには接頭辞 `satysfi-` が付いています。従って、`grcnum` という名前の Satyrographos ライブラリは、OPAM 上では `satysfi-grcnum` という名前の OPAM ライブラリとして扱われます。

例えば、SATySFi 0.0.3 版と `fonts-theano` パッケージを一緒にダウンロードするには、以下のコマンドを実行します。

```sh
$ opam install satysfi.0.0.3 satysfi-fonts-theano
```

ここで、`satysfi.0.0.3` の `.0.0.3` はバージョン番号の指定です。`satysfi.0.0.3` の代わりに `satysfi` とすると、開発版のスナップショットがインストールされます。

### パッケージ一覧

利用可能なパッケージ一覧は `opam list 'satysfi-*'` で取得することができます。

```
$ opam list 'satysfi-*'
# Packages matching: (installed | available) & name-match(satysfi-*)
# Name                     # Installed                      # Synopsis
satysfi-class-exdesign     0.2                              A class file easy to customize with SATySFi
satysfi-class-exdesign-doc 0.2                              Documentation: A class file easy to customize with SATySFi
satysfi-class-stjarticle   1.3.2                            Extended SATySFi document package for Japanese
satysfi-dist               0.0.3+dev2019.11.16              Standard library of SATySFi
satysfi-fonts-geolab       1+satysfi0.0.3+satyrograhos0.0.2 SATySFi Font Package for GeoLab's Georgian fonts
satysfi-fonts-theano       opam                             SATySFi Font Package for Alexey Kryukov's Theano Classical Fonts
satysfi-fonts-theano-doc   --                               Document of SATySFi Font Package for Alexey Kryukov's Theano Classical Fonts
satysfi-grcnum             0.2                              SATySFi Package for Greek Numeral System
satysfi-grcnum-doc         --                               Documentation of SATySFi Package for Greek Numeral System
satysfi-karnaugh           opam                             Drawing Karnaugh maps in SATySFi
satysfi-lib                --                               A collection of utility functions and modules for SATySFi
satysfi-lib-dist           0.0.3+dev2019.11.16              DEPRECATED: Install satysfi-dist instead!
satysfi-lib-doc            --                               Document: A collection of utility functions and modules for SATySFi
satysfi-matrix             0.0.1+dev2019.10.15              Math matrix library for SATySFi
satysfi-matrix-doc         --                               Document: Math matrix library for SATySFi
satysfi-siunitx            --                               A comprehensive (SI) units package
satysfi-zrbase             0.2.1                            SATySFi Packages for Ordinary Programming
satysfi-zrsatz             0.2.0                            ZR's miscellaneous SATySFi packages
```

### アップデート

SATySFi本体やパッケージのアップデートをするには、`opam update` と `opam upgrade` を実行します。

```
$ opam update

<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><>
....

$ opam upgrade
```

### パッケージのインストール

パッケージをインストールするには `opam install` を使います。インストールする際、パッケージ名には必ず `satysfi-*` を付けてください。

```
$ opam install satysfi-zrbase
```

**注意：** SATySFi 標準ライブラリは `satysfi-dist` という名前で OPAM ライブラリ化されています。一般的な用途では `satysfi-dist` は忘れずインストールして下さい。

```
$ opam install satysfi-dist
```

### パッケージのアンインストール

前節と同様に、パッケージをアンインストールするには `opam uninstall` が使えます。

```
$ opam uninstall satysfi-zrbase
```

## ライブラリの利用準備方法

現在インストールされているライブラリを全て SATySFi で利用可能にするには、`satyrographos install` コマンドを使います[^install-command]。`Installation completed!` と出たら成功です。

[^install-command]: 2019年12月現在、国際化されていないので、ロカールに<ruby>拘<rp>（</rp><rt>かかわ</rt><rp>）</rp></ruby>らず英語でメッセージが出る。

```
$ satyrographos install
Reading runtime dist: /home/na4zagin3/.opam/4.07.1/share/satysfi/dist
Read user libraries: ()
Reading opam libraries: (class-exdesign class-exdesign-doc dist matrix)
Overriding dist with user installed one
Not gathering system fonts
Installing libraries: (class-exdesign class-exdesign-doc dist matrix)
Removing destination /home/na4zagin3/.satysfi/dist
Installation completed!

Compatibility notice for library class-exdesign:

  Packages have been renamed.
  
    article-ja.satyh -> class-exdesign/article-ja.satyh
    exdesign.satyh -> class-exdesign/exdesign.satyh
```

`~/.satysfi/dist` が Satyrographos の管理下に無いときには、以下のようなメッセージが出て停止します。

```
$ satyrographos install
Reading runtime dist: /home/na4zagin3/.opam/4.07.1/share/satysfi/dist
Read user libraries: ()
Reading opam libraries: (class-exdesign class-exdesign-doc dist matrix)
Overriding dist with user installed one
Not gathering system fonts
Installing libraries: (class-exdesign class-exdesign-doc dist matrix)
Directory /home/na4zagin3/.satysfi/dist is not managed by Satyrographos.
Please remove /home/na4zagin3/.satysfi/dist first.
```

以上のように `Please remove /home/na4zagin3/.satysfi/dist first.` と言われた場合は、`~/.satysfi/dist` を消すか他の場所に移動されるかした後、`satyrographos install`をやりなおして下さい。

```
$ mv ~/.satysfi/dist ~/.satysfi/dist.old
$ satyrographos install
```

#### 互換性警告（Compatibility Warning）
ライブラリ内に含まれるパッケージやフォントの名前が最近のバージョンで変更されている時には、`satyrographos install`実行時に以下のような互換性警告が出力されます。

```
Compatibility notice for library grcnum:
  Packages have been renamed.

    grcnum.satyh -> grcnum/grcnum.satyh
```

```
Compatibility notice for library fonts-theano:
  Fonts have been renamed.

    TheanoDidot -> fonts-theano:TheanoDidot
    TheanoModern -> fonts-theano:TheanoModern
    TheanoOldStyle -> fonts-theano:TheanoOldStyle
```

# 応用

## システムにあるフォントがSATySFiで使えるようにしたい

`satyrographos install` の代わりに `satyrographos install -system-font-prefix 'system:'` を実行して下さい。

```
$ satyrographos install -system-font-prefix 'system:'
```

`system:PostScriptFileName` の形式でシステムにインストールされているフォントが使用できるようになります。例として、`Tahoma-Bold` と `HiraKakuStd-W8` を使う SATySFi 文書を以下に示します。

```satysfi
@require: stdjabook

let-inline ctx \set-non-cjk-font name it =
  let ctx =
    ctx |> set-font Latin (name, 1., 0.)
        |> set-font OtherScript (name, 1., 0.)
  in
  read-inline ctx it

let-inline ctx \set-cjk-font name it =
  let ctx =
    ctx |> set-font HanIdeographic (name, 1., 0.)
        |> set-font Kana (name, 1., 0.)
  in
  read-inline ctx it
in

document (|
  title = {System Fonts};
  author = {\@na4zagin3};
  show-title = true;
  show-toc = false;
|) '<
  +p {
    ABCDabcd
    \set-non-cjk-font(`system:Tahoma-Bold`){ABCDabcd}
  }
  +p {
    あいうえお漢字
    \set-cjk-font(`system:HiraKakuStd-W8`){あいうえお漢字}
  }
>
```

## 特定のライブラリだけ使用したい

稀に、別々のライブラリが同名のファイルを提供するなどして衝突してしまうことがあります。

`satyrographos install` に `-library <library-name>` オプションを与えることで、指定したライブラリのみを準備することができます。

```
$ satyrographos install -library class-exdesign -library class-exdesign-doc
Reading runtime dist: /home/na4zagin3/.opam/4.07.1/share/satysfi/dist
Read user libraries: ()
Reading opam libraries: (class-exdesign class-exdesign-doc dist matrix)
Overriding dist with user installed one
Not gathering system fonts
Installing libraries: (class-exdesign dist)
Removing destination /home/na4zagin3/.satysfi/dist
Installation completed!
```

## ライブラリのドキュメントが見たい

`satyrographos install` によって、ライブラリのドキュメントは `~/.satysfi/dist/docs` に準備されます。

## `~/.satysfi/dist` 以外の場所が使いたい

`satyrographos install` に引数を追加して下さい。

```
$ satyrographos install ./satysfi-document-root
Reading runtime dist: /home/na4zagin3/.opam/4.07.1/share/satysfi/dist
Read user libraries: ()
Reading opam libraries: (class-exdesign class-exdesign-doc dist matrix)
Overriding dist with user installed one
Not gathering system fonts
Installing libraries: (class-exdesign class-exdesign-doc dist matrix)
Removing destination ./satysfi-document-root
Installation completed!

$ ls
docs  fonts  hash  hyph  md  metadata  packages  unidata
```

# トラブルシュート
## Satyrographos コマンドの用法が分からない
とにかく `-help` オプションを追加して実行してみましょう。

```
$ satyrographos -help
Simple SATySFi Package Manager

  satyrographos SUBCOMMAND

=== subcommands ===

  install       Install SATySFi runtime
  library       Install libraries (experimental)
  library-opam  Inspect libraries installed in the OPAM managed directory
                (experimental)
  opam          OPAM related functionalities (experimental)
  pin           Manipulate libraries (experimental)
  status        Show status (experimental)
  version       print version information
  help          explain a given subcommand (perhaps recursively)

$ satyrographos install -help
Install SATySFi runtime

  satyrographos install [DIR]

Install SATySFi Libraries to a directory environmental variable SATYSFI_RUNTIME has or /home/na4zagin3/.satysfi/dist. Currently it accepts an argument DIR, but this is experimental.

=== flags ===

  [-copy]                                 Copy files instead of making symlinks
  [-library LIBRARY]                      Library
  [-system-font-prefix FONT_NAME_PREFIX]  Installing system fonts with names
                                          with the given prefix
  [-verbose]                              Make verbose
  [-help]                                 print this help text and exit
                                          (alias: -?)
```

## 使いたいパッケージが `opam list 'satysfi-*'` で出てこない
使いたいパッケージ `opam list 'satysfi-*'` で出てこない場合は、[na4zagin3/satyrographos-repo](https://github.com/na4zagin3/satyrographos-repo/issues) に issue を立てたり、プルリクエストを送ったりして下さい。

私は個人的に英語を作業言語としていますが、他の人に強制するつもりはありませんので、issue やプルリクエストの言語は、私の読み書きできる言語なら何でも OK です。日本語での貢献は大歓迎です。

## 標準ライブラリから変なエラーが出る
標準ライブラリから妙なエラーが出る場合は、利用している SATySFi エンジンと標準ライブラリの版号が異なっていることが考えられます。これは、

1. `dist` ライブラリがインストールされておらず、
2. `/usr/local/share/satysfi/dist` 等に、現在利用中の SATySFi エンジンとの互換性が無い SATySFi 標準ライブラリが存在する

場合に発生します。

この問題は `dist` ライブラリをインストールし、`/usr/local/share/satysfi` を削除することで解消します。

```
$ opam install satysfi-dist
$ sudo rm -rf /usr/local/share/satysfi
$ satyrographos install
```

## `Can't find SATySFi lib. Please install it`
`satyrographos install` 実行時に、`Can't find SATySFi lib. Please install it` なるエラーが出ることがあります。これは、SATySFi 標準ライブラリがインストールされておらず、また、`/usr/local/share/satysfi/dist` 等にも存在しない場合に発生します。

```
$ satyrographos install

...

Uncaught exception:
  
  (Failure "Can't find SATySFi lib. Please install it.")

Raised at file "stdlib.ml", line 33, characters 17-33
Called from file "bin/commandInstall.ml", line 26, characters 25-56
Called from file "bin/commandInstall.ml", line 143, characters 20-65
Called from file "src/command.ml", line 2817, characters 8-205
Called from file "src/exn.ml", line 107, characters 6-10
zsh: exit 1     satyrographos install
```

`dist` をインストールしてから再実行してください。

```
$ opam install satysfi-dist
$ satyrographos install
```

## `opam install` したライブラリが使えない
`opam install` は、指定したライブラリを Satyrographos ライブラリ置き場に置くだけで、それだけでは SATySFi から利用可能にはなりません。`opam install` の後は `satyrographos install` を実行してください。

```
$ opam install satysfi-zrbase
$ satyrographos install
```

## `command not found: satyrographos`
OPAM で Satyrographos インストールした場合には、`eval $(opam env)` を実行しないと`satyrographos` が発見可能な状態になりません。

```
$ satyrographos install
zsh: command not found: satyrographos
zsh: exit 127   satyrographos

$ eval $(opam env)

$ satyrographos install
Simple SATySFi Package Manager

  satyrographos SUBCOMMAND

...
```


<ruby>尚<rp>（</rp><rt>なお</rt><rp>）</rp></ruby>、`opam init` を実行し、`~/.bashrc` に `eval $(opam env)` を追加することを勧めます。

## バグ・不具合・機能要望

ここのコメント欄か作者の [Twitter アカウント（@na4zagin3）](https://twitter.com/na4zagin3) に報告してくださるか、問題によって [Satyrographos](https://github.com/na4zagin3/satyrographos/issues) か [Satyrographos-repo](https://github.com/na4zagin3/satyrographos-repo/issues) に Issue を立ててくださると喜びます。

# まとめ

```
$ opam install satysfi-パッケージ名
$ satyrographos install
```