1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
use typst::eval::Scope;
use super::*;
/// A text operator in an equation.
///
/// ## Example
/// ```example
/// $ tan x = (sin x)/(cos x) $
/// $ op("custom",
/// limits: #true)_(n->oo) n $
/// ```
///
/// ## Predefined Operators
/// Typst predefines the operators `arccos`, `arcsin`, `arctan`, `arg`,
/// `cos`, `cosh`, `cot`, `ctg`, `coth`, `csc`, `deg`, `det`, `dim`,
/// `exp`, `gcd`, `hom`, `mod`, `inf`, `ker`, `lg`, `lim`, `ln`, `log`,
/// `max`, `min`, `Pr`, `sec`, `sin`, `sinh`, `sup`, `tan`, `tg`, `tanh`,
/// `liminf`, and `limsup`.
///
/// Display: Text Operator
/// Category: math
#[element(LayoutMath)]
pub struct OpElem {
/// The operator's text.
#[required]
pub text: EcoString,
/// Whether the operator should force attachments to display as limits.
///
/// Defaults to `{false}`.
#[default(false)]
pub limits: bool,
}
impl LayoutMath for OpElem {
fn layout_math(&self, ctx: &mut MathContext) -> SourceResult<()> {
let frame = ctx.layout_content(&TextElem::packed(self.text()))?;
ctx.push(
FrameFragment::new(ctx, frame)
.with_class(MathClass::Large)
.with_limits(self.limits(ctx.styles())),
);
Ok(())
}
}
macro_rules! ops {
($($name:ident $(: $value:literal)? $(($tts:tt))?),* $(,)?) => {
pub(super) fn define(math: &mut Scope) {
$(math.define(
stringify!($name),
OpElem::new(ops!(@name $name $(: $value)?).into())
.with_limits(ops!(@limit $($tts)*))
.pack()
);)*
let dif = |d| {
HElem::new(THIN.into()).pack()
+ MathStyleElem::new(TextElem::packed(d)).with_italic(Some(false)).pack()
};
math.define("dif", dif('d'));
math.define("Dif", dif('D'));
}
};
(@name $name:ident) => { stringify!($name) };
(@name $name:ident: $value:literal) => { $value };
(@limit limits) => { true };
(@limit) => { false };
}
ops! {
arccos,
arcsin,
arctan,
arg,
cos,
cosh,
cot,
ctg,
coth,
csc,
deg,
det (limits),
dim,
exp,
gcd (limits),
hom,
mod,
inf (limits),
ker,
lg,
lim (limits),
ln,
log,
max (limits),
min (limits),
Pr (limits),
sec,
sin,
sinh,
sup (limits),
tan,
tg,
tanh,
liminf: "lim inf" (limits),
limsup: "lim sup" (limits),
}
|