typst_library/math/frac.rs
1use typst_syntax::Spanned;
2
3use crate::diag::bail;
4use crate::foundations::{Cast, Content, Value, elem};
5use crate::math::Mathy;
6
7/// A mathematical fraction.
8///
9/// # Example
10/// ```example
11/// $ 1/2 < (x+1)/2 $
12/// $ ((x+1)) / 2 = frac(a, b) $
13/// ```
14///
15/// # Syntax
16/// This function also has dedicated syntax: Use a slash to turn neighbouring
17/// expressions into a fraction. Multiple atoms can be grouped into a single
18/// expression using round grouping parentheses. Such parentheses are removed
19/// from the output, but you can nest multiple to force them.
20#[elem(title = "Fraction", Mathy)]
21pub struct FracElem {
22 /// The fraction's numerator.
23 #[required]
24 pub num: Content,
25
26 /// The fraction's denominator.
27 #[required]
28 pub denom: Content,
29
30 /// How the fraction should be laid out.
31 ///
32 /// ```example:"Styles"
33 /// $ frac(x, y, style: "vertical") $
34 /// $ frac(x, y, style: "skewed") $
35 /// $ frac(x, y, style: "horizontal") $
36 /// ```
37 ///
38 /// ```example:"Setting the default"
39 /// #set math.frac(style: "skewed")
40 /// $ a / b $
41 /// ```
42 ///
43 /// ```example:"Handling of grouping parentheses"
44 /// // Grouping parentheses are removed.
45 /// #set math.frac(style: "vertical")
46 /// $ (a + b) / b $
47 ///
48 /// // Grouping parentheses are removed.
49 /// #set math.frac(style: "skewed")
50 /// $ (a + b) / b $
51 ///
52 /// // Grouping parentheses are retained.
53 /// #set math.frac(style: "horizontal")
54 /// $ (a + b) / b $
55 /// ```
56 ///
57 /// ```example:"Different styles in inline vs block equations"
58 /// // This changes the style for inline equations only.
59 /// #show math.equation.where(block: false): set math.frac(style: "horizontal")
60 ///
61 /// This $(x-y)/z = 3$ is inline math, and this is block math:
62 /// $ (x-y)/z = 3 $
63 /// ```
64 #[default(FracStyle::Vertical)]
65 pub style: FracStyle,
66
67 /// Whether the numerator was originally surrounded by parentheses
68 /// that were stripped by the parser.
69 #[internal]
70 #[parse(None)]
71 #[default(false)]
72 pub num_deparenthesized: bool,
73
74 /// Whether the denominator was originally surrounded by parentheses
75 /// that were stripped by the parser.
76 #[internal]
77 #[parse(None)]
78 #[default(false)]
79 pub denom_deparenthesized: bool,
80}
81
82/// Fraction style
83#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Cast)]
84pub enum FracStyle {
85 /// Stacked numerator and denominator with a bar.
86 #[default]
87 Vertical,
88 /// Numerator and denominator separated by a slash.
89 Skewed,
90 /// Numerator and denominator placed inline and parentheses are not
91 /// absorbed.
92 Horizontal,
93}
94
95/// A binomial expression.
96///
97/// # Example
98/// ```example
99/// $ binom(n, k) $
100/// $ binom(n, k_1, k_2, k_3, ..., k_m) $
101/// ```
102#[elem(title = "Binomial", Mathy)]
103pub struct BinomElem {
104 /// The binomial's upper index.
105 #[required]
106 pub upper: Content,
107
108 /// The binomial's lower index.
109 #[required]
110 #[variadic]
111 #[parse(
112 let values = args.all::<Spanned<Value>>()?;
113 if values.is_empty() {
114 // Prevents one element binomials
115 bail!(args.span, "missing argument: lower");
116 }
117 values.into_iter().map(|spanned| spanned.v.display()).collect()
118 )]
119 pub lower: Vec<Content>,
120}