summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-17 23:45:03 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-17 23:45:03 +0200
commit6d7e7d945b315469b80bca3466a96534b2a17639 (patch)
tree1b6c5e0ae7fb683ff7f3b6b1d961151a8e467a80 /src/library
parent3cbca56a7195bb2a7996530d584300d697c11dc8 (diff)
Tidy up library functions 🧺
Diffstat (limited to 'src/library')
-rw-r--r--src/library/align.rs40
-rw-r--r--src/library/boxed.rs21
-rw-r--r--src/library/font.rs74
-rw-r--r--src/library/mod.rs14
-rw-r--r--src/library/page.rs56
-rw-r--r--src/library/spacing.rs21
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)
}