LaTeX用户指南
如果你已经使用过LaTeX,并想要尝试Typst,这篇文章是个很好的入门指南。我们将从用户的角度出发,解释这两套系统之间主要的不同点。虽然Typst并不基于LaTeX,语法也完全不同,但通过这篇文章,你可以方便地将LaTeX的使用经验转化过来。
跟LaTeX一样,Typst是一门「基于标记的排版系统」。首先在纯文本里编写文档,然后通过一系列命令和语法对其进行修饰,最后使用编译器将源文件排版并渲染成PDF文件。然而,Typst跟LaTeX之间也在以下几个方面存在区别:首先,在日常任务上,Typst使用更专用的语法(这一点可以类比Markdown)。Typst的命令也更加统一:在LaTeX中,你可能需要为不同软件包学习不同的语法和约定,但在Typst中,命令总是保持一致,所以你只需要理解一些基本的概念。此外Typst比LaTeX快得多:Typst文件的编译通常只需要几毫秒,而不是几秒,正因如此Typst的网页版和编译器可以实现实时增量渲染。
在接下来的部分里,我们将回答从LaTeX切换到Typst时一些常见的问题。如果你更喜欢从头了解Typst,请阅读我们的教程。 [⚠️]
安装[⚠️]
你有两种方式使用Typst:在我们的Web应用程序中,或者在你的计算机上安装编译器。当你使用Web应用程序时,我们提供一个内置的协作编辑器,并在你的浏览器中运行Typst,无需安装。
如果你选择在你的计算机上使用Typst,你可以将编译器作为一个单独的小二进制文件下载,任何用户都可以运行,无需root权限。与LaTeX不同,包在你第一次使用时下载,然后在本地缓存,保持你的Typst安装精简。你可以使用你自己的编辑器,并决定在本地编译器中存储文件的位置。 [⚠️]
如何创建一个新的空文档?[⚠️]
很简单,你只需要创建一个空的文本文档(文件后缀是.typ),无需额外的模板,你就可以直接开始编写,默认使用A4纸张大小。如果您使用的是Web App,可以单击 “+ Empty document”,创建一个带有文件的新项目,然后进入编辑器。
段落分隔符和LaTeX相同,空一行即可: [⚠️💀]
Hey there!
Here are two paragraphs. The
output is shown to the right.

如果你想直接从原有的LaTeX文档迁移过来,你可以使用Pandoc将其转换为Typst格式。这个转换的工具也集成进了Typst的Web App中,你可以直接上传你的LaTeX文件,然后在上面继续编写。 [⚠️]
我如何创建章节标题,强调,…?[⚠️]
LaTeX使用\section命令创建章节标题。多级标题分别用\subsection、\subsection等表示。根据文档种类的不同,还有\part和\chapter。
在Typst中,标题没那么啰嗦:在标题所在的行,前面加上等号和空格,就得到了一级标题:= Introduction。 如果你需要一个二级标题,使用两个等号:== In this paper。 在前面加上更多的等号,你可以嵌套任意层级的标题。
译者注:
类比Markdown中#的作用,在接下来的阅读中你会不断看到这种「Markdown+LaTeX」杂糅的产物,结合这两者分别的痛点,可以更加深入了解Typst设计这些语法的原因。
强调(通常以斜体字呈现)是通过用_underscores_来表达,而着重的强调(通常以黑体字呈现)是通过使用*Star*来表达。
下面是LaTeX中使用的常见标记命令,以及Typst中对应的表示方式。你也可以查看完整的语法备忘单。 [⚠️]
| 元素[⚠️] | LaTeX | Typst | See |
|---|---|---|---|
| 着重强调[⚠️] | \textbf{strong} | *strong* | strong |
| 强调[⚠️] | \emph{emphasis} | _emphasis_ | emph |
| 链接 | \url{https://typst.app} | https://typst.app/ | link |
| 标签 | \label{intro} | <intro> | label |
| 交叉引用 | \ref{intro} | @intro | ref |
| 文献引用 | \cite{humphrey97} | @humphrey97 | cite |
| 等宽文字 / 代码[⚠️] | \texttt{mono} | text or mono functions | text, mono |
| Code | lstlisting环境[⚠️] | `print(f"{x}")` | raw |
| Verbatim | verbatim环境[⚠️] | `#typst-code()` | raw |
| 项目符号列表 | itemize环境[⚠️] | - List | list |
| 编号列表 | enumerate环境[⚠️] | + List | enum |
| 术语列表 | description环境[⚠️] | / Term: List | terms |
| 图表[⚠️] | figure环境[⚠️] | figure function | figure |
| 表格 | table环境[⚠️] | table function | table |
| 公式 | $x$, align/equation环境[⚠️] | $x$, $ x = y $ | equation |
在Typst中,使用列表并不需要创建「环境」,而采用一种更为轻量的语法。只需要在每行开头前,加入连字符-,就可以创建一个无序列表(itemize): [⚠️]
To write this list in Typst...
```latex
\begin{itemize}
\item Fast
\item Flexible
\item Intuitive
\end{itemize}
```
...just type this:
- Fast
- Flexible
- Intuitive

通过正确的缩进,可以实现列表间嵌套。在每项间添加空行,可以得到一个行间距更大的列表。
用+代替连字符-,可以得到有序列表(enumerate)。用/Term: Description,可以得到术语列表(description)。 [⚠️]
Note that the raw function and syntax (e.g. `raw`) only work for verbatim (unformatted) text. If you require formatting, you can use the text function with a monospace font instead, like in the example below:
#text(
font: "DejaVu Sans Mono",
size: 0.8em,
)[monospace *bold*]

我如何使用一个命令?[⚠️]
LaTeX十分依赖以反斜杠\开头的命令,它需要通过这些宏来排版、插入或改变内容。有些命令接受参数,通常使用大括号括起来。\cite{rasmus}
Typst区分两种模式:「标记模式」和「脚本模式」。默认处在「标记模式」下。此模式中,你可以直接编排文本、使用不同的语法结构,如*使用星号标记粗体文本*。而「脚本模式」下,则提供一个类似Python的编程语言,提供了输入、执行代码的选项。
在Typst的标记模式中,你可以使用井号(#)来使用单个命令(或者表达式)。例如,你可以通过这种方式来分割不同的文件,或者基于某些条件渲染文字。在「脚本模式」下,也可以通过方括号来包含正常的内容块,这些内容如同其他变量一样,被视作一种值。 [⚠️]
First, a rectangle:
#rect()
Let me show how to do
#underline([_underlined_ text])
We can also do some maths:
#calc.max(3, 2 * 4)
And finally a little loop:
#for x in range(3) [
Hi #x.
]

译者注:
这段英文原文就表述的很不清晰,这里提供一点解释。
标记模式,如同Markdown,不需要额外的内容,默认就处在这个标记模式下:可以直接使用_text_或者*text*来实现斜体/粗体(参考上文)。
脚本模式,以#开头(类比LaTeX中以\开头来书写命令),仅仅存在于一个命令(表达式)中,当这个表达式结束之后,一切又回到标记模式中。在脚本模式中,无需额外使用#(命令/关键字会直接识别,不同于LaTeX),同时在命令中也可以使用标记模式(使用,比如例子给出的Hi #x)。
此外:
- 在标记模式中,可以引用脚本模式的函数、值,都通过
#进行标记。 - 在脚本模式中,函数返回值为
content的会在当前位置渲染出来,如果没有显示指明返回值,则默认会将函数体内的所有内容块相加并返回。 - 在脚本模式中,使用标记模式的内容(
Content),也可以作为变量的值。
不同于LaTeX,Typst中函数定义总是要求函数名(rect, underline, calc.max, range)+ 括号的形式(而LaTeX中,没有参数的情况下,@[]和{}都是可以忽略的)。需要向函数传递的具体参数可以在参考中找到。 [⚠️]
参数[⚠️]
一个函数可以有多个参数,有些参数是位置参数,只需提供变量的值即可(不需要提供参数名称),例如:函数#lower("SCREAM")以全小写的方式返回其传入值。很多函数使用命名参数来提高可读性,例如创建一个指定大小和描边的正方形,可以使用如下命名参数: [⚠️]
#rect(
width: 2cm,
height: 1cm,
stroke: red,
)

指定一个命名参数时,首先输入参数名(上面的width、height和stroke),然后是冒号和对应的值(2cm、1cm、red)。你可以在「函数的参考页」或者「自动补全」中找到可用的命名参数。命名参数类似于一些LaTeX环境的配置方式,例如,你可以输入\begin{enumerate}[label={alph*)}]来启动一个带有标签a)、b)等的列表。
多数情况,你会想要向函数传递一些内容块。例如,在LaTeX中的命令\underline{Alternative A},在Typst中可以写成#underline([Alternative A])。方括号表示其中的值是一个内容块。在这些方括号中,你可以使用正常的标记语法。不过这样写的话,需要的括号还是太多了,因此你可以把「位于尾部的内容块」移到括号外(如果没有其他参数,可以忽略()): [⚠️]
Typst is an #underline[alternative]
to LaTeX.
#rect(fill: aqua)[Get started here!]

数据类型[⚠️]
你可能已经注意到了,上文提到的这些参数有着不同的数据类型。Typst支持多种数据类型,下表是其中一些比较重要的类型和以及他们的声明办法。只有处在脚本模式中才能声明这些类型: [⚠️]
| 数据类型[⚠️] | 示例[⚠️] |
|---|---|
| 内容块 (content)[⚠️] | [*fast* typesetting] |
| 字符串 (str)[⚠️] | "Pietro S. Author" |
| 整型 (int)[⚠️] | 23 |
| 浮点数 (float)[⚠️] | 1.459 |
| 绝对长度 (absolute length)[⚠️] | 12pt, 5in, 0.3cm, … |
| 相对长度 (relative length)[⚠️] | 65% |
内容块和字符串的区别在于,内容可以包含标记,包括函数调用,而字符串实际上只是一个普通的字符序列。
Typst提供了条件分支、循环结构,以及常用的运算符,例如+和==。
你也可以在你定义的变量中存储值(包括函数)。在计算、流程复用或者需要反复使用一个值的时候可能会用到。创建新变量的关键字是let,和LaTeX中\newcommand类似。 [⚠️]
// Store the integer `5`.
#let five = 5
// Define a function that
// increments a value.
#let inc(i) = i + 1
// Reference the variables.
I have #five fingers.
If I had one more, I'd have
#inc(five) fingers. Whoa!

影响后续内容的命令[⚠️]
在LaTeX中,例如 \textbf{bold text} 的命令通过大括号传入参数,并且只影响括号内的内容。而有些命令,比如 \bfseries bold text「起到开关的作用」(在LaTeX中这被叫做声明),在这行命令后的所有内容都会受这个命令的影响。
在Typst中,一个函数既可以用来影响文档的剩余部分,也可以只影响传入的参数。举例来说,#text(weight: "bold")[bold text] 仅仅会加粗传入的参数,而 #set text(weight: "bold") 的影响会持续「到当前块结束」(或者,如果不在内容块中,影响文档的剩余部分)。根据使用方式的不同(直接调用/在setrule)可以直观的表示函数的作用方式。 [⚠️]
I am starting out with small text.
#set text(14pt)
This is a bit #text(18pt)[larger,]
don't you think?

Set rules 可以出现在文档的任何部分。它们的作用方式可以类比向函数传递默认参数。 [⚠️]
#set enum(numbering: "I.")
Good results can only be obtained by
+ following best practices
+ being aware of current results
of other researchers
+ checking the data for biases

+是调用 enum 函数的语法糖(可以把它看作是一种简写),我们在上面应用了一个set rule。从这个意义上讲,大多数的特殊语法都是只是某一个函数的简写。如果你需要重新定义一个组件的样式(仅修改传递参数无法实现),你可以通过show规则完全重定义其样式(与LaTeX中\renewcommand相似,类似于定义了一个宏).
你可以通过font、style和weight参数来实现LaTeX命令\textbf,\textsf,\rmfamily,\mdseries,和\itshape的效果。text函数可以在set规则(声明风格)中使用,也可以带有内容参数。为了替换\textsc,你可以使用smallcaps函数,它会将其内容参数渲染为小型大写字母。如果你想要使用它的声明风格(类似于\scshape),你可以使用一个everything show规则来将这个函数应用到作用域的其余部分: [⚠️]
#show: smallcaps
Boisterous Accusations

如何加载一个文档类 / 模板?[⚠️]
在LaTeX中,.tex文件通常以\documentclass{article}开头,来定义文档的样式。在这个命令中,你也可以把article替换为report和amsart来更改文档的样式。
在Typst中,你可以通过函数来修改文档的样式。通常情况下,你可以使用模板中提供的函数来修改整个文档。首先,你可以通过#import来导入模板函数。然后你使用这个函数来对文档使用样式。具体的做法是通过show规则来将整个文档包装在这个函数中,具体如下: [⚠️]
#import "conf.typ": conf
#show: conf.with(
title: [
Towards Improved Modelling
],
authors: (
(
name: "Theresa Tungsten",
affiliation: "Artos Institute",
email: "tung@artos.edu",
),
(
name: "Eugene Deklan",
affiliation: "Honduras State",
email: "e.deklan@hstate.hn",
),
),
abstract: lorem(80),
)
Let's get started writing this
article by putting insightful
paragraphs right here!

这里的import命令,导入了在其他文件中声明的函数,从而可以在当前文件中使用。在这个例子中,它从conf.typ中导入了conf函数。这个函数会将整个文章的样式整理成一个会议论文。我们通过show rule把这个样式应用到全局,同时也设置了文档的一些元数据。在应用show rule之后,我们就可以开始写文章了。
在Typst中,函数被称为“命令”,它们可以将其参数转化为输出值,包括文档内容。函数是“纯”的,这意味着它们除了创建一个输出值/输出内容外,不能产生任何副作用。这与LaTeX的宏形成了鲜明的对比,后者可以对你的文档产生任意的效果。
为了使一个函数应用到整个文档,showrule会处理其后的所有内容,并将其结果作为参数传递给指定的函数。.with是一个方法,它接受conf函数,并在将其传递给show规则之前预先配置一些参数。
译者注:
#show: conf.with(title: [标题]) 等价于Lambda表达式形式的 #show: it => conf(title: [标题], it)
在Web App中,你可以选择一些预先定义好的模板,甚至可以通过模板向导创建自己的模板。在本地命令行中,你也可以使用typst init来从模板创建项目。查看发布在TypstUniverse上的模板列表, 这是官方的包管理库。你也可以访问Awesome Typst 仓库来查看一些社区提供,尚没有以包发布的模板。
你也可以创建你自己的自定义的模板。它们比相应的LaTeX的.sty文件短得多,可读性也高得多,所以不妨一试! [⚠️]
如何导入包?[⚠️]
Typst就像那种自带电池的玩具,许多流行的LaTeX包的对应功能是直接内置到Typst里的。在下面我们列出一些LaTeX中常用的包,和他们对应的Typst命令: [⚠️]
| LaTeX包[⚠️] | Typst替代[⚠️] |
|---|---|
| graphicx, svg | image 函数[⚠️] |
| tabularx, tabularray | table, grid 函数[⚠️] |
| fontenc, inputenc, unicode-math | 直接编写![⚠️] |
| babel, polyglossia | text函数:#set text(lang: "zh")[⚠️] |
| amsmath | 数学模式[⚠️] |
| amsfonts, amssymb | sym模块和syntax[⚠️] |
| geometry, fancyhdr | page函数[⚠️] |
| xcolor | text函数:#set text(fill: rgb("#0178A4"))[⚠️] |
| hyperref | link 函数[⚠️] |
| bibtex, biblatex, natbib | cite、bibliography函数[⚠️] |
| lstlisting, minted | raw函数和语法[⚠️] |
| parskip | block和par函数[⚠️] |
| csquotes | 设置text语言,并输入"or'[⚠️] |
| caption | figure函数[⚠️] |
| enumitem | list、enum、terms函数[⚠️] |
| nicefrac | frac.style property |
尽管很多东西是内置的,但并非所有东西都可以内置。这也是Typst提供一个内置的link(“https://typst.app/universe/”)[包管理器]的原因,社区成员可以在其中共享他们的工作和自动化工具。以CeTZ包为例,这个包允许你绘制复杂图形和函数图像。要在文档中使用CeTZ,你只需要编写: [⚠️]
#import "@preview/cetz:0.4.1"(@preview是一个namespace,在包管理器还处于早期和实验状态时使用,它将在将来被替换。)
除了官方的软件包存储库,您可能还会想看 Awesome Typst 仓库,其中集合了为 Typst 创建的资源精选列表。
如果您需要从项目中的另一个文档加载函数和变量,例如使用模板,则可以使用相同的 import 语句,其中应该包含文档名,而不是特定的包。 要包含另一个文档的文本内容,您可以使用 include 语句。它将读取指定文档的内容,并将其直接置入文档中。
[⚠️]
如何输入数学公式?[⚠️]
在Typst中,把公式包含在$记号中即可,在两个$$中添加额外的空格/换行符可以创建块状公式。 [⚠️]
The sum of the numbers from
$1$ to $n$ is:
$ sum_(k=1)^n k = (n(n+1))/2 $

数学模式的工作方式与普通标记或代码模式不同。数字和单个字符被逐字显示,而多个连续(非数字)字符将被解释为Typst变量。
Typst在数学模式下预先定义了很多有用的变量。所有希腊字母(alpha, beta, …)和一些希伯来字母(alef, bet, …)都可以通过它们的名字直接使用。一些符号还可以通过缩写轻松使用,如<=、>=和->。
符号的完整列表请参考符号页面。如果缺少某些符号,你也可以通过Unicode转义序列访问它。
符号的变体通常可以通过在句点后附加一个.点修饰符来选择。例如,arrow.l.squiggly插入了一个向左倾斜的箭头。如果你想在你的表达式中插入多字母纯文本,可以用双引号将其括起来: [⚠️]
$ delta "if" x <= 5 $

在 Typst 中,定界符将根据内部表达式自动缩放大小,就像在 LaTeX 中自动添加了隐藏的 \left 和 \right 命令一样。 你可以使用 lr 函数自定义定界符的行为。如果你不需要对定界符进行缩放,你可以用反斜线转义定界符。
在不破坏运算优先级的前提下,Typst 会自动将斜线 / 的两端内容识别成分数。所有没必要的括号将不会出现在编译结果中: [⚠️]
$ f(x) = (x + 1) / x $

下标和上标 在 Typst 和 LaTeX 中的作用是相似的。$x^2$ 将产生一个上标,$x_2$ 产生一个下标。 如果你想在下标或上标中包含一个以上的值,请把它们的内容放在括号里:$x_(a -> epsilon)$。
由于数学模式下的变量不需要在前面加上 # 或 / ,所以你也可以无需额外的井号字符来调用函数: [⚠️]
$ f(x, y) := cases(
1 "if" (x dot y)/2 <= 0,
2 "if" x "is even",
3 "if" x in NN,
4 "else",
) $

上面的例子用cases函数来表述f。在cases函数中,参数用逗号来分隔,参数也被解释为数学模式下的内容。如果你需要传递Typst变量,可以用#号作为前缀使用: [⚠️]
$ (a + b)^2
= a^2
+ text(fill: #maroon, 2 a b)
+ b^2 $

在数学模式下,你可以使用任意的Typst函数或者任何内容,如果你希望他们正常工作,只需要使用#前缀,没人可以阻止你把长方体或者emoji表情作为参数传入: [⚠️]
$ sum^10_(🤓=1)
#rect(width: 4mm, height: 2mm)/🤓
= 🧠 maltese $

如果你希望直接以Unicode形式输入数学符号,也是可以的。
数学调用可以有二维参数列表,使用;作为分隔符。这方面最常见的用途是使用mat函数创建矩阵: [⚠️]
$ mat(
1, 2, ..., 10;
2, 2, ..., 10;
dots.v, dots.v, dots.down, dots.v;
10, 10, ..., 10;
) $

如何获得 “LaTeX 外观”?[⚠️]
用LaTeX编写的论文有一种美观且易于识别的外观。这主要是由于它们的字体Computer Modern、对齐方式、窄行距和宽边距。
下面是一个示例:
[⚠️]
#set page(margin: 1.75in)
#set par(leading: 0.55em, spacing: 0.55em, first-line-indent: 1.8em, justify: true)
#set text(font: "New Computer Modern")
#show raw: set text(font: "New Computer Modern Mono")
#show math.equation: set text(weight: "regular")
#show heading: set block(above: 1.4em, below: 1em)这应该是一个很好的起点!如果你想更进一步,为什么不创建一个可重复使用的模板呢? [⚠️]
参考文献[⚠️]
Typst 的参考文献系统与 BibTeX 文件兼容。你可以通过 bibliography 函数加载你的 .bib 文献库。 也可以使用 Typst 原生基于 YAML 的格式.
Typst 使用引文样式语言(Citation Style Language)来定义和处理引文和参考文献样式。你可以将 CSL 文件与 BibLaTeX 的 .bbx 文件进行类比。 编译器已经包含了 80 多种引文样式,但你可以使用 CSL 仓库 中的任何符合 CSL 标准的样式,或者编写自己的样式。
你可以通过相同的语法 @key 来引用参考文献中的条目或者引用文档中的标签(这将引用一个名为 key 的条目)。 或者,你可以使用 cite 函数。
你可以使用 #cite(<key>, form: "prose") 来引用你的引文的其他形式,比如仅年份或者用于自然语言的引文(类似于 \citet 和 \textcite)。
你可以在 bibliography 函数的文档页面上找到更多信息。 [⚠️]
与LaTeX相比,Typst目前有哪些不足?[⚠️]
对于大多数人,Typst现在已经是一个很好的LaTeX替代品。然而,如果你是一个重度LaTeX用户,你可能会发现Typst还缺少一些功能:
原生图表和绘图。LaTeX用户通常会在PGF/TikZ中创建图表。Typst目前还没有包含绘图工具,但社区正在提供解决方案,比如
cetz。你可以将这些添加到你的文档中绘制图表。更改页面边距而不换页。在LaTeX中,你可以在不换页的前提下,调整页边距。你可以使用
page函数,但这将强制换页。如果你只是需要调整几个段落的边距,你可以使用pad函数来进行负填充。
[⚠️💀]