diff --git a/src/library/align.rs b/src/library/align.rs index 616ede6b3..e6952dc21 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -13,8 +13,8 @@ function! { parse(args, body, ctx) { let mut map = ConsistentMap::new(); - map.add_opt_span(Key::First, args.get_pos_opt::()?)?; - map.add_opt_span(Key::Second, args.get_pos_opt::()?)?; + map.add_opt(Key::First, args.get_pos_opt::()?)?; + map.add_opt(Key::Second, args.get_pos_opt::()?)?; for arg in args.keys() { let axis = AxisKey::from_ident(&arg.v.key)?; diff --git a/src/library/boxed.rs b/src/library/boxed.rs index c205eec66..2d0d6e6b6 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -14,9 +14,7 @@ function! { Boxed { body: parse!(optional: body, ctx).unwrap_or(SyntaxTree::new()), map: ExtentMap::new(&mut args, false)?, - debug: args.get_key_opt::("debug")? - .map(Spanned::value) - .unwrap_or(true), + debug: args.get_key_opt::("debug")?.unwrap_or(true), } } diff --git a/src/library/direction.rs b/src/library/direction.rs index ac1fac08f..59c0d1fd2 100644 --- a/src/library/direction.rs +++ b/src/library/direction.rs @@ -13,8 +13,8 @@ function! { parse(args, body, ctx) { let mut map = ConsistentMap::new(); - map.add_opt_span(AxisKey::Primary, args.get_pos_opt::()?)?; - map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::()?)?; + map.add_opt(AxisKey::Primary, args.get_pos_opt::()?)?; + map.add_opt(AxisKey::Secondary, args.get_pos_opt::()?)?; for arg in args.keys() { let axis = AxisKey::from_ident(&arg.v.key)?; diff --git a/src/library/maps.rs b/src/library/maps.rs index 4eafd9cc9..13b4dc5d6 100644 --- a/src/library/maps.rs +++ b/src/library/maps.rs @@ -31,13 +31,6 @@ impl ConsistentMap where K: Hash + Eq { }) } - /// Add a key-spanned-value pair the value is not `None`. - pub fn add_opt_span(&mut self, key: K, value: Option>) -> ParseResult<()> { - Ok(if let Some(spanned) = value { - self.add(key, spanned.v)?; - }) - } - /// Call a function with the value if the key is present. pub fn with(&self, key: K, callback: F) where F: FnOnce(&V) { if let Some(value) = self.map.get(&key) { @@ -143,7 +136,7 @@ impl PaddingMap { pub fn new(args: &mut FuncArgs, enforce: bool) -> ParseResult { let mut map = ConsistentMap::new(); - map.add_opt_span(PaddingKey::All, args.get_pos_opt::()?)?; + map.add_opt(PaddingKey::All, args.get_pos_opt::()?)?; for arg in args.keys() { let key = match PaddingKey::from_ident(&arg.v.key) { diff --git a/src/library/mod.rs b/src/library/mod.rs index 0fcc86470..9a49896b2 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -133,7 +133,7 @@ function! { let spacing = if let Some(axis) = meta { Spacing { axis, - spacing: FSize::from_expr(args.get_pos::()?)?, + spacing: FSize::from_expr(args.get_pos::>()?)?, } } else { if let Some(arg) = args.get_key_next() { @@ -178,15 +178,7 @@ function! { layout(self, ctx) { let mut style = ctx.style.text.clone(); style.toggle_class(self.class.clone()); - - match &self.body { - Some(body) => vec![ - SetTextStyle(style), - LayoutTree(body), - SetTextStyle(ctx.style.text.clone()), - ], - None => vec![SetTextStyle(style)] - } + styled(&self.body, &ctx, style) } } @@ -201,21 +193,29 @@ function! { parse(args, body, ctx) { FontSize { body: parse!(optional: body, ctx), - size: args.get_pos::()?.v, + size: args.get_pos::()?, } } layout(self, ctx) { let mut style = ctx.style.text.clone(); style.font_size = self.size; - - match &self.body { - Some(body) => vec![ - SetTextStyle(style), - LayoutTree(body), - SetTextStyle(ctx.style.text.clone()), - ], - None => vec![SetTextStyle(style)] - } + styled(&self.body, &ctx, style) + } +} + +/// Layout the body with the style or update the style if there is no body. +fn styled<'a>( + body: &'a Option, + ctx: &LayoutContext, + style: TextStyle +) -> Commands<'a> { + match &body { + Some(body) => vec![ + SetTextStyle(style), + LayoutTree(body), + SetTextStyle(ctx.style.text.clone()), + ], + None => vec![SetTextStyle(style)] } } diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index 2f64bc9b4..57488121d 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -121,16 +121,15 @@ impl FuncArgs { } /// Force-extract the first positional argument. - pub fn get_pos(&mut self) -> ParseResult> { + pub fn get_pos(&mut self) -> ParseResult { expect(self.get_pos_opt()) } /// Extract the first positional argument. - pub fn get_pos_opt(&mut self) -> ParseResult>> { + pub fn get_pos_opt(&mut self) -> ParseResult> { Ok(if !self.pos.is_empty() { let spanned = self.pos.remove(0); - let span = spanned.span; - Some(Spanned::new(E::from_expr(spanned)?, span)) + Some(E::from_expr(spanned)?) } else { None }) @@ -143,15 +142,15 @@ impl FuncArgs { } /// Force-extract a keyword argument. - pub fn get_key(&mut self, name: &str) -> ParseResult> { + pub fn get_key(&mut self, name: &str) -> ParseResult { expect(self.get_key_opt(name)) } /// Extract a keyword argument. - pub fn get_key_opt(&mut self, name: &str) -> ParseResult>> { + pub fn get_key_opt(&mut self, name: &str) -> ParseResult> { Ok(if let Some(index) = self.key.iter().position(|arg| arg.v.key.v.0 == name) { - let Spanned { v, span } = self.key.swap_remove(index); - Some(Spanned::new(E::from_expr(v.value)?, span)) + let value = self.key.swap_remove(index).v.value; + Some(E::from_expr(value)?) } else { None }) @@ -181,7 +180,7 @@ impl FuncArgs { } /// Extract the option expression kind from the option or return an error. -fn expect(opt: ParseResult>>) -> ParseResult> { +fn expect(opt: ParseResult>) -> ParseResult { match opt { Ok(Some(spanned)) => Ok(spanned), Ok(None) => error!("expected {}", E::NAME), @@ -308,3 +307,13 @@ kind!(ScaleSize, "number or size", Expression::Size(size) => ScaleSize::Absolute(size), Expression::Num(scale) => ScaleSize::Scaled(scale as f32) ); + +impl ExpressionKind for Spanned where T: ExpressionKind { + const NAME: &'static str = T::NAME; + + fn from_expr(expr: Spanned) -> ParseResult> { + let span = expr.span; + T::from_expr(expr) + .map(|v| Spanned::new(v, span)) + } +}