Skip to content

Commit 17aa7f0

Browse files
committed
Implement and use aliases
1 parent 5d8c954 commit 17aa7f0

File tree

2 files changed

+116
-21
lines changed

2 files changed

+116
-21
lines changed

build.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::fmt::Write;
23
use std::iter::Peekable;
34
use std::path::Path;
@@ -24,6 +25,7 @@ enum Def<'a> {
2425
enum Symbol<'a> {
2526
Single(char),
2627
Multi(Vec<(&'a str, char)>),
28+
MultiAlias(Vec<(Cow<'a, str>, char)>),
2729
}
2830

2931
/// A single line during parsing.
@@ -34,6 +36,7 @@ enum Line<'a> {
3436
ModuleEnd,
3537
Symbol(&'a str, Option<char>),
3638
Variant(&'a str, char),
39+
Alias(&'a str, &'a str, &'a str, bool),
3740
}
3841

3942
fn main() {
@@ -102,6 +105,23 @@ fn tokenize(line: &str) -> StrResult<Line> {
102105
}
103106
let c = decode_char(tail.ok_or("missing char")?)?;
104107
Line::Variant(rest, c)
108+
} else if let Some(alias) = head.strip_prefix('@') {
109+
validate_ident(alias)?;
110+
let mut value = tail.ok_or("missing value")?;
111+
let mut deep = false;
112+
if let Some(v) = value.strip_suffix(".*") {
113+
deep = true;
114+
value = v;
115+
}
116+
let (head, rest) = value.split_once('.').unwrap_or((value, ""));
117+
validate_ident(head)?;
118+
if !rest.is_empty() {
119+
for part in rest.split('.') {
120+
validate_ident(part)?;
121+
}
122+
}
123+
124+
Line::Alias(alias, head, rest, deep)
105125
} else {
106126
validate_ident(head)?;
107127
let c = tail.map(decode_char).transpose()?;
@@ -139,9 +159,13 @@ fn parse<'a>(
139159
p: &mut Peekable<impl Iterator<Item = StrResult<Line<'a>>>>,
140160
) -> StrResult<Vec<(&'a str, Def<'a>)>> {
141161
let mut defs = vec![];
162+
let mut aliases = vec![];
142163
loop {
143164
match p.next().transpose()? {
144165
None | Some(Line::ModuleEnd) => break,
166+
Some(Line::Alias(alias, name, variant, deep)) => {
167+
aliases.push((alias, name, variant, deep));
168+
}
145169
Some(Line::Symbol(name, c)) => {
146170
let mut variants = vec![];
147171
while let Some(Line::Variant(name, c)) = p.peek().cloned().transpose()? {
@@ -169,6 +193,83 @@ fn parse<'a>(
169193
other => return Err(format!("expected definition, found {other:?}")),
170194
}
171195
}
196+
for (alias, name, variant, deep) in aliases {
197+
let aliased_symbol: &Symbol<'a> = defs
198+
.iter()
199+
.filter(|(n, _)| *n == name)
200+
.find_map(|(_, def)| match def {
201+
Def::Symbol(s) => Some(s),
202+
_ => None,
203+
})
204+
.ok_or_else(|| format!("alias to nonexistent symbol: {name}"))?;
205+
206+
match aliased_symbol {
207+
&Symbol::Single(c) => {
208+
if variant != "" {
209+
return Err(format!(
210+
"alias to nonexistent variant: {name}.{variant}"
211+
));
212+
}
213+
defs.push((alias, Def::Symbol(Symbol::Single(c))));
214+
}
215+
Symbol::MultiAlias(_) => {
216+
return Err(format!("alias to alias: {name}.{variant}"));
217+
}
218+
Symbol::Multi(variants) => {
219+
let variants: Vec<(Cow<'a, str>, char)> = variants
220+
.iter()
221+
.filter_map(|&(var, c)| {
222+
if var == variant {
223+
Some((Cow::Borrowed(""), c))
224+
} else if deep {
225+
var.strip_prefix(variant)?
226+
.strip_prefix('.')
227+
.map(|v| (Cow::Borrowed(v), c))
228+
.or_else(|| {
229+
// might just be in a different order
230+
231+
let mut alias_modifs = if variant.is_empty() {
232+
vec![]
233+
} else {
234+
variant.split('.').collect()
235+
};
236+
237+
let mut new_variant = Cow::Borrowed("");
238+
for modif in var.split('.') {
239+
if let Some(i) =
240+
alias_modifs.iter().position(|m| *m == modif)
241+
{
242+
alias_modifs.swap_remove(i);
243+
} else if new_variant.is_empty() {
244+
new_variant = Cow::Borrowed(modif);
245+
} else {
246+
new_variant = Cow::Owned(format!(
247+
"{new_variant}.{modif}"
248+
));
249+
}
250+
}
251+
alias_modifs.is_empty().then_some((new_variant, c))
252+
})
253+
} else {
254+
None
255+
}
256+
})
257+
.collect();
258+
if variants.is_empty() {
259+
return Err(format!(
260+
"alias to nonexistent variant: {name}.{variant}"
261+
));
262+
}
263+
if let [(ref s, c)] = variants[..] {
264+
if s.is_empty() {
265+
defs.push((alias, Def::Symbol(Symbol::Single(c))));
266+
continue;
267+
}
268+
}
269+
defs.push((alias, Def::Symbol(Symbol::MultiAlias(variants))));
270+
}
271+
}
272+
}
172273
Ok(defs)
173274
}
174275

@@ -188,6 +289,7 @@ fn encode(buf: &mut String, module: &Module) {
188289
match symbol {
189290
Symbol::Single(c) => write!(buf, "Single({c:?})").unwrap(),
190291
Symbol::Multi(list) => write!(buf, "Multi(&{list:?})").unwrap(),
292+
Symbol::MultiAlias(list) => write!(buf, "Multi(&{list:?})").unwrap(),
191293
}
192294
buf.push_str(")");
193295
}

src/modules/sym.txt

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ breve ˘
193193
caret ‸
194194
caron ˇ
195195
hat ^
196-
diaer ¨
196+
@diaer dot.double
197197
grave `
198198
macron ¯
199199
quote
@@ -359,8 +359,7 @@ succ ≻
359359
.not ⊁
360360
.ntilde ⋩
361361
.tilde ≿
362-
equiv ≡
363-
.not ≢
362+
@equiv eq.triple.*
364363
smt ⪪
365364
.eq ⪬
366365
lat ⪫
@@ -378,12 +377,7 @@ emptyset ∅
378377
.bar ⦱
379378
.circle ⦲
380379
.rev ⦰
381-
nothing ∅
382-
.arrow.r ⦳
383-
.arrow.l ⦴
384-
.bar ⦱
385-
.circle ⦲
386-
.rev ⦰
380+
@nothing emptyset.*
387381
without ∖
388382
complement ∁
389383
in ∈
@@ -441,10 +435,10 @@ infinity ∞
441435
.bar ⧞
442436
.incomplete ⧜
443437
.tie ⧝
444-
oo
438+
@oo infinity
445439
partial ∂
446440
gradient ∇
447-
nabla
441+
@nabla gradient.*
448442
sum ∑
449443
.integral ⨋
450444
product ∏
@@ -474,8 +468,8 @@ laplace ∆
474468
forall ∀
475469
exists ∃
476470
.not ∄
477-
top
478-
bot
471+
@top tack.b
472+
@bot tack.t
479473
not ¬
480474
and ∧
481475
.big ⋀
@@ -487,8 +481,7 @@ or ∨
487481
.curly ⋎
488482
.dot ⟇
489483
.double ⩔
490-
xor ⊕
491-
.big ⨁
484+
@xor plus.circle.*
492485
models ⊧
493486
forces ⊩
494487
.not ⊮
@@ -497,8 +490,8 @@ because ∵
497490
qed ∎
498491

499492
// Function and category theory.
500-
compose
501-
convolve
493+
@compose circle.stroked.tiny
494+
@convolve ast.op
502495
multimap ⊸
503496
.double ⧟
504497

@@ -987,13 +980,13 @@ Zeta Ζ
987980
// from Letterlike Symbols.
988981
// See https://github.com/typst/typst/pull/3375.
989982
aleph א
990-
alef א
983+
@alef aleph
991984
beth ב
992-
bet ב
985+
@bet beth
993986
gimmel ג
994-
gimel ג
987+
@gimel gimmel
995988
daleth ד
996-
dalet ד
989+
@dalet daleth
997990
shin ש
998991

999992
// Double-struck.

0 commit comments

Comments
 (0)