Merge text and math symbols

This commit is contained in:
Laurenz 2023-02-02 18:09:13 +01:00
parent e9ff2d6463
commit 10675cd6d5
18 changed files with 2325 additions and 2293 deletions

View File

@ -7,6 +7,7 @@ pub mod math;
pub mod meta; pub mod meta;
pub mod prelude; pub mod prelude;
pub mod shared; pub mod shared;
pub mod symbols;
pub mod text; pub mod text;
pub mod visualize; pub mod visualize;
@ -17,15 +18,14 @@ use self::layout::LayoutRoot;
/// Construct the standard library. /// Construct the standard library.
pub fn build() -> Library { pub fn build() -> Library {
let sym = text::sym(); let math = math::module();
let math = math::module(&sym);
let calc = compute::calc(); let calc = compute::calc();
let global = global(sym, math.clone(), calc); let global = global(math.clone(), calc);
Library { global, math, styles: styles(), items: items() } Library { global, math, styles: styles(), items: items() }
} }
/// Construct the module with global definitions. /// Construct the module with global definitions.
fn global(sym: Module, math: Module, calc: Module) -> Module { fn global(math: Module, calc: Module) -> Module {
let mut global = Scope::deduplicating(); let mut global = Scope::deduplicating();
// Basics. // Basics.
@ -50,8 +50,6 @@ fn global(sym: Module, math: Module, calc: Module) -> Module {
global.def_func::<text::StrikeNode>("strike"); global.def_func::<text::StrikeNode>("strike");
global.def_func::<text::OverlineNode>("overline"); global.def_func::<text::OverlineNode>("overline");
global.def_func::<text::RawNode>("raw"); global.def_func::<text::RawNode>("raw");
global.define("sym", sym);
global.define("emoji", text::emoji());
// Math. // Math.
global.define("math", math); global.define("math", math);
@ -92,6 +90,10 @@ fn global(sym: Module, math: Module, calc: Module) -> Module {
global.def_func::<meta::LinkNode>("link"); global.def_func::<meta::LinkNode>("link");
global.def_func::<meta::OutlineNode>("outline"); global.def_func::<meta::OutlineNode>("outline");
// Symbols.
global.define("sym", symbols::sym());
global.define("emoji", symbols::emoji());
// Compute. // Compute.
global.def_func::<compute::TypeFunc>("type"); global.def_func::<compute::TypeFunc>("type");
global.def_func::<compute::ReprFunc>("repr"); global.def_func::<compute::ReprFunc>("repr");

View File

@ -15,7 +15,6 @@ mod row;
mod spacing; mod spacing;
mod stretch; mod stretch;
mod style; mod style;
mod symbols;
mod underover; mod underover;
pub use self::accent::*; pub use self::accent::*;
@ -46,7 +45,7 @@ use crate::text::{
}; };
/// Create a module with all math definitions. /// Create a module with all math definitions.
pub fn module(sym: &Module) -> Module { pub fn module() -> Module {
let mut math = Scope::deduplicating(); let mut math = Scope::deduplicating();
math.def_func::<FormulaNode>("formula"); math.def_func::<FormulaNode>("formula");
math.def_func::<TextNode>("text"); math.def_func::<TextNode>("text");
@ -96,10 +95,13 @@ pub fn module(sym: &Module) -> Module {
math.def_func::<OpNode>("op"); math.def_func::<OpNode>("op");
op::define(&mut math); op::define(&mut math);
// Symbols and spacing. // Spacings.
symbols::define(&mut math);
spacing::define(&mut math); spacing::define(&mut math);
math.copy_from(sym.scope());
// Symbols.
for (name, symbol) in crate::symbols::SYM {
math.define(*name, symbol.clone());
}
Module::new("math").with_scope(math) Module::new("math").with_scope(math)
} }

View File

@ -443,6 +443,10 @@ pub(super) fn styled_char(style: MathStyle, c: char) -> char {
'∂' | 'ϵ' | 'ϑ' | 'ϰ' | 'ϕ' | 'ϱ' | 'ϖ' '∂' | 'ϵ' | 'ϑ' | 'ϰ' | 'ϕ' | 'ϱ' | 'ϖ'
)); ));
if let Some(c) = basic_exception(c) {
return c;
}
if let Some(c) = latin_exception(c, variant, bold, italic) { if let Some(c) = latin_exception(c, variant, bold, italic) {
return c; return c;
} }
@ -537,6 +541,16 @@ pub(super) fn styled_char(style: MathStyle, c: char) -> char {
std::char::from_u32(start + (c as u32 - base as u32)).unwrap() std::char::from_u32(start + (c as u32 - base as u32)).unwrap()
} }
fn basic_exception(c: char) -> Option<char> {
Some(match c {
'〈' => '⟨',
'〉' => '⟩',
'《' => '⟪',
'》' => '⟫',
_ => return None,
})
}
fn latin_exception( fn latin_exception(
c: char, c: char,
variant: MathVariant, variant: MathVariant,

View File

@ -1,426 +0,0 @@
use typst::model::symbols;
symbols! {
define,
// Lowercase Greek.
alpha: 'α',
beta: ['β', "alt": 'ϐ'],
chi: 'χ',
delta: 'δ',
epsilon: ['ε', "alt": 'ϵ'],
eta: 'η',
gamma: 'γ',
iota: 'ι',
kai: 'ϗ',
kappa: ['κ', "alt": 'ϰ'],
lambda: 'λ',
mu: 'μ',
nu: 'ν',
ohm: ['Ω', "inv": ''],
omega: 'ω',
omicron: 'ο',
phi: ['φ', "alt": 'ϕ'],
pi: ['π', "alt": 'ϖ'],
psi: 'ψ',
rho: ['ρ', "alt": 'ϱ'],
sigma: 'σ',
tau: 'τ',
theta: ['θ', "alt": 'ϑ'],
upsilon: 'υ',
xi: 'ξ',
zeta: 'ζ',
// Uppercase Greek.
Alpha: 'Α',
Beta: 'Β',
Chi: 'Χ',
Delta: 'Δ',
Epsilon: 'Ε',
Eta: 'Η',
Gamma: 'Γ',
Iota: 'Ι',
Kai: 'Ϗ',
Kappa: 'Κ',
Lambda: 'Λ',
Mu: 'Μ',
Nu: 'Ν',
Omega: 'Ω',
Omicron: 'Ο',
Phi: 'Φ',
Pi: 'Π',
Psi: 'Ψ',
Rho: 'Ρ',
Sigma: 'Σ',
Tau: 'Τ',
Theta: 'Θ',
Upsilon: 'Υ',
Xi: 'Ξ',
Zeta: 'Ζ',
// Hebrew.
alef: 'א',
bet: 'ב',
gimel: 'ג',
shin: 'ש',
// Double-struck.
AA: '𝔸',
BB: '𝔹',
CC: '',
DD: '𝔻',
EE: '𝔼',
FF: '𝔽',
GG: '𝔾',
HH: '',
II: '𝕀',
JJ: '𝕁',
KK: '𝕂',
LL: '𝕃',
MM: '𝕄',
NN: '',
OO: '𝕆',
PP: '',
QQ: '',
RR: '',
SS: '𝕊',
TT: '𝕋',
UU: '𝕌',
VV: '𝕍',
WW: '𝕎',
XX: '𝕏',
YY: '𝕐',
ZZ: '',
// Override.
angled: [
"l": '',
"l.double": '',
"r": '',
"r.double": '',
],
// Operators.
plus: [
'+',
"circle": '',
"circle.arrow": '',
"circle.big": '',
"dot": '',
"minus": '±',
"small": '',
"square": '',
"triangle": '',
],
minus: [
'',
"circle": '',
"dot": '',
"plus": '',
"square": '',
"tilde": '',
"triangle": '',
],
dot: [
'⋅',
"circle": '',
"circle.big": '',
"square": '',
],
div: [
'',
"circle": '',
"sign": '÷',
"sign.circle": '',
],
times: [
'×',
"big": '',
"circle": '',
"circle.big": '',
"div": '',
"l": '',
"r": '',
"square": '',
"triangle": '',
],
ast: [
'',
"circle": '',
"small": '',
"sq": '',
],
star: '',
smash: '',
wreath: '',
// Relations.
eq: [
'=',
"ast": '',
"circle": '',
"colon": '',
"def": '',
"delta": '',
"equi": '',
"est": '',
"gt": '',
"lt": '',
"m": '',
"not": '',
"prec": '',
"quest": '',
"small": '',
"succ": '',
],
gt: [
'>',
"circle": '',
"dot": '',
"double": '',
"eq": '',
"eq.lt": '',
"eq.not": '',
"eqq": '',
"lt": '',
"lt.not": '',
"neqq": '',
"not": '',
"ntilde": '',
"small": '',
"tilde": '',
"tilde.not": '',
"triple": '',
"triple.nested": '',
],
lt: [
'<',
"circle": '',
"dot": '',
"double": '',
"eq": '',
"eq.gt": '',
"eq.not": '',
"eqq": '',
"gt": '',
"gt.not": '',
"neqq": '',
"not": '',
"ntilde": '',
"small": '',
"tilde": '',
"tilde.not": '',
"triple": '',
"triple.nested": '',
],
prec: [
'≺',
"approx": '',
"double": '',
"eq": '',
"eq.not": '',
"eqq": '',
"napprox": '',
"neqq": '',
"not": '',
"ntilde": '',
"tilde": '',
],
succ: [
'≻',
"approx": '',
"double": '',
"eq": '',
"eq.not": '',
"eqq": '',
"napprox": '',
"neqq": '',
"not": '',
"ntilde": '',
"tilde": '',
],
ident: ['≡', "not": '', "strict": ''],
approx: ['≈', "eq": '', "not": ''],
tilde: [
'',
"eq": '',
"eq.not": '',
"eq.rev": '',
"eqq": '',
"eqq.not": '',
"neqq": '',
"not": '',
"rev": '',
"rev.eqq": '',
"triple": '',
],
// Set theory.
nothing: ['∅', "rev": ''],
in: [
'∈',
"not": '',
"rev": '',
"rev.not": '',
"rev.small": '',
"small": '',
],
subset: [
'⊂',
"dot": '',
"double": '',
"eq": '',
"eq.not": '',
"eq.sq": '',
"eq.sq.not": '',
"neq": '',
"not": '',
"sq": '',
"sq.neq": '',
],
supset: [
'⊃',
"dot": '',
"double": '',
"eq": '',
"eq.not": '',
"eq.sq": '',
"eq.sq.not": '',
"neq": '',
"not": '',
"sq": '',
"sq.neq": '',
],
union: [
'',
"arrow": '',
"big": '',
"dot": '',
"dot.big": '',
"double": '',
"minus": '',
"or": '',
"plus": '',
"plus.big": '',
"sq": '',
"sq.big": '',
"sq.double": '',
],
sect: [
'∩',
"and": '',
"big": '',
"dot": '',
"double": '',
"sq": '',
"sq.big": '',
"sq.double": '',
],
without: '',
complement: '',
// Relational algebra.
join: [
'⨝',
"r": '',
"l": '',
"l.r": '',
],
// Logic.
forall: '',
exists: ['∃', "not": ''],
top: '',
bot: '',
not: '¬',
and: [
'∧',
"big": '',
"curly": '',
"dot": '',
"double": '',
],
or: [
'',
"big": '',
"curly": '',
"dot": '',
"double": '',
],
models: '',
therefore: '',
because: '',
qed: '',
tack: [
"r": '',
"r.long": '',
"l": '',
"l.long": '',
"l.short": '',
"t": '',
"t.big": '',
"t.double": '',
"t.short": '',
"b": '',
"b.big": '',
"b.double": '',
"b.short": '',
"l.r": '',
],
// Geometry.
perp: ['⟂', "circle": ''],
parallel: ['∥', "circle": '', "not": ''],
angle: [
'∠',
"acute": '',
"arc": '',
"arc.rev": '',
"rev": '',
"right": '',
"right.rev": '',
"right.arc": '',
"right.dot": '',
"right.sq": '',
"spatial": '',
"spheric": '',
"spheric.rev": '',
"spheric.top": '',
],
// Analysis.
infty: '',
sum: ['∑', "integral": ''],
prod: ['∏', "co": ''],
integral: [
'∫',
"arrow.hook": '',
"ccw": '',
"cont": '',
"cont.ccw": '',
"cont.cw": '',
"cw": '',
"double": '',
"quad": '',
"sect": '',
"sq": '',
"surf": '',
"times": '',
"triple": '',
"union": '',
"vol": '',
],
prop: '',
divides: ['', "not": ''],
compose: '',
// Miscellaneous.
diff: '',
nabla: '',
kelvin: '',
micro: 'µ',
degree: ['°', "c": '', "f": ''],
planck: ['', "reduce": ''],
angstrom: '',
diameter: '',
}

1356
library/src/symbols/emoji.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
//! Modifiable symbols.
mod emoji;
mod sym;
pub use emoji::*;
pub use sym::*;

808
library/src/symbols/sym.rs Normal file
View File

@ -0,0 +1,808 @@
use typst::model::{symbols, Module, Scope, Symbol};
/// A module with all general symbols.
pub fn sym() -> Module {
let mut scope = Scope::new();
for (name, symbol) in SYM {
scope.define(*name, symbol.clone());
}
Module::new("sym").with_scope(scope)
}
/// The list of general symbols.
pub(crate) const SYM: &[(&'static str, Symbol)] = symbols! {
// Control.
wj: '\u{2060}',
zwj: '\u{200D}',
zwnj: '\u{200C}',
zws: '\u{200B}',
// Spaces.
space: [
' ',
nobreak: '\u{A0}',
en: '\u{2002}',
quad: '\u{2003}',
third: '\u{2004}',
quarter: '\u{2005}',
sixth: '\u{2006}',
med: '\u{205F}',
fig: '\u{2007}',
punct: '\u{2008}',
thin: '\u{2009}',
hair: '\u{200A}',
],
// Delimiters.
paren: [l: '(', r: ')', t: '', b: ''],
brace: [l: '{', r: '}', t: '', b: ''],
bracket: [l: '[', r: ']', t: '', b: ''],
turtle: [l: '', r: '', t: '', b: ''],
bar: [v: '|', v.double: '', v.triple: '', v.broken: '¦', v.circle: '', h: ''],
fence: [l: '', l.double: '', r: '', r.double: '', dotted: ''],
angle: [
'∠',
l: '',
r: '',
l.double: '',
r.double: '',
acute: '',
arc: '',
arc.rev: '',
rev: '',
right: '',
right.rev: '',
right.arc: '',
right.dot: '',
right.sq: '',
spatial: '',
spheric: '',
spheric.rev: '',
spheric.top: '',
],
// Punctuation.
amp: ['&', inv: ''],
ast: [
'*',
low: '',
double: '',
triple: '',
small: '',
op: '',
circle: '',
sq: '',
],
at: '@',
backslash: ['\\', circle: '', not: ''],
co: '',
colon: [':', eq: '', double.eq: ''],
comma: ',',
dagger: ['†', double: ''],
dash: [
en: '',
em: '',
fig: '',
wave: '',
colon: '',
circle: '',
wave.double: '',
],
dot: ['.', op: '', c: '·', circle: '', circle.big: '', square: ''],
excl: ['!', double: '', inv: '¡', quest: ''],
quest: ['?', double: '', excl: '', inv: '¿'],
interrobang: '',
hash: '#',
hyph: ['', minus: '\u{2D}', nobreak: '\u{2011}', point: '', soft: '\u{ad}'],
percent: '%',
copyright: ['©', sound: ''],
permille: '',
pilcrow: ['¶', rev: ''],
section: '§',
semi: [';', rev: ''],
slash: ['/', double: '', triple: ''],
dots: [h: '', h.c: '', v: '', down: '', up: ''],
tilde: [
'~',
op: '',
eq: '',
eq.not: '',
eq.rev: '',
eqq: '',
eqq.not: '',
neqq: '',
not: '',
rev: '',
rev.eqq: '',
triple: '',
],
// Accents, quotes, and primes.
acute: ['´', double: '˝'],
breve: '˘',
caret: '',
caron: 'ˇ',
hat: '^',
diaer: '¨',
grave: '`',
macron: '¯',
quote: [
double: '"',
single: '\'',
l.double: '',
l.single: '',
r.double: '',
r.single: '',
angle.l.double: '«',
angle.l.single: '',
angle.r.double: '»',
angle.r.single: '',
high.double: '',
high.single: '',
low.double: '',
low.single: '',
],
prime: [
'',
rev: '',
double: '',
double.rev: '',
triple: '',
triple.rev: '',
quad: '',
],
// https://en.wikipedia.org/wiki/List_of_mathematical_symbols_by_subject
// Arithmetic.
plus: [
'+',
circle: '',
circle.arrow: '',
circle.big: '',
dot: '',
minus: '±',
small: '',
square: '',
triangle: '',
],
minus: [
'',
circle: '',
dot: '',
plus: '',
square: '',
tilde: '',
triangle: '',
],
div: ['÷', circle: ''],
times: [
'×',
big: '',
circle: '',
circle.big: '',
div: '',
l: '',
r: '',
square: '',
triangle: '',
],
ratio: '',
// Relations.
eq: [
'=',
star: '',
circle: '',
colon: '',
def: '',
delta: '',
equi: '',
est: '',
gt: '',
lt: '',
m: '',
not: '',
prec: '',
quest: '',
small: '',
succ: '',
],
gt: [
'>',
circle: '',
dot: '',
double: '',
eq: '',
eq.lt: '',
eq.not: '',
eqq: '',
lt: '',
lt.not: '',
neqq: '',
not: '',
ntilde: '',
small: '',
tilde: '',
tilde.not: '',
triple: '',
triple.nested: '',
],
lt: [
'<',
circle: '',
dot: '',
double: '',
eq: '',
eq.gt: '',
eq.not: '',
eqq: '',
gt: '',
gt.not: '',
neqq: '',
not: '',
ntilde: '',
small: '',
tilde: '',
tilde.not: '',
triple: '',
triple.nested: '',
],
approx: ['≈', eq: '', not: ''],
prec: [
'≺',
approx: '',
double: '',
eq: '',
eq.not: '',
eqq: '',
napprox: '',
neqq: '',
not: '',
ntilde: '',
tilde: '',
],
succ: [
'≻',
approx: '',
double: '',
eq: '',
eq.not: '',
eqq: '',
napprox: '',
neqq: '',
not: '',
ntilde: '',
tilde: '',
],
ident: ['≡', not: '', strict: ''],
prop: '',
// Set theory.
nothing: ['∅', rev: ''],
without: '',
complement: '',
in: [
'∈',
not: '',
rev: '',
rev.not: '',
rev.small: '',
small: '',
],
subset: [
'⊂',
dot: '',
double: '',
eq: '',
eq.not: '',
eq.sq: '',
eq.sq.not: '',
neq: '',
not: '',
sq: '',
sq.neq: '',
],
supset: [
'⊃',
dot: '',
double: '',
eq: '',
eq.not: '',
eq.sq: '',
eq.sq.not: '',
neq: '',
not: '',
sq: '',
sq.neq: '',
],
union: [
'',
arrow: '',
big: '',
dot: '',
dot.big: '',
double: '',
minus: '',
or: '',
plus: '',
plus.big: '',
sq: '',
sq.big: '',
sq.double: '',
],
sect: [
'∩',
and: '',
big: '',
dot: '',
double: '',
sq: '',
sq.big: '',
sq.double: '',
],
// Calculus.
infty: '',
diff: '',
nabla: '',
sum: ['∑', integral: ''],
product: ['∏', co: ''],
integral: [
'∫',
arrow.hook: '',
ccw: '',
cont: '',
cont.ccw: '',
cont.cw: '',
cw: '',
double: '',
quad: '',
sect: '',
sq: '',
surf: '',
times: '',
triple: '',
union: '',
vol: '',
],
// Logic.
forall: '',
exists: ['∃', not: ''],
top: '',
bot: '',
not: '¬',
and: ['∧', big: '', curly: '', dot: '', double: ''],
or: ['', big: '', curly: '', dot: '', double: ''],
models: '',
therefore: '',
because: '',
qed: '',
// Function and category theory.
compose: '',
convolve: '',
multimap: '',
// Number theory.
divides: ['', not: ''],
perp: ['⟂', circle: ''],
// Geometry.
parallel: ['∥', circle: '', not: ''],
// Miscellaneous Technical.
diameter: '',
join: ['⨝', r: '', l: '', l.r: ''],
degree: ['°', c: '', f: ''],
smash: '',
wreath: '',
// Currency.
bitcoin: '',
dollar: '$',
euro: '',
franc: '',
lira: '',
peso: '',
pound: '£',
ruble: '',
rupee: '',
won: '',
yen: '¥',
// Miscellaneous.
ballot: ['☐', x: ''],
checkmark: ['✓', light: '🗸'],
floral: ['❦', l: '', r: ''],
notes: [up: '🎜', down: '🎝'],
refmark: '',
servicemark: '',
maltese: '',
suit: [club: '', diamond: '', heart: '', spade: ''],
// Shapes.
circle: [
stroked: '',
stroked.tiny: '',
stroked.small: '',
stroked.big: '',
filled: '',
filled.tiny: '',
filled.small: '',
filled.big: '',
dotted: '',
nested: '',
],
ellipse: [
stroked.h: '',
stroked.v: '',
filled.h: '',
filled.v: '',
],
triangle: [
stroked.r: '',
stroked.l: '',
stroked.t: '',
stroked.b: '',
stroked.bl: '',
stroked.br: '',
stroked.tl: '',
stroked.tr: '',
stroked.small.r: '',
stroked.small.b: '',
stroked.small.l: '',
stroked.small.t: '',
stroked.rounded: '🛆',
stroked.nested: '',
stroked.dot: '',
filled.r: '',
filled.l: '',
filled.t: '',
filled.b: '',
filled.bl: '',
filled.br: '',
filled.tl: '',
filled.tr: '',
filled.small.r: '',
filled.small.b: '',
filled.small.l: '',
filled.small.t: '',
],
square: [
stroked: '',
stroked.tiny: '',
stroked.small: '',
stroked.medium: '',
stroked.big: '',
stroked.dotted: '',
stroked.rounded: '',
filled: '',
filled.tiny: '',
filled.small: '',
filled.medium: '',
filled.big: '',
],
rect: [
stroked.h: '',
stroked.v: '',
filled.h: '',
filled.v: '',
],
penta: [stroked: '', filled: ''],
hexa: [stroked: '', filled: ''],
diamond: [
stroked: '',
stroked.small: '',
stroked.medium: '',
stroked.dot: '',
filled: '',
filled.medium: '',
filled.small: '',
],
lozenge: [
stroked: '',
stroked.small: '',
stroked.medium: '',
filled: '',
filled.small: '',
filled.medium: '',
],
star: [op: '', stroked: '', filled: ''],
// Arrows, harpoons, and tacks.
arrow: [
r: '',
r.long.bar: '',
r.bar: '',
r.curve: '',
r.dashed: '',
r.dotted: '',
r.double: '',
r.double.bar: '',
r.double.long: '',
r.double.long.bar: '',
r.double.not: '',
r.filled: '',
r.hook: '',
r.long: '',
r.long.squiggly: '',
r.loop: '',
r.not: '',
r.quad: '',
r.squiggly: '',
r.stop: '',
r.stroked: '',
r.tail: '',
r.triple: '',
r.twohead.bar: '',
r.twohead: '',
r.wave: '',
l: '',
l.bar: '',
l.curve: '',
l.dashed: '',
l.dotted: '',
l.double: '',
l.double.bar: '',
l.double.long: '',
l.double.long.bar: '',
l.double.not: '',
l.filled: '',
l.hook: '',
l.long: '',
l.long.bar: '',
l.long.squiggly: '',
l.loop: '',
l.not: '',
l.quad: '',
l.squiggly: '',
l.stop: '',
l.stroked: '',
l.tail: '',
l.triple: '',
l.twohead.bar: '',
l.twohead: '',
l.wave: '',
t: '',
t.bar: '',
t.curve: '',
t.dashed: '',
t.double: '',
t.filled: '',
t.quad: '',
t.stop: '',
t.stroked: '',
t.triple: '',
t.twohead: '',
b: '',
b.bar: '',
b.curve: '',
b.dashed: '',
b.double: '',
b.filled: '',
b.quad: '',
b.stop: '',
b.stroked: '',
b.triple: '',
b.twohead: '',
l.r: '',
l.r.double: '',
l.r.double.long: '',
l.r.double.not: '',
l.r.filled: '',
l.r.long: '',
l.r.not: '',
l.r.stroked: '',
l.r.wave: '',
t.b: '',
t.b.double: '',
t.b.filled: '',
t.b.stroked: '',
tr: '',
tr.double: '',
tr.filled: '',
tr.hook: '',
tr.stroked: '',
br: '',
br.double: '',
br.filled: '',
br.hook: '',
br.stroked: '',
tl: '',
tl.double: '',
tl.filled: '',
tl.hook: '',
tl.stroked: '',
bl: '',
bl.double: '',
bl.filled: '',
bl.hook: '',
bl.stroked: '',
tl.br: '',
tr.bl: '',
ccw: '',
ccw.half: '',
cw: '',
cw.half: '',
zigzag: '',
],
arrows: [
rr: '',
ll: '',
tt: '',
bb: '',
lr: '',
lr.stop: '',
rl: '',
tb: '',
bt: '',
rrr: '',
lll: '',
],
arrowhead: [
t: '',
b: '',
],
harpoon: [
rt: '',
rt.bar: '',
rt.stop: '',
rb: '',
rb.bar: '',
rb.stop: '',
lt: '',
lt.bar: '',
lt.stop: '',
lb: '',
lb.bar: '',
lb.stop: '',
tl: '',
tl.bar: '',
tl.stop: '',
tr: '',
tr.bar: '',
tr.stop: '',
bl: '',
bl.bar: '',
bl.stop: '',
br: '',
br.bar: '',
br.stop: '',
lt.rt: '',
lb.rb: '',
lb.rt: '',
lt.rb: '',
tl.bl: '',
tr.br: '',
tl.br: '',
tr.bl: '',
],
harpoons: [
rtrb: '',
blbr: '',
bltr: '',
lbrb: '',
ltlb: '',
ltrb: '',
ltrt: '',
rblb: '',
rtlb: '',
rtlt: '',
tlbr: '',
tltr: '',
],
tack: [
r: '',
r.long: '',
l: '',
l.long: '',
l.short: '',
t: '',
t.big: '',
t.double: '',
t.short: '',
b: '',
b.big: '',
b.double: '',
b.short: '',
l.r: '',
],
// Lowercase Greek.
alpha: 'α',
beta: ['β', alt: 'ϐ'],
chi: 'χ',
delta: 'δ',
epsilon: ['ε', alt: 'ϵ'],
eta: 'η',
gamma: 'γ',
iota: 'ι',
kai: 'ϗ',
kappa: ['κ', alt: 'ϰ'],
lambda: 'λ',
mu: 'μ',
nu: 'ν',
ohm: ['Ω', inv: ''],
omega: 'ω',
omicron: 'ο',
phi: ['φ', alt: 'ϕ'],
pi: ['π', alt: 'ϖ'],
psi: 'ψ',
rho: ['ρ', alt: 'ϱ'],
sigma: 'σ',
tau: 'τ',
theta: ['θ', alt: 'ϑ'],
upsilon: 'υ',
xi: 'ξ',
zeta: 'ζ',
// Uppercase Greek.
Alpha: 'Α',
Beta: 'Β',
Chi: 'Χ',
Delta: 'Δ',
Epsilon: 'Ε',
Eta: 'Η',
Gamma: 'Γ',
Iota: 'Ι',
Kai: 'Ϗ',
Kappa: 'Κ',
Lambda: 'Λ',
Mu: 'Μ',
Nu: 'Ν',
Omega: 'Ω',
Omicron: 'Ο',
Phi: 'Φ',
Pi: 'Π',
Psi: 'Ψ',
Rho: 'Ρ',
Sigma: 'Σ',
Tau: 'Τ',
Theta: 'Θ',
Upsilon: 'Υ',
Xi: 'Ξ',
Zeta: 'Ζ',
// Hebrew.
alef: 'א',
bet: 'ב',
gimel: 'ג',
shin: 'ש',
// Double-struck.
AA: '𝔸',
BB: '𝔹',
CC: '',
DD: '𝔻',
EE: '𝔼',
FF: '𝔽',
GG: '𝔾',
HH: '',
II: '𝕀',
JJ: '𝕁',
KK: '𝕂',
LL: '𝕃',
MM: '𝕄',
NN: '',
OO: '𝕆',
PP: '',
QQ: '',
RR: '',
SS: '𝕊',
TT: '𝕋',
UU: '𝕌',
VV: '𝕍',
WW: '𝕎',
XX: '𝕏',
YY: '𝕐',
ZZ: '',
// Miscellaneous letter-likes.
ell: '',
planck: ['', reduce: ''],
angstrom: '',
kelvin: '',
Re: '',
Im: '',
};

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,18 @@
//! Text handling. //! Text handling.
mod deco; mod deco;
mod emoji;
mod misc; mod misc;
mod quotes; mod quotes;
mod raw; mod raw;
mod shaping; mod shaping;
mod shift; mod shift;
mod symbols;
pub use self::deco::*; pub use self::deco::*;
pub use self::emoji::*;
pub use self::misc::*; pub use self::misc::*;
pub use self::quotes::*; pub use self::quotes::*;
pub use self::raw::*; pub use self::raw::*;
pub use self::shaping::*; pub use self::shaping::*;
pub use self::shift::*; pub use self::shift::*;
pub use self::symbols::*;
use std::borrow::Cow; use std::borrow::Cow;

View File

@ -1,458 +0,0 @@
use typst::model::{symbols, Module, Scope};
/// A module with all symbols.
pub fn sym() -> Module {
let mut scope = Scope::new();
define(&mut scope);
Module::new("sym").with_scope(scope)
}
symbols! {
define,
// Space and control.
space: [
' ',
"em": '\u{2003}',
"en": '\u{2002}',
"fig": '\u{2007}',
"hair": '\u{200A}',
"ideo": '\u{3000}',
"nobreak": '\u{A0}',
"punct": '\u{2008}',
"quarter": '\u{2005}',
"sixth": '\u{2006}',
"thin": '\u{2009}',
"third": '\u{2004}',
],
wj: '\u{2060}',
zwj: '\u{200D}',
zwnj: '\u{200C}',
zws: '\u{200B}',
// Punctuation.
dot: ['.', "c": '·'],
dots: [
"h": '',
"h.c": '',
"v": '',
"down": '',
"up": '',
],
colon: [
':',
"eq": '',
"double.eq": '',
],
comma: ',',
semi: [';', "rev": ''],
quest: ['?', "double": '', "excl": '', "inv": '¿'],
excl: ['!', "double": '', "inv": '¡', "quest": ''],
interrobang: '',
hash: '#',
at: '@',
section: '§',
percent: '%',
permille: '',
co: '',
pilcrow: ['¶', "rev": ''],
dagger: ['†', "double": ''],
slash: ['/', "double": '', "triple": ''],
backslash: ['\\', "circle": '', "not": ''],
ast: ['*', "low": '', "double": '', "triple": ''],
amp: ['&', "inv": ''],
dash: [
"en": '',
"em": '',
"fig": '',
"wave": '',
"colon": '',
"circle": '',
"wave.double": '',
],
hyph: [
'',
"minus": '\u{2D}',
"nobreak": '\u{2011}',
"point": '',
"soft": '\u{ad}',
],
prime: [
'',
"rev": '',
"double": '',
"double.rev": '',
"triple": '',
"triple.rev": '',
"quad": '',
],
quote: [
"double": '"',
"single": '\'',
"l.double": '',
"l.single": '',
"r.double": '',
"r.single": '',
"angle.l.double": '«',
"angle.l.single": '',
"angle.r.double": '»',
"angle.r.single": '',
"high.double": '',
"high.single": '',
"low.double": '',
"low.single": '',
],
// Delimiters.
paren: [
"l": '(',
"r": ')',
"t": '',
"b": '',
],
bracket: [
"l": '[',
"r": ']',
"t": '',
"b": '',
],
brace: [
"l": '{',
"r": '}',
"t": '',
"b": '',
],
turtle: [
"l": '',
"r": '',
"t": '',
"b": '',
],
angled: ["l": '', "r": ''],
bar: [
"v": '|',
"v.double": '',
"v.triple": '',
"v.broken": '¦',
"v.circle": '',
"h": '',
],
fence: [
"l": '',
"l.double": '',
"r": '',
"r.double": '',
"dotted": '',
],
// Accents.
acute: ['´', "double": '˝'],
breve: '˘',
caret: '',
caron: 'ˇ',
hat: '^',
diaer: '¨',
grave: '`',
macron: '¯',
tilde: '~',
// Currency.
bitcoin: '',
dollar: '$',
euro: '',
franc: '',
lira: '',
peso: '',
pound: '£',
ruble: '',
rupee: '',
won: '',
yen: '¥',
// Miscellaneous.
ballot: ['☐', "x": ''],
checkmark: ['✓', "light": '🗸'],
copyright: ['©', "sound": ''],
floral: ['❦', "l": '', "r": ''],
notes: ["up": '🎜', "down": '🎝'],
refmark: '',
servicemark: '',
maltese: '',
suit: [
"club": '',
"diamond": '',
"heart": '',
"spade": '',
],
// Shapes.
circle: [
"stroked": '',
"stroked.tiny": '',
"stroked.small": '',
"stroked.big": '',
"filled": '',
"filled.tiny": '',
"filled.small": '',
"filled.big": '',
"dotted": '',
"nested": '',
],
square: [
"stroked": '',
"stroked.tiny": '',
"stroked.small": '',
"stroked.medium": '',
"stroked.big": '',
"stroked.dotted": '',
"stroked.rounded": '',
"filled": '',
"filled.tiny": '',
"filled.small": '',
"filled.medium": '',
"filled.big": '',
],
ellipse: [
"stroked.h": '',
"stroked.v": '',
"filled.h": '',
"filled.v": '',
],
rect: [
"stroked.h": '',
"stroked.v": '',
"filled.h": '',
"filled.v": '',
],
triangle: [
"stroked.r": '',
"stroked.l": '',
"stroked.t": '',
"stroked.b": '',
"stroked.bl": '',
"stroked.br": '',
"stroked.tl": '',
"stroked.tr": '',
"stroked.small.r": '',
"stroked.small.b": '',
"stroked.small.l": '',
"stroked.small.t": '',
"stroked.rounded": '🛆',
"stroked.nested": '',
"stroked.dot": '',
"filled.r": '',
"filled.l": '',
"filled.t": '',
"filled.b": '',
"filled.bl": '',
"filled.br": '',
"filled.tl": '',
"filled.tr": '',
"filled.small.r": '',
"filled.small.b": '',
"filled.small.l": '',
"filled.small.t": '',
],
diamond: [
"stroked": '',
"stroked.small": '',
"stroked.medium": '',
"stroked.dot": '',
"filled": '',
"filled.medium": '',
"filled.small": '',
],
lozenge: [
"stroked": '',
"stroked.small": '',
"stroked.medium": '',
"filled": '',
"filled.small": '',
"filled.medium": '',
],
penta: ["stroked": '', "filled": ''],
hexa: ["stroked": '', "filled": ''],
// Arrows and harpoons.
arrow: [
"r": '',
"r.long.bar": '',
"r.bar": '',
"r.curve": '',
"r.dashed": '',
"r.dotted": '',
"r.double": '',
"r.double.bar": '',
"r.double.long": '',
"r.double.long.bar": '',
"r.double.not": '',
"r.filled": '',
"r.hook": '',
"r.long": '',
"r.long.squiggly": '',
"r.loop": '',
"r.not": '',
"r.quad": '',
"r.squiggly": '',
"r.stop": '',
"r.stroked": '',
"r.tail": '',
"r.triple": '',
"r.twohead.bar": '',
"r.twohead": '',
"r.wave": '',
"l": '',
"l.bar": '',
"l.curve": '',
"l.dashed": '',
"l.dotted": '',
"l.double": '',
"l.double.bar": '',
"l.double.long": '',
"l.double.long.bar": '',
"l.double.not": '',
"l.filled": '',
"l.hook": '',
"l.long": '',
"l.long.bar": '',
"l.long.squiggly": '',
"l.loop": '',
"l.not": '',
"l.quad": '',
"l.squiggly": '',
"l.stop": '',
"l.stroked": '',
"l.tail": '',
"l.triple": '',
"l.twohead.bar": '',
"l.twohead": '',
"l.wave": '',
"t": '',
"t.bar": '',
"t.curve": '',
"t.dashed": '',
"t.double": '',
"t.filled": '',
"t.quad": '',
"t.stop": '',
"t.stroked": '',
"t.triple": '',
"t.twohead": '',
"b": '',
"b.bar": '',
"b.curve": '',
"b.dashed": '',
"b.double": '',
"b.filled": '',
"b.quad": '',
"b.stop": '',
"b.stroked": '',
"b.triple": '',
"b.twohead": '',
"l.r": '',
"l.r.double": '',
"l.r.double.long": '',
"l.r.double.not": '',
"l.r.filled": '',
"l.r.long": '',
"l.r.not": '',
"l.r.stroked": '',
"l.r.wave": '',
"t.b": '',
"t.b.double": '',
"t.b.filled": '',
"t.b.stroked": '',
"tr": '',
"tr.double": '',
"tr.filled": '',
"tr.hook": '',
"tr.stroked": '',
"br": '',
"br.double": '',
"br.filled": '',
"br.hook": '',
"br.stroked": '',
"tl": '',
"tl.double": '',
"tl.filled": '',
"tl.hook": '',
"tl.stroked": '',
"bl": '',
"bl.double": '',
"bl.filled": '',
"bl.hook": '',
"bl.stroked": '',
"tl.br": '',
"tr.bl": '',
"ccw": '',
"ccw.half": '',
"cw": '',
"cw.half": '',
"zigzag": '',
],
arrows: [
"rr": '',
"ll": '',
"tt": '',
"bb": '',
"lr": '',
"lr.stop": '',
"rl": '',
"tb": '',
"bt": '',
"rrr": '',
"lll": '',
],
arrowhead: [
"t": '',
"b": '',
],
harpoon: [
"rt": '',
"rt.bar": '',
"rt.stop": '',
"rb": '',
"rb.bar": '',
"rb.stop": '',
"lt": '',
"lt.bar": '',
"lt.stop": '',
"lb": '',
"lb.bar": '',
"lb.stop": '',
"tl": '',
"tl.bar": '',
"tl.stop": '',
"tr": '',
"tr.bar": '',
"tr.stop": '',
"bl": '',
"bl.bar": '',
"bl.stop": '',
"br": '',
"br.bar": '',
"br.stop": '',
"lt.rt": '',
"lb.rb": '',
"lb.rt": '',
"lt.rb": '',
"tl.bl": '',
"tr.br": '',
"tl.br": '',
"tr.bl": '',
],
harpoons: [
"rtrb": '',
"blbr": '',
"bltr": '',
"lbrb": '',
"ltlb": '',
"ltrb": '',
"ltrt": '',
"rblb": '',
"rtlb": '',
"rtlt": '',
"tlbr": '',
"tltr": '',
],
}

View File

@ -22,6 +22,7 @@ mod capable;
mod castable; mod castable;
mod func; mod func;
mod node; mod node;
mod symbols;
use proc_macro::TokenStream as BoundaryStream; use proc_macro::TokenStream as BoundaryStream;
use proc_macro2::{TokenStream, TokenTree}; use proc_macro2::{TokenStream, TokenTree};
@ -68,6 +69,14 @@ pub fn castable(stream: BoundaryStream) -> BoundaryStream {
.into() .into()
} }
/// Define a list of symbols.
#[proc_macro]
pub fn symbols(stream: BoundaryStream) -> BoundaryStream {
symbols::symbols(stream.into())
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
/// Extract documentation comments from an attribute list. /// Extract documentation comments from an attribute list.
fn documentation(attrs: &[syn::Attribute]) -> String { fn documentation(attrs: &[syn::Attribute]) -> String {
let mut doc = String::new(); let mut doc = String::new();

104
macros/src/symbols.rs Normal file
View File

@ -0,0 +1,104 @@
use syn::ext::IdentExt;
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::Token;
use super::*;
/// Expand the `symbols!` macro.
pub fn symbols(stream: TokenStream) -> Result<TokenStream> {
let list: List = syn::parse2(stream)?;
let pairs = list.0.iter().map(Symbol::expand);
Ok(quote! { &[#(#pairs),*] })
}
struct List(Punctuated<Symbol, Token![,]>);
impl Parse for List {
fn parse(input: ParseStream) -> Result<Self> {
Punctuated::parse_terminated(input).map(Self)
}
}
struct Symbol {
name: syn::Ident,
kind: Kind,
}
impl Parse for Symbol {
fn parse(input: ParseStream) -> Result<Self> {
let name = input.call(Ident::parse_any)?;
input.parse::<Token![:]>()?;
let kind = input.parse()?;
Ok(Self { name, kind })
}
}
impl Symbol {
fn expand(&self) -> TokenStream {
let name = self.name.to_string();
let kind = self.kind.expand();
quote! { (#name, #kind) }
}
}
enum Kind {
Single(syn::LitChar),
Multiple(Punctuated<Variant, Token![,]>),
}
impl Parse for Kind {
fn parse(input: ParseStream) -> Result<Self> {
if input.peek(syn::LitChar) {
Ok(Self::Single(input.parse()?))
} else {
let content;
syn::bracketed!(content in input);
Ok(Self::Multiple(Punctuated::parse_terminated(&content)?))
}
}
}
impl Kind {
fn expand(&self) -> TokenStream {
match self {
Self::Single(c) => quote! { typst::model::Symbol::new(#c), },
Self::Multiple(variants) => {
let variants = variants.iter().map(Variant::expand);
quote! {
typst::model::Symbol::list(&[#(#variants),*])
}
}
}
}
}
struct Variant {
name: String,
c: syn::LitChar,
}
impl Parse for Variant {
fn parse(input: ParseStream) -> Result<Self> {
let mut name = String::new();
if input.peek(syn::Ident::peek_any) {
name.push_str(&input.call(Ident::parse_any)?.to_string());
while input.peek(Token![.]) {
input.parse::<Token![.]>()?;
name.push('.');
name.push_str(&input.call(Ident::parse_any)?.to_string());
}
input.parse::<Token![:]>()?;
}
let c = input.parse()?;
Ok(Self { name, c })
}
}
impl Variant {
fn expand(&self) -> TokenStream {
let name = &self.name;
let c = &self.c;
quote! { (#name, #c) }
}
}

View File

@ -109,15 +109,6 @@ impl Scope {
self.0.insert(var.into(), Slot::new(value.into(), Kind::Captured)); self.0.insert(var.into(), Slot::new(value.into(), Kind::Captured));
} }
/// Copy definitions from another scope that aren't yet defined in this one.
pub fn copy_from(&mut self, other: &Self) {
for (name, value) in other.iter() {
self.0
.entry(name.clone())
.or_insert_with(|| Slot::new(value.clone(), Kind::Normal));
}
}
/// Try to access a variable immutably. /// Try to access a variable immutably.
pub fn get(&self, var: &str) -> Option<&Value> { pub fn get(&self, var: &str) -> Option<&Value> {
self.0.get(var).map(Slot::read) self.0.get(var).map(Slot::read)

View File

@ -7,26 +7,8 @@ use crate::diag::StrResult;
use crate::util::EcoString; use crate::util::EcoString;
/// Define a list of symbols. /// Define a list of symbols.
#[macro_export]
#[doc(hidden)]
macro_rules! __symbols {
($func:ident, $($name:ident: $value:tt),* $(,)?) => {
pub(super) fn $func(scope: &mut $crate::model::Scope) {
$(scope.define(stringify!($name), $crate::model::symbols!(@one $value));)*
}
};
(@one $c:literal) => { $crate::model::Symbol::new($c) };
(@one [$($first:literal $(: $second:literal)?),* $(,)?]) => {
$crate::model::Symbol::list(&[
$($crate::model::symbols!(@pair $first $(: $second)?)),*
])
};
(@pair $first:literal) => { ("", $first) };
(@pair $first:literal: $second:literal) => { ($first, $second) };
}
#[doc(inline)] #[doc(inline)]
pub use crate::__symbols as symbols; pub use typst_macros::symbols;
/// A symbol. /// A symbol.
#[derive(Clone, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
@ -45,13 +27,13 @@ enum Repr {
impl Symbol { impl Symbol {
/// Create a new symbol from a single character. /// Create a new symbol from a single character.
pub fn new(c: char) -> Self { pub const fn new(c: char) -> Self {
Self { repr: Repr::Single(c), modifiers: EcoString::new() } Self { repr: Repr::Single(c), modifiers: EcoString::new() }
} }
/// Create a symbol with a static variant list. /// Create a symbol with a static variant list.
#[track_caller] #[track_caller]
pub fn list(list: &'static [(&'static str, char)]) -> Self { pub const fn list(list: &'static [(&'static str, char)]) -> Self {
debug_assert!(!list.is_empty()); debug_assert!(!list.is_empty());
Self { Self {
repr: Repr::Static(list), repr: Repr::Static(list),

View File

@ -2,7 +2,7 @@
--- ---
$ f(x, y) := cases( $ f(x, y) := cases(
1 quad &"if" (x dot y)/2 <= 0, 1 quad &"if" (x dot.op y)/2 <= 0,
2 &"if" x divides 2, 2 &"if" x divides 2,
3 &"if" x in NN, 3 &"if" x in NN,
4 &"else", 4 &"else",

View File

@ -3,12 +3,12 @@
--- ---
// Test semicolon syntax. // Test semicolon syntax.
#set align(center) #set align(center)
$mat() dot $mat() dot.op
mat(;) dot mat(;) dot.op
mat(1, 2) dot mat(1, 2) dot.op
mat(1, 2;) \ mat(1, 2;) \
mat(1; 2) dot mat(1; 2) dot.op
mat(1, 2; 3, 4) dot mat(1, 2; 3, 4) dot.op
mat(1 + &2, 1/2; &3, 4)$ mat(1 + &2, 1/2; &3, 4)$
--- ---

View File

@ -4,13 +4,13 @@
// Test basic alignment. // Test basic alignment.
$ x &= x + y \ $ x &= x + y \
&= x + 2z \ &= x + 2z \
&= sum x dot 2z $ &= sum x dot.op 2z $
--- ---
// Test text before first alignment point. // Test text before first alignment point.
$ x + 1 &= a^2 + b^2 \ $ x + 1 &= a^2 + b^2 \
y &= a + b^2 \ y &= a + b^2 \
z &= alpha dot beta $ z &= alpha dot.op beta $
--- ---
// Test space between inner alignment points. // Test space between inner alignment points.

View File

@ -10,7 +10,7 @@ $-a, +a$ \
$a not b$ \ $a not b$ \
$a+b, a*b$ \ $a+b, a*b$ \
$sum x, sum(x)$ \ $sum x, sum(x)$ \
$sum prod x$ \ $sum product x$ \
$f(x), zeta(x), "frac"(x)$ $f(x), zeta(x), "frac"(x)$
--- ---