diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-17 23:45:03 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-17 23:45:03 +0200 |
| commit | 6d7e7d945b315469b80bca3466a96534b2a17639 (patch) | |
| tree | 1b6c5e0ae7fb683ff7f3b6b1d961151a8e467a80 /src/library | |
| parent | 3cbca56a7195bb2a7996530d584300d697c11dc8 (diff) | |
Tidy up library functions 🧺
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/align.rs | 40 | ||||
| -rw-r--r-- | src/library/boxed.rs | 21 | ||||
| -rw-r--r-- | src/library/font.rs | 74 | ||||
| -rw-r--r-- | src/library/mod.rs | 14 | ||||
| -rw-r--r-- | src/library/page.rs | 56 | ||||
| -rw-r--r-- | src/library/spacing.rs | 21 |
6 files changed, 127 insertions, 99 deletions
diff --git a/src/library/align.rs b/src/library/align.rs index c716faef..14692eca 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -10,28 +10,30 @@ use super::*; /// - `vertical`: Any of `top`, `bottom` or `center`. /// /// There may not be two alignment specifications for the same axis. -pub async fn align(mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Value> { +pub async fn align(_: Span, mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); let content = args.take::<SyntaxTree>(); - let aligns: Vec<_> = args.take_all_num_vals::<Spanned<SpecAlign>>().collect(); - let h = args.take_with_key::<_, Spanned<SpecAlign>>("horizontal", &mut f); - let v = args.take_with_key::<_, Spanned<SpecAlign>>("vertical", &mut f); - args.unexpected(&mut f); - - ctx.base = ctx.spaces[0].size; - let axes = ctx.axes; - let all = aligns.iter() - .map(|align| { - let spec = align.v.axis().unwrap_or(axes.primary.axis()); - (spec, align) - }) - .chain(h.iter().map(|align| (Horizontal, align))) - .chain(v.iter().map(|align| (Vertical, align))); + let h = args.take_key::<Spanned<SpecAlign>>("horizontal", &mut f); + let v = args.take_key::<Spanned<SpecAlign>>("vertical", &mut f); + let all = args + .take_all_num_vals::<Spanned<SpecAlign>>() + .map(|align| (align.v.axis(), align)) + .chain(h.into_iter().map(|align| (Some(Horizontal), align))) + .chain(v.into_iter().map(|align| (Some(Vertical), align))); let mut had = [false; 2]; for (axis, align) in all { + let axis = axis.unwrap_or_else(|| align.v.axis().unwrap_or_else(|| { + let primary = ctx.axes.primary.axis(); + if !had[primary as usize] { + primary + } else { + ctx.axes.secondary.axis() + } + })); + if align.v.axis().map(|a| a != axis).unwrap_or(false) { error!( @f, align.span, @@ -47,12 +49,16 @@ pub async fn align(mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Val } } - Pass::commands(match content { + let commands = match content { Some(tree) => { + ctx.base = ctx.spaces[0].size; let layouted = layout(&tree, ctx).await; f.extend(layouted.feedback); vec![AddMultiple(layouted.output)] } None => vec![SetAlignment(ctx.align)], - }, f) + }; + + args.unexpected(&mut f); + Pass::commands(commands, f) } diff --git a/src/library/boxed.rs b/src/library/boxed.rs index c03043ae..5c727bb6 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -6,32 +6,33 @@ use super::*; /// # Keyword arguments /// - `width`: The width of the box (length of relative to parent's width). /// - `height`: The height of the box (length of relative to parent's height). -pub async fn boxed(mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Value> { +pub async fn boxed(_: Span, mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); + let content = args.take::<SyntaxTree>().unwrap_or(SyntaxTree::new()); - let width = args.take_with_key::<_, ScaleLength>("width", &mut f); - let height = args.take_with_key::<_, ScaleLength>("height", &mut f); - args.unexpected(&mut f); + ctx.base = ctx.spaces[0].size; ctx.spaces.truncate(1); ctx.repeat = false; - width.with(|v| { - let length = v.raw_scaled(ctx.base.x); + if let Some(w) = args.take_key::<ScaleLength>("width", &mut f) { + let length = w.raw_scaled(ctx.base.x); ctx.base.x = length; ctx.spaces[0].size.x = length; ctx.spaces[0].expansion.horizontal = true; - }); + } - height.with(|v| { - let length = v.raw_scaled(ctx.base.y); + if let Some(h) = args.take_key::<ScaleLength>("height", &mut f) { + let length = h.raw_scaled(ctx.base.y); ctx.base.y = length; ctx.spaces[0].size.y = length; ctx.spaces[0].expansion.vertical = true; - }); + } let layouted = layout(&content, ctx).await; let layout = layouted.output.into_iter().next().unwrap(); f.extend(layouted.feedback); + + args.unexpected(&mut f); Pass::commands(vec![Add(layout)], f) } diff --git a/src/library/font.rs b/src/library/font.rs index 71e9552f..ae059512 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -18,60 +18,66 @@ use super::*; /// ```typst /// serif = ("Source Serif Pro", "Noto Serif") /// ``` -pub async fn font(mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { +pub async fn font(_: Span, mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); + let mut text = ctx.style.text.clone(); + let mut updated_fallback = false; let content = args.take::<SyntaxTree>(); - let size = args.take::<ScaleLength>(); - let style = args.take_with_key::<_, FontStyle>("style", &mut f); - let weight = args.take_with_key::<_, FontWeight>("weight", &mut f); - let width = args.take_with_key::<_, FontWidth>("width", &mut f); + + if let Some(s) = args.take::<ScaleLength>() { + match s { + ScaleLength::Absolute(length) => { + text.base_font_size = length.as_raw(); + text.font_scale = 1.0; + } + ScaleLength::Scaled(scale) => text.font_scale = scale, + } + } + let list: Vec<_> = args.take_all_num_vals::<StringLike>() - .map(|s| s.0.to_lowercase()) - .collect(); - let classes: Vec<(_, Vec<_>)> = args.take_all_str::<TableValue>() - .map(|(class, mut table)| { - let fallback = table.take_all_num_vals::<StringLike>() - .map(|s| s.0.to_lowercase()) - .collect(); - (class, fallback) - }) + .map(|s| s.to_lowercase()) .collect(); - args.unexpected(&mut f); + if !list.is_empty() { + *text.fallback.list_mut() = list; + updated_fallback = true; + } - let mut text = ctx.style.text.clone(); + if let Some(style) = args.take_key::<FontStyle>("style", &mut f) { + text.variant.style = style; + } - size.with(|s| match s { - ScaleLength::Absolute(length) => { - text.base_font_size = length.as_raw(); - text.font_scale = 1.0; - } - ScaleLength::Scaled(scale) => text.font_scale = scale, - }); + if let Some(weight) = args.take_key::<FontWeight>("weight", &mut f) { + text.variant.weight = weight; + } - style.with(|s| text.variant.style = s); - weight.with(|w| text.variant.weight = w); - width.with(|w| text.variant.width = w); + if let Some(width) = args.take_key::<FontWidth>("width", &mut f) { + text.variant.width = width; + } - if !list.is_empty() { - *text.fallback.list_mut() = list.iter() + for (class, mut table) in args.take_all_str::<TableValue>() { + let fallback = table.take_all_num_vals::<StringLike>() .map(|s| s.to_lowercase()) .collect(); - } - for (class, fallback) in classes { - text.fallback.set_class_list(class.clone(), fallback.clone()); + text.fallback.set_class_list(class, fallback); + updated_fallback = true; } - text.fallback.flatten(); + if updated_fallback { + text.fallback.flatten(); + } - Pass::commands(match content { + let commands = match content { Some(tree) => vec![ SetTextStyle(text), LayoutSyntaxTree(tree), SetTextStyle(ctx.style.text.clone()), ], None => vec![SetTextStyle(text)], - }, f) + }; + + args.unexpected(&mut f); + Pass::commands(commands, f) } diff --git a/src/library/mod.rs b/src/library/mod.rs index 1999ba31..eaab72fc 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -30,7 +30,7 @@ macro_rules! std { macro_rules! wrap { ($func:expr) => { - Rc::new(|args, ctx| Box::pin($func(args, ctx))) + Rc::new(|name, args, ctx| Box::pin($func(name, args, ctx))) }; } @@ -51,14 +51,16 @@ std! { /// /// This is also the fallback function, which is used when a function name /// cannot be resolved. -pub async fn val(mut args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { - Pass::commands(match args.take::<SyntaxTree>() { +pub async fn val(_: Span, mut args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { + let commands = match args.take::<SyntaxTree>() { Some(tree) => vec![LayoutSyntaxTree(tree)], None => vec![], - }, Feedback::new()) + }; + + Pass::commands(commands, Feedback::new()) } -/// `dump`: Dumps its arguments. -pub async fn dump(args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { +/// `dump`: Dumps its arguments into the document. +pub async fn dump(_: Span, args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { Pass::okay(Value::Table(args)) } diff --git a/src/library/page.rs b/src/library/page.rs index 42f29dbb..f6f9c1c8 100644 --- a/src/library/page.rs +++ b/src/library/page.rs @@ -16,45 +16,55 @@ use super::*; /// - `top`: The top margin (length or relative to height). /// - `bottom`: The bottom margin (length or relative to height). /// - `flip`: Flips custom or paper-defined width and height (boolean). -pub async fn page(mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { +pub async fn page(_: Span, mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); - let paper = args.take::<Paper>(); - let width = args.take_with_key::<_, Length>("width", &mut f); - let height = args.take_with_key::<_, Length>("height", &mut f); - let margins = args.take_with_key::<_, ScaleLength>("margins", &mut f); - let left = args.take_with_key::<_, ScaleLength>("left", &mut f); - let right = args.take_with_key::<_, ScaleLength>("right", &mut f); - let top = args.take_with_key::<_, ScaleLength>("top", &mut f); - let bottom = args.take_with_key::<_, ScaleLength>("bottom", &mut f); - let flip = args.take_with_key::<_, bool>("flip", &mut f).unwrap_or(false); - args.unexpected(&mut f); - let mut style = ctx.style.page; - if let Some(paper) = paper { + if let Some(paper) = args.take::<Paper>() { style.class = paper.class; style.size = paper.size(); - } else if width.is_some() || height.is_some() { + } + + if let Some(width) = args.take_key::<Length>("width", &mut f) { style.class = PaperClass::Custom; + style.size.x = width.as_raw(); } - width.with(|v| style.size.x = v.as_raw()); - height.with(|v| style.size.y = v.as_raw()); - margins.with(|v| style.margins.set_all(Some(v))); - left.with(|v| style.margins.left = Some(v)); - right.with(|v| style.margins.right = Some(v)); - top.with(|v| style.margins.top = Some(v)); - bottom.with(|v| style.margins.bottom = Some(v)); + if let Some(height) = args.take_key::<Length>("height", &mut f) { + style.class = PaperClass::Custom; + style.size.y = height.as_raw(); + } + + if let Some(margins) = args.take_key::<ScaleLength>("margins", &mut f) { + style.margins.set_all(Some(margins)); + } - if flip { + if let Some(left) = args.take_key::<ScaleLength>("left", &mut f) { + style.margins.left = Some(left); + } + + if let Some(right) = args.take_key::<ScaleLength>("right", &mut f) { + style.margins.right = Some(right); + } + + if let Some(top) = args.take_key::<ScaleLength>("top", &mut f) { + style.margins.top = Some(top); + } + + if let Some(bottom) = args.take_key::<ScaleLength>("bottom", &mut f) { + style.margins.bottom = Some(bottom); + } + + if args.take_key::<bool>("flip", &mut f).unwrap_or(false) { style.size.swap(); } + args.unexpected(&mut f); Pass::commands(vec![SetPageStyle(style)], f) } /// `pagebreak`: Ends the current page. -pub async fn pagebreak(args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { +pub async fn pagebreak(_: Span, args: TableValue, _: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); args.unexpected(&mut f); Pass::commands(vec![BreakPage], f) diff --git a/src/library/spacing.rs b/src/library/spacing.rs index 3cd775c9..91049db8 100644 --- a/src/library/spacing.rs +++ b/src/library/spacing.rs @@ -6,32 +6,35 @@ use super::*; /// /// # Positional arguments /// - The spacing (length or relative to font size). -pub async fn h(args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { - spacing(args, ctx, Horizontal).await +pub async fn h(name: Span, args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { + spacing(name, args, ctx, Horizontal) } /// `v`: Add vertical spacing. /// /// # Positional arguments /// - The spacing (length or relative to font size). -pub async fn v(args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { - spacing(args, ctx, Vertical).await +pub async fn v(name: Span, args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { + spacing(name, args, ctx, Vertical) } -async fn spacing( +fn spacing( + name: Span, mut args: TableValue, ctx: LayoutContext<'_>, axis: SpecAxis, ) -> Pass<Value> { let mut f = Feedback::new(); - let spacing = args.expect::<ScaleLength>(&mut f).map(|s| (axis, s)); - args.unexpected(&mut f); - Pass::commands(if let Some((axis, spacing)) = spacing { + let spacing = args.expect::<ScaleLength>("spacing", name, &mut f); + let commands = if let Some(spacing) = spacing { let axis = axis.to_generic(ctx.axes); let spacing = spacing.raw_scaled(ctx.style.text.font_size()); vec![AddSpacing(spacing, SpacingKind::Hard, axis)] } else { vec![] - }, f) + }; + + args.unexpected(&mut f); + Pass::commands(commands, f) } |
