use crate::foundations::{elem, func, Content, NativeElement, SymbolElem}; use crate::layout::{Length, Rel}; use crate::math::Mathy; /// Scales delimiters. /// /// While matched delimiters scale by default, this can be used to scale /// unmatched delimiters and to control the delimiter scaling more precisely. #[elem(title = "Left/Right", Mathy)] pub struct LrElem { /// The size of the brackets, relative to the height of the wrapped content. #[resolve] #[default(Rel::one())] pub size: Rel, /// The delimited content, including the delimiters. #[required] #[parse( let mut arguments = args.all::()?.into_iter(); let mut body = arguments.next().unwrap_or_default(); arguments.for_each(|arg| body += SymbolElem::packed(',') + arg); body )] pub body: Content, } /// Scales delimiters vertically to the nearest surrounding `{lr()}` group. /// /// ```example /// $ { x mid(|) sum_(i=1)^n w_i|f_i (x)| < 1 } $ /// ``` #[elem(Mathy)] pub struct MidElem { /// The content to be scaled. #[required] pub body: Content, } /// Floors an expression. /// /// ```example /// $ floor(x/2) $ /// ``` #[func] pub fn floor( /// The size of the brackets, relative to the height of the wrapped content. #[named] size: Option>, /// The expression to floor. body: Content, ) -> Content { delimited(body, '⌊', '⌋', size) } /// Ceils an expression. /// /// ```example /// $ ceil(x/2) $ /// ``` #[func] pub fn ceil( /// The size of the brackets, relative to the height of the wrapped content. #[named] size: Option>, /// The expression to ceil. body: Content, ) -> Content { delimited(body, '⌈', '⌉', size) } /// Rounds an expression. /// /// ```example /// $ round(x/2) $ /// ``` #[func] pub fn round( /// The size of the brackets, relative to the height of the wrapped content. #[named] size: Option>, /// The expression to round. body: Content, ) -> Content { delimited(body, '⌊', '⌉', size) } /// Takes the absolute value of an expression. /// /// ```example /// $ abs(x/2) $ /// ``` #[func] pub fn abs( /// The size of the brackets, relative to the height of the wrapped content. #[named] size: Option>, /// The expression to take the absolute value of. body: Content, ) -> Content { delimited(body, '|', '|', size) } /// Takes the norm of an expression. /// /// ```example /// $ norm(x/2) $ /// ``` #[func] pub fn norm( /// The size of the brackets, relative to the height of the wrapped content. #[named] size: Option>, /// The expression to take the norm of. body: Content, ) -> Content { delimited(body, '‖', '‖', size) } fn delimited( body: Content, left: char, right: char, size: Option>, ) -> Content { let span = body.span(); let mut elem = LrElem::new(Content::sequence([ SymbolElem::packed(left), body, SymbolElem::packed(right), ])); // Push size only if size is provided if let Some(size) = size { elem.push_size(size); } elem.pack().spanned(span) }