まえがき

SATySFiはいいぞ

導入

これはSATySFiに関する入門書です。

SATySFiを始める

SATySFiを始めましょう!この章では

  • satyrographosというライブラリマネージャを使う
  • SATySFiを実行できる環境を整える
  • Hello worldと書かれたPDFファイルを出力する

という3つのことについて説明します。

satyrographosをインストールする

@na4zagin3氏によってsatyrographosというSATySFiのパッケージマネージャが開発されています(日本語読みは「サテュログラポ̣ス」です)。 多数のパッケージがsatyrographosに登録されているばかりか、SATySFi自体もサポートしているため、satyrographosをインストールすることをオススメします。

まだ必要が無いと思う方は先に進み、必要になった時点でこの説明に帰ってくるのが良いでしょう。

satyrographosはまだ開発途中であるため、一部のコマンドラインインターフェースが予告なく変更される可能性があります。ドキュメントや表示をよく読むようにしてください。

GitHubのリポジトリはna4zagin3/satyrographosにあります。

OCamlによって記述され、OPAMによって管理されているライブラリを使用しているため、どちらもインストールする必要があります。 また、OPAMはWindowsとの相性が悪いため、WindowsでインストールするためにはWindows Subsystem for Linux(WSL)やCygwinなどを使う必要があります。 以下の説明では*nix環境があるという前提で説明をします。

インストールするための環境を整える

上に説明している通り、Windows使用者はWSLやCygwinを事前にインストールしてください。

OPAMのインストール

OPAMのドキュメントが存在しますが、ここでは必要な分だけ説明します。

Ubuntu18.04以降

ppaが用意されているのでこれを用います。

sudo add-apt-repository ppa:avsm/ppa
sudo apt update
sudo apt install opam

Ubuntu18.04以前

バイナリを直接インストールします。OCaml本体のインストールに必要なソフトウェアもついでにインストールします。

sudo apt-get update
sudo apt-get install build-essential git m4 unzip curl pkg-config
sh <(curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)

macOS

Homebrewを使います。

brew install gpatch
brew install opam

OCamlのインストール

インストールしたOPAMを使ってOCamlをインストールします。

一部のOSではsandboxという機能が使えないらしいので、インストール時に--disable-sandboxingオプションが必要となります。詳しくはFAQを見てください。 この現象は少なくともWSL1では確認されていますので、WSL1を使用している人は必ずこのオプションを付けてください。WSL2では不要という情報もあります。それ以外の主要なOSでは必要ないはずです。 このオプションが必要なOSで--disable-sandboxingオプションを付けないでインストールしようとすると、FAQへのリンクの付いたエラーが出るのでわかりやすいと思います。

インストールするOCamlのバージョンは、執筆している2020年6月時点では最新版の4.10.0です。 SATySFiやsatyrographosのREADMEを読んで必要なバージョンを確かめてください。

WSLなど

opam init --comp 4.11.1 --disable-sandboxing
eval $(opam env)

それ以外

opam init --comp 4.11.1
eval $(opam env)

外部リポジトリを登録する

SATySFiもsatyrographosも外部リポジトリを使って独自のライブラリを利用します。 ですので、これを登録します。

opam repository add satysfi-external https://github.com/gfngfn/satysfi-external-repo.git

opam repository add satyrographos-repo https://github.com/na4zagin3/satyrographos-repo.git

opam update

本体をインストールする

satyrographos本体はOPAMに登録されているため、すぐにインストールすることができます。

opam depext satyrographos
opam install satyrographos

もし

No switch is currently set. Please use 'opam switch' to set or install a switch

のようなエラーが出た場合は

opam switch create 4.11.1

をするとエラーが解消されます。

インストール

SATySFiを使える環境を整える方法はいくつかあります。 以下の説明を読んで自分にあったものを選んでみてください。

  • satyrographosでインストールする:様々なバージョンを簡単にインストールできます。
  • SATySFiのリポジトリのmasterブランチのHEAD版をインストールする:最新の機能や開発版の機能を使うことができますが、情報は少なくなります。
  • SATySFiのv0.0.5をインストールする:挙動が固定され、それなりに新しい機能を使うことができます。
  • docker imageを使う:様々な環境で様々なバージョンを使うことができますが、Dockerの環境構築が必要です。
  • ブラウザで使う:色々な環境で使えます。

個人的には、SATySFiを単に使いたいだけの人はsatyrographosを使ってインストールするのが良いと思います。

satyrographosでインストールする

satyrographosをインストールした後に

opam depext satysfi satysfi-dist
opam install satysfi satysfi-dist
satyrographos install

とすることでインストールが完了します。

satysfi --version

でインストールとバージョンを確認することができます。

SATySFiのHEAD版をインストールする

GitHubのリポジトリのHEAD版をインストールします。

環境構築

OPAMとOCamlがインストールされている必要があります。 satyrographosをインストールしていれば環境は自動で整っています。 もし、インストールしていないのであれば、「satyrographosをインストールする」を読んでOPAMとOCamlをインストールしてください。

リポジトリをクローンする

GitHubにあるリポジトリを丸ごとクローンしてきます。

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

SATySFiをビルドする

クローンしてきたSATySFiフォルダに移動し、OPAMを使ってインストールします。 必要なライブラリは自動でインストールされます。

cd SATySFi

opam pin add satysfi .
opam install satysfi

フォントや標準ライブラリをインストールする

フォントのインストールと標準ライブラリのインストールはそれぞれ別々のシェルスクリプトに分離されています。

install-libs.shの実行には管理者権限が必要です。

./download-fonts.sh
sudo ./install-libs.sh

SATySFiのv0.0.6をインストールする

GitHubのリポジトリでリリースされているv0.0.6をインストールします。

環境構築

OPAMとOCamlがインストールされている必要があります。 satyrographosをインストールしていれば環境は自動で整っています。 もし、インストールしていないのであれば、「satyrographosをインストールする」を読んでOPAMとOCamlをインストールしてください。

リリースされているファイルをダウンロードする

リリースされているファイルをダウンロードし、展開します。

curl https://github.com/gfngfn/SATySFi/archive/v0.0.6.zip
unzip v0.0.6.zip -d SATySFi

でSATySFiというフォルダが出来上がります。

SATySFiをビルドする

作成したSATySFiフォルダに移動し、OPAMを使ってインストールします。 必要なライブラリは自動でインストールされます。

cd SATySFi

opam pin add satysfi .
opam install satysfi

フォントや標準ライブラリをインストールする

フォントのインストールと標準ライブラリのインストールはそれぞれ別々のシェルスクリプトに分離されています。

install-libs.shの実行には管理者権限が必要です。

./download-fonts.sh
sudo ./install-libs.sh

docker imageを使う

Dockerイメージが多くの人によって作成され、公開されています。 ここでは@amutakeによって作成されているdocker-satysfiを紹介します。

Dockerのインストール

まずはDockerをインストールします。 Dockerのインストール方法についてはDockerの公式ドキュメントをご覧ください。

インストールが完了したら以下のコマンドを実行し、Hello from Docker!と表示されることを確認してください。

docker run hello-world

docker-satysfiの基本的な使い方

docker-satysfiはamutake/satysfiという名前でDocker Hubから提供されています。 このDockerイメージにはsatysfiコマンドとsatyrographosコマンドが含まれており、docker run amutake/satysfi以降にこれらのコマンドを指定することで利用することができます。

例えばDockerイメージに含まれているsatysfisatyrographosのバージョンを確認したい場合は以下のようにします。

docker run amutake/satysfi satysfi --version
docker run amutake/satysfi satyrographos version

文書ファイルをコンパイルする

ではdocker-satysfiに含まれるsatysfiコマンドを使って文書ファイルをコンパイルしてみましょう。なお、satysfiコマンドの詳しい使い方は後述のHello SATySFi!に書かれているので、ここではdockerコマンドのオプションのみ説明します。

カレントディレクトリにdemo.satyという文書ファイルがあり、この文書ファイルをコンパイルしたい場合、以下のコマンドを実行します。

docker run --rm -v $(pwd):/satysfi amutake/satysfi satysfi demo.saty

これでdemo.pdfというファイルができあがります。

このコマンドを分解してみると以下のようになります。

  • docker run: Dockerコンテナを実行
  • --rm: 終了時にコンテナを削除(省略可)
  • -v $(pwd):/satysfi: カレントディレクトリをコンテナ内の/satysfiにマウント
  • amutake/satysfi: イメージ名
  • satysfi demo.saty: demo.satyをコンパイル

docker-satysfiでは/satysfiというディレクトリがデフォルトのワーキングディレクトリとして設定されています。 コンテナ内で実行されるコマンドはこのディレクトリ内で実行されます。

この例ではホストのカレントディレクトリにdemo.satyがあるので、-v $(pwd):/satysfiを指定することでコンテナ内からdemo.satyが見えるようになり、satysfi demo.satyでコンパイルすることができるようになります。

コンパイル結果のPDFはコンテナ内の/satysfiに出力されます。/satysfiにはホストのカレントディレクトリがマウントされているので、結果としてPDFはホストのカレントディレクトリに置かれるということになります。

SATySFiのバージョンを指定する

SATySFiの特定のバージョンを使いたい場合はdocker-satysfiを使うと簡単です。 例えばv0.0.6を使いたい場合は以下のようにamutake/satysfi:0.0.6と指定します。

docker run amutake/satysfi:0.0.6 satysfi --version

上記のコマンドを実行するとSATySFi version 0.0.6と表示され、確かにv0.0.6が使われていることが確認できます。

docker-satysfiの発展的な使い方

opamとsatyrographosでライブラリをインストールする

docker-satysfiには(後述する一部のタグを除いて)opamコマンドとsatyrographosコマンドが含まれているため、satyrographos-repoに登録されているSATySFiのライブラリを利用することができます。

例えばsatysfi-baseをインストールしつつdemo.satyという文書ファイルをコンパイルしたい場合、以下のようにします。

docker run --rm -v $(pwd):/satysfi amutake/satysfi \
  sh -c "opam update && opam install satysfi-base && satyrographos install && satysfi demo.saty"

Satyrographosの詳しい使い方についてはパッケージの読み込み・インストールを参照してください。

より小さいサイズのイメージを使う

ここまでの説明で使ってきたイメージは圧縮後で1GB程度という比較的大きいイメージでした。 これは、OCamlコンパイラや、SATySFi・Satyrographos自体のビルドに必要なライブラリがすべて含まれているためです。

docker-satysfiでは、CIなどでの利用でイメージのダウンロード時間を少しでも削減したい場合や、機能を削ってもいいので小さいサイズのイメージが使いたい場合のために、slimタグとopam-slimタグが用意されています。

slimタグがつけられているイメージはsatysfiコマンドとsatyrographosコマンドのみを含むイメージです。 docker-satysfiでは最も小さいイメージですが、opamやOCamlコンパイラは含まれていません。

opam-slimタグのイメージにはsatysfiコマンドやsatyrographosコマンドそしてopamコマンドが含まれていますが、OCamlコンパイラなど、satysfisatyrographosをビルドするのに必要なバイナリ・ライブラリは一切含まれていません。しかし通常SATySFiで文書をコンパイルする場合はこれらのOCamlライブラリは必要ないので、ほとんどのユースケースではこのタグの機能で事足ります。なお、2021-03-24時点でopam-slimは実験的なイメージであることに注意してください。

以上のように、slimopam-slimは機能を削っている代わりに小さいイメージとなっています。

なお、slimopam-slimはともに0.0.6-slim0.0.6-opam-slimと指定することでSATySFiの特定のバージョンで利用することができます。

SATySFiの最新版を使う

docker-satysfiではnightlyというタグも提供しています。 これは毎日日本時間9:00にその時点でのSATySFiとSatyrographosの最新版をビルドしているイメージです。

nightlyタグはslimタグと同様にsatysfisatyrographosしか含まれていない(opamコマンドが含まれていない)ことに注意してください。

ブラウザを使う

ブラウザでSATySFiを使える環境を整えてくださった方がいます。 2020年6月現在、使えるサービスは以下の2つになります。

お好きな方をご利用ください。

Hello SATySFi!

一般的なプログラミング言語と同じように、Hello SATySFi!というテキストがあるPDFファイルを作り、SATySFiの世界に慣れてみましょう。

フォルダを作る

このPDFファイルを作成するためのフォルダをmkdirなどを使って作りましょう。

WSLを利用している場合は、Windows側にフォルダを作り、/mnt/c/Users/hogehoge/DocumentsのようにWSL側からアクセスするのが良いでしょう。

そのフォルダの場所に移動してwslコマンドを使ってWSLを起動すれば自動で上記のパスになっていると思います。

ファイルを作る

hello_satysfi.satyというファイルを作ります。SATySFiでの文書ファイルは.saty拡張子です。

文書を書いて実行する

作成したhello_satysfi.satyを開き、以下のコードを入力してください。

@require: stdja

document(|
  title = {Hello \SATySFi;};
  author = {私};
  show-title = true;
  show-toc = false;
|) '<
  +p{
    Hello \SATySFi;!
    はじめまして!
  }
>

VSCode, Vim, Emacs, AtomではそれぞれSATySFi用のシンタックスハイライトをする拡張が存在しています。 各自インストールしてみると良いでしょう。

satysfi hello_satysfi.saty

とすることでPDFファイルが出力されます。

ブラウザやDockerを使っている人は、それぞれの利用方法を確認してください。 これ以降はsatysfiコマンドを使う方法を説明しますが、特に変わらないと思っていてください。

また、このようにPDFファイルを生成することを便宜的に「コンパイル」と呼んでいきます。

出力されたPDFファイルを開いてみてください。「Hello SATySFi! はじめまして!」と書かれているはずです。

ToDo: スクリーンショットを貼る

文書の解剖

書かれた文書を詳しく確認していきましょう。

まず、ファイル冒頭の

@require: stdja

です。

ここでSATySFiの標準ライブラリに含まれているクラスファイルの一つである、stdja.satyhを読み込んでいます。

出力されるPDFファイルの体裁を決定する特殊なパッケージファイルの一つです。LaTeXのそれとは細かいところは違いますが、果たす役割は同じと思って良いと思います。

次に、document (| ~ |) '< ~ >の部分です。

ここでは「documentという関数に(| ~ |)という値と'< ~ >という値を与える」ということをしています。

documentという関数はstdjaクラスファイルによって提供されるもので、二つの引数を取って文書となる値を返す関数です。

全てのクラスファイルがdocumentという関数を提供するとも限りませんし、引数が二つに限定されるとも限りません。不安であれば各クラスファイルのドキュメントを確認しましょう。

document関数に渡す引数を確認しましょう。

(|
  title = {Hello \SATySFi;};
  author = {私};
  show-title = true;
  show-toc = false;
|)

は「レコード」というデータ構造を表します。レコードは「ラベルに値を結び付けている」ものをまとめているもので、並べる順番は関係ありません。ですので、上のコードと

(|
  show-title = true;
  show-toc = false;
  title = {Hello \SATySFi;};
  author = {私};
|)

は同一のものです。

document関数が要求しているレコードでは、

  • title
  • author
  • show-title
  • show-toc

という4つのラベルを要求しています。

titleでは文書のタイトルを{}で囲まれた中に書き、authorでは文書のタイトルを{}で囲まれた中に書きます。 show-titleでは「タイトルをPDFに表示するかしないか」をtruefalseのどちらかで指定します。 show-tocでは「目次をPDFに表示するかしないか」をtruefalseのどちらかで指定します。

'<
  +p{
    Hello \SATySFi;!
    はじめまして!
  }
>

は文書の本体です。'<>という記法は、「文章のブロック」を示します。縦方向に連なる“箱”をイメージしてみてください。厳密には、箱になる前の“生の箱”です。 この“生の箱”をdocument関数の中で“箱”に組み上げ、さらにPDF文書に変換しています。 以降、この“生の箱”のことを「ブロックテキスト」と呼びます(ちなみに、“箱”の方は「ブロックボックス」と呼びます)。

+p{}は「文字からなる段落を箱にする機能」を持つ特殊な関数です。ブロックテキスト内では+から始まる特殊な関数しか使えません。この特殊な関数を「ブロックコマンド」と呼んでいきます。 通常の関数は小文字から始まりますが、ブロックコマンドは+の後は任意のアルファベットから始まり、アルファベット・数字・-の3種類の文字が任意の組み合わせで使うことができます。

ブロックコマンドはブロックテキスト内で何個も連ねることができます。 例えば、

'<
  +p{
    1個目の段落
  }
  +p{
    2個目の段落
  }
>

という風にです。

+pブロックコマンドに与える値を見てみましょう。{}という記法は「一文字ごとに箱になったものが横にたくさん連なっている枠」のイメージです。これもまた厳密にはそうなる前の“生の枠”です。“生の枠”の方を「インラインテキスト」と呼び、“枠”の方を「インラインブロック」と呼んでいます。

インラインテキスト内では行頭行末の空白と改行は(ほとんど)意味を持ちません。 見やすいように改行し、インデントを付けましょう。

インラインテキスト内ではほとんどの文字がそのまま使えます。 ただし、

  • `
  • %
  • \
  • ;
  • $
  • *
  • @
  • #
  • {
  • }
  • <
  • >
  • |

の文字は\を使ってエスケープする必要があります。

さて、このインラインテキスト内で関数を使いたくなる時は\から始まる「インラインコマンド」を使います。 \SATySFiというコマンドは「SATYSFIという文字列の内、YIを少し下げて表示する」という関数です。 ブロックコマンドと同じように、インラインコマンドには引数として値を受け取り、様々な機能を実現することができます。

ブロックコマンドやインラインコマンドがインラインテキストやブロックテキストの引数を取らないときは;を使うことで「コマンドの終了」を宣言します。 厳密な使い分けについては後の章を読んでください。

SATySFiで文書を書く

SATySFiで文書を書くために必要な知識を付けて生きましょう。 必要なものは文書構造に対する意識と、「横に伸びる枠」・「縦に連なる箱」のイメージだけです!

具体的なコマンドにも踏み込んでいきます。

  • コメントアウト
  • パッケージの読み込み
  • 文書構造の記述の仕方
  • コマンドの記述
  • インラインコマンド・ブロックコマンドの紹介
  • 文中数式
  • 別行建て数式
  • 数学コマンドの紹介
  • 箇条書き
  • 相互参照

について解説していきます。

コメントアウト

SATySFiでは他のプログラミングと同じようにコメントを書くことができます。

推敲するときやメッセージを書く時に使ってみてはいかがでしょうか。 単純にコメントとして使うだけではなく「改行文字のキャンセル」としても使えます。

コメントアウトはLaTeXと同じように%を使います。 %から始まって最初の改行文字までがコメントとして扱われます。

複数行のコメントアウトはできません。

パッケージの読み込み

@require: (パッケージ名)@import: (パッケージファイルへの相対パス)でパッケージの読み込みができます。 パッケージを読み込む場合は、拡張子を必ず省略します。

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

satyrographosを使うことで有志の作成したパッケージを簡単にインストールすることができます。

例えば、satysfi-baseというパッケージ群をインストールするには

opam update
opam install satysfi-base
satyrographos install

をするだけです。

ここでインストールしたパッケージは@require: base/intのようにして読み込むことができます。 satyrographosによってインストールされるパッケージは、ファイル名の衝突を避けるためにライブラリごとに一つのフォルダに入っています。そのため、そのフォルダを含めて指定する必要があります。

satyrographosによってインストールされるライブラリの名前はsatysfi-から始まるようになっています。 しかし、satyrographosによってシステムにインストールされるときには基本的にsatysfi-の部分が外れるようになっています。詳しくはsatyrographosのREADMEや「Satyrographos でパッケージの簡単インストール」を読んでください。

インストールできるライブラリの一覧は

opam list 'satysfi-*'

によって確認できます。

手動でパッケージをインストールする

satyrographosを使っている場合、~/.satysfi/dist/packages/にパッケージはインストールされます。

しかし、~/.satysfi/dist/以下は基本的に人が弄ることは想定されていません。 そこで、ユーザ自身がパッケージ類を格納することを想定している~/.satysfi/local/以下にパッケージファイルをコピーします。

distの方が優先順位が高いので、distからの相対パスとlocalからの相対パスが同じファイルが存在しない限り、localに置いたファイルが読み込まれます。

文書構造の記述

章節を記述することができます。 構造的な文章を書くためには欠かせません。

stdjaとstdjabookの両パッケージでは+section+subsectionコマンドが、stdjareportパッケージでは+chapter+section+subsectionの3つのコマンドが提供されます。

どのコマンドも+section{(タイトル)}<(中身)>という使い方をします。

例えば

+section {1節} <
  +subsection{小節} <
    +p{段落}
  >
  +subsection{小節その2} <
    +p{段落2}
  >
>

のような感じです。

コマンドの記述

ブロックテキストやインラインテキスト内で書ける関数のようなものを「コマンド」と呼んでいます。

SATySFiのコマンドの書き方はLaTeXのコマンドに比べて初見は難しいですが、慣れればとても単純です。

まず、引数は基本的に()で括られ、最後に;がつくと考えてください。 例えば、\cmd(1)(2.0)({テキスト});+cmd(1)(2.0)({テキスト});のような形です。

しかし、インラインテキストやブロックテキスト、後程紹介するレコードやリストなど、既に「括弧のようなもの」で囲われている値も()で括らなければならないのは不便です。

そこで、{}, <>, []が最後に来るときのみ;を省略することができるというルールが存在します。

インラインコマンド・ブロックコマンドの紹介

文中数式

別行建て数式

数学コマンドの紹介

箇条書き

脚注

相互参照

SATySFiのエラーメッセージと対処法

SATySFiの強みは静的な型付けおよび静的解析です. 静的解析によって実際に文書を組む前に誤りを発見することができ, エラーの原因に関する情報を具体的に知ることができます.

事前に誤りを発見するということは,逆に言えばユーザが正しいコードを書くまで永遠に文書が生成されないということでもあります. SATySFiをはじめたばかりでまだ構文や型の区別に慣れていないユーザにとっては, よくわからないエラーばかり出てきてちっとも望む出力が得られない, という不満につながってしまうかもしれません. しかしそれは勿体無いことです. ある程度正確にコードが書けるようになった人にとってコンパイルエラーはありがたいものであり, 自分が混入させてしまったバグを素早く取り除くための有益な情報となります. この章では,典型的なエラーメッセージと考えられる原因,対処法を紹介します.

SATySFi のエラーの見方

エラーの見方を学ぶには,実際に誤ったソースコードをコンパイルしてエラー表示を眺めるのが確実です. たとえば,以下のコードをコンパイルしてみましょう.

@require: stdja

document(| title = {}; author = {}; show-title = true; show-toc = false |) '<

  +command-not-defined{
    Hello, World!
  }

>

このコードに登場する +command-not-defined というコマンドは,それまでのどこにも定義されていません. このコードをコンパイルすると以下のようなエラーが出力され,処理が停止します.

 ---- ---- ---- ----
  target file: 'example1.pdf'
  dump file: 'example1.satysfi-aux' (already exists)

(中略)

 ---- ---- ---- ----
  type checking 'example1.saty' ...
! [Type Error] at "example1.saty", line 5, characters 2-22:
    undefined variable '+command-not-defined'.

ここで大事なのは ! から始まる行と,それ以降です. エラーの文言はたいてい以下の3要素からなります.

  • エラーの種類:ここでは [Type Error] です. つまり,字句解析の段階で生じた文法エラーであることを表しています.
  • エラーの位置:ここでは "example1.saty", line 5, characters 2-22 です. example1.saty という名前のファイルの8行目の2文字目から22文字目のところでエラーが見つかったことを示しています. なお文字は 0-index でカウントし,終端を含みません. 1からカウントを始める人がもしいれば,3文字目から22文字目にかけて,と読むのが良いでしょう.
  • エラーの具体的な内容:ここでは undefined variable '+command-not-defined'. です. つまり, +command-not-defined という変数(コマンド)は存在しない,と書かれています.

代表的なエラーの種類には以下のようなものがあります.

  • モジュールのパス解決エラー
  • 構文エラー
  • 型エラー
  • 実行時エラー

構文エラー

SATySFi 処理系では, ソースコードを処理するとき最初に字句解析器 (lexer) と構文解析器 (parser) に通すことで構文のパースを行います. この時点で生じるエラーは 構文エラー として処理され, 以下のメッセージから始まるエラー文を出力します.

  • [Syntax Error at Lexer]
  • [Syntax Error at Parser]

両者には字句解析の段階で失敗したか,構文解析の段階で失敗したかという違いがあるものの, どちらもユーザが何らかの文法ミスを犯したときに出るエラーという点では共通しているため, 普段はそこまで違いを気にする必要はありません.

構文エラーの原因

SATySFi で犯しやすい構文エラーは以下のとおりです.

  • インラインテキストとブロックテキストの混同. SATySFi では,インラインテキストとブロックテキストをしっかり区別する必要がある. インラインテキストでは通常の文字を書くことができるが,ブロックテキストではできない. たとえば以下のコードはエラーになる.

    +section{テスト}<
      本文
    >
    

    「本文」と書かれている箇所はブロックテキストの入る箇所であり, 直接文を書くと構文解析ができず構文エラーとなる.以下の例などのように書けば問題ない.

    +section{テスト}<
      +p{
        本文
      }
    >
    
  • コマンドの構文誤り. たとえば,+p{} とすべきところを +p{}; としたり, \eqn(${\pi}); とすべきところを \eqn(${\pi}) としたりすると構文エラーとなる.

  • 括弧の対応ミス. 当然ながら,()[]{} といった括弧の対応が正しく取れていないコードは正しく処理できない. また,リストやレコードの区切り文字は , ではなく ; であることにも注意 (カンマ区切りの他言語などを書いているとつい忘れがち).

  • ヘッダの構文誤り. SATySFi では,冒頭に @import:, @require: から始まる宣言を付けることで他のヘッダファイルやパッケージを読み込むことができる. ヘッダは常にファイルの冒頭に固めて記述する必要があり, また @ の後や : の直前にスペースを入れることは許されない.

Vim, Emacs, VSCode といった著名なテキストエディタでは, 有志の手によって SATySFi のシンタックスハイライトを行ってくれる拡張機能が開発されています. 単にコードが見やすくなるだけでなく,構文エラーを引き起こす記述にも気づきやすくなるため, 可能であればそれらを活用するのがおすすめです.

依存解決エラー

依存解決エラーの原因

  • @require@import の混同

    @require は「SATySFi にインストールされている(=特定のディレクトリに格納されている)パッケージ」を指定する際に, @import は「読み込みたいファイルへの相対パス」を指定する際に用いる.

  • .satyh.satyg のファイルパスが正しくない

  • 必要なフォントファイルがSATySFiの読める場所にない

  • フォントファイルは適切な場所にあるものの,ハッシュファイルに情報が記載されていない

型エラー

SATySFi は,型推論に基づいて静的な型付けを行う言語です. ユーザが指定した型や型推論の結果に不整合があったなどの原因で正しく型推論を行えなかった場合, 静的解析の段階でそれがエラーとして表出されます.

型エラーの代表的な原因

  • 未定義の変数やコマンド. 他言語と同様に未定義の変数やコマンドがあればエラーとなる.

  • 用いる演算子のミス. SATySFi は OCaml と同様に,演算子のオーバーロードが存在しない. たとえば + という演算子はint型とint型同士の加算にしか用いることができず, float型(浮動小数点数)同士の加算やlength型(長さ,寸法)同士の加算には用いられない. 2.0 + 3.0 のように書くと,以下のような型エラーが生じる.

      type checking 'example1.saty' ...
    ! [Type Error] at "example1.saty", line 3, characters 8-11:
        this expression has type
          float,
        but is expected of type
          int.
    

    演算子 + によってint型が来ることが期待されているにも関わらず float 型の数値が来たことを意味する. float型同士なら 2.0 +. 3.0,length型同士なら 2pt +' 3mm のように,演算子を区別する必要がある.

  • 浮動小数点にはマイナスを付けられない. 上と関連しているが, SATySFi では現状 -2.0 のように書くことができない. そのため -2.0 と書くと「単項演算子 - の後ろには int が期待されている」という型エラーになる. なお長さの場合は,リテラルに限り -2pt-2.5pt と書くことができる (マイナスと数値の間にはスペースを空けてはいけない). ただし,length 型を持つ変数 x に対して -x とするとやはり型エラーとなるので注意.

  • プリアンブルと本文の間に in がない. これは本来ユーザが誤った文法で書いてしまったことが原因で生じるエラーであるものの, SATySFiの文法の都合上文法エラーではなく型エラーとして扱われる.

  • その他,様々な型のミス.

実行時エラー

静的型付け言語であるSATySFiは,多くのミスを静的解析の段階で検出できるようになっています. しかし,実際に値を評価するときに初めて表出するエラーもあります.

実行時エラーの代表的な原因

  • 画像のファイルパスが正しくないとき
  • ユーザまたはパッケージ開発者が abort-with-message プリミティヴを用いて意図的にエラーを出したとき
  • ゼロ除算を行ったとき
  • 部分文字列を求める際の範囲外アクセスを行ったとき

デバッグオプションの使い方

SATySFiでは、「スペースがどう入っているのか」などの情報をPDFに直接表示させるデバッグのためのオプションがあります。

直接PDFに描画するため、印刷・配布用のPDFを生成する際には使えませんが、SATySFi本体の改造やパッケージの作成を行っている際にはとても便利な機能です。

また、SATySFi本体が提供している機能であるため、「デバッグオプションを使ったときと使わなかったときとで分割位置が変化した」といった現象は発生しません。

v0.0.5時点でデバッグオプションは4つあり、v0.0.6で5つ目が入る予定です。

v0.0.5で提供されているのは

  • --debug-show-bbox
  • --debug-show-space
  • --debug-show-block-bbox
  • --debug-show-block-space

で、v0.0.6で入る予定(2020/12/19にHEAD版に追加)のオプションは

  • --debug-show-overfull

です。

どれも、起動時に付けるだけで有効になります。引数は必要ありません。

例えば、

satysfi input.saty --debug-show-bbox --debug-show-space --debug-show-block-bbox --debug-show-block-space

とすると、

  • --debug-show-bbox
  • --debug-show-space
  • --debug-show-block-bbox
  • --debug-show-block-space

が4つ有効になります。

それでは、一つずつ役割や出力結果の見方などについて説明していきます。

--debug-show-bbox

文字やブロックの枠を薄い赤色の枠で表示します。

また、ベースラインも同じ色の線で表示されます。

--debug-show-bboxの出力結果

--debug-show-space

文字やブロック間のスペースを青い枠で表示します。

--debug-show-spaceの出力結果

--debug-show-block-bbox

行が薄い緑色の枠で囲われ、テキストが入る領域の高さを表示するピンクの線が左側に付きます。

--debug-show-block-bboxの出力結果

--debug-show-block-space

高さ関係のスペースが濃い緑色の線と三角形で表示されます。

段落間のスペースが三角形で表示され、より大きい方のスペースが採用されていることがわかります。 行間が細めの緑色の線です。

なお、段落間での改ページが抑制されているときは塗りつぶされていない枠だけの三角形が描画されます。

--debug-show-block-spaceの出力結果

--debug-show-overfull

overfullやunderfullを起こした行に赤い枠が付きます。

--debug-show-overfull-spaceの出力結果