Implement expression kind for Spanned<T> 👩💻
This commit is contained in:
parent
f549914ff8
commit
971ff3a2dc
@ -13,8 +13,8 @@ function! {
|
||||
parse(args, body, ctx) {
|
||||
let mut map = ConsistentMap::new();
|
||||
|
||||
map.add_opt_span(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
|
||||
map.add_opt_span(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;
|
||||
map.add_opt(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
|
||||
map.add_opt(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;
|
||||
|
||||
for arg in args.keys() {
|
||||
let axis = AxisKey::from_ident(&arg.v.key)?;
|
||||
|
@ -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::<bool>("debug")?
|
||||
.map(Spanned::value)
|
||||
.unwrap_or(true),
|
||||
debug: args.get_key_opt::<bool>("debug")?.unwrap_or(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,8 +13,8 @@ function! {
|
||||
parse(args, body, ctx) {
|
||||
let mut map = ConsistentMap::new();
|
||||
|
||||
map.add_opt_span(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
|
||||
map.add_opt_span(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
|
||||
map.add_opt(AxisKey::Primary, args.get_pos_opt::<Direction>()?)?;
|
||||
map.add_opt(AxisKey::Secondary, args.get_pos_opt::<Direction>()?)?;
|
||||
|
||||
for arg in args.keys() {
|
||||
let axis = AxisKey::from_ident(&arg.v.key)?;
|
||||
|
@ -31,13 +31,6 @@ impl<K, V> ConsistentMap<K, V> 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<Spanned<V>>) -> 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<F>(&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<PaddingMap> {
|
||||
let mut map = ConsistentMap::new();
|
||||
|
||||
map.add_opt_span(PaddingKey::All, args.get_pos_opt::<Size>()?)?;
|
||||
map.add_opt(PaddingKey::All, args.get_pos_opt::<Size>()?)?;
|
||||
|
||||
for arg in args.keys() {
|
||||
let key = match PaddingKey::from_ident(&arg.v.key) {
|
||||
|
@ -133,7 +133,7 @@ function! {
|
||||
let spacing = if let Some(axis) = meta {
|
||||
Spacing {
|
||||
axis,
|
||||
spacing: FSize::from_expr(args.get_pos::<Expression>()?)?,
|
||||
spacing: FSize::from_expr(args.get_pos::<Spanned<Expression>>()?)?,
|
||||
}
|
||||
} 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::<Size>()?.v,
|
||||
size: args.get_pos::<Size>()?,
|
||||
}
|
||||
}
|
||||
|
||||
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<SyntaxTree>,
|
||||
ctx: &LayoutContext,
|
||||
style: TextStyle
|
||||
) -> Commands<'a> {
|
||||
match &body {
|
||||
Some(body) => vec![
|
||||
SetTextStyle(style),
|
||||
LayoutTree(body),
|
||||
SetTextStyle(ctx.style.text.clone()),
|
||||
],
|
||||
None => vec![SetTextStyle(style)]
|
||||
}
|
||||
}
|
||||
|
@ -121,16 +121,15 @@ impl FuncArgs {
|
||||
}
|
||||
|
||||
/// Force-extract the first positional argument.
|
||||
pub fn get_pos<E: ExpressionKind>(&mut self) -> ParseResult<Spanned<E>> {
|
||||
pub fn get_pos<E: ExpressionKind>(&mut self) -> ParseResult<E> {
|
||||
expect(self.get_pos_opt())
|
||||
}
|
||||
|
||||
/// Extract the first positional argument.
|
||||
pub fn get_pos_opt<E: ExpressionKind>(&mut self) -> ParseResult<Option<Spanned<E>>> {
|
||||
pub fn get_pos_opt<E: ExpressionKind>(&mut self) -> ParseResult<Option<E>> {
|
||||
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<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Spanned<E>> {
|
||||
pub fn get_key<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<E> {
|
||||
expect(self.get_key_opt(name))
|
||||
}
|
||||
|
||||
/// Extract a keyword argument.
|
||||
pub fn get_key_opt<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Option<Spanned<E>>> {
|
||||
pub fn get_key_opt<E: ExpressionKind>(&mut self, name: &str) -> ParseResult<Option<E>> {
|
||||
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<E: ExpressionKind>(opt: ParseResult<Option<Spanned<E>>>) -> ParseResult<Spanned<E>> {
|
||||
fn expect<E: ExpressionKind>(opt: ParseResult<Option<E>>) -> ParseResult<E> {
|
||||
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<T> ExpressionKind for Spanned<T> where T: ExpressionKind {
|
||||
const NAME: &'static str = T::NAME;
|
||||
|
||||
fn from_expr(expr: Spanned<Expression>) -> ParseResult<Spanned<T>> {
|
||||
let span = expr.span;
|
||||
T::from_expr(expr)
|
||||
.map(|v| Spanned::new(v, span))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user