properly parse and emit bracketed lists
This commit is contained in:
parent
9233b1d2ba
commit
981bf27cb8
@ -18,7 +18,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
if args.len() == 1 {
|
||||
let mut channels = match arg!(args, 0, "channels") {
|
||||
Value::List(v, _) => v,
|
||||
Value::List(v, ..) => v,
|
||||
_ => return Err("Missing argument $channels.".into()),
|
||||
};
|
||||
|
||||
@ -96,7 +96,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
if args.len() == 1 {
|
||||
let mut channels = match arg!(args, 0, "channels") {
|
||||
Value::List(v, _) => v,
|
||||
Value::List(v, ..) => v,
|
||||
_ => return Err("Missing argument $channels.".into()),
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
if args.len() == 1 {
|
||||
let mut channels = match arg!(args, 0, "channels") {
|
||||
Value::List(v, _) => v,
|
||||
Value::List(v, ..) => v,
|
||||
_ => return Err("Missing argument $channels.".into()),
|
||||
};
|
||||
|
||||
@ -139,7 +139,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
if args.len() == 1 {
|
||||
let mut channels = match arg!(args, 0, "channels") {
|
||||
Value::List(v, _) => v,
|
||||
Value::List(v, ..) => v,
|
||||
_ => return Err("Missing argument $channels.".into()),
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
|
||||
use super::Builtin;
|
||||
use crate::common::{ListSeparator, QuoteKind};
|
||||
use crate::common::{Brackets, ListSeparator, QuoteKind};
|
||||
use crate::unit::Unit;
|
||||
use crate::value::{Number, Value};
|
||||
|
||||
@ -13,7 +13,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 1);
|
||||
let len = match arg!(args, 0, "list") {
|
||||
Value::List(v, _) => Number::from(v.len()),
|
||||
Value::List(v, ..) => Number::from(v.len()),
|
||||
_ => Number::one(),
|
||||
};
|
||||
Ok(Value::Dimension(len, Unit::None))
|
||||
@ -24,7 +24,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 2);
|
||||
let list = match arg!(args, 0, "list") {
|
||||
Value::List(v, _) => v,
|
||||
Value::List(v, ..) => v,
|
||||
v => vec![v],
|
||||
};
|
||||
let n = match arg!(args, 1, "n") {
|
||||
@ -62,7 +62,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
max_args!(args, 1);
|
||||
Ok(Value::Ident(
|
||||
match arg!(args, 0, "list") {
|
||||
Value::List(_, sep) => sep.name(),
|
||||
Value::List(_, sep, ..) => sep.name(),
|
||||
_ => ListSeparator::Space.name(),
|
||||
}
|
||||
.to_owned(),
|
||||
@ -75,7 +75,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 3);
|
||||
let (mut list, sep) = match arg!(args, 0, "list") {
|
||||
Value::List(v, sep) => (v, sep),
|
||||
Value::List(v, sep, ..) => (v, sep),
|
||||
v => (vec![v], ListSeparator::Space),
|
||||
};
|
||||
let n = match arg!(args, 1, "n") {
|
||||
@ -107,7 +107,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
list[len - n.abs().to_integer().to_usize().unwrap()] = val;
|
||||
}
|
||||
|
||||
Ok(Value::List(list, sep))
|
||||
Ok(Value::List(list, sep, Brackets::None))
|
||||
}),
|
||||
);
|
||||
f.insert(
|
||||
@ -115,7 +115,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 3);
|
||||
let (mut list, sep) = match arg!(args, 0, "list") {
|
||||
Value::List(v, sep) => (v, sep),
|
||||
Value::List(v, sep, ..) => (v, sep),
|
||||
v => (vec![v], ListSeparator::Space),
|
||||
};
|
||||
let val = arg!(args, 1, "val");
|
||||
@ -137,16 +137,16 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
list.push(val);
|
||||
|
||||
Ok(Value::List(list, sep))
|
||||
Ok(Value::List(list, sep, Brackets::None))
|
||||
}),
|
||||
);
|
||||
f.insert(
|
||||
"join".to_owned(),
|
||||
Box::new(|args, _| {
|
||||
max_args!(args, 3);
|
||||
let (mut list1, sep1) = match arg!(args, 0, "list") {
|
||||
Value::List(v, sep) => (v, sep),
|
||||
v => (vec![v], ListSeparator::Space),
|
||||
let (mut list1, sep1, brackets) = match arg!(args, 0, "list") {
|
||||
Value::List(v, sep, brackets) => (v, sep, brackets),
|
||||
v => (vec![v], ListSeparator::Space, Brackets::None),
|
||||
};
|
||||
let list2 = match arg!(args, 1, "list") {
|
||||
Value::List(v, ..) => v,
|
||||
@ -176,7 +176,7 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
||||
|
||||
list1.extend(list2);
|
||||
|
||||
Ok(Value::List(list1, sep))
|
||||
Ok(Value::List(list1, sep, brackets))
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -383,6 +383,12 @@ impl Display for QuoteKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum Brackets {
|
||||
None,
|
||||
Bracketed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ListSeparator {
|
||||
Space,
|
||||
|
@ -2,7 +2,7 @@ use std::fmt::{self, Display, Write};
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::common::{ListSeparator, Op, QuoteKind};
|
||||
use crate::common::{Brackets, ListSeparator, Op, QuoteKind};
|
||||
use crate::error::SassResult;
|
||||
use crate::unit::Unit;
|
||||
pub(crate) use number::Number;
|
||||
@ -18,7 +18,7 @@ pub(crate) enum Value {
|
||||
False,
|
||||
Null,
|
||||
Dimension(Number, Unit),
|
||||
List(Vec<Value>, ListSeparator),
|
||||
List(Vec<Value>, ListSeparator, Brackets),
|
||||
Color(Color),
|
||||
UnaryOp(Op, Box<Value>),
|
||||
BinaryOp(Box<Value>, Op, Box<Value>),
|
||||
@ -39,14 +39,24 @@ impl Display for Value {
|
||||
}
|
||||
_ => write!(f, "{}{}", num, unit),
|
||||
},
|
||||
Self::List(vals, sep) => write!(
|
||||
Self::List(vals, sep, brackets) => match brackets {
|
||||
Brackets::None => write!(
|
||||
f,
|
||||
"{}",
|
||||
vals.iter()
|
||||
.map(std::string::ToString::to_string)
|
||||
.collect::<Vec<String>>()
|
||||
.join(sep.as_str())
|
||||
.join(sep.as_str()),
|
||||
),
|
||||
Brackets::Bracketed => write!(
|
||||
f,
|
||||
"[{}]",
|
||||
vals.iter()
|
||||
.map(std::string::ToString::to_string)
|
||||
.collect::<Vec<String>>()
|
||||
.join(sep.as_str()),
|
||||
),
|
||||
},
|
||||
Self::Color(c) => write!(f, "{}", c),
|
||||
Self::UnaryOp(..) | Self::BinaryOp(..) => write!(
|
||||
f,
|
||||
|
@ -8,7 +8,7 @@ use num_traits::pow;
|
||||
use crate::args::eat_call_args;
|
||||
use crate::builtin::GLOBAL_FUNCTIONS;
|
||||
use crate::color::Color;
|
||||
use crate::common::{Keyword, ListSeparator, Op, QuoteKind, Symbol};
|
||||
use crate::common::{Brackets, Keyword, ListSeparator, Op, QuoteKind, Symbol};
|
||||
use crate::error::SassResult;
|
||||
use crate::scope::Scope;
|
||||
use crate::selector::Selector;
|
||||
@ -82,19 +82,23 @@ impl Value {
|
||||
None => return Ok(left),
|
||||
};
|
||||
match next.kind {
|
||||
TokenKind::Symbol(Symbol::SemiColon) | TokenKind::Symbol(Symbol::CloseParen) => {
|
||||
Ok(left)
|
||||
}
|
||||
TokenKind::Symbol(Symbol::SemiColon)
|
||||
| TokenKind::Symbol(Symbol::CloseParen)
|
||||
| TokenKind::Symbol(Symbol::CloseSquareBrace) => Ok(left),
|
||||
TokenKind::Symbol(Symbol::Comma) => {
|
||||
toks.next();
|
||||
devour_whitespace_or_comment(toks);
|
||||
let right = Self::from_tokens(toks, scope, super_selector)?;
|
||||
if let Value::List(v, ListSeparator::Comma) = right {
|
||||
if let Value::List(v, ListSeparator::Comma, Brackets::None) = right {
|
||||
let mut v2 = vec![left];
|
||||
v2.extend(v);
|
||||
Ok(Value::List(v2, ListSeparator::Comma))
|
||||
Ok(Value::List(v2, ListSeparator::Comma, Brackets::None))
|
||||
} else {
|
||||
Ok(Value::List(vec![left, right], ListSeparator::Comma))
|
||||
Ok(Value::List(
|
||||
vec![left, right],
|
||||
ListSeparator::Comma,
|
||||
Brackets::None,
|
||||
))
|
||||
}
|
||||
}
|
||||
TokenKind::Symbol(Symbol::Plus)
|
||||
@ -120,12 +124,16 @@ impl Value {
|
||||
_ => {
|
||||
devour_whitespace_or_comment(toks);
|
||||
let right = Self::from_tokens(toks, scope, super_selector)?;
|
||||
if let Value::List(v, ListSeparator::Space) = right {
|
||||
if let Value::List(v, ListSeparator::Space, Brackets::None) = right {
|
||||
let mut v2 = vec![left];
|
||||
v2.extend(v);
|
||||
Ok(Value::List(v2, ListSeparator::Space))
|
||||
Ok(Value::List(v2, ListSeparator::Space, Brackets::None))
|
||||
} else {
|
||||
Ok(Value::List(vec![left, right], ListSeparator::Space))
|
||||
Ok(Value::List(
|
||||
vec![left, right],
|
||||
ListSeparator::Space,
|
||||
Brackets::None,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -184,7 +192,11 @@ impl Value {
|
||||
devour_whitespace_or_comment(toks);
|
||||
if toks.peek().unwrap().is_symbol(Symbol::CloseParen) {
|
||||
toks.next();
|
||||
return Ok(Value::List(Vec::new(), ListSeparator::Space));
|
||||
return Ok(Value::List(
|
||||
Vec::new(),
|
||||
ListSeparator::Space,
|
||||
Brackets::None,
|
||||
));
|
||||
}
|
||||
let val = Self::from_tokens(toks, scope, super_selector)?;
|
||||
let next = toks.next();
|
||||
@ -265,6 +277,15 @@ impl Value {
|
||||
| q @ TokenKind::Symbol(Symbol::SingleQuote) => {
|
||||
parse_quoted_string(toks, scope, &q, super_selector)
|
||||
}
|
||||
TokenKind::Symbol(Symbol::OpenSquareBrace) => {
|
||||
let inner = Self::from_tokens(toks, scope, super_selector)?;
|
||||
devour_whitespace_or_comment(toks);
|
||||
toks.next();
|
||||
Ok(match inner {
|
||||
Value::List(v, sep, ..) => Value::List(v, sep, Brackets::Bracketed),
|
||||
v => Value::List(vec![v], ListSeparator::Space, Brackets::Bracketed),
|
||||
})
|
||||
}
|
||||
TokenKind::Variable(ref v) => Ok(scope.get_var(v)?),
|
||||
TokenKind::Interpolation => {
|
||||
let mut s = parse_interpolation(toks, scope, super_selector)?.to_string();
|
||||
|
@ -140,8 +140,12 @@ test!(
|
||||
"a {\n color: join((a, b), (c, d), space);\n}\n",
|
||||
"a {\n color: a b c d;\n}\n"
|
||||
);
|
||||
// test!(
|
||||
// join_bracketed,
|
||||
// "a {\n color: join([a], b);\n}\n",
|
||||
// "a {\n color: [a b];\n}\n"
|
||||
// );
|
||||
test!(
|
||||
join_bracketed,
|
||||
"a {\n color: join([a], b);\n}\n",
|
||||
"a {\n color: [a b];\n}\n"
|
||||
);
|
||||
test!(bracketed_ident, "a {\n color: [a];\n}\n");
|
||||
test!(bracketed_space_list, "a {\n color: [a b];\n}\n");
|
||||
test!(bracketed_comma_list, "a {\n color: [a, b];\n}\n");
|
||||
test!(bracketed_as_space_list, "a {\n color: [a b] c;\n}\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user