From 03fddaf3aea778057aedd74dbcb27bae971ec22f Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 24 Jan 2020 12:44:04 +0100 Subject: =?UTF-8?q?Non-fatal=20argument=20parsing=20=F0=9F=8C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/syntax/func/keys.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 src/syntax/func/keys.rs (limited to 'src/syntax/func/keys.rs') diff --git a/src/syntax/func/keys.rs b/src/syntax/func/keys.rs new file mode 100644 index 00000000..dff97bde --- /dev/null +++ b/src/syntax/func/keys.rs @@ -0,0 +1,121 @@ +use crate::layout::prelude::*; +use super::*; + +use AxisKey::*; +use PaddingKey::*; +use AlignmentValue::*; + + +pub trait Key { + type Output: Eq; + + fn parse(key: Spanned<&str>) -> Option; +} + +impl Key for Spanned { + type Output = Spanned; + + fn parse(key: Spanned<&str>) -> Option { + K::parse(key).map(|v| Spanned { v, span: key.span }) + } +} + +macro_rules! key { + ($type:ty, $output:ty, $($($p:pat)|* => $r:expr),* $(,)?) => { + impl Key for $type { + type Output = $output; + + fn parse(key: Spanned<&str>) -> Option { + match key.v { + $($($p)|* => Some($r)),*, + other => None, + } + } + } + }; +} + +/// An argument key which identifies a layouting axis. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum AxisKey { + Generic(GenericAxis), + Specific(SpecificAxis), +} + +impl AxisKey { + /// The generic version of this axis key in the given system of axes. + pub fn to_generic(self, axes: LayoutAxes) -> GenericAxis { + match self { + Generic(axis) => axis, + Specific(axis) => axis.to_generic(axes), + } + } + + /// The specific version of this axis key in the given system of axes. + pub fn to_specific(self, axes: LayoutAxes) -> SpecificAxis { + match self { + Generic(axis) => axis.to_specific(axes), + Specific(axis) => axis, + } + } +} + +key!(AxisKey, Self, + "horizontal" | "h" => Specific(Horizontal), + "vertical" | "v" => Specific(Vertical), + "primary" | "p" => Generic(Primary), + "secondary" | "s" => Generic(Secondary), +); + +pub struct ExtentKey; + +key!(ExtentKey, AxisKey, + "width" | "w" => Specific(Horizontal), + "height" | "h" => Specific(Vertical), + "primary-size" | "ps" => Generic(Primary), + "secondary-size" | "ss" => Generic(Secondary), +); + +/// An argument key which identifies an axis, but allows for positional +/// arguments with unspecified axes. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum PosAxisKey { + /// The first positional argument. + First, + /// The second positional argument. + Second, + /// An axis keyword argument. + Keyword(AxisKey), +} + +/// An argument key which identifies a margin or padding target. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub enum PaddingKey { + /// All four sides should have the specified padding. + All, + /// Both sides of the given axis should have the specified padding. + Both(Axis), + /// Only the given side of the given axis should have the specified padding. + Side(Axis, AlignmentValue), +} + +key!(PaddingKey, Self, + "horizontal" | "h" => Both(Specific(Horizontal)), + "vertical" | "v" => Both(Specific(Vertical)), + "primary" | "p" => Both(Generic(Primary)), + "secondary" | "s" => Both(Generic(Secondary)), + + "left" => Side(Specific(Horizontal), Left), + "right" => Side(Specific(Horizontal), Right), + "top" => Side(Specific(Vertical), Top), + "bottom" => Side(Specific(Vertical), Bottom), + + "primary-origin" => Side(Generic(Primary), Align(Origin)), + "primary-end" => Side(Generic(Primary), Align(End)), + "secondary-origin" => Side(Generic(Secondary), Align(Origin)), + "secondary-end" => Side(Generic(Secondary), Align(End)), + "horizontal-origin" => Side(Specific(Horizontal), Align(Origin)), + "horizontal-end" => Side(Specific(Horizontal), Align(End)), + "vertical-origin" => Side(Specific(Vertical), Align(Origin)), + "vertical-end" => Side(Specific(Vertical), Align(End)), +); -- cgit v1.2.3