summaryrefslogtreecommitdiff
path: root/src/library/align.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/library/align.rs')
-rw-r--r--src/library/align.rs96
1 files changed, 83 insertions, 13 deletions
diff --git a/src/library/align.rs b/src/library/align.rs
index acd3a85c..d6b14692 100644
--- a/src/library/align.rs
+++ b/src/library/align.rs
@@ -1,4 +1,5 @@
use crate::prelude::*;
+use std::fmt::{self, Display, Formatter};
/// `align`: Align content along the layouting axes.
///
@@ -18,10 +19,10 @@ pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
let snapshot = ctx.state.clone();
let body = args.find::<SynTree>();
- let first = args.get::<_, Spanned<SpecAlign>>(ctx, 0);
- let second = args.get::<_, Spanned<SpecAlign>>(ctx, 1);
- let hor = args.get::<_, Spanned<SpecAlign>>(ctx, "horizontal");
- let ver = args.get::<_, Spanned<SpecAlign>>(ctx, "vertical");
+ let first = args.get::<_, Spanned<AlignArg>>(ctx, 0);
+ let second = args.get::<_, Spanned<AlignArg>>(ctx, 1);
+ let hor = args.get::<_, Spanned<AlignArg>>(ctx, "horizontal");
+ let ver = args.get::<_, Spanned<AlignArg>>(ctx, "vertical");
args.done(ctx);
let iter = first
@@ -50,10 +51,10 @@ pub fn align(mut args: Args, ctx: &mut EvalContext) -> Value {
/// Deduplicate alignments and deduce to which axes they apply.
fn dedup_aligns(
ctx: &mut EvalContext,
- iter: impl Iterator<Item = (Option<SpecAxis>, Spanned<SpecAlign>)>,
-) -> Gen2<GenAlign> {
+ iter: impl Iterator<Item = (Option<SpecAxis>, Spanned<AlignArg>)>,
+) -> Gen<Align> {
let mut aligns = ctx.state.aligns;
- let mut had = Gen2::new(false, false);
+ let mut had = Gen::new(false, false);
let mut had_center = false;
for (axis, Spanned { v: align, span }) in iter {
@@ -77,15 +78,15 @@ fn dedup_aligns(
} else {
// We don't know the axis: This has to be a `center` alignment for a
// positional argument.
- debug_assert_eq!(align, SpecAlign::Center);
+ debug_assert_eq!(align, AlignArg::Center);
if had.main && had.cross {
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 = Gen2::new(GenAlign::Center, GenAlign::Center);
- had = Gen2::new(true, true);
+ aligns = Gen::new(Align::Center, Align::Center);
+ had = Gen::new(true, true);
} else {
had_center = true;
}
@@ -95,10 +96,10 @@ fn dedup_aligns(
// alignment.
if had_center && (had.main || had.cross) {
if had.main {
- aligns.cross = GenAlign::Center;
+ aligns.cross = Align::Center;
had.cross = true;
} else {
- aligns.main = GenAlign::Center;
+ aligns.main = Align::Center;
had.main = true;
}
had_center = false;
@@ -108,8 +109,77 @@ fn dedup_aligns(
// If center has not been flushed by now, it is the only argument and then
// we default to applying it to the cross axis.
if had_center {
- aligns.cross = GenAlign::Center;
+ aligns.cross = Align::Center;
}
aligns
}
+
+/// An alignment argument.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+enum AlignArg {
+ Left,
+ Right,
+ Top,
+ Bottom,
+ Center,
+}
+
+impl AlignArg {
+ /// The specific axis this alignment refers to.
+ ///
+ /// Returns `None` if this is `Center` since the axis is unknown.
+ pub fn axis(self) -> Option<SpecAxis> {
+ match self {
+ Self::Left => Some(SpecAxis::Horizontal),
+ Self::Right => Some(SpecAxis::Horizontal),
+ Self::Top => Some(SpecAxis::Vertical),
+ Self::Bottom => Some(SpecAxis::Vertical),
+ Self::Center => None,
+ }
+ }
+}
+
+impl Switch for AlignArg {
+ type Other = Align;
+
+ fn switch(self, dirs: Gen<Dir>) -> Self::Other {
+ let get = |dir: Dir, at_positive_start| {
+ if dir.is_positive() == at_positive_start {
+ Align::Start
+ } else {
+ Align::End
+ }
+ };
+
+ let dirs = dirs.switch(dirs);
+ match self {
+ Self::Left => get(dirs.horizontal, true),
+ Self::Right => get(dirs.horizontal, false),
+ Self::Top => get(dirs.vertical, true),
+ Self::Bottom => get(dirs.vertical, false),
+ Self::Center => Align::Center,
+ }
+ }
+}
+
+convert_ident!(AlignArg, "alignment", |v| match v {
+ "left" => Some(Self::Left),
+ "right" => Some(Self::Right),
+ "top" => Some(Self::Top),
+ "bottom" => Some(Self::Bottom),
+ "center" => Some(Self::Center),
+ _ => None,
+});
+
+impl Display for AlignArg {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.pad(match self {
+ Self::Left => "left",
+ Self::Right => "right",
+ Self::Top => "top",
+ Self::Bottom => "bottom",
+ Self::Center => "center",
+ })
+ }
+}