SATySFiに関すること

この記事は2018年に投稿されたのち、2023年2月に更新を行いました。


# はじめに
## SATySFiとは

[SATySFi](https://github.com/gfngfn/SATySFi)とは、型による静的検証能力の高い組版システムです。

従来の組版システムであるLaTeXにはない特徴である可読性の高さと詳細なエラー報告機能を持つことを目指して作られています。

The SATySFibook（SATySFiのマニュアル）が無料で見ることができるようになりました。[URL](https://gfngfn.booth.pm/items/1127224)はここです。わからないところがあったらその箇所を読みましょう。
投げ銭もできます。紙とインクでできた方も欲しい方は[ここ](https://gfngfn.booth.pm/items/1046747)から買いましょう！

## SATySFiの特徴

- マークアップ言語
- 裏でTeXを使っていたりせずに自前でPDFファイルを出力してくれる
- PDFファイルだけではなく、HTMLファイルやTeXファイルを出力する機能もある 
- 数式を表現することが非常に得意
- エラーが表示されるタイミングが早く、わかりやすい
- 機能の拡張が便利
- 非常に若いソフトであり、オワコン化が囁かれているLaTeXに代わりになることが可能かもしれない
- LGPLv3の元GitHubで公開されているOSSである（つまり、タダで使用できる）

## （今更だけど）この記事の目的

SATySFiを始めようと思った人のため、そして自分のためにSATySFi関係の情報を集めておくことが目的です。

「SATySFi完全に理解した」という人のためではないのでご了承くださいませ。

間違っていることが書いてありましたら教えてください。直していきたいと思います（根本から間違っているという場合でも見捨てずに教えていただけると嬉しいです）。

## 注意事項

書く内容に関しては正確なものになるように気をつけていますが、間違っていることを書いているかもしれません。この記事に頼り切らず、他の情報と合わせて使用してください。

この記事を使用したことで受けた被害等の責任は取りかねます。

SATySFiはまだバージョンが0.0.8であり、また近々後方互換性のない変更が入る0.1.0がリリースされる予定があります。このように、どんどん機能が追加されていったり、今まであった機能が廃止されたりと言った変化が起きることは充分ありえるため、注意をしてください（v1.0.0までに互換性のない変更があることは十分にありえるので、パッケージ作成者は情報を追うべきです）。

この記事に情報は2023年2月時点での最新版のSATySFiについて述べていきます（大きな変更がSATySFiに加わったらなるべく対応していくつもりです）。
ですので古いSATySFiにはない機能について述べたりしていきますが、ご了承ください。

## 筆者のスペック

これを書いている人のスペックです。参考までに

- 使用OSはUbuntuやWindows11
- よく使う言語はRust・OCamlなど
- Ubuntu on WSLにSATySFiの最新版を入れている。

# SATySFiのインストール方法

[SATySFi インストール手引き 2021年5月版](https://qiita.com/na4zagin3/items/a6e025c17ef991a4c923)を読むと良いと思います。ここではSATySFiのパッケージマネージャである[satyrographos（サティログラポス）](https://github.com/na4zagin3/satyrographos)を使ってインストールする方法を主に紹介しています。

他にはソースコードから手動でビルドする方法があり、これは[公式README](https://github.com/gfngfn/SATySFi/blob/master/README-ja.md)を参照すると良いでしょう。


いずれにせよ、WindowsではWindows Subsystem for Linux(WSL)を使用する必要があります。最新のWindowsであればMicrosoft Storeからボタンを推すだけでインストールすることができるため、手軽に行えます。


## opamとsatyrographosを使ったインストール

一番標準です

まずはopamのインストールを行います。正確な情報は[opamのドキュメント](https://opam.ocaml.org/doc/Install.html)を参照してください。概ね

```sh
bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"
```

を実行すればよいと思います。

インストール時に必要とするソフトウェアとしては

- bubblewrap
- build-essential
- curl
- git
- m4
- unzip

あたりがあります

次にOCamlのコンパイラをインストールします。必要なバージョンは2023年2月時点では`4.12.0`以上です。各自で確認したい場合は[`satysfi.opam`](https://github.com/gfngfn/SATySFi/blob/master/satysfi.opam)ファイルの制約を確認してください。

```sh
opam init --comp 4.14.0
eval $(opam env)
```

のようなコードになります。

もしWSLなどでインストールに失敗した場合にはsandboxが使えないからかもしれません。その場合には無効化するオプションでインストールをしてください。

```sh
opam init --comp 4.14.0 --disable-sandboxing
eval $(opam env)
```

`.bashrc`ファイルなどの設定ファイルに`eval $(opam env)`を書いておくと、シェル起動時に常にopam環境を呼び出すことができます。

次にopamの外部リポジトリを登録します。

```
opam repository add satysfi-external https://github.com/gfngfn/satysfi-external-repo.git
opam repository add satyrographos https://github.com/na4zagin3/satyrographos-repo.git
opam update
```

最後にsatysfiとその標準ライブラリ、そしてsatyrographosをインストールし、パッケージのインストールを行います。

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

これで最新版のSATySFi及びパッケージマネージャを使用することができます。

## ソースコードからのインストール

ソースコードからのインストールではSATySFiの最新版を使用することができます。また、satyrographosのみをインストールすることでパッケージマネージャの恩恵も得ることができます。

手順としては、opamとOCamlのインストールと外部リポジトリの登録までは一緒です。

その後SATySFiのリポジトリを手元にcloneします。

```
git clone https://github.com/gfngfn/SATySFi.git
```

その後、フォルダに移動しビルド及びインストールをします。

```
cd SATySFi
opam pin add satysfi .
opam install satysfi
```

標準ライブラリのインストールには2種類の方法があります。一つはsatyrographosを使ったインストールで、もう一つはSATySFiのリポジトリの中にあるインストーラを使う方法です。

satyrographosを使う場合にはsatyrographosと標準ライブラリをインストールします。

```
opam install satyrographos stysfi-dist
satyrographos install
```

インストーラを使う場合には、SATySFiフォルダでインストーラを起動します。

```
# 必要であればフォルダに移動
# cd SATySFi
./download-fonts.sh
sudo ./install-libs.sh
```

## Docker Imageを使う

SATySFi単体のイメージの他にもSATySFi本体以外にもsatyrographosが入ったイメージなどがあり、便利です。

詳しくは["docker imageを使う"](https://puripuri2100.github.io/learn-satysfi/chapter3/use_docker.html)を読んでください。

## satysfi-unofficial
matsud224氏が「SATySFiをちょっと試してみたい人がOCamlのビルドからやらないといけないのはハードルが高い」と思ったらしく、少し簡単にSATySFiを入れられるようなものを整えてくださいました。

[satysfi-unofficial](https://packagecloud.io/matsud224/satysfi-unofficial)のREADMEを読んでそれに従えばインストールできます。

## [SATySFi Playground](http://satysfi-playground.tech/)

正確にはインストールするものではありませんが、インターネット上でコンパイルすることができるものです。

# demoファイルのコンパイル

とりあえずdemoファイルをコンパイルしてみましょう。
[SATySFiのリポジトリ](https://github.com/gfngfn/SATySFi)をcloneもしくはダウンロードするか、[SATySFiのリリース](https://github.com/gfngfn/SATySFi/releases)をダウンロードするかしましょう。


準備ができたらターミナルを開きます。ターミナルで、demoフォルダまで移動し、ビルドします。

```sh
cd demo
make
```

するとログが出てPDFファイルが出力されると思います。


ココらへんはLaTeXのコンパイルと似たようなものでしょう。。

コンパイルが終わったら出力されたPDFファイルを見てみましょう。

ヘッダーやフッター、画像の出力、数式の出力等ができていることがわかるでしょう。

これの中身はdemo.satyに書いてあります。見てみると面白いでしょう。

# SATySFi関係の拡張子

まずは通常の文を書くのが`.saty`ファイルです。LaTeXで言うところの`.tex`ファイルでしょう。

機能を拡張、追加するコマンドを書くのが`.satyh`ファイルです。LaTeXで言うところの`.sty`ファイルでしょう。

ページ数などの一時情報が記録されているのが`satysfi-aux`ファイルです。LaTeXで言うところの`.aux`ファイルでしょう。これは自動で作成されるので触る必要はありません。

これ以外にもSATySFiによって提供される拡張子はいくつかありますが、表に出てくるのはこれくらいです。

# コンパイルオプション

```sh
satysfi demo.saty -o output.pdf
satysfi --help
```

などのようにしてオプションを付けてコンパイルしたりすることができます。
`--help`で全てのオプションを確認することができます。

# 主なパッケージ

## 標準ライブラリ

SATySFiで提供されるパッケージです。
これらは[`lib/dist/packages`](https://github.com/gfngfn/SATySFi/tree/master/lib-satysfi/dist/packages)内にあります。

これらはSATySFiが見つけることが出来る場所に置いてあるので、文書の冒頭で`@require: stdjabook`の様に書いて読み込むことができます。

`.satyh`ファイルと同じフォルダ内にある`.satyh`ファイルを読み込むときは`@import: local`の様に書いて読み込みます。（[参考ツイート1](https://twitter.com/bd_gfngfn/status/961476981442277376),[参考ツイート2](https://twitter.com/bd_gfngfn/status/961477626538770433),[参考ツイート3](https://twitter.com/bd_gfngfn/status/993502360189132800)）

## satyrographosでインストールできるパッケージ

satyrographosでインストールできるパッケージの一覧は[Satyrographos Package Index](https://satyrographos-packages.netlify.app/)というサイトで見ることができます。概要のほかにドキュメントも見ることができるので非常に便利です。

ここではここからいくつか紹介してみます（ここにあるのが全てではありません）。

### クラスファイル

- [class-jlreq](https://satyrographos-packages.netlify.app/packages/class-jlreq)：日本語組版の要件になるべく沿うような組版をしてくれる
- [class-slydifi](https://satyrographos-packages.netlify.app/packages/class-slydifi)：スライド作成ができる
- [class-stjarticle](https://satyrographos-packages.netlify.app/packages/class-stjarticle)：標準ライブラリを少し改造してみたもの

### 数学関係

- [azmath](https://satyrographos-packages.netlify.app/packages/azmath)：様々な便利関数の追加
- [derive](https://satyrographos-packages.netlify.app/packages/derive)：証明木を描画する
- [ncsq](https://satyrographos-packages.netlify.app/packages/ncsq)：ダイアグラムを描画する
- [karnaugh](https://satyrographos-packages.netlify.app/packages/karnaugh)：カルノー図を描画する
- [siunitx](https://satyrographos-packages.netlify.app/packages/siunitx)：単位記号の提供
- [chemfml](https://satyrographos-packages.netlify.app/packages/chemfml)：化学式の記述

### ソースコード描画

- [code-printer](https://satyrographos-packages.netlify.app/packages/code-printer)：シンタックスハイライトとカラーテーマを提供する
- [algorithm](https://satyrographos-packages.netlify.app/packages/algorithm)：疑似コード生成

### 図表

- [easytable](https://satyrographos-packages.netlify.app/packages/easytable)：表組
- [figgox](https://satyrographos-packages.netlify.app/packages/figbox)：自由度の高い図表の配置
- [image](https://satyrographos-packages.netlify.app/packages/image)：画像の貼り付け
- [enumitem](https://satyrographos-packages.netlify.app/packages/enumitem)：箇条書きのカスタマイズ
- [colorbox](https://satyrographos-packages.netlify.app/packages/colorbox)：綺麗な枠機能の提供
- [arrows](https://satyrographos-packages.netlify.app/packages/arrows)：矢印描画
- [parallel](https://satyrographos-packages.netlify.app/packages/parallel)：minipage機能の提供

### その他便利機能

- [latexcmds](https://satyrographos-packages.netlify.app/packages/latexcmds)：LaTeX標準のよくあるコマンドの提供
- [uline](https://satyrographos-packages.netlify.app/packages/uline)：下線・打消し線の提供
- [ruby](https://satyrographos-packages.netlify.app/packages/ruby)：ルビ機能


### フォント

- [fss](https://satyrographos-packages.netlify.app/packages/fss)：フォントの切り替えをサポートします

フォントファイルのダウンロード及び設定を行ってくれるライブラリ達です。
沢山あるので色々とみて自分の手で選んでください！

- [fonts-noto-*]：Notoフォント系列（[sans](https://satyrographos-packages.netlify.app/packages/fonts-noto-sans)・[sans cjk jp](https://satyrographos-packages.netlify.app/packages/fonts-noto-sans-cjk-jp)・[serif](https://satyrographos-packages.netlify.app/packages/fonts-noto-serif)・[serif cjk jp](https://satyrographos-packages.netlify.app/packages/fonts-noto-serif-cjk-jp)・[emoji](https://satyrographos-packages.netlify.app/packages/fonts-noto-emoji)）
- [han sans jp](https://satyrographos-packages.netlify.app/packages/fonts-han-sans-jp)
- [han serif jp](https://satyrographos-packages.netlify.app/packages/fonts-han-serif-jp)
- [dejavu](https://satyrographos-packages.netlify.app/packages/fonts-dejavu)
- [asana math](https://satyrographos-packages.netlify.app/packages/fonts-asana-math)
- [computer modern unicode](https://satyrographos-packages.netlify.app/packages/fonts-computer-modern-unicode)
- [theano](https://satyrographos-packages.netlify.app/packages/fonts-theano)

### プログラミング関係

- [base](https://satyrographos-packages.netlify.app/packages/base)：事実上の標準ライブラリです。多数の便利な関数が提供されています。
- [zrbase](https://satyrographos-packages.netlify.app/packages/zrbase)：便利な関数が多数提供されています
- [num-conversion](https://satyrographos-packages.netlify.app/packages/num-conversion)：様々な数字表記法との相互変換
- [railway](https://satyrographos-packages.netlify.app/packages/railway)：パスの記述の際に補助情報を表示する
- [json](https://satyrographos-packages.netlify.app/packages/json)：JSONパーサ
- [csv](https://satyrographos-packages.netlify.app/packages/csv)：CSVパーサ

# エディタ拡張
ファイルを編集する際、なにも補助がないとなかなか厳しいです。そこでSATySFiを書く時に補助してくれる拡張機能を紹介します。

- [satysfi.vim](https://github.com/qnighy/satysfi.vim)
    VimでSATySFiを使う時に補助してくれる拡張機能です。
- [satysfi.el](https://github.com/gfngfn/satysfi.el)
    EmacsでSATySFiを使う時に補助してくれる拡張機能だと思います。
- [satysfi-workshop](https://github.com/pickoba/satysfi-workshop)
    VSCodeでSATySFiを使う時に補助してくれる拡張機能です。


# その他便利ツール

- [satysfi-formatter](https://github.com/usagrada/satysfi-formatter)：コードフォーマッタ
- [satysfi-language-server](https://github.com/monaqa/satysfi-language-server)：SATySFiのLSPです


# 書き方

※SATySFiに標準で含まれているパッケージであるstdjabookを使用する想定で書きます。

まずは簡単なドキュメントです。

```
@require: stdjabook
StdJaBook.document(|
    title = {Hello \SATySFi;};
    author = {私};
    show-title = true;
    show-toc = true;
|)'<
    +p{
        はじめてのサティスファイ！
    }
>
```

これをHello.satyとして保存し、

```sh
satysfi Hello.saty
```

とするとHello.pdfという名前のPDFファイルが出てきます。

次に中身を見ていきましょう。

一番最初の`@require: stdjabook`ですが、これは既に説明したように、パッケージを読み込むためのコマンドです（stdjabookはLaTeXでいうところのクラスファイルに相当するもの）。

二番目の`StdJaBook.document(||)'<>`ですが、この文書全体に関する指定です。`document(||)'<>`でも良いのですが、「stdjabookによって提供されたものを使うことを明らかにするために`StdJaBook.`を付けるべき」という考えのもとStdJaBookをつけています。これはどちらでも良いです（[参考ツイート](https://twitter.com/bd_gfngfn/status/1031512917814857733)）。`document`の中身ですが、こうなる理由はstdjabook側で`document`が以下のように定義されているからです。

```
  val document : 'a -> block-text -> document
    constraint 'a :: (|
      title : inline-text;
      author : inline-text;
      show-toc : bool;
      show-title : bool;
    |)
```

なので、`title`と`author`にはインラインテキスト（普通の文章）を、`show-toc`と`show-title`には`ture`か`false`のどちらかを入れましょう。
これらの役割は名の通りですが、`title`はこの文書のタイトルを、`author`は著者名を入れるものです。`show-toc`は目次を出力するかしないかの選択を、`show-title`はタイトルを出力するかしないかの選択です。

三番目の`+p`ですが、これは段落を表すコマンドです。
stdjabookでは以下のように定義されています。

この他にも、行頭インデントなしの段落を表す`+pn`というコマンドもあります。

一応stdjabookが提供するコマンドとその役割を書いておきます。

- `title`（inline-textを入れてください。最初のdocumentの部分で指定します。名前の通り、文書のタイトルを書きます。）
- `author`（inline-textを入れてください。最初のdocumentの部分で指定します。名前の通り、文書の作者の名前を書きます。）
- `show-title`（trueかfalseを指定します。最初のdocumentの部分で指定します。タイトルを表示するか否かを選択します。）
- `show-toc`（trueかfalseを指定します。最初のdocumentの部分で指定します。目次を表示するか否かを選択します。）
- `\ref`（相互参照です。本文中で使用します。）
- `\ref-page`（ページの相互参照です。本文中で使用します。）
- `\figure`（画像の配置です。）
- `+p`（行頭インデントのある段落を書くのに使用します。）
- `+pn`（行頭インデントのない段落を書くのにしようします。）
- `+section`（節です。）
- `+subsectioon`（小節です。）
- `\emaph`（強調です。）
- `\footnote`（フットノートです。）

この時、`+section`や`+subsection`は、

```
+section{節タイトル}<
    +p{文章}
>
```

のように`<>`を後ろにつけます。これは

> 水平方向（文字が行をなす向き）の入力を { 〜 } で，垂直方向（行が段落をなす向き）の入力を < 〜 > で括って両者を区別する

ということらしいです（[参照ツイート](https://twitter.com/bd_gfngfn/status/909753869084762112)）。

数式の書き方についてですが、基本的に`${}`の中に書けば良いらしいです（あまり数式を書かないのでよくわからない）。

```
${a^5 \times a^7 \times a^3 = a^{15}}
```

と書くと

$a^5 \times a^7 \times a^3 = a^{15}$

と出力されます。書き方はLaTeXと“ほぼ一緒”と考えて構わないでしょう（[gfncmd](https://github.com/gfngfn/gfncmd)が提供する書き方寄りだと思います（作者が同じだからある意味当然かも））。

# 資料

リポジトリなどでは

- The SATySFibookのPDFファイルで[ここ](https://gfngfn.booth.pm/items/1127224)で公開されている
- 提供されているプリミティブな関数の説明が[doc/doc-primitives.saty](https://github.com/gfngfn/SATySFi/blob/master/doc/doc-primitives.saty)に書かれている
- 様々な機能の説明のある[Wikiページ](https://github.com/gfngfn/SATySFi/wiki)
- [日本語で書かれたメモ](https://github.com/gfngfn/SATySFi/blob/66fdd27e2ba65e4b4c4c0612834e6c547905ab11/memo-ja-how-to-use.md)があります。

が公開されています。


他に、qnighy氏がまとめてくださった「[SATySFi構文メモ](https://gist.github.com/qnighy/951d1ee5a7ee7c8f95bb323e881eaf8a)」および、forestaa氏による[更新版](https://gist.github.com/forestaa/2cfdf7e05fb4093930ee2228dc846c73)があります。

また、設計思想等を知ることが出来るものとして、「[【2017年度未踏／No.2】型による静的検証能力の高い組版システムの開発](https://www.youtube.com/watch?time_continue=1&v=VPJCneHFyNM) 」という動画と、「[スライド](https://drive.google.com/file/d/1BB7ZAiwPO3hVtq7PGImPtMs1-kOd7SzW/view)」があります。

SATySFi Advent Calendar及びSATySFi Confから多くの資料に当たることができます。

- [SATySFi Advent Calendar 2018](https://adventar.org/calendars/3418)
- [SATySFi Advent Calendar 2019](https://adventar.org/calendars/3929)
- [SATySFi Advent Calendar 2020](https://adventar.org/calendars/4965)
- [SATySFi Advent Calendar 2021](https://adventar.org/calendars/6336)
- [SATySFi Advent Calendar 2022](https://adventar.org/calendars/7515)
- [SATySFi Conf 2020](https://puripuri2100.hatenablog.com/entry/2020/07/26/164203)
- [SATySFi Conf 2021](https://puripuri2100.hatenablog.com/entry/2022/01/20/205344)
- [SATySFi Conf 2022](https://puripuri2100.hatenablog.com/entry/2022/12/16/190500)


# 情報共有場所

SATySFiのSlackチャンネルがあります。

[招待リンク](https://join.slack.com/t/satysfi/shared_invite/enQtNzE2NDIyNzM4NDE3LTljYTcwYjlkMjY3MjgwZmVjOTI5NTFlNDE1MmU5ODkyODhhYjVjODk2YzkwM2FkNTNhYjI0MDIzMjdmMTIyNTU)から参加してみてください。