diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-08-29 11:32:32 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-08-29 11:32:32 +0200 |
| commit | 6febc0327304451bc956985b7cadb07a0b563c79 (patch) | |
| tree | bfdef2d7615985a35f4d2dd4052d43e84e6edd56 /src/library/align.rs | |
| parent | 8a45ec2875a4f72cb02d574b63b5dda141da35c1 (diff) | |
Make align not behave box-like and smarter 📦
Doesn't layout contents into a box anymore, instead layouting inline in the parent context. Also makes axis inferring for center alignents smarter (just because I had fun doing it). It's unsure whether we want to keep it because it might be confusing.
Diffstat (limited to 'src/library/align.rs')
| -rw-r--r-- | src/library/align.rs | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/src/library/align.rs b/src/library/align.rs index 14692eca..55e0f65e 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -5,16 +5,19 @@ use super::*; /// # Positional arguments /// - At most two of `left`, `right`, `top`, `bottom`, `center`. /// +/// When `center` is used as a positional argument, it is automatically inferred +/// which axis it should apply to depending on further arguments, defaulting +/// to the axis, text is set along. +/// /// # Keyword arguments /// - `horizontal`: Any of `left`, `right` or `center`. /// - `vertical`: Any of `top`, `bottom` or `center`. /// /// There may not be two alignment specifications for the same axis. -pub async fn align(_: Span, mut args: TableValue, mut ctx: LayoutContext<'_>) -> Pass<Value> { +pub async fn align(_: Span, mut args: TableValue, ctx: LayoutContext<'_>) -> Pass<Value> { let mut f = Feedback::new(); let content = args.take::<SyntaxTree>(); - let h = args.take_key::<Spanned<SpecAlign>>("horizontal", &mut f); let v = args.take_key::<Spanned<SpecAlign>>("vertical", &mut f); let all = args @@ -23,40 +26,69 @@ pub async fn align(_: Span, mut args: TableValue, mut ctx: LayoutContext<'_>) -> .chain(h.into_iter().map(|align| (Some(Horizontal), align))) .chain(v.into_iter().map(|align| (Some(Vertical), align))); + let mut aligns = ctx.align; let mut had = [false; 2]; + let mut deferred_center = false; + 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 + // 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. + if let Some(axis) = axis { + if align.v.axis().map(|a| a != axis).unwrap_or(false) { + error!( + @f, align.span, + "invalid alignment {} for {} axis", align.v, axis, + ); + } else if had[axis as usize] { + error!(@f, align.span, "duplicate alignment for {} axis", axis); } else { - ctx.axes.secondary.axis() + let gen_align = align.v.to_generic(ctx.axes); + *aligns.get_mut(axis.to_generic(ctx.axes)) = gen_align; + had[axis as usize] = true; } - })); - - if align.v.axis().map(|a| a != axis).unwrap_or(false) { - error!( - @f, align.span, - "invalid alignment {} for {} axis", align.v, axis, - ); - } else if had[axis as usize] { - error!(@f, align.span, "duplicate alignment for {} axis", axis); } else { + if had == [true, true] { + error!(@f, 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]; + aligns = LayoutAlign::new(Center, Center); + } else { + deferred_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[Horizontal as usize] { + Horizontal + } else { + Vertical + }; + + *aligns.get_mut(axis.to_generic(ctx.axes)) = Center; + had[axis as usize] = true; - let gen_axis = axis.to_generic(ctx.axes); - let gen_align = align.v.to_generic(ctx.axes); - *ctx.align.get_mut(gen_axis) = gen_align; + deferred_center = false; } } + // If center has not been flushed by known, it is the only argument and then + // we default to applying it to the primary axis. + if deferred_center { + aligns.primary = Center; + } + 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)], + Some(tree) => vec![ + SetAlignment(aligns), + LayoutSyntaxTree(tree), + SetAlignment(ctx.align), + ], + None => vec![SetAlignment(aligns)], }; args.unexpected(&mut f); |
