これはSATySFi advent calendarの七日目の記事です.昨日はpuripuri2100さんの予定です.明日はamutakeさんの予定です.
ちょっと長めの文書をSATySFiで最近作っています.で,図式を描く必要が起こったので,パッケージMatrixCDを作りました.LaTeXパッケージのtikz-cdのように書けるようにしました.実は標準パッケージに図式を描くものがあったり,それとは別に既存のパッケージNon-Commutative Squaresというのがあったりするんですが,前者はすっかり忘れていて後者は存在に気がついたのが大分できてからでした.シンタックス大分違うのでまぁいいかと.tikz-cd万歳.
ドキュメント書こうと思っていたのですが間に合わずでした.
インストール
Satyrographosが入っていれば楽です.
$ opam install satysfi-matrixcd
$ satyrographos install
またはmatrixcd.satyを適当なフォルダに置けばよいです.
使い方
プリアンブルに次が書かれていることを仮定します.
@require: matrixcd/matrixcd
open MatrixCD
簡単な例は次の通りです.
+p{
\eqn(${
\matrixcd{
|A \arrow![to `r`; label ${f}]\arrow![to `rd`] | B\arrow![to `d`;label ${g}]\cr
| | D
|}
});
}
これで次のような出力が得られます.
+p{}
は段落,\eqn(${...});
がディスプレイ数式なのはSATySFiのいつも通りです.その中の\matrixcd
が図式を出力します.書式は(tikz-cdと同様に)表の形で並べて,\arrow
で矢印を引きます.表組みの区切りは|
です.easytableとかと同じですね.改行は\cr
で指定します.
矢印へのもろもろの指定は\arrow![<引数>]
への引数で行います.複数の設定をする場合は;
で区切ります.ほぼ必須設定がto
で,矢印の行き先を指定します.引数は``
で囲まれた文字列でrlud
の四文字の組み合わせです.それぞれ右,左,上,下で始点からの相対位置で指定します.
矢印に付随させてラベルをつけられます.label ${<ラベル>}
で指定します.
\arrow
のオプション
\matrixcd{
|A\arrow![to `r`;label ?:[swap] ${f}] | B
|}
\arrow
ではなくlabel
のオプションです.label
へのオプションはこのようにlabel ?:[<オプション>] ${<ラベル>}
のように指定します.swap
は表示位置を反転させるオプションです.
\matrixcd{
|A\arrow![to `r`;hook] | B\arrow![to `r`;twoheadrightarrow] | C\arrow![to `r`;equal] | D | E\arrow![to `l`;hook-swap]\cr
|F\arrow![to `r`;dotted] | G\arrow![to `r`;dashed] | H\arrow![to `r`;mapsto] | I
|}
色々な矢印.
\matrixcd{
|A\arrow![to `r`;label ?:[description] ${f}] | B
|}
これもlabel
へのオプション.矢印の間に挟む.
\matrixcd{
|A \arrow![to `d`;shift (10pt,0pt)] \arrow![to `r`;shift (0pt,5pt)] | B\cr
|C \arrow![to `u`;shift (-10pt,0pt)] | D \arrow![to `lu`;shift (5pt,5pt)]
|}
矢印をずらす.shift (<x>,<y>)
で右にx,上にyずらします.
\matrixcd{
|A \arrow![to `r`; shift-out (0pt,5pt)] | B\arrow![to `r`;shift-in (0pt,-5pt)] | C
|}
矢印の出発地点をずらすshift-out
と到着地点をずらすshift-in
.
\matrixcd{
|A \arrow![to `r`; bend 90.0] | B\arrow![to `r`;bend-right] | C\arrow![to `r`;bend-left] |D\cr
|E \arrow![to `r`; arrow-in 315.0; arrow-out 225.0] | F
|}
曲がる矢印.矢印がでたり入ったりする角度をずらします.bend
は引数の角度分だけ矢印の出入りの方向を回します.bend-left
はbend 30.0
,bend-right
は
bend 330.0
です.この小数点は省略できません.bend 30
はエラーです.arrow-in
とarrow-out
は指定された方向へと矢印の入る方向と出る方向を変更します.
\matrixcd{
|a \arrow![to `r`; phantom; label ${\in}] | A
|}
phantom
を指定すると矢印が消えてラベルが真ん中に出ます.
\matrixcd{
|A \arrow![to `r`; label ?:[pos 0.2] ${f}] | B\arrow![to `r`; label ?:[pos 0.8] ${g}] | C
|}
これもlabel
へのオプション.pos
は指定された値の割合に応じてラベルの位置をずらします.0から1までの値を指定し,0の方が始点に近く,1の方が始点から遠い.
\matrixcd{
|A \arrow![to `rd`;crossing-over] | B\arrow![to `ld`] \cr
|C | D
|}
crossing-over
で矢印を重ねます.たまにうまく行きません.上に引く矢印が後にあるとまずいみたいなんですが,逆ならともかく何でだろう.
\matrixcd{
|A \arrow![to `r`;arrow-color Color.red] | B\arrow![to `r`; label ?:[label-color Color.blue] ${f}] | C
|}
色をつけます.
\matrixcd{
|A | B\arrow![from `l`]
|}
矢印はto
で終点を指定する方がわかりやすいと思いますが,始点をfrom
で指定することもできます.両方使うこともできて,もう全然関係ない場所から矢印がでちゃう.
\matrixcd ?:![row-sep 15pt; column-sep 60pt]{
|A\arrow![to `r`]\arrow![to `d`] | B\cr
| C |
|}
これは\matrixcd
へのオプション.各行,各列の間の距離を指定します.デフォルトは40pt.
実装
半分メモ書きです.
- 上のシンタックスを実現するために,可変参照を多用しています.例えば
\cr
の実装は次のようになっています.
このようにlet-mutable ref-cr <- false let-math \cr = let aux ctx = let () = ref-cr <- true in ${} in text-in-math MathOrd (fun ctx -> embed-math ctx (aux ctx))
ref-cr
に\cr
が現れたというフラグをたてるだけです.なお,aux
の引数ctx
は不要そうに見えますが,これを消すと評価場所の関係でref-cr
にうまく値が入りません.いずれにせよ,このような命令が含まれているmath listを\matrixcd
は受け取ります.\matrixcd
はこのリストを
という感じで処理します.% リストの中身を順番に処理している % itに今処理しているmathが入っている. let () = ref-cr >- false in % ref-crにfalseをセット let ib = embed-math ctx it in % itをinline-boxesに変換,\crがあればここで処理される. % 以下ref-crの値に応じて改行するか否かの処理
\arrow
も同様で,矢印の設定などの情報を適当な可変参照に代入していきます. - 矢印は「head」「tail」「body」の三カ所に分けて作っています.外からいじれるわけじゃないですが…….headとtailを出力するのは
という関数で,arrow-option-data -> length * length -> length * length -> context -> (length * length) * graphics list;
<オプション> <始点> <終点> <context>
を受け取り,(<pt>,<graphics list>)
を返します.オプションは\arrow
のオプションとして渡される物(の一部)であまり重要ではありません.<graphics list>
が矢印の形そのものです.<pt>
は,bodyの終点と始点を表します.bodyを出力する関数には,tailとheadから返されたこの始点と終点が渡されます.bodyを出力する関数は
です.やはり始点,終点,contextを受け取り,graphics listを返します.ここに渡される始点,終点はtailおよびheadが返したものです.最も単純な実装としては始点から終点まで線を引くだけのものになります.arrow-option-data -> length * length -> length * length -> context -> graphics list;
0 件のコメント:
コメントを投稿
コメントの追加にはサードパーティーCookieの許可が必要です