SLyDIFi でらくらくスライド作成

この記事は [SATySFi Advent Calendar 2019](https://adventar.org/calendars/3929) 18 日目の記事です．前日は [puripuri2100](https://qiita.com/puripuri2100) さんの「[SATySFiのoption型を扱おう](https://qiita.com/puripuri2100/items/b7d8a1d73f4bba89bd03)」という記事でした．明日は hsjoihs さんの記事が入る予定です．

monaqa です．本記事では，今年作成した SLyDIFi というパッケージを紹介します．

# SLyDIFi とは

SLyDIFi は，組版用言語 SATySFi でスライド作成を行うためのパッケージ（クラスファイル）です．LaTeX でいうところの beamer のような立ち位置に相当します．
なお，SATySFi でスライドを作成するためのクラスファイルはこれが初めてではなく，先発のものとして [satysfi-steamer](https://github.com/konn/satysfi-steamer) があります．SLyDIFi 作成の際にも参考にさせていただきながら，自分好みの仕様に変えています．

# SLyDIFi でできること

スライド作成ができます．

## 全体の構造

SLyDIFi を用いるためには，パッケージを適切な場所に配置した上でインポートする必要があります．[slydifi パッケージ](https://github.com/monaqa/slydifi) の README に従ってください．おそらくインポートできると思います．

SLyDiFi での文書の書き方は以下のとおりです．

```
@require: slydifi/slydifi

Slydifi.document(|
  draft-mode = false;
  fonts = (|
    frame-title-cjk = `mplus-sans-b`;    % 自分が持っているフォントに変えること
    normal-text-cjk  = `mplus-sans-r`;   % 自分が持っているフォントに変えること
    frame-title-latin = `mplus-sans-b`;  % 自分が持っているフォントに変えること
    normal-text-latin  = `mplus-sans-r`; % 自分が持っているフォントに変えること
    mono-text-latin  = `mplus-mono-r`;   % 自分が持っているフォントに変えること
    font-ratio-cjk = 1.0;
  |);
|)'<

  +frame{title}<
    +p{}

    ... (block commands) ...
  >

  ... (frames) ...

>
```

すなわち，

* `slydifi` という名前のパッケージをインポート
* `Slydifi.document(|options|)'<block>` における `options` にてオプション指定，`block` にて本文を記述
* 本文の中では `+frame` コマンドで1つのフレーム（スライドの1ページ）を作成し，それを並べることで1つのスライドを作成する
* `+frame` コマンドではフレームのタイトル及び中身を指定でき，中身では `+p` などのブロックコマンドを配置できる

という構造からなります．
ちなみにオプションの `draft-mode` というのを true にすると，背景に一定間隔で罫線が引かれます．図表を絶対座標配置したいときに便利です．


## スライド作成

`+frame` コマンドによって1枚のスライドを作成します．

```
+frame{\SLyDiFi; を使うと，こんなスライドが書けます}<
  +p{
    \jugem;
  }
  +listing{
    * listing も対応！
      ** デフォルトの箇条書きはネストごとにラベルが変わります
      ** enumitem パッケージを用いているのでユーザ定義も簡単
    * \textbf{テキスト}の\emph{装飾}にも対応\footnotemark(`test`);
      \footnotetext(`test`){こんなふうに，脚注を付けることができます．}
  }
>
```

![slydifi-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231599/8677bbdc-9335-ae0d-ffc6-c16a05fd23eb.png)


SATySFi 慣れしている方はもうなんとなく使い方が分かったかもしれません．`+frame` コマンドは `+frame{title}<inner>` という形で使います．タイトル部分はインラインテキストを，本文はブロックテキストを入れることができます．

本文では，以下のようなコマンドを用いることができます．

* `+p` (`[inline-text] block-cmd`)[^1]: 段落作成用のコマンド．他のクラスファイルにもありますね．
* `+listing`, `+enumerate` (`[item] block-cmd`): 箇条書き用のコマンド．
  こちらもお馴染みだと思いますが，SLyDIFi 用にカスタマイズされています．
* `\footnotemark` (`[string] inline-cmd`)/ `\footnotetext` (`[string; inline-text] inline-cmd`): 脚注生成用のコマンド．
  [namachan10777](https://github.com/namachan10777) さんの PR により入りました．ありがとうございます！

なお，SLyDIFi ではどれだけ長い文章を1フレーム内に書いても，改ページは行われません（下に見切れます），これは steamer と設計を変えた箇所の一つです．

## タイトルページ

`+frame` の代わりに以下のような `+make-title` コマンドを用いることでタイトルフレームを挿入できます．

```
+make-title<
  +title{|\SLyDiFi; デモ用スライド|〜タイトルの改行もできるよ！〜|}
  +author{|monaqa|}
  +date{|2019年12月18日|}
>
```

![slydifi-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231599/b7e500d4-2112-59c7-273c-2227f5ee17cb.png)


タイトルを指定するコマンド `+title` の引数は `inline-text` ではなく `inline-text list` であることに注意してください．長いタイトルのときに中央揃え，左揃えなどのテーマ指定を柔軟に行うためにそのような仕様としています．`+author`, `+date` もそれに準じています．

## セクションページ

フレームは，（ただ羅列するだけでなく）`+section` コマンドを用いてセクションにグルーピングできます．`+section` コマンドを用いると，各セクションの冒頭に以下のようなセクションページが挟まります．

```
+section{|はじめに|}<
  +frame{\SLyDiFi; を使うと，こんなスライドが書けます}<
    % 中略
  >
>
```

![slydifi-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231599/72ba494d-f349-3444-33dc-6a5090bb94c2.png)


## 図の挿入

SLyDIFi では，図を挿入するためのコマンドが複数用意されています．

* `+fig-abs-pos`/`\fig-abs-pos`: 絶対座標配置．
* `+centered-image`: 中央揃え配置．
* `\insert-image`: 本文中にインラインボックスとして配置．
* `\fig-right`: 本文の右側に配置．インラインテキスト中にアンカーを置くと，その右側に図が入る．

`\fig-right` は「本文中で説明をして，右側にその補足図を入れる」ようなときに便利です．ただし本文の回り込み機能は無いので気をつけてください．

さて，上のコマンド群は基本的に imginfo 型の引数を取ります（fig-abs-pos コマンドに限り，追加で (length * length) 型の引数を取ります）．この imginfo とは代数的データ型であり，以下のような種類の図を取り扱うことができます．

* JPEG 画像，`JPEG(width, filepath)` の形で指定
* PDF 画像．`PDF(width, filepath, pagenum)` の形で指定
* ダミーボックス（長方形の線だけが引かれた箱）．`DummyBox(width, height)` の形で指定
* 任意の block-boxes．`Block(length, block-text)` の形で指定
* imginfo を任意方向に平行移動させたもの． `Shift(xshift, yshift, imginfo)` の形で指定

具体的には以下のように使います．

```
+frame{画像はりテスト
\fig-abs-pos
((Slydifi.paper-width *' 0.9, Slydifi.paper-height *' 0.9))
(DummyBox(30pt, 30pt));
}<
  +p{
    \fig-right(DummyBox(100pt, 50pt));
    いろんな画像が貼れる．JPEG と PDF に対応している他，\br;
    \code(`DummyBox`); を用いてダミー画像を貼ることも出来る．
  }
  +listing{
    * \code(`\insert-image`);: 本文中に画像を貼る．
    * \code(`\fig-abs-pos`);: 絶対座標を指定して画像を貼る．
    * \code(`\fig-right`);: コマンド挿入箇所の右端に画像を貼る．
  }
  % +centered-image(PDF(500pt, `./logo.pdf`, 1));
  % +centered-image(JPEG(500pt, `./logo.jpg`));
  +centered-image(DummyBox(500pt, 120pt));
>
```

![slydifi-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/231599/0f6ea429-79d9-2c13-e42d-f402dd7a3064.png)

# 課題

いくつか課題があります．

## フレキシブルなテーマ変更

デフォルトのテーマは私が適当に作成したものです（色は [gruvbox](https://github.com/morhetz/gruvbox) というカラースキームから借りました）．しかし，デフォルトのテーマを変更したいという人も当然いらっしゃると思います．現行ではテーマを簡単に変更する方法はなく，slydifi のクラスファイルを直接編集する必要があります．クラスファイル本体とテーマを定義するファイルとを分離したいところです． 

## satyrographos への対応

SATySFi のインストール事情に未だ詳しくないため，まだ未対応です．対応したいという気持ちはあるので，[7日目の記事](https://qiita.com/na4zagin3/items/14fe2647b663eeac6ac2) や [12日目の記事](https://qiita.com/na4zagin3/items/b392f5d522f9bcc0493b) を読んで対応したいなと思っています．

## オーバーレイ

LaTeX のスライド作成用クラスファイルである beamer では，PowerPoint のアニメーションに類似した機能である，オーバーレイを提供しています．これは，PDF で1ページ進めることではじめ表示されなかった文字をパッと表示させたり，特定の要素を上から順に表示させたりするときに用いられる機能です．現行の SLyDIFi ではオーバーレイに対応していません．実装のつもりがないわけではなくいくらか構想はあり，現在プロトタイプ版を作成中です．ただし少々特殊な SATySFi のコーディングスタイルである [Blockless SATySFi](https://qiita.com/wasabiz/items/9271e5521d04f419dbd2) を用いているため， 現行の SLyDIFi との互換性が失われます． そんなわけで，どういうふうに落ち着かせようか，まだ考え中という感じです．

# おわりに

実は自分も一度 SLyDIFi を用いて[プレゼン資料](https://speakerdeck.com/monaqa/f-mosiyondezong-heng-wu-jin-niyi-dong-siyou)を作成してみたのですが，SATySFi は一度慣れてさえしまえばかなり書きやすく，面倒な図版を別のソフトで描きさえすれば，プレゼンの体を成したものを作るのは結構簡単でした（[Steamer](https://github.com/konn/satysfi-steamer) という偉大な先人がいらっしゃったことがかなり大きいのですが）．ぜひ皆さんも，SATySFi で思い思いの組版にトライされてみてはいかがでしょうか．そしてあわよくば，SLyDIFi も使ってみていただけると幸いです．