summaryrefslogtreecommitdiff
path: root/src/library/align.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-29 11:32:32 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-29 11:32:32 +0200
commit6febc0327304451bc956985b7cadb07a0b563c79 (patch)
treebfdef2d7615985a35f4d2dd4052d43e84e6edd56 /src/library/align.rs
parent8a45ec2875a4f72cb02d574b63b5dda141da35c1 (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.rs84
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);