Typst 初体验
句法
Typst 有三种语法模式:
- 标记模式(Markup),是 Typst 的默认模式。
- 数学模式,用来编写公式。
- 代码模式,用来使用脚本功能。
模式 | 句法 | 例如 |
---|---|---|
代码模式 | 以 # 作为前缀 | Number: #(1 + 2) |
数学模式 | 用 $..$ 包围标记 | $-x$ is the opposite of $x$ |
标记模式 | 用 [..] 包围标记 | let name = [*Typst!*] |
注意,用 #
是不需要用两个井号[1]的。
标记模式
Typst 内置的标记类似于 markdown ,主要有:
名字 | 例子 | 参考 |
---|---|---|
段落分隔符 | Blank line | parbreak |
强烈强调 | *strong* | strong |
强调[2] | _emphasis_ | emph |
原始文本 | `print(1)` | raw |
链接 | https://typst.app/ | link |
标签 | <intro> | label |
引用 | @intro | ref |
标题 | = Heading | heading |
无序列表 | - item | list |
编号列表 | + item | enum |
术语列表 | / Term: description | terms |
数学公式 | $x^2$ | Math |
换行 | \ | linebreak |
根据语言,智能地展示文字引用 | 'single' or "double" | smartquote |
符号简写 | ~ , --- | Symbols |
调用 Typst 代码 | #rect(width: 1cm) | Scripting |
转义符 | Tweet at us \#ad | Below |
注释 | /* block */ , // line | Below |
数学模式
如果公式中,以至少一个空格开头和结尾,则会将其单独排版到其自己的块中。可以通过删除空格来生成行内公式。
名字 | 例子 | 参考 |
---|---|---|
行内公式 | $x^2$ | Math |
块级 / 行间公式 | $ x^2 $ | Math |
下标 | $x_1$ | attach |
上标 | $x^2$ | attach |
分数 | $1 + (a+b)/5$ | frac |
换行 | $x \ y$ | linebreak |
换行时对齐的点 | $x &= 2 \ &= 3$ | Math |
调用变量 | $#x$, $pi$ | Math |
调用字段 / 成员(field) | $arrow.r.long$ | Scripting |
省略掉乘号的乘法 | $x y$ | Math |
符号简写 | $->$ , $!=$ | Symbols |
公式里的字符串 | $a "is natural"$ | Math |
调用数学函数 | $floor(x)$ | Math |
调用 Typst 代码 | $#rect(width: 1cm)$ | Scripting |
转义符 | $x\^2$ | Below |
注释 | $/* comment */$ | Below |
代码模式
代码模式下,有些表达式是可以不用 #
作为前缀的,参考表:
名字 | 例子 | 参考 |
---|---|---|
none | none | none |
auto | auto | auto |
布尔值 | false , true | bool |
整数 | 10 , 0xff | int |
浮点数 | 3.14 , 1e5 | float |
绝对长度 | 2pt , 3mm , 1em , … | length |
角度 | 90deg , 1rad | angle |
分数 | 2fr [3] | fraction |
比率 | 50% | ratio |
字符串 | "hello" | str |
标签 | <intro> | label |
数学公式 | $x^2$ | Math |
原文本 | `print(1)` | raw |
调用变量 | x | Scripting |
代码块 | { let x = 1; x + 2 } | Scripting |
内容块 | [*Hello*] | Scripting |
括号表达式 | (1 + 2) | Scripting |
数组 | (1, 2, 3) | Array |
键值对 | (a: "hi", b: 2) | Dictionary |
单元运算符 | -x | Scripting |
双元运算符 | x + y | Scripting |
赋值[4] | x = 1 | Scripting |
访问成员 | x.y | Scripting |
调用成员函数 | x.flatten() | Scripting |
调用函数 | min(x, y) | Function |
参数展开[5] | min(..nums) | Arguments |
匿名函数 | (x, y) => x + y | Function |
声明并赋值[6] | let x = 1 | Scripting |
非匿名的函数 | let f(x) = 2 * x | Function |
设置规则 | set text(14pt) | Styling |
条件设置规则 | set text(..) if .. | Styling |
设置 show 规则 | show heading: set block(..) | Styling |
用函数设置 show 规则 | show raw: it => {..} | Styling |
Show-everything rule | show: template | Styling |
Context expression | context text.lang | Context |
条件 | if x == 1 {..} else {..} | Scripting |
for 循环 | for x in (1, 2, 3) {..} | Scripting |
while 循环 | while x < 10 {..} | Scripting |
循环控制流 | break, continue | Scripting |
函数返回 | return x | Function |
包含模块 | include "bar.typ" | Scripting |
引入模块[7] | import "bar.typ" | Scripting |
引入模块中的成员 | import "bar.typ": a, b, c | Scripting |
注释 | /* block */ , // line | Below |
转义符
在 Typst 中如果要转义字符,就要在其前面加上反斜杠 \
。
可以用十六进制转义序列插入任意 Unicode 字符,比如 \u{1f600}
,转义出来的是😀
。
样式
set
规则
set
规则可以配置文档元素的基本属性,用来设置大多常用文档样式。它后面紧随一个文档元素的函数调用。例如:
1 |
|
顶层 set
规则一直作用到文件结束,当在块内使用时,只作用到块结束。例如,这个例子中 set
规则只对这个列表起作用:
1 |
|
可以使用条件 set
设置:
1 |
|
show
规则
使用 show
规则可以深度定制特定类型文档元素的外观,最常用的基本形式是 show-set
规则, 以 show
关键字作为开始标记,紧随一个选择器,一个冒号,最后是一个 set
规则。 例如:
1 |
|
选择器有:
- 所有文档:
show: rest => ..
转换 show 规则后的所有文档元素,这样就免于将所有文档元素都包含在一个巨大的函数调用中,来实现更复杂的布局。 - 特定文本:
show "Text": ..
设置特定文本样式,转变或替换特定文本。 - 正则表达式:
show regex("\w+"): ..
更自由的选择并转换匹配特定正则表达式的文本,详见于 regex 函数文档。 - 字段选择函数:
show heading.where(level: 1): ..
转换具有特定字段的文档元素。比如,可以只设置文档一级标题样式。 - 标签:
show <intro>: ..
选择并转换具有特定标签的文档元素,详见于标签函数文档。
脚本表达式
Typst 中,除了最常用的文档元素,其他所有均是由函数生成。
Typst 可以将代码嵌入在标记中:用 #
(井号) 来引入一个代码表达式, 表达式结束后,再恢复到正常的标记语法解析。 有些字符能够使其后字符继续解析为表达式,如果想将其解释为文本,可以用分号(;
)来强制结束表达式解析。
块
Typst 为了架构代码以及将代码嵌入内容中,设计了两种块:
- 代码块:
{ let x = 1; x + 2 }
编写代码时,一个计算过程可能需要分解为多个语句,创建多个中间变量,等等。 可以将多个表达式组成一个代码块,就像一个表达式一样。在代码块中,多个表达式由换行符或者分号分割。 其中每个表达式的输出值被合并起来,作为代码块的值。 有些表达式没有有用的输出,比如let
绑定返回none
,与其他值合并,没有任何效果。上面的表达式输出3
。 - 文档内容块
[*Hey* there!]
使用文档内容块,可以将标记/文档内容作为可编程值,存储到变量,传送给函数。 文档内容块由方括号包裹,可以包含任何标记。 一个文档内容块产生一个 content 类型的值。 文档内容块可以后缀参数形式任意多个传递给函数,就是说,list[A][B]
等效于list([A], [B])
。
文档内容块和代码块可以相互内嵌,例如:
1 |
|
绑定
上面已经展示,变量由 let
绑定定义。 =
符号后表达式的值被赋值给变量,这里赋值可以被省略,如果没有赋值,变量会初始化为 none
。 let
关键词也可以用来生成一个自定义的有名函数。
let
绑定的变量可以在接下来的块中或者文档中被访问。
1 |
|
let
绑定也常用来解构数组和字典, 解构时,等号左边的形式需要与数组或字典相似, ..
模式操作符只可被使用一次,用来指代数组或字典剩余的条目。
1 |
|
- 这句话的文档原文是“Once you have entered code mode with
#
, you don’t need to use further hashes unless you switched back to markup or math mode in between.”,本人英语不好,一开始把 “hash” 理解成了哈希,所以没读懂这是什么意思。其实 “hash” 这个词指的就是井号#
这个符号,和哈希没关系。外国人也会把#
叫做pound sign,number sign,hex 或者 square,可以看看这篇文章:https://zhuanlan.zhihu.com/p/683936872。类似的称呼有:ampersand -&
,asterisk -*
,tilde -~
,caret -^
。 ↩ - 强调(emphasis)在英语中一般对应的是斜体,强烈强调(strong emphasis)则对应加粗。 ↩
fr
是 fraction 的缩写,表示比例份数,一般用在分配空间的时候,相当于给这部分分几份。 ↩- 原文是 assign ,指定,赋值。 ↩
- 原文是 arguments spreading ,也就是把一个参数(arguement)集合(比如数组、列表、元组等)“摊开”,一个个作为独立的参数传给函数。 ↩
- 原文是 let binding 。 let: 声明,binding: 绑定。所以字面意思就是声明+赋值。 ↩
- include 的字面意思就是把对应的内容在本位置展开,简单粗暴;import 就则是结构化的导入了。 ↩