$30 off During Our Annual Pro Sale. View Details »

ユーザーがカスタマイズできるクラスファイル ―v0.0.x と v0.1.x それぞれでの実装 ―

puripuri2100
September 24, 2022

ユーザーがカスタマイズできるクラスファイル ―v0.0.x と v0.1.x それぞれでの実装 ―

SATySFi Conf 2022で発表したスライドです
SATySFiのクラスファイルでカスタマイズ性を高めるためのテクニックや、今後リリース予定のv0.1.xでの実装例を紹介しています

puripuri2100

September 24, 2022
Tweet

More Decks by puripuri2100

Other Decks in Programming

Transcript

  1. ユーザーがカスタマイズできる
    クラスファイル
    ―v0.0.x と v0.1.x それぞれでの実装 ―
    金子尚樹 (@puripuri2100)
    2022/9/24

    View Slide

  2. 1/14
    自己紹介
    所属:筑波大学情報学群情報科学類 1 年
    GitHub:https://github.com/puripuri2100
    e-mail: [email protected]
    twitter: @puripuri2100
    使ってる言語: SATYSFI, Rust, OCaml など

    View Slide

  3. クラスファイルについて

    View Slide

  4. 2/14
    SATYSFIのクラスファイル
    document 型を生成する関数を提供するパッケージのこと
    SATYSFI でのクラスファイルの例:
    stdjabook
    stdjareport
    exdesign
    SLYDIFI
    (の各テーマ)

    View Slide

  5. 3/14
    SATYSFIのクラスファイルの特徴
    document 型を生成するための document 関数を提供する
    document 関数の引数として一つ目にオプション指定のレコードなどを、二つ目
    に文書の内容の bock-text を取る
    実装が隠蔽された文章構造や簡単な装飾に関するコマンドを提供する
    などの特徴がある。

    View Slide

  6. 3/14
    SATYSFIのクラスファイルの特徴
    document 型を生成するための document 関数を提供する
    document 関数の引数として一つ目にオプション指定のレコードなどを、二つ目
    に文書の内容の bock-text を取る
    実装が隠蔽された文章構造や簡単な装飾に関するコマンドを提供する
    などの特徴がある。
    フォントの設定やデザインについても各コマンドの実装がモジュールで隠されるた
    め、上書きが不可能であり、各クラスファイルが独自に提供する設定の変更方法を使
    うしか方法が無い。

    View Slide

  7. 4/14
    標準ライブラリでの設定方法
    1 StdJaBook.document (|
    2 title = {title};
    3 author = {author};
    4 show-title = true;
    5 show-toc = false;
    6 |) ?:((|
    7 StdJaBook.default-config with
    8 show-pages = false;
    9 paper-size = A5Paper;
    10 |))'<
    11 +p{test}
    12 >

    View Slide

  8. 4/14
    標準ライブラリでの設定方法
    1 つ目の引数でレコードを使用してタイトルや著者名などの文書の生成に必須な情
    報を入力させる
    2 つ目の引数でページサイズや余白の情報などのデフォルト値がすでにあるが変更
    できると嬉しい情報をオプション引数で与えさせる(with 構文を使うことで入力が
    楽になっている)
    3 つ目の引数で文書本体を入力させている

    View Slide

  9. 5/14
    exdeisgn での設定方法
    1 document (|
    2 title = {title};
    3 author = {author};
    4 date = {2022/9/24};
    5 show-title = true;
    6 show-toc = false;
    7 style = ArticleJa.a4paper ;
    8 design = ArticleJa.article;
    9 header-footer = ArticleJa.normalHF;
    10 fonts = ArticleJa.fonts;
    11 |) '<
    12 +p{test}
    13 >

    View Slide

  10. 5/14
    exdeisgn での設定方法
    変更できる値を増やし、それらを全てレコード型で毎回与える形を取っている
    良く使う値を定数としてパッケージレベルで提供することで、
    書く時の労力を減らし
    ている(with 構文による部分的な変更もできる)

    View Slide

  11. 6/14
    SLYDIFIでの設定方法
    1 document '<
    2 +set-config (|
    3 SlydifiThemeAkasaka.default-config with
    4 color-bg = Color.of-css `lightcyan`;
    5 color-emph = Color.of-css `darkred`;
    6 |);
    7 +make-title (|
    8 title = {|title|};
    9 author = {|author|};
    10 date = {|2022/9/24|};
    11 |);
    12 +frame {} <>
    13 >

    View Slide

  12. 6/14
    SLYDIFIでの設定方法
    デフォルトの設定から with 構文を使って部分的に設定を変更するところまでは標準
    ライブラリや exdesign と共通しているが、コマンドを使って文書中で設定するとこ
    ろに特徴がある
    タイトルなどの必須な情報もコマンドを使っており、
    L
    ATEX の書き方に似ている

    View Slide

  13. 新しく提案する手法

    View Slide

  14. 7/14
    思い出す話
    去年の SATySFi Conf 2021 での Murase さんの発表:
    「SATySFi で DSL を作る / 使うと便利って話」
    https://docs.google.com/presentation/d/1CmP_OdwNTNx46M0mqlK_EyO123
    BOGQNMTb25SwFhVnI/edit#slide=id.p
    1 \cmd (
    2 open TestModule in
    3 config
    4 |> set-hoge 42
    5 |> head {text}
    6 |> set-fuga 100
    7 |> body '<+code(`code`);>
    8 );

    View Slide

  15. 7/14
    思い出す話
    コマンドの引数で式を取れるようにする
    コマンドの引数内で局所的にモジュールを open できて便利
    設定を元にパイプライン演算子で設定を加えたりコンテンツを繋げたりする
    このような記述方法を取ることで、
    型検査の恩恵を十分に受けられる
    関数を使った十分に意味ベースな記述が可能
    という利点があり、非常に良いという指摘

    View Slide

  16. 7/14
    思い出す話
    コマンドの引数で式を取れるようにする
    コマンドの引数内で局所的にモジュールを open できて便利
    設定を元にパイプライン演算子で設定を加えたりコンテンツを繋げたりする
    このような記述方法を取ることで、
    型検査の恩恵を十分に受けられる
    関数を使った十分に意味ベースな記述が可能
    という利点があり、非常に良いという指摘
    👉これってドキュメントの設定にも使えませんか?

    View Slide

  17. 8/14
    v0.0.x での実装例
    GitHub の template 機能で使えるように実装
    https://github.com/puripuri2100/satysfi-class-template

    View Slide

  18. 8/14
    v0.0.x での実装例
    GitHub の template 機能で使えるように実装
    https://github.com/puripuri2100/satysfi-class-template
    使用例
    1 document (
    2 open Cls in
    3 default-config
    4 |> set-title {title}
    5 |> set-author {author}
    6 |> set-show-toc true
    7 |> set-title-page false
    8 ) '<
    9 +p{test}
    10 >

    View Slide

  19. 8/14
    v0.0.x での実装例
    GitHub の template 機能で使えるように実装
    https://github.com/puripuri2100/satysfi-class-template
    大学の講義の課題レポートでもたくさん使用(画像は確率論の講義での使用例)

    View Slide

  20. 9/14
    v0.1.x での実装例
    SATYSFI の dev-0-1-0 ブランチを使用して開発しているコンセプト版
    https://github.com/puripuri2100/satysfi-class-clsor-concept

    View Slide

  21. 9/14
    v0.1.x での実装例
    使用例
    1 module Local = struct
    2 module MyCls1Settings = struct
    3 val config = Clsor.default ()
    4 |> Clsor.set-font-size-normal 10pt
    5 end
    6 module MyCls = Clsor.Make MyCls1Settings
    7 end
    8 ---------------------------------------------------------
    9 Local.MyCls.document '<
    10 +Local.MyCls.p{test}
    11 >

    View Slide

  22. 9/14
    v0.1.x での実装例
    「モジュールを生成する関数」であるファンクタという機能を使用する実装
    クラスファイルを 「document 関数や文書記述用のコマンドを提供するモジュール
    である」と捉えることで、必要なフォントやデザインの情報を与えてクラスモジュー
    ルを生成する関数を作ることができる。
    メリットとして「コマンドが共通であるため、設定用モジュールを切り替えるだけで
    文書の記述を一切変えることなくデザインを変更できる」というものを確認した

    View Slide

  23. 実装の説明 (v0.0.x)

    View Slide

  24. 10/14
    設定関数の扱い
    1 document (
    2 open Cls in
    3 default-config
    4 |> set-title {title}
    5 |> set-author {author}
    6 |> set-show-toc true
    7 |> set-title-page false
    8 ) '<
    9 +p{test}
    10 >
    set-title や set-show-toc、
    default-config の取扱いについて扱う

    View Slide

  25. 10/14
    設定関数の扱い
    default-config は config 型を持つ
    set-* 関数は x -> config -> config 型を持つ
    という設計にしてあるため、パイプライン演算子で繋げていくことができる。

    View Slide

  26. 10/14
    設定関数の扱い
    default-config は config 型を持つ
    set-* 関数は x -> config -> config 型を持つ
    という設計にしてあるため、パイプライン演算子で繋げていくことができる。
    config 型の内部実装は
    1 (|
    2 title : inline-text list;
    3 author : inline-text option;
    4 show-toc : bool;
    5 ...
    6 |)
    のようなレコードになっている
    set-* 関数はこのレコード内の必要な項目を書き換える実装である

    View Slide

  27. 11/14
    コマンドに影響を与える設定への対処
    「+figure コマンドのキャプションの表示を変えられるようにしたい」場合を考える
    set-fig-caption : (int -> inline-text -> inline-boxes) -> config -> config
    という設定用関数を用意する
    しかしこのままでは config の影響は document 関数のみに閉じている

    View Slide

  28. 11/14
    コマンドに影響を与える設定への対処
    「+figure コマンドのキャプションの表示を変えられるようにしたい」場合を考える
    set-fig-caption : (int -> inline-text -> inline-boxes) -> config -> config
    という設定用関数を用意する
    しかしこのままでは config の影響は document 関数のみに閉じている
    そこで可変参照を利用して document 関数内で書き換えを行う

    View Slide

  29. 11/14
    コマンドに影響を与える設定への対処
    1 let-mutable fig-caption <- (fun n title -> (
    2 let n-it = n |> arabic |> embed-string in
    3 {図#n-it; #title;}
    4 ))
    5
    6 let document config inner =
    7 let () = fig-caption <- config#fig-caption in
    8 ...
    9
    10 let-block ctx +figure title inner =
    11 let () = fig-count <- !fig-count + 1 in
    12 let caption = !fig-caption !fig-count title in
    13 ...

    View Slide

  30. 実装の説明 (v0.1.x)

    View Slide

  31. 12/14
    設定関数の扱い
    v0.0.x のときと同じように、設定用のデータの内部実装はレコード型である
    設定用の set-* 関数もレコード内の項目を書き換える実装で共通である

    View Slide

  32. 13/14
    コマンドに影響を与える設定への対処
    v0.0.x のときと違い、
    「クラスモジュール全体に設定が与えられる」という状態であ
    るため、特別な処理が要らない
    1 module Make = fun(Config : DocumentConfig) -> struct
    2 val config-data = Config.config
    3 val block ctx +figure title inner =
    4 let () = fig-count <- !fig-count + 1 in
    5 let caption = config-data#fig-caption !fig-count titl
    e in
    6 ...
    のような実装でできる

    View Slide

  33. 13/14
    コマンドに影響を与える設定への対処
    v0.0.x のときと違い、
    「クラスモジュール全体に設定が与えられる」という状態であ
    るため、特別な処理が要らない
    1 module Make = fun(Config : DocumentConfig) -> struct
    2 val config-data = Config.config
    3 val block ctx +figure title inner =
    4 let () = fig-count <- !fig-count + 1 in
    5 let caption = config-data#fig-caption !fig-count titl
    e in
    6 ...
    のような実装でできる

    View Slide

  34. 13/14
    コマンドに影響を与える設定への対処
    v0.0.x のときと違い、
    「クラスモジュール全体に設定が与えられる」という状態であ
    るため、特別な処理が要らない
    1 module Make = fun(Config : DocumentConfig) -> struct
    2 val config-data = Config.config
    3 val block ctx +figure title inner =
    4 let () = fig-count <- !fig-count + 1 in
    5 let caption = config-data#fig-caption !fig-count titl
    e in
    6 ...
    のような実装でできる

    View Slide

  35. まとめ

    View Slide

  36. 14/14
    まとめ
    DSL 形式でクラスファイルのデザインを弄る実装はできる
    実用的に便利かはまだわからない(少なくとも v0.0.x の方での実装はレポート等で
    実績あり)

    View Slide