Typst-语法基础

Typst 官网

Modes

Typst 主要有三种 syntactical modes:

  • Code, 以 # 开头, lets you use Typst’s scripting features
  • Math, 用 $$ 包裹
  • Markup, 用 [] 包裹, 其内的特殊符号被解析为样式, 在非 Code 和 Math 模式时, 默认为 Markup 模式 (此时没有用 [] 包裹)

注释

单行用 //.

多行用 /* */.

转义

\, 也可以用 \u{} 显示 utf8 字符:

1
2
I got an ice cream for
\$1.50! \u{1f600}

Scripting 语法

这里演示: 函数调用, 访问字段, 以及调用 methods:

1
2
3
#emph[Hello] \
#emoji.face \
#"hello".len()

Blocks

两种 blocks:

  • Code block, 如 { let x = 1; x + 2 }
    多语句同一行用 ; 分割, 或者写作多行. 在 {} 中的语句不再需要 # 开头. 返回值可以是 block 中的最后一个语句.
  • Content block, 如 [*Hey* there!]
    也就是 Markup 的 block, 可以把整个 block 赋值给一个变量.

如:

1
2
3
4
5
6
#{
let a = [from]
let b = [*world*]
[hello ]
a + [ the ] + b
}

Bindings and Destructuring

let 创建变量称为 bindings, 用 = 进行赋值. 如果没有初始化, 则其值为 none. 如:

1
2
3
#let name = "Typst"
This is #name's documentation.
It explains #name.

也可以用 let 创建具名函数. 如:

1
2
#let add(x, y) = x + y
Sum is #add(2, 3).

创建 arrays 和 dictionaries, 都是用 (), 如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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 (Homer, ..other) = books, 这里 other 就赋值为除 Homer 以外的键值对.

注意这里的 #let (Austen,) = books 用于取出 Austen 键的值.

循环迭代 dictionaries 的值, 如:

1
2
3
#for (author, title) in other [
#author wrote #title.
]

可以用 _ 当作占位符:

1
#let (_, y, _) = (2, 4, 5)

zip 方法可以将两个数组配对成一个新的数组列表, 如:

1
2
3
#let left = (2, 4, 5)
#let right = (3, 2, 6)
#let left.zip(right) // ((2,3), (4,2), (5,6))

map 方法来直接操作数组:

1
2
3
4
5
#let left = (2, 4, 5)
#let right = (3, 2, 6)
#let left.zip(right).map(
((a,b)) => a + b
) // (5, 6, 11)

交换两个变量的值可以直接为:

1
2
3
4
5
6
#{
let a = 1
let b = 2
(a, b) = (b, a)
[a = #a, b = #b]
}

Conditions

语法为:

  • if condition {..}
  • if condition [..]
  • if condition [..] else {..}
  • if condition [..] else if condition {..} else [..]

Loops

Typst 支持 forwhile 循环. 语法为:

  • for .. in collection {..}
  • for .. in collection [..]
  • while condition {..}
  • while condition [..]

如:

1
2
3
4
5
6
7
8
9
#for c in "ABC" [
#c is a letter.
]

#let n = 2
#while n < 10 {
n = (n * 2) - 1
(n,)
}

同时也支持 breakcontinue. 如:

1
2
3
4
5
6
7
#for letter in "abc nope" {
if letter == " " {
break
}

letter
}

Fields

. 访问, 可以是:

  • dictionary 的键
  • module 下的定义
  • symbol 中的 modifier
  • element 包含的 content

如:

1
2
3
4
5
6
7
#let dict = (greet: "Hello")
#dict.greet \
#emoji.face

#let it = [= Heading]
#it.body \
#it.depth

Methods

Methods 与 type 相绑定. 比如字符串调用 len 的两种方式;

1
2
3
4
5
6
7
8
9
10
#str.len("abc") is the same as
#"abc".len()

#let array = (1, 2, 3, 4)
#array.pop() \
#array.len() \

#("a, b, c"
.split(", ")
.join[ --- ])

语法格式为:

1
2
value.method(..args) // The same as
type(value).method(value, ..args)

Modules

  • include "bar.typ", Evaluates the file at the path bar.typ 并返回其内容
  • import "bar.typ", 将 bar.typ 的内容作为 bar 关键字导入, 可以起别名: import "bar.typ" as hhh
  • import "bar.typ": a, b, 导入变量, 可以用 * 导入全部, 也可以起别名, 如: import "bar.typ": a as one, b as two

如:

1
2
#import emoji: face
#face.grin

Packages

@namespace/name:version 的格式导入:

1
2
#import "@preview/example:0.1.0": add
#add(2, 7)

Context

Style context

可以用 context 关键字来访问一些上下文信息. 如这里用 set 设置的 style context:

1
2
#set text(lang: "de")
#context text.lang

这里先用 set 设置了 text(lang: "de") 作用于后面所有的文档, 因此产生了一个上下文, 可以用 context 来访问.

似乎由于 bindings 的机制, 可以实现:

1
2
3
4
5
6
7
8
#let value = context text.lang
#value

#set text(lang: "de")
#value

#set text(lang: "fr")
#value

的输出为:

1
2
3
en
de
fr

value 的值在随上下文而变化.

Location context

文本在 document 中所处的位置, 即 location context (比如周围是什么 element, 位于哪一 page 等) 也可以用 conotext 关键字访问.
如:

1
2
3
4
5
6
7
8
9
10
11
#set heading(numbering: "1.")

= Introduction
#lorem(5)

#context counter(heading).get()

= Background
#lorem(5)

#context counter(heading).get()

这里的 counter.get 隐式借助了 location context.

使用 counter.athere 更加灵活:

1
2
3
4
5
6
7
8
9
10
11
12
13
#set heading(numbering: "1.")

= Introduction <intro>
#lorem(5)

= Background <back>
#lorem(5)

#context [
#counter(heading).get() \
#counter(heading).at(here()) \
#counter(heading).at(<intro>)
]

locate 函数来获取具体的位置信息:

1
2
3
4
5
6
7
8
9
Background is at: \
#context locate(<back>).position()

= Introduction <intro>
#lorem(5)
#pagebreak()

= Background <back>
#lorem(5)

Nested contexts

1
2
3
4
5
6
#set text(lang: "de")
#context [
#set text(lang: "fr")
#text.lang \
#context text.lang
]

也就是说, 当前层的 context 都需要用 context 来访问, 不然就是访问外层的.

Label

可以直接为 markup content 附上一个 label, 也可以先给 label 赋予一定的 style 后 attach 到 content 中, 如:

1
2
3
4
5
#show <a>: set text(blue)
#show label("b"): set text(red)

= Heading <a>
*Strong* #label("b")

Type

Typst 中的常见的类型包括, 如:

1
2
3
4
5
6
7
#type(12) \
#type(14.7) \
#type("hello") \
#type(<glacier>) \
#type([Hi]) \
#type(x => x + 1) \
#type(type)

输出为:

1
2
3
4
5
6
7
integer
float
string
label
content
function
type

arguments

在 Typst 中, arguments 也是一种类型, 指剩下的参数:

1
2
3
4
5
#let check_args(s, ..other) = {
[The type of arge is #type(other)]
}

#check_args("Jie", "hello", "world")

这里输出的类型就是 arguments.

arguments() 函数为 constructor, 返回一个 arguments 类型的值.

pos() 方法, 将参数以 array 返回.

named() 方法, 将参数以 dictionary 返回.

array

Array 中的元素不需要为同一类型.

array() 函数为 constructor, 返回一个 array 类型值.

at 方法, 取数组中指定 index 的元素, 可指定默认值.

比较直观的方法有:

  • len()
  • first()
  • last()
  • push()
  • pop()
  • insert()
  • remove()
  • slice()
  • contains()
  • rev(), reverse
  • split()
  • join()

filter(function) 函数和 perl 中的 grep 类似.

map(function) 函数和 perl 中的 map 类似.

sorted(function) 函数和 perl 中的 sort 类似.

zip(..array) 函数, 用于整合数组.

dedup(), 函数, 可移除数组中的重复元素.

content

所有的 markup 都是 content 类型 (也就是 [] 包裹的部分).

datetime

Datetime 类型用于表示时间.

datetime() 函数为 constructor.

display() 方法用于显示.

dictionary

键值对间用 :.

dictionary() 函数为 constructor.

at() 方法指定键, 访问其值.

比较直观的函数有:

  • len()
  • keys()
  • values()
  • insert()
  • remove()
  • pairs()

Integer

对于每一个 integer, 常用的 methods 有:

  • signum, 返回整数的符号

selector

selector 实际就是 filter, 用于选择自己想要找到的 elements. 有多种方式得到 selector 类型:

  • 用 element function
  • string, regular expression
  • <label>
  • location
  • selector constructor

selector() constructor, 可以将一个 value 转换为 selector. 这个 value 可以是;

  • element function
  • <label>
  • more complex selector

其函数声明为:

1
selector(str regex label selector location function) -> selector

和 query 配合使用

1
2
3
4
5
6
7
8
#context query(
heading.where(level: 1)
.or(heading.where(level: 2))
)

= This will be found
== So will this
=== But this will not.

这里的 heading 是一个 element constructor.

Calculation 模块

默认导入为 calc.

eval

和 Perl 语言中类似, 这里是将 string 视为 Typst code, 如:

1
2
3
#eval("1 + 1") \
#eval("(1, 2, 3, 4)").len() \
#eval("*Markup!*", mode: "markup") \

这里可以指定的 mode 包括 code, markup, math. 默认是 code.

function

创建具名函数

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#let alert(body, fill: red) = {
set text(white)
set align(center)
rect(
fill: fill,
inset: 8pt,
radius: 4pt,
[*Warning:\ #body*],
)
}

#alert[
Danger is imminent!
]

#alert(fill: blue)[
KEEP OFF TRACKS
]

这里使用 let 将一段 typst code 和一个 name 绑定在一起.

创建匿名函数

用 parameter list 加上 => 在加上 function body. 如果只有一个 parameter, 则可省略 parameter list 两侧的括号.

如:

1
2
#show "once?": it => [#it #it]
once?

这里参数为 it, 函数体为 [#it #it].

panic

用于输出到编译的输出中:

1
#panic("this is wrong")

Typst-语法基础
http://example.com/2024/04/12/Typst-语法基础/
作者
Jie
发布于
2024年4月12日
许可协议