スクリプト記述
Typstには強力なスクリプト言語が組み込まれています。これにより、ドキュメントを自動化し、コードを使用してより洗練されたスタイルを作成できます。 以下は、スクリプト記述の概念の概要です。
式
Typstでは、マークアップとコードが一体となっています。
最も一般的な要素以外のものは 関数 を使って作成されます。
これを可能な限り便利にするため、Typstはコード式をマークアップに埋め込むためのコンパクトな構文を提供しています。式はハッシュ(#
)で始まり、
この式が終了すると通常のマークアップの解析が再開されます。
式の直後に通常の文字列として解釈されるべき文字が続く場合、セミコロン(;
)を使って式を強制的に終了できます。
#emph[Hello] \
#emoji.face \
#"hello".len()
上記の例では、関数呼び出し、
フィールドアクセス、
そしてメソッド呼び出しなどのいくつかの使用可能な式を示しています。
この章の残りでは、より多くの種類の式について説明します。
いくつかの種類の式はハッシュ構文と互換性がありません(例えば二項演算子式)。
このような式をマークアップに埋め込むためには、#(1+2)
のように丸括弧を使用します。
ブロック
コードを構造化し、マークアップを埋め込むために、Typstは次の二種類の ブロック を提供します。
-
コードブロック
{ let x = 1; x + 2 }
コードを書く際には、計算を複数のステートメントに分割したり、中間変数を作成したりすることがあるでしょう。 コードブロックを使用すると、複数の式を1つのブロックにまとめられます。ブロック内の個々の式は改行またはセミコロンで区切られます。 コードブロック内の個々の式の出力値は結合され、ブロックの値を決定します。let
バインディングのように有用な出力のない式はnone
を生成し、これはどの値とも影響なく結合できます。 -
コンテンツブロック
[*Hey* there!]
コンテンツブロックを使用すると、マークアップやコンテンツをプログラム的な値として扱い、変数に保存したり、関数に渡したりできます。 コンテンツブロックは角括弧で囲まれ、任意のマークアップを含められます。 コンテンツブロックはcontent型の値を生成します。 任意の数のコンテンツブロックを可変長引数として関数に渡せます。つまり、list[A][B]
はlist([A], [B])
と等価です。
コンテンツブロックとコードブロックは任意にネストできます。以下の例では、[hello]
がa + [ the ] + b
の出力と結合され、[hello from the *world*]
が生成されます。
#{
let a = [from]
let b = [*world*]
[hello ]
a + [ the ] + b
}
バインディングと分割
前述のように、変数はlet
バインディングで定義できます。
変数には=
記号のあとに続く式の値が代入されます。値の代入は任意であり、値が代入されなければ変数はnone
として初期化されます。
let
キーワードは、カスタム名前付き関数を作成するためにも使用できます。
変数は、それが含まれるブロックの残りの部分(または、変数が含まれるブロックがない場合はファイル全体)の中でアクセスできます。
#let name = "Typst"
This is #name's documentation.
It explains #name.
#let add(x, y) = x + y
Sum is #add(2, 3).
letバインディングは配列や辞書の分割にも使用できます。
この場合、代入の左辺は配列や辞書と同じ形式でなければなりません。
..
演算子はパターン内で一度だけ、配列や辞書の残りの項目を受け取るために使用できます。
#let (x, y) = (1, 2)
The coordinates are #x, #y.
#let (a, .., b) = (1, 2, 3, 4)
The first element is #a.
The last element is #b.
#let books = (
Shakespeare: "Hamlet",
Homer: "The Odyssey",
Austen: "Persuasion",
)
#let (Austen,) = books
Austen wrote #Austen.
#let (Homer: h) = books
Homer wrote #h.
#let (Homer, ..other) = books
#for (author, title) in other [
#author wrote #title.
]
分割パターンでアンダースコアを使用して、要素を破棄できます。
#let (_, y, _) = (1, 2, 3)
The y coordinate is #y.
分割は関数の引数リスト内でも機能します。
#let left = (2, 4, 5)
#let right = (3, 2, 6)
#left.zip(right).map(
((a,b)) => a + b
)
そして通常の代入の左辺でも機能します。これは、変数の値を交換するなどの場合に便利です。
#{
let a = 1
let b = 2
(a, b) = (b, a)
[a = #a, b = #b]
}
条件式
条件式を使用すると、ある条件が満たされているかどうかに応じて、異なるものを表示したり計算したりできます。
Typstはif
式、else if
式、およびelse
式をサポートしています。
条件がtrue
の場合、条件式はif
の部分の結果が得られ、そうでない場合はelse
の部分の結果が得られます。
#if 1 < 2 [
This is shown
] else [
This is not.
]
各条件分岐は、その本文としてコードブロックまたはコンテンツブロックを含められます。
if condition {..}
if condition [..]
if condition [..] else {..}
if condition [..] else if condition {..} else [..]
ループ
ループを使用すると、コンテンツを繰り返したり、何かを反復的に計算したりできます。
Typstは、for
ループとwhile
ループの2つのループをサポートしています。
前者は指定されたコレクションを反復するのに対し、後者は条件が満たされている限り反復を続けます。
ブロックと同様に、ループは各反復からの結果を1つの値に 結合 します。
以下の例では、forループによって作成された3つの文が1つのコンテンツ値に結合され、whileループの中の長さ1の配列が1つの大きな配列に結合されます。
#for c in "ABC" [
#c is a letter.
]
#let n = 2
#while n < 10 {
n = (n * 2) - 1
(n,)
}
forループはさまざまなコレクションを反復処理できます。
-
for value in array {..}
配列内の各項目を反復処理します。letバインディングで説明されている分割構文もここで使用できます。 -
for pair in dict {..}
辞書のキーと値のペアを反復処理します。ペアはfor (key, value) in dict {..}
を使用しても分割できます。これは、すべてのキーと値のペアの一時配列を作成しないため、for pair in dict.pairs() {..}
よりも効率的です。 -
for letter in "abc" {..}
文字列の各文字を反復処理します。厳密に言うと、文字列の書記素クラスタの反復処理を行います。ほとんどの場合、書記素クラスタは単一のコードポイントに対応します。しかし、書記素クラスタは複数のコードポイントを含むことがあります。例えば、国旗の絵文字などです。 -
for byte in bytes("😀") {..}
文字列から変換されたり、エンコーディングなしでファイルから読み取ることができるバイトを反復処理します。各バイト値は0
から255
までの整数です。
ループの実行を制御するために、Typstはbreak
とcontinue
ステートメントを提供しています。
前者はループを早期終了し、後者はループの次の反復を開始します。
#for letter in "abc nope" {
if letter == " " {
break
}
letter
}
ループの本体はコードブロックまたはコンテンツブロックにできます。
for .. in collection {..}
for .. in collection [..]
while condition {..}
while condition [..]
フィールド
ドット記法 を使用することで値のフィールドにアクセスできます。コンテンツ型の値については、fields関数を使用してフィールドを一覧表示できます。
対象の値は以下のいずれかです。
- 指定されたキーを持つ辞書、
- 指定された修飾子を持つ記号、
- 指定された定義を含むモジュール、
- 指定されたフィールドを持つ要素で構成されたコンテンツ。利用可能なフィールドは、その要素が構築された際に与えられた要素関数の引数と一致します。
#let it = [= Heading]
#it.body \
#it.depth \
#it.fields()
#let dict = (greet: "Hello")
#dict.greet \
#emoji.face
メソッド
メソッド呼び出しは、値の型で定義された関数を呼び出す便利な方法です。
例えば、str.len
関数は下記の2つの同等の方法で呼び出せます。
#str.len("abc") is the same as
#"abc".len()
メソッド呼び出しの構造はvalue.method(..args)
であり、これと等価である完全な関数呼び出しはtype(value).method(value, ..args)
です。各型のドキュメントには、その型に関連付けられた関数が一覧表示されています。現在、独自のメソッドは定義できません
#let values = (1, 2, 3, 4)
#values.pop() \
#values.len() \
#("a, b, c"
.split(", ")
.join[ --- ])
#"abc".len() is the same as
#str.len("abc")
特定の値に対して呼び出された際に、その値を変更する特別な関数がいくつかあります(例: array.push
)。
これらの関数は、必ず メソッド形式で呼び出す必要があります。
場合によっては、メソッドが副作用のためだけに呼び出されるとき、その戻り値は無視されるべきです(結合に加わるべきではありません)。
値を破棄する標準的な方法は、let _ = array.remove(1)
のように
letバインディングを使用することです。
モジュール
Typstプロジェクトを、モジュール と呼ばれる複数のファイルに分割できます。 モジュールは他のモジュールの内容や定義を複数の方法で参照できます。
-
インクルード:
include "bar.typ"
パスbar.typ
にあるファイルを評価し、その結果として得られるコンテンツを返します。 -
インポート:
import "bar.typ"
パスbar.typ
にあるファイルを評価し、その結果として得られる モジュールを現在のスコープにbar
(拡張子なしのファイル名)として挿入します。次のように、as
キーワードを使用してモジュール名を変更できます。import "bar.typ" as baz
You can import nested items using dot notation:import "bar.typ": baz.a
. -
アイテムのインポート:
import "bar.typ": a, b
パスbar.typ
にあるファイルを評価して、変数a
とb
の値 (これらはbar.typ
で、例えばlet
バインディングを通じて定義されている必要があります) を抽出し、現在のファイルで定義します。a, b
を*
に置き換えると、モジュールで定義されたすべての変数が読み込まれます。 次のように、as
キーワードを使用してモジュール名を変更できます。import "bar.typ": a as one, b as two
以下の例に示すように、パスの代わりにモジュール値を使用できます。
#import emoji: face
#face.grin
パッケージ
プロジェクト間でビルド中のブロックを再利用するために、Typstの パッケージ を作成してインポートできます。 パッケージのインポートは、名前空間、名前、バージョンの3つの組み合わせとして指定されます。
#import "@preview/example:0.1.0": add
#add(2, 7)
preview
名前空間には、コミュニティで共有されているパッケージが含まれています。すべての利用可能なコミュニティパッケージはTypst Universeにあります。
Typstをローカルで使用している場合、独自のシステムローカルパッケージを作成できます。詳細については、パッケージリポジトリを参照してください。
演算子
以下の表は、使用可能なすべての単項および二項演算子の効果、引数の個数(単項あるいは二項)、および優先度(高いほど強く結合)を示しています。
演算子 | 効果 | 引数の個数 | 優先度 |
---|---|---|---|
- | 負号 | 単項 | 7 |
+ | 効果なし (対称性のために存在) | 単項 | 7 |
* | 乗算 | 二項 | 6 |
/ | 除算 | 二項 | 6 |
+ | 加算 | 二項 | 5 |
- | 減算 | 二項 | 5 |
== | 等価性の評価 | 二項 | 4 |
!= | 非等価性の評価 | 二項 | 4 |
< | 小なりの評価 | 二項 | 4 |
<= | 以下の評価 | 二項 | 4 |
> | 大なりの評価 | 二項 | 4 |
>= | 以上の評価 | 二項 | 4 |
in | コレクション内に存在することの評価 | 二項 | 4 |
not in | コレクション内に存在しないことの評価 | 二項 | 4 |
not | 論理否定 | 単項 | 3 |
and | 短絡論理積 | 二項 | 3 |
or | 短絡論理和 | 二項 | 2 |
= | 代入 | 二項 | 1 |
+= | 加算代入 | 二項 | 1 |
-= | 減算代入 | 二項 | 1 |
*= | 乗算代入 | 二項 | 1 |
/= | 除算代入 | 二項 | 1 |