Skip to content

Commit c03ed74

Browse files
feat: 编辑排版Ⅰ和脚本Ⅰ
1 parent 2762309 commit c03ed74

12 files changed

+487
-696
lines changed

src/basic/scripting-access.typ

Lines changed: 14 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,21 @@
88
// + #term("array literal", postfix: "。")
99
// + #term("dictionary literal", postfix: "。")
1010

11-
== 成员 <grammar-member-exp>
12-
1311
Typst提供了一系列「成员」和「方法」访问字面量、变量与函数中存储的“信息”。
1412

15-
其实在上一节(甚至是第二节),你就已经见过了「成员」语法。你可以通过「点号」,即```typc `OvO`.text ```获得代码块的“text”(文本内容):
13+
其实在上一节(甚至是第二节),你就已经见过了「成员」语法。<grammar-member-exp>你可以通过「点号」获得代码块的“text”(文本内容):
1614

1715
#code(```typ
18-
这是一个代码块:#repr(`OvO`)
19-
20-
这是一段文本:#repr(`OvO`.text)
16+
#repr(`OvO`.text), #type(`OvO`), #type(`OvO`.text)
2117
```)
2218

23-
每个类型有哪些「成员」是由Typst决定的。你需要逐渐积累经验以知晓这些「成员」的分布,才能更快地通过访问成员快速编写出收集和处理信息的脚本。(todo: 建议阅读)
19+
每个类型有哪些「成员」是由Typst决定的。你需要逐渐积累经验以知晓这些「成员」的分布,才能更快地通过访问成员快速编写出收集和处理信息的脚本。(todo: 建议阅读《参考:XXX》)
2420

2521
当然,为防你不知道,大家不都是死记硬背的:有软件手段帮助你使用这些「成员」。许多编辑器都支持LSP(Language Server Protocol,语言服务),例如VSCode安装Tinymist LSP。当你对某个对象后接一个点号时,编辑器会自动为你做代码补全。
2622

2723
#figure(image("./IDE-autocomplete.png", width: 120pt), caption: [作者使用编辑器作代码补全的精彩瞬间。])
2824

29-
从图中可以看出来,该代码片段对象上有七个「成员」。特别是“text”成员赫然立于其中,就是它了。除了「成员」列表,编辑器还会告诉你每个「成员」的作用,以及如何使用。这时候只需要选择一个「成员」作为补全结果即可。
25+
从图中可以看出来,该代码片段「对象」上有七个「成员」。特别是“text”成员赫然立于其中,就是它了。除了「成员」列表,编辑器还会告诉你每个「成员」的作用,以及如何使用。这时候只需要选择一个「成员」作为补全结果即可。
3026

3127
== 方法 <grammar-method-exp>
3228

@@ -104,7 +100,14 @@ Typst提供了一系列「成员」和「方法」访问字面量、变量与函
104100

105101
== 数组和字典的「存在谓词」
106102

107-
与数组相关的另一个重要语法是`in``x in (...)`,表示判断`x`是否*存在于*某个数组中:<grammar-array-in>
103+
为了访问数组,你可以使用`contains`方法。“contain”在中文里是“包含”的意思,如下所示:
104+
105+
#code(```typ
106+
#let x = (1, "OvO", [一段内容])
107+
#x.contains[一段内容]
108+
```)
109+
110+
因为这太常用了,typst专门提供了`in`语法,表示判断`x`是否*存在于*某个数组中:<grammar-array-in>
108111

109112
#code(```typ
110113
#([一段内容] in (1, "OvO", [一段内容])) \
@@ -143,97 +146,8 @@ Typst提供了一系列「成员」和「方法」访问字面量、变量与函
143146

144147
// 这意味着,如果你发现了Typst中与一般语言的不同之处,可以思考以上种种优势对用户脚本的增强或限制。
145148

146-
基于《字面量、变量和函数》掌握的知识你应该可以:
147-
+ 查看#(refs.ref-type-builtin)[《参考:内置类型》],以掌握内置类型的使用方法。
148-
+ 查看#(refs.ref-visualization)[《参考:图形与几何元素》],以掌握图形和几何元素的使用方法。
149-
+ 查看#(refs.ref-wasm-plugin)[《参考:WASM插件》],以掌握在Typst中使用Rust、JavaScript、Python等语言编写插件库。
150-
+ 阅读#(refs.ref-grammar)[《参考:语法示例检索表》],以检查自己的语法掌握程度。
151-
+ 查看#(refs.ref-typebase)[《参考:基本类型》],以掌握基本类型的使用方法。
152-
+ 查看#(refs.ref-color)[《参考:颜色、色彩渐变与模式》],以掌握色彩的高级管理方法。
153-
+ 查看#(refs.ref-data-process)[《参考:数据读写与数据处理》],以助你从外部读取数据或将文档数据输出到文件。
154-
+ 查看#(refs.ref-bibliography)[《参考:导入和使用参考文献》],以助你导入和使用参考文献。
155-
+ 阅读基本参考部分中的所有内容。
149+
#todo-box[总结]
156150

157151
== 习题
158152

159-
#let q1 = ````typ
160-
#let a0 = 2
161-
#let a1 = a0 * a0
162-
#let a2 = a1 * a1
163-
#let a3 = a2 * a2
164-
#let a4 = a3 * a3
165-
#let a5 = a4 * a4
166-
#a5
167-
````
168-
169-
#exercise[
170-
使用本节所讲述的语法,计算$2^32$的值:#rect(width: 100%, eval(q1.text, mode: "markup"))
171-
][
172-
#q1
173-
]
174-
175-
#let q1 = ````typ
176-
#let a = [一]
177-
#let b = [渔]
178-
#let c = [江]
179-
#let f(x, y) = a + x + a + y
180-
#let g(x, y, z, u, v) = [#f(x, y + a + z),#f(u, v)。]
181-
#g([帆], [桨], [#(b)舟], [个#(b)翁], [钓钩]) \
182-
#g([俯], [仰], [场笑], [#(c)明月], [#(c)秋])
183-
````
184-
185-
#exercise[
186-
输出下面的诗句,但你的代码中至多只能出现17个汉字:#rect(width: 100%, eval(q1.text, mode: "markup"))
187-
][
188-
#q1
189-
]
190-
191-
#let q1 = ````typ
192-
#let calc-fib() = {
193-
let res = range(2).map(float)
194-
for i in range(2, 201) {
195-
res.push(res.at(i - 1) + res.at(i - 2))
196-
}
197-
198-
res
199-
}
200-
#let fib(n) = calc-fib().at(n)
201-
202-
#fib(75)
203-
````
204-
205-
#exercise[
206-
已知斐波那契数列的递推式为$F_n = F_(n-1) + F_(n-2)$,且$F_0 = 0, F_1 = 1$。使用本节所讲述的语法,计算$F_75$的值:#rect(width: 100%, eval(q1.text, mode: "markup"))
207-
][
208-
#q1
209-
]
210-
211-
#let q1 = ````typ
212-
#set align(center)
213-
#let matrix-fmt(..args) = table(
214-
columns: args.at(0).len(),
215-
..args.pos().flatten().flatten().map(str)
216-
)
217-
#matrix-fmt(
218-
(1, 2, 3),
219-
(4, 5, 6),
220-
(7, 8, 9),
221-
)
222-
````
223-
224-
#exercise[
225-
编写函数,使用`table`(表格)元素打印任意$N times M$矩阵,例如:
226-
227-
```typ
228-
#matrix-fmt(
229-
(1, 2, 3),
230-
(4, 5, 6),
231-
(7, 8, 9),
232-
)
233-
```
234-
235-
#rect(width: 100%, eval(q1.text, mode: "markup"))
236-
][
237-
#q1
238-
]
239-
153+
#todo-box[习题]

src/basic/scripting-block-and-expression.typ

Lines changed: 92 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#show: book.page.with(title: "表达式")
44

5+
Typst中绝大部分语法结构都可作表达式,可以说学习完了所有表达式,则学会了Typst所有语法。当然,其吸取了一定历史经验,仅有少量的语句不是表达式。
6+
57
#pro-tip[
68
Typst借鉴了Rust,遵从「面向表达式编程」(expression-oriented programming)的哲学。它将所有的语句都根据可折叠规则(见后文)设计为表达式。
79
+ 如果一个语句能产生值,那么该语句的结果是按*控制流*顺序所产生所有值的折叠。
@@ -10,10 +12,6 @@
1012
$ forall v in T union {"none"}, op("fold")_T (v, "none") = v $
1113
]
1214

13-
== 表达式 <scripting-expression>
14-
15-
Typst中绝大部分语法结构都可作表达式,可以说学习完了所有表达式,则学会了Typst所有语法。当然,其吸取了一定历史经验,仅有少量的语句不是表达式。
16-
1715
#pro-tip[
1816
`show`语句和`set`语句不是表达式。
1917
]
@@ -25,11 +23,43 @@ Typst中绝大部分语法结构都可作表达式,可以说学习完了所有
2523
+ 赋值表达式。
2624
+ 项。
2725

28-
其中第五项又是一个大类。我们上一章所学的所有常量、变量以及变量的应用都是项。块表达式也是项,将在本节后半部分详细介绍。
26+
== 代数运算表达式 <grammar-arith-exp>
27+
28+
Typst支持对数字的算数运算,其中浮点运算遵守IEEE-754标准。整数和浮点数之间可以混合运算:
29+
30+
#code(```typ
31+
//加 减 乘 除
32+
#(1 + 2, 1.0 - 2, 1 * 2, 1 / 2 + 1)
33+
```)
34+
35+
从上可以看出,整数和整数运算尽可能*保持*整数,但是整数和浮点数运算则结果变为浮点数。除法运算的结果是浮点数。算数之间遵守四则运算规则。
36+
37+
#pro-tip[
38+
更高级的运算,例如数字的位运算和数值计算隐藏在类型的方法和`calc`标准库中:
39+
40+
#code(```typ
41+
#(0o755.bit-and(0o644)), // 8进制位运算
42+
#(calc.pow(9, 4)) // 9的4次方
43+
```)
44+
45+
请参考《》。
46+
]
47+
48+
除了数字运算,字符串、数组等还支持加法和乘法运算。它们的加法实际上是连接操作,它们的乘法则是重复元素的累加。
49+
50+
#code(```typ
51+
//乘 加
52+
#("1" * 2, "4" + "5", ) \
53+
#((1,) * 2, (4,) + (5,),)
54+
```)
55+
56+
字典只支持加法操作。若有重复键值对,则右侧列表的键值对会覆盖左侧列表的键值对。
57+
58+
#code(```typ
59+
#((a: 1) + (b: 2),
60+
(a: 1) + (b: 3, a: 2) + (a: 4 , c: 5))
61+
```)
2962

30-
== 计算标准库
31-
#todo-box[写完]
32-
请参见#link("https://typst.app/docs/reference/foundations/calc")[Typst Reference - Calculation]。
3363

3464
== 浮点数陷阱
3565

@@ -85,43 +115,6 @@ Typst中绝大部分语法结构都可作表达式,可以说学习完了所有
85115

86116
这些都是编程语言中的共通问题。凡是令数字保持有效精度,都会产生如上问题。
87117

88-
== 代数运算表达式 <grammar-arith-exp>
89-
90-
Typst支持对数字的算数运算,其中浮点运算遵守IEEE-754标准。整数和浮点数之间可以混合运算:
91-
92-
#code(```typ
93-
//加 减 乘 除
94-
#(1 + 2, 1.0 - 2, 1 * 2, 1 / 2 + 1)
95-
```)
96-
97-
从上可以看出,整数和整数运算尽可能*保持*整数,但是整数和浮点数运算则结果变为浮点数。除法运算的结果是浮点数。算数之间遵守四则运算规则。
98-
99-
#pro-tip[
100-
更高级的运算,例如数字的位运算和数值计算隐藏在类型的方法和`calc`标准库中:
101-
102-
#code(```typ
103-
#(0o755.bit-and(0o644)), // 8进制位运算
104-
#(calc.pow(9, 4)) // 9的4次方
105-
```)
106-
107-
请参考《》。
108-
]
109-
110-
除了数字运算,字符串、数组等还支持加法和乘法运算。它们的加法实际上是连接操作,它们的乘法则是重复元素的累加。
111-
112-
#code(```typ
113-
//乘 加
114-
#("1" * 2, "4" + "5", ) \
115-
#((1,) * 2, (4,) + (5,),)
116-
```)
117-
118-
字典只支持加法操作。若有重复键值对,则右侧列表的键值对会覆盖左侧列表的键值对。
119-
120-
#code(```typ
121-
#((a: 1) + (b: 2),
122-
(a: 1) + (b: 3, a: 2) + (a: 4 , c: 5))
123-
```)
124-
125118
== 逻辑比较表达式 <grammar-logical-cmp-exp>
126119

127120
有三大简单比较关系:
@@ -236,16 +229,56 @@ Typst支持对数字的算数运算,其中浮点运算遵守IEEE-754标准。
236229
#repr(a += 2), #a, #repr(a -= 2), #a, #repr(a *= 2), #a, #repr(a /= 2), #a
237230
```)
238231

232+
== 数组和字典的「解构赋值」
233+
234+
除了使用字面量「构造」元素,Typst还支持「构造」的反向操作:「解构赋值」。顾名思义,你可以在左侧用相似的语法从数组<grammar-destruct-array>或字典中获取值并赋值到*对应*的变量上。<grammar-destruct-dict>
235+
236+
#code(```typ
237+
#let (attr: a) = (attr: [kawaii\~])
238+
#a
239+
```)
240+
241+
「解构赋值」必须一一对应,但你也可以使用「占位符」(`_`)或「延展符」(`..`)以作*部分*解构:<grammar-destruct-array-eliminate>
242+
243+
#code(```typ
244+
#let (first, ..) = (1, 2, 3)
245+
#let (.., second-last, _) = (7, 8, 9, 10)
246+
#first, #second-last
247+
```)
248+
249+
数组的「解构赋值」有一个妙用,那就是重映射内容。<grammar-array-remapping>
250+
251+
#code(```typ
252+
#let (a, b, c) = (1, 2, 3)
253+
#let (b, c, a) = (a, b, c); #a, #b, #c
254+
```)
255+
256+
特别地,如果两个变量相互重映射,这种操作被称为「交换」:<grammar-array-swap>
257+
258+
#code(```typ
259+
#let (a, b) = (1, 2)
260+
#((a, b) = (b, a)); #a, #b
261+
```)
262+
263+
// field access
264+
// - dictionary
265+
// - symbol
266+
// - module
267+
// - content
268+
269+
=== 参数解构 <grammar-destructing-param>
270+
271+
#todo-box[写完]
272+
todo参数解构。
273+
239274
== 代码块 <grammar-code-block>
240275

241-
在Typst中,代码块和内容块是等同的。与「代码块」
276+
除了字面量,由于「面向表达式编程」,「代码块」也可以作为表达式的「项」。在Typst中,代码块和内容块是等同的。将「内容块」与「代码块」作比较:
242277

243278
- 代码块:按顺序包含一系列语句,内部为#term("code mode")。
244279
- 内容块:按顺序包含一系列内容,内部为#term("markup mode")。
245280

246-
内容块(标记模式)内部没有语句的概念,一个个内容或元素按顺序排列。但你可以通过#mark("#")将解释器的「解释模式」从「标记模式」*临时*改为「脚本模式」。当执行完脚本后,将脚本结果转换成内容,并放置在「井号」处。
247-
248-
相比,代码块内部则有语句概念。每个语句可以是换行分隔,也可以是#mark(";")分隔。
281+
内容块(标记模式)内部没有语句的概念,一个个内容或元素按顺序排列。相比,代码块内部则有语句概念。每个语句可以是换行分隔,也可以是#mark(";")分隔。
249282

250283
#code(```typ
251284
#{
@@ -255,6 +288,16 @@ Typst支持对数字的算数运算,其中浮点运算遵守IEEE-754标准。
255288
#{ "a"; "b" }
256289
```)
257290

291+
#pro-tip[
292+
公式块只是一种特殊的内容块,只不过其内容处于「数学模式」。对比:
293+
#code(```typ
294+
文本优先:#[ab] v.s. $#[a]#[b]$ \
295+
数学优先:#[$lambda$$(x)$] v.s. $lambda(x)$
296+
```)
297+
]
298+
299+
「代码块」和值(表达式)的关系与「控制流」息息相关。我们将会在下一节(todo:添加链接)详细介绍「控制流」。
300+
258301
// 整数转浮点数:<grammar-int-to-float>
259302

260303
// #code(```typ

src/basic/scripting-control-flow.typ

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@
22

33
#show: book.page.with(title: "控制流")
44

5-
#pro-tip[
6-
Typst借鉴了Rust,遵从「面向表达式编程」(expression-oriented programming)的哲学。它将所有的语句都根据可折叠规则(见后文)设计为表达式。
7-
+ 如果一个语句能产生值,那么该语句的结果是按*控制流*顺序所产生所有值的折叠。
8-
+ 否则,如果一个语句不能产生值,那么该语句的结果是```typc none```
9-
+ 特别地,任意类型 $T$ 的值 $v$```typc none```折叠仍然是值本身。
10-
$ forall v in T union {"none"}, op("fold")_T (v, "none") = v $
11-
]
12-
135
== `none`类型和`if`语句 <grammar-if>
146

157
默认情况下,在逻辑上,Typst按照顺序执行执行你的代码,即先执行前面的语句,再执行后面的语句。开发者如果想要控制程序执行的流程,就必须使用流程控制的语法结构,主要是条件执行和循环执行。

src/basic/scripting-destruct.typ

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)