From b13ed627fff73a599b34d760cd99aa2f08d58ea8 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 30 Nov 2019 14:10:35 +0100 Subject: =?UTF-8?q?Better=20error=20reporting=20=F0=9F=9A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/align.rs | 155 +++++++++++++++++++++++++++++++++++++++++++++++++ src/library/axes.rs | 151 ----------------------------------------------- src/library/mod.rs | 2 +- src/library/spacing.rs | 2 +- 4 files changed, 157 insertions(+), 153 deletions(-) create mode 100644 src/library/align.rs delete mode 100644 src/library/axes.rs (limited to 'src/library') diff --git a/src/library/align.rs b/src/library/align.rs new file mode 100644 index 00000000..55063ebe --- /dev/null +++ b/src/library/align.rs @@ -0,0 +1,155 @@ +use crate::func::prelude::*; + +/// 📐 `align`: Aligns content in different ways. +#[derive(Debug, PartialEq)] +pub struct Align { + body: Option, + positional_1: Option, + positional_2: Option, + primary: Option, + secondary: Option, + horizontal: Option, + vertical: Option, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +enum AlignSpecifier { + Origin, + Center, + End, + Left, + Right, + Top, + Bottom, +} + +function! { + data: Align, + + parse(args, body, ctx) { + let body = parse!(optional: body, ctx); + + let mut align = Align { + body, + positional_1: None, + positional_2: None, + primary: None, + secondary: None, + horizontal: None, + vertical: None, + }; + + if let Some(arg) = args.get_pos_opt::()? { + align.positional_1 = Some(parse_align_specifier(arg)?); + } + + if let Some(arg) = args.get_pos_opt::()? { + align.positional_2 = Some(parse_align_specifier(arg)?); + } + + let mut parse_arg = |axis, target: &mut Option| { + Ok(if let Some(arg) = args.get_key_opt::(axis)? { + if target.is_none() { + *target = Some(parse_align_specifier(arg)?); + } else { + perr!("duplicate alignment specification for {} axis", axis); + } + }) + }; + + parse_arg("primary", &mut align.primary)?; + parse_arg("secondary", &mut align.secondary)?; + parse_arg("horizontal", &mut align.horizontal)?; + parse_arg("vertical", &mut align.vertical)?; + + args.done()?; + + Ok(align) + } + + layout(this, ctx) { + let mut axes = ctx.axes; + let primary_horizontal = axes.primary.axis.is_horizontal(); + + let mut primary = false; + let mut secondary = false; + + let mut set_axis = |is_primary: bool, spec: Option| -> LayoutResult<()> { + if let Some(spec) = spec { + let (axis, was_set, name) = match is_primary { + true => (&mut axes.primary, &mut primary, "primary"), + false => (&mut axes.secondary, &mut secondary, "secondary"), + }; + + if *was_set { + panic!("duplicate alignment for {} axis", name); + } + + *was_set = true; + + let horizontal = axis.axis.is_horizontal(); + let alignment = generic_alignment(spec, horizontal)?; + + if axis.alignment == Alignment::End && alignment == Alignment::Origin { + axis.expand = true; + } + + axis.alignment = alignment; + } + + Ok(()) + }; + + if let Some(spec) = this.positional_1 { + let positional = generic_alignment(spec, primary_horizontal).is_ok(); + set_axis(positional, this.positional_1)?; + } + + if let Some(spec) = this.positional_2 { + let positional = generic_alignment(spec, primary_horizontal).is_ok(); + set_axis(positional, this.positional_2)?; + } + + set_axis(true, this.primary)?; + set_axis(false, this.secondary)?; + set_axis(primary_horizontal, this.horizontal)?; + set_axis(!primary_horizontal, this.vertical)?; + + Ok(match &this.body { + Some(body) => commands![AddMultiple( + layout_tree(body, LayoutContext { + axes, + .. ctx.clone() + })? + )], + None => commands![Command::SetAxes(axes)] + }) + } +} + +fn parse_align_specifier(arg: Spanned<&str>) -> ParseResult { + Ok(match arg.val { + "origin" => AlignSpecifier::Origin, + "center" => AlignSpecifier::Center, + "end" => AlignSpecifier::End, + "left" => AlignSpecifier::Left, + "right" => AlignSpecifier::Right, + "top" => AlignSpecifier::Top, + "bottom" => AlignSpecifier::Bottom, + s => perr!("invalid alignment specifier: {}", s), + }) +} + +fn generic_alignment(spec: AlignSpecifier, horizontal: bool) -> LayoutResult { + use AlignSpecifier::*; + Ok(match (spec, horizontal) { + (Origin, _) | (Left, true) | (Top, false) => Alignment::Origin, + (Center, _) => Alignment::Center, + (End, _) | (Right, true) | (Bottom, false) => Alignment::End, + _ => lerr!( + "invalid alignment specifier `{}` for {} axis", + format!("{:?}", spec).to_lowercase(), + if horizontal { "horizontal" } else { "vertical" }, + ), + }) +} diff --git a/src/library/axes.rs b/src/library/axes.rs deleted file mode 100644 index 29b624ab..00000000 --- a/src/library/axes.rs +++ /dev/null @@ -1,151 +0,0 @@ -use crate::func::prelude::*; - -/// 📐 `align`: Aligns content in different ways. -#[derive(Debug, PartialEq)] -pub struct Align { - body: Option, - positional_1: Option, - positional_2: Option, - primary: Option, - secondary: Option, - horizontal: Option, - vertical: Option, -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -enum AlignSpecifier { - Origin, - Center, - End, - Left, - Right, - Top, - Bottom, -} - -function! { - data: Align, - - parse(args, body, ctx) { - let body = parse!(optional: body, ctx); - - let mut align = Align { - body, - positional_1: None, - positional_2: None, - primary: None, - secondary: None, - horizontal: None, - vertical: None, - }; - - if let Some(arg) = args.get_pos_opt::()? { - align.positional_1 = Some(parse_align_specifier(arg)?); - } - - if let Some(arg) = args.get_pos_opt::()? { - align.positional_2 = Some(parse_align_specifier(arg)?); - } - - let mut parse_arg = |axis, target: &mut Option| { - Ok(if let Some(arg) = args.get_key_opt::(axis)? { - if target.is_none() { - *target = Some(parse_align_specifier(arg)?); - } else { - err!("duplicate alignment specification for {} axis", axis); - } - }) - }; - - parse_arg("primary", &mut align.primary)?; - parse_arg("secondary", &mut align.secondary)?; - parse_arg("horizontal", &mut align.horizontal)?; - parse_arg("vertical", &mut align.vertical)?; - - args.done()?; - - Ok(align) - } - - layout(this, ctx) { - let mut axes = ctx.axes; - let primary_horizontal = axes.primary.axis.is_horizontal(); - - let mut primary = false; - let mut secondary = false; - - let mut set_axis = |is_primary: bool, spec: Option| -> LayoutResult<()> { - if let Some(spec) = spec { - let (axis, was_set, name) = match is_primary { - true => (&mut axes.primary, &mut primary, "primary"), - false => (&mut axes.secondary, &mut secondary, "secondary"), - }; - - if *was_set { - panic!("duplicate alignment for {} axis", name); - } - - *was_set = true; - - let horizontal = axis.axis.is_horizontal(); - let alignment = generic_alignment(spec, horizontal)?; - - if axis.alignment == Alignment::End && alignment == Alignment::Origin { - axis.expand = true; - } - - axis.alignment = alignment; - } - - Ok(()) - }; - - if let Some(spec) = this.positional_1 { - let positional = generic_alignment(spec, primary_horizontal).is_ok(); - set_axis(positional, this.positional_1)?; - } - - if let Some(spec) = this.positional_2 { - let positional = generic_alignment(spec, primary_horizontal).is_ok(); - set_axis(positional, this.positional_2)?; - } - - set_axis(true, this.primary)?; - set_axis(false, this.secondary)?; - set_axis(primary_horizontal, this.horizontal)?; - set_axis(!primary_horizontal, this.vertical)?; - - Ok(match &this.body { - Some(body) => commands![AddMultiple( - layout_tree(body, LayoutContext { - axes, - .. ctx.clone() - })? - )], - None => commands![Command::SetAxes(axes)] - }) - } -} - -fn parse_align_specifier(arg: Spanned<&str>) -> ParseResult { - Ok(match arg.val { - "origin" => AlignSpecifier::Origin, - "center" => AlignSpecifier::Center, - "end" => AlignSpecifier::End, - "left" => AlignSpecifier::Left, - "right" => AlignSpecifier::Right, - "top" => AlignSpecifier::Top, - "bottom" => AlignSpecifier::Bottom, - s => err!("invalid alignment specifier: {}", s), - }) -} - -fn generic_alignment(spec: AlignSpecifier, horizontal: bool) -> LayoutResult { - use AlignSpecifier::*; - Ok(match (spec, horizontal) { - (Origin, _) | (Left, true) | (Top, false) => Alignment::Origin, - (Center, _) => Alignment::Center, - (End, _) | (Right, true) | (Bottom, false) => Alignment::End, - _ => Err(LayoutError::UnalignedAxis("invalid alignment"))?, - }) -} diff --git a/src/library/mod.rs b/src/library/mod.rs index 5fa326c8..adcb974b 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -3,7 +3,7 @@ use crate::func::Scope; pub_use_mod!(boxed); -pub_use_mod!(axes); +pub_use_mod!(align); pub_use_mod!(spacing); pub_use_mod!(style); pub_use_mod!(page); diff --git a/src/library/spacing.rs b/src/library/spacing.rs index 01059484..d52153b1 100644 --- a/src/library/spacing.rs +++ b/src/library/spacing.rs @@ -38,7 +38,7 @@ macro_rules! space_func { let spacing = match arg.val { Expression::Size(s) => Spacing::Absolute(*s), Expression::Num(f) => Spacing::Relative(*f as f32), - _ => err!("invalid spacing, expected size or number"), + _ => perr!("invalid spacing, expected size or number"), }; Ok($ident(spacing)) -- cgit v1.2.3