はじめに
Typstは、最近にわかに流行の兆しを見せている組版ソフトウェアです。TypstではLaTeXでamsmathやamssymbなどのパッケージで実現されていた機能の大部分がデフォルトで実装されており、簡単に文書を書くことができます。
さらに、標準にはない機能を補う優れたパッケージが数多く公開されており、容易に使うことができます。この記事では、Typstの便利なパッケージを紹介します。
Typstのインストール方法や基本的な文法については解説しません。他のネット記事や公式ドキュメントを参照してください。
パッケージの導入方法
公式のパッケージリポジトリに登録されているパッケージについては、ファイル中に
#import "@preview/{パッケージ名}:{バージョン}"
と書くことで自動的にダウンロードされ、使えるようになります。上記の書き方ではパッケージ名の名前空間に変数などが展開されますが、
#import "@preview/{パッケージ名}:{バージョン}: *"
と書くとデフォルトの名前空間に展開されます1。公式のパッケージリポジトリに登録されているパッケージについては、Typstの公式サイトに簡単な説明つきの一覧があります。
公式のパッケージリポジトリに登録されていないパッケージについては、これほど簡単に導入することはできません。そのようなパッケージの導入方法については個々のパッケージのReadmeを参照してください。以下で紹介するパッケージは全て公式のパッケージリポジトリに登録されています。
Physica
Physicaは物理でよく使われる多種多様なシンボルを追加するパッケージです2。
#import "@preview/physica:0.9.5": *
- 微分
$
dv(f,x),quad dv(f,x,2),quad dv(f,x,s:\/),quad \
dd(f),quad dd(x,y,z),\
pdv(f, x),quad pdv(f,x,y),quad pdv(,x),quad pdv(,x,y,z,[2,1,3])
$
- ブラケット
$
ket(psi),quad bra(phi),quad braket(psi,phi),quad ketbra(psi,phi),quad mel(psi,A,phi)
$
- テンソル
$
tensor(Gamma,+mu,-nu,-rho),quad tensor(R,+mu,-nu,-rho,-sigma),quad tensor(A,+mu,-nu,-rho,+sigma)
$
- 原子
$
isotope("U",a:238,z:92) --> isotope("Th",a:234,z:90)+isotope("He",a:4,z:2)
$
Physicaにはこの他にもたくさんの便利な関数があります。
ディラック定数についての注意
ディラック定数を表すものとしてTypst本体にはplanck.reduce
がありますが、デフォルトでは横棒が斜めになっています。これはデフォルトの数式フォントでディラック定数を表す文字 ℏ (U+210F) の横棒が斜めになっているからです。
Physicaパッケージのhbar
は横棒がまっすぐです。これはプランク定数を表す文字 ℎ (U+210E) に打ち消し線(strike
)を加えて実装されているためです。このため打ち消し線の色を変えるとhbar
の横棒の色が変わってしまいます。
これらの問題は、ℏ の横棒がまっすぐであるような代替字形を含むフォントを使うことで解決することができます。例えば次のようにhbar
を定義することでまっすぐな横棒を持つディラック定数が得られます。
#let hbar = (sym.wj, text(font: "Stix Two Math", stylistic-set: 3)[#math.planck.reduce], sym.wj).join()
sym.wj
を使っているのは、text
だけだと前後のスペースがおかしくなるからです。
3種類の方法を比較します。
#import "@preview/physica:0.9.2" as physica
#let hbar = (sym.wj, text(font: "Stix Two Math", stylistic-set: 3)[#math.planck.reduce], sym.wj).join()
$
"planck.reduce: " &planck.reduce,quad E=planck.reduce omega,quad i planck.reduce c\
"physica.hbar: " &physica.hbar,quad E=physica.hbar omega,quad i physica.hbar c\
"hbar: " &hbar,quad E=hbar omega,quad i hbar c
$
Physicaのhbar
と代替字形で定義したhbar
では横棒がまっすぐになっていることが分かります。代替字形で定義したhbar
にはstrike
の色などに関する問題がないので、こちらを使った方が良いと思います。
CeTZ
CeTZはTeXにおけるTikZに相当する図を描画するパッケージです。Typst本体でも基本的な図形の描画を行うことができますが(公式ドキュメント)、CeTZを使うとより高度な描画ができます。詳しい使い方はマニュアルを参照していただくとして、描画できる図の例をお見せします。
CeTZはバージョン0.2.0で大きな変更がありました。古いバージョンではこのコードは動きません。
#import "@preview/cetz:0.3.4"
#let linspace(start, end, n)=range(0,n).map(x => x / n * (end - start) + start)
#cetz.canvas({
import cetz.draw: *
line((0,0), (5,0), mark: (end: "stealth", fill: black))
content((), block(inset: 0.2em)[$abs(bold(p))$], anchor: "west")
line((0,-5), (0,5), mark: (end: "stealth", fill: black))
content((), block(inset: 0.2em)[$p^0$], anchor: "east")
let pa = linspace(0, 4, 100).map(x => (x, calc.sqrt(9+x*x)))
line(..pa, stroke: red)
let pb = linspace(0, 4, 100).map(x => (x, -calc.sqrt(9+x*x)))
line(..pb, stroke: blue)
line((0,0), (5,5), stroke: red)
line((0,0), (5,-5), stroke: blue)
let pe = linspace(-4, 4, 100).map(x => (calc.sqrt(9+x*x), x))
line(..pe, stroke: olive)
let draw-point(pos, text, color, anchor) = {
circle(pos, radius: 0.1, fill: color, stroke: none)
content((), block(inset: 0.3em)[#text], anchor: anchor)
}
draw-point((0, 3), "(a)", red, "east")
draw-point((0, -3), "(b)", blue, "east")
draw-point((1, 1), "(c)", red, "south-east")
draw-point((1, -1), "(d)", blue, "north-east")
draw-point((3, 0), "(e)", olive, "north-east")
draw-point((0, 0), "(f)", olive, "east")
})
Typstではlet
を使って簡単に関数を定義することができるので、描画中の共通する操作を関数にまとめることができ簡潔にコードが書けます。この例でもdraw-point
というラベル付きの点を描画する関数を定義して使っています。
Fletcher
Fletcherは先に紹介したCeTZを使って作られたパッケージで、矢印を使った図を簡単に描くことができます。こちらも詳しい使い方はマニュアルを参照してもらうとして、例をお見せします。
#import "@preview/fletcher:0.5.7": diagram, node, edge
#diagram($
T(i) edge("rd", mu_i, ->, #right) edge("rr", T(f), ->) & & T(j) edge("ld", mu_j, ->, #left)\
& C
$)
ファインマンダイアグラムも描けます。
#import "@preview/fletcher:0.5.7": diagram, node, edge
#diagram($
e^+ edge("rd", "-<|-") & & & edge("ld", "-|>-") e^+ \
& edge("wave") \
e^- edge("ru", "-|>-") & & & edge("lu", "-<|-") e^-
$)
次のような非常に複雑な図も描くことができます。
プログラムは長いので折り畳み
#import "@preview/fletcher:0.5.7" as fletcher: diagram, node, edge
#import "@preview/cetz:0.3.4": draw
#let kamaboko(node, extrude) = {
let (w, h) = node.size.map(i => i / 2 + extrude)
draw.arc-through((-w, -h), (0, w - h), (+w, -h), mode: "CLOSE")
}
#let kamaboko2(node, extrude) = {
let (w, h) = node.size.map(i => i / 2 + extrude)
draw.merge-path({
draw.arc-through((-w, -w), (0, 0), (+w, -w))
draw.line((), (+w, -w + h * 2), (-w, -w + h * 2), (-w, -w))
})
}
$
#block(diagram(
spacing: (1em, 2em),
node-stroke: black,
node((0pt, 0pt), enclose: ((0, -1), (1, 1)), width: 11em, inset: 1em, fill: gray.lighten(50%), corner-radius: 1em, snap: false),
node(enclose: ((0, -1), (0, 1)), width: 4em, inset: 0pt, stroke: (dash: "dashed"), fill: white, corner-radius: 1em),
node((0, -1), name: <i1>),
node((0, 1), name: <x1>),
node((0, 0), width: 3em, height: 1em, shape: kamaboko, fill: red.saturate(100%), name: <k1>),
edge(<k1>, <x1>, $X$, "-|>-", left),
edge(<i1>, <k1>, $i$, "-|>-", left),
node(enclose: ((1, -1), (1, 1)), width: 4em, inset: 0pt, stroke: (dash: "dashed"), fill: white, corner-radius: 1em),
node((1, 0), width: 3em, height: 2.5em, shape: kamaboko2, fill: red.saturate(100%), name: <k2>),
node((1, -1), name: <i2>),
node((1, 1), name: <x2>),
edge(<k2>, <x2>, $i$, "-|>-", left),
edge(<i2>, <k2>, $X$, "-|>-", left),
))
quad=quad sum_(alpha in A)quad
#block(diagram(
spacing: (1em, 2em),
node-stroke: black,
node((0pt, 0pt), enclose: ((0, -1), (1, 1)), width: 11em, inset: 1em, fill: gray.lighten(50%), corner-radius: 1em, snap: false),
node(enclose: ((0, -1), (0, 1)), width: 4em, inset: 0pt, stroke: (dash: "dashed"), fill: white, corner-radius: 1em),
node((0, -1), name: <i1>),
node((0, 1), name: <x1>),
node((0, 0), $p_alpha$, shape: rect, name: <k1>),
edge(<k1>, <x1>, $X$, "-|>-", left),
edge(<i1>, <k1>, $i$, "-|>-", left),
node(enclose: ((1, -1), (1, 1)), width: 4em, inset: 0pt, stroke: (dash: "dashed"), fill: white, corner-radius: 1em),
node((1, 0), $q_alpha$, shape: rect, name: <k2>),
node((1, -1), name: <i2>),
node((1, 1), name: <x2>),
edge(<k2>, <x2>, $i$, "-|>-", left),
edge(<i2>, <k2>, $X$, "-|>-", left),
))
$
unify
unifyは単位を扱うことができるパッケージです。TeXにおけるsiunitxに相当します。
#import "@preview/unify:0.7.1": *
- 数値: #num("1.23e8"), #num("e4")
- 数値の別表記: #num("1.23e8", multiplier: "times")
- 単位: #unit("keV"), #unit("m/s"), #unit("J/K/m^3")
- 単位の別表記: #unit("m/s", per: "\\/")
- 単位の中に括弧は使えない。
- 単位付きの数値: #qty("511", "keV"), #qty("1.23e8", "m/s")
- 誤差付き: #qty("511+-3", "keV"), #qty("1.23+-0.01e8", "m/s")
- 括弧は消せない。
次のような関数があります。
関数 | 機能 |
---|---|
num |
数値 |
unit |
単位 |
qty |
単位付きの数値 |
詳しい使い方はマニュアルを参照してください。
その他
これまで紹介したパッケージの他にもTypstには数多くのパッケージが存在します。いくつかのパッケージをまとめて紹介します。
おわりに
Typstは積極的に開発が行われており、パッケージの作成といったユーザーの活動も活発です。ぜひTypstを使って文書を作りましょう。
追記
2023-12-9: @Yarakashi_Kikohshi 様のコメントを基にPhysicaパッケージの解説に「ディラック定数についての注意」という節を加えました。
2024-3-18: Typst 0.11.0に伴うtable
まわりの変更について追記しました。
2025-4-25: Tablexはもう更新がなさそうなのでFletcherに変えました。また、metroも長い間メンテナンスされておらずTypst 0.13.0でついに動かなくなったのでunifyに変えました。
-
import
の詳細については公式ドキュメントの記載を参照してください: https://typst.app/docs/reference/scripting/#modules ↩ -
LaTeXでいうphysicsパッケージに相当するものですが、physicsパッケージが抱える数多くの問題はPhysicaにはないと思います。 ↩