implement builtin function nth
This commit is contained in:
parent
fb84361fae
commit
dd1c1e5b06
@ -1,5 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use num_traits::cast::ToPrimitive;
|
||||||
|
|
||||||
use super::Builtin;
|
use super::Builtin;
|
||||||
use crate::unit::Unit;
|
use crate::unit::Unit;
|
||||||
use crate::value::{Number, Value};
|
use crate::value::{Number, Value};
|
||||||
@ -16,4 +18,41 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
|
|||||||
Ok(Value::Dimension(len, Unit::None))
|
Ok(Value::Dimension(len, Unit::None))
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
f.insert(
|
||||||
|
"nth".to_owned(),
|
||||||
|
Box::new(|args, _| {
|
||||||
|
max_args!(args, 2);
|
||||||
|
let list = match arg!(args, 0, "list") {
|
||||||
|
Value::List(v, _) => v,
|
||||||
|
_ => return Err("Missing argument $list.".into()),
|
||||||
|
};
|
||||||
|
let n = match arg!(args, 1, "n") {
|
||||||
|
Value::Dimension(num, _) => num,
|
||||||
|
v => return Err(format!("$n: {} is not a number.", v).into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if n == Number::from(0) {
|
||||||
|
return Err("$n: List index may not be 0.".into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.abs() > Number::from(list.len()) {
|
||||||
|
return Err(format!(
|
||||||
|
"$n: Invalid index {} for a list with {} elements.",
|
||||||
|
n,
|
||||||
|
list.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.is_decimal() {
|
||||||
|
return Err(format!("$n: {} is not an int.", n).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if n > Number::from(0) {
|
||||||
|
Ok(list[n.to_integer().to_usize().unwrap() - 1].clone())
|
||||||
|
} else {
|
||||||
|
Ok(list[list.len() - n.abs().to_integer().to_usize().unwrap()].clone())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -28,25 +28,25 @@ impl Number {
|
|||||||
Number::new(BigRational::new(a.into(), b.into()))
|
Number::new(BigRational::new(a.into(), b.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn round(self) -> Self {
|
pub fn round(&self) -> Self {
|
||||||
Number {
|
Number {
|
||||||
val: self.val.round(),
|
val: self.val.round(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ceil(self) -> Self {
|
pub fn ceil(&self) -> Self {
|
||||||
Number {
|
Number {
|
||||||
val: self.val.ceil(),
|
val: self.val.ceil(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn floor(self) -> Self {
|
pub fn floor(&self) -> Self {
|
||||||
Number {
|
Number {
|
||||||
val: self.val.floor(),
|
val: self.val.floor(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn abs(self) -> Self {
|
pub fn abs(&self) -> Self {
|
||||||
Number {
|
Number {
|
||||||
val: self.val.abs(),
|
val: self.val.abs(),
|
||||||
}
|
}
|
||||||
|
@ -18,3 +18,18 @@ test!(
|
|||||||
"a {\n color: length((1, 2, 3, 4, 5));\n}\n",
|
"a {\n color: length((1, 2, 3, 4, 5));\n}\n",
|
||||||
"a {\n color: 5;\n}\n"
|
"a {\n color: 5;\n}\n"
|
||||||
);
|
);
|
||||||
|
test!(
|
||||||
|
nth_space_separated,
|
||||||
|
"a {\n color: nth(a b c, 1);\n}\n",
|
||||||
|
"a {\n color: a;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
nth_negative_index,
|
||||||
|
"a {\n color: nth(a b c, -2);\n}\n",
|
||||||
|
"a {\n color: b;\n}\n"
|
||||||
|
);
|
||||||
|
test!(
|
||||||
|
nth_comma_separated,
|
||||||
|
"a {\n color: nth((a, b, c), 3);\n}\n",
|
||||||
|
"a {\n color: c;\n}\n"
|
||||||
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user