From 93eaafb236bba73cd72c8cd142279366b8afa0be Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 5 Oct 2020 16:06:25 +0200 Subject: [PATCH] =?UTF-8?q?Tidy=20up=20align=20function=20=F0=9F=A7=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/library/align.rs | 101 +++++++++++++++++++++++-------------------- src/library/font.rs | 8 ++-- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/library/align.rs b/src/library/align.rs index ba5de18a9..e7a8eb77d 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -16,18 +16,21 @@ use crate::prelude::*; /// There may not be two alignment specifications for the same axis. pub async fn align(mut args: Args, ctx: &mut LayoutContext) -> Value { let body = args.find::(); - let h = args.get::<_, Spanned>(ctx, "horizontal"); - let v = args.get::<_, Spanned>(ctx, "vertical"); - let pos = args.find_all::>(); - - let iter = pos - .map(|align| (align.v.axis(), align)) - .chain(h.into_iter().map(|align| (Some(SpecAxis::Horizontal), align))) - .chain(v.into_iter().map(|align| (Some(SpecAxis::Vertical), align))); - - let aligns = parse_aligns(ctx, iter); - + let first = args.get::<_, Spanned>(ctx, 0); + let second = args.get::<_, Spanned>(ctx, 1); + let hor = args.get::<_, Spanned>(ctx, "horizontal"); + let ver = args.get::<_, Spanned>(ctx, "vertical"); args.done(ctx); + + let iter = first + .into_iter() + .chain(second.into_iter()) + .map(|align| (align.v.axis(), align)) + .chain(hor.into_iter().map(|align| (Some(SpecAxis::Horizontal), align))) + .chain(ver.into_iter().map(|align| (Some(SpecAxis::Vertical), align))); + + let aligns = dedup_aligns(ctx, iter); + Value::Commands(match body { Some(tree) => vec![ SetAlignment(aligns), @@ -39,63 +42,67 @@ pub async fn align(mut args: Args, ctx: &mut LayoutContext) -> Value { } /// Deduplicate alignments and deduce to which axes they apply. -fn parse_aligns( +fn dedup_aligns( ctx: &mut LayoutContext, iter: impl Iterator, Spanned)>, ) -> LayoutAlign { let mut aligns = ctx.state.align; - let mut had = [false; 2]; - let mut deferred_center = false; + let mut had = Gen2::new(false, false); + let mut had_center = false; - for (axis, align) in iter { - // Check whether we know which axis this alignment belongs to. We don't - // if the alignment is `center` for a positional argument. Then we set - // `deferred_center` to true and handle the situation once we know more. + for (axis, Spanned { v: align, span }) in iter { + // Check whether we know which axis this alignment belongs to. if let Some(axis) = axis { - if align.v.axis().map_or(false, |a| a != axis) { + // We know the axis. + let gen_axis = axis.to_gen(ctx.state.sys); + let gen_align = align.to_gen(ctx.state.sys); + + if align.axis().map_or(false, |a| a != axis) { ctx.diag(error!( - align.span, - "invalid alignment {} for {} axis", align.v, axis, + span, + "invalid alignment `{}` for {} axis", align, axis, )); - } else if had[axis as usize] { - ctx.diag(error!(align.span, "duplicate alignment for {} axis", axis)); + } else if had.get(gen_axis) { + ctx.diag(error!(span, "duplicate alignment for {} axis", axis)); } else { - let gen_align = align.v.to_gen(ctx.state.sys); - *aligns.get_mut(axis.to_gen(ctx.state.sys)) = gen_align; - had[axis as usize] = true; + *aligns.get_mut(gen_axis) = gen_align; + *had.get_mut(gen_axis) = true; } } else { - if had == [true, true] { - ctx.diag(error!(align.span, "duplicate alignment")); - } else if deferred_center { - // We have two unflushed centers, meaning we know that both axes - // are to be centered. - had = [true, true]; + // We don't know the axis: This has to be a `center` alignment for a + // positional argument. + debug_assert_eq!(align, SpecAlign::Center); + + if had.primary && had.secondary { + ctx.diag(error!(span, "duplicate alignment")); + } else if had_center { + // Both this and the previous one are unspecified `center` + // alignments. Both axes should be centered. aligns = LayoutAlign::new(GenAlign::Center, GenAlign::Center); + had.primary = true; + had.secondary = true; } else { - deferred_center = true; + had_center = true; } } - // Flush a deferred center alignment if we know have had at least one - // known alignment. - if deferred_center && had != [false, false] { - let axis = if !had[SpecAxis::Horizontal as usize] { - SpecAxis::Horizontal + // If we we know one alignment, we can handle the unspecified `center` + // alignment. + if had_center && (had.primary || had.secondary) { + if had.primary { + aligns.secondary = GenAlign::Center; + had.secondary = true; } else { - SpecAxis::Vertical - }; - - *aligns.get_mut(axis.to_gen(ctx.state.sys)) = GenAlign::Center; - - had[axis as usize] = true; - deferred_center = false; + aligns.primary = GenAlign::Center; + had.primary = true; + } + had_center = false; } } - // If center has not been flushed by known, it is the only argument and then + // If center has not been flushed by now, it is the only argument and then // we default to applying it to the primary axis. - if deferred_center { + if had_center { aligns.primary = GenAlign::Center; } diff --git a/src/library/font.rs b/src/library/font.rs index 60380def1..21fb2d13a 100644 --- a/src/library/font.rs +++ b/src/library/font.rs @@ -51,7 +51,7 @@ use crate::prelude::*; /// ``` pub async fn font(mut args: Args, ctx: &mut LayoutContext) -> Value { let mut text = ctx.state.text.clone(); - let mut needs_flatten = false; + let mut needs_flattening = false; let body = args.find::(); @@ -67,7 +67,7 @@ pub async fn font(mut args: Args, ctx: &mut LayoutContext) -> Value { let list: Vec<_> = args.find_all::().map(|s| s.to_lowercase()).collect(); if !list.is_empty() { text.fallback.list = list; - needs_flatten = true; + needs_flattening = true; } if let Some(style) = args.get::<_, FontStyle>(ctx, "style") { @@ -89,12 +89,12 @@ pub async fn font(mut args: Args, ctx: &mut LayoutContext) -> Value { .collect(); text.fallback.update_class_list(class, fallback); - needs_flatten = true; + needs_flattening = true; } args.done(ctx); - if needs_flatten { + if needs_flattening { text.fallback.flatten(); }