typst_library/math/
op.rs

1use ecow::EcoString;
2
3use crate::foundations::{elem, Content, NativeElement, Scope, SymbolElem};
4use crate::layout::HElem;
5use crate::math::{upright, Mathy, THIN};
6use crate::text::TextElem;
7
8/// A text operator in an equation.
9///
10/// # Example
11/// ```example
12/// $ tan x = (sin x)/(cos x) $
13/// $ op("custom",
14///      limits: #true)_(n->oo) n $
15/// ```
16///
17/// # Predefined Operators { #predefined }
18/// Typst predefines the operators `arccos`, `arcsin`, `arctan`, `arg`, `cos`,
19/// `cosh`, `cot`, `coth`, `csc`, `csch`, `ctg`, `deg`, `det`, `dim`, `exp`,
20/// `gcd`, `lcm`, `hom`, `id`, `im`, `inf`, `ker`, `lg`, `lim`, `liminf`,
21/// `limsup`, `ln`, `log`, `max`, `min`, `mod`, `Pr`, `sec`, `sech`, `sin`,
22/// `sinc`, `sinh`, `sup`, `tan`, `tanh`, `tg` and `tr`.
23#[elem(title = "Text Operator", Mathy)]
24pub struct OpElem {
25    /// The operator's text.
26    #[required]
27    pub text: Content,
28
29    /// Whether the operator should show attachments as limits in display mode.
30    #[default(false)]
31    pub limits: bool,
32}
33
34macro_rules! ops {
35    ($($name:ident $(: $value:literal)? $(($tts:tt))?),* $(,)?) => {
36        pub(super) fn define(math: &mut Scope) {
37            $({
38                let operator = EcoString::from(ops!(@name $name $(: $value)?));
39                math.define(
40                    stringify!($name),
41                    // Latex also uses their equivalent of `TextElem` here.
42                    OpElem::new(TextElem::new(operator).into())
43                        .with_limits(ops!(@limit $($tts)*))
44                        .pack()
45                );
46            })*
47
48            let dif = |d| {
49                HElem::new(THIN.into()).with_weak(true).pack()
50                    + upright(SymbolElem::packed(d))
51            };
52            math.define("dif", dif('d'));
53            math.define("Dif", dif('D'));
54        }
55    };
56    (@name $name:ident) => { stringify!($name) };
57    (@name $name:ident: $value:literal) => { $value };
58    (@limit limits) => { true };
59    (@limit) => { false };
60}
61
62ops! {
63    arccos,
64    arcsin,
65    arctan,
66    arg,
67    cos,
68    cosh,
69    cot,
70    coth,
71    csc,
72    csch,
73    ctg,
74    deg,
75    det (limits),
76    dim,
77    exp,
78    gcd (limits),
79    lcm (limits),
80    hom,
81    id,
82    im,
83    inf (limits),
84    ker,
85    lg,
86    lim (limits),
87    liminf: "lim inf" (limits),
88    limsup: "lim sup" (limits),
89    ln,
90    log,
91    max (limits),
92    min (limits),
93    mod,
94    Pr (limits),
95    sec,
96    sech,
97    sin,
98    sinc,
99    sinh,
100    sup (limits),
101    tan,
102    tanh,
103    tg,
104    tr,
105}