summaryrefslogtreecommitdiff
path: root/src/syntax/func/keys.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-01-24 12:44:04 +0100
committerLaurenz <laurmaedje@gmail.com>2020-01-24 12:44:04 +0100
commit03fddaf3aea778057aedd74dbcb27bae971ec22f (patch)
tree37e3136e29e0e5d69ec8f56e43d156739d2931ab /src/syntax/func/keys.rs
parent78da2bdd5d77d1b8572e5e9da119bfa68127a3fa (diff)
Non-fatal argument parsing 🌋
Diffstat (limited to 'src/syntax/func/keys.rs')
-rw-r--r--src/syntax/func/keys.rs121
1 files changed, 121 insertions, 0 deletions
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<Self::Output>;
+}
+
+impl<K: Key> Key for Spanned<K> {
+ type Output = Spanned<K::Output>;
+
+ fn parse(key: Spanned<&str>) -> Option<Self::Output> {
+ 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<Self::Output> {
+ 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<Axis> {
+ /// 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<AxisKey>, 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)),
+);