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}