implement builtin function set-nth()

This commit is contained in:
ConnorSkees 2020-03-20 19:27:26 -04:00
parent 5ce2515fb6
commit 4fdac4c5f1
2 changed files with 60 additions and 0 deletions

View File

@ -70,4 +70,44 @@ pub(crate) fn register(f: &mut HashMap<String, Builtin>) {
)) ))
}), }),
); );
f.insert(
"set-nth".to_owned(),
Box::new(|args, _| {
max_args!(args, 3);
let (mut list, sep) = match arg!(args, 0, "list") {
Value::List(v, sep) => (v, sep),
v => (vec![v], ListSeparator::Space),
};
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());
}
let len = list.len();
if n.abs() > Number::from(len) {
return Err(
format!("$n: Invalid index {} for a list with {} elements.", n, len).into(),
);
}
if n.is_decimal() {
return Err(format!("$n: {} is not an int.", n).into());
}
let val = arg!(args, 2, "value");
if n > Number::from(0) {
list[n.to_integer().to_usize().unwrap() - 1] = val;
} else {
list[len - n.abs().to_integer().to_usize().unwrap()] = val;
}
Ok(Value::List(list, sep))
}),
);
} }

View File

@ -60,3 +60,23 @@ test!(
// "a {\n color: list-separator(((a b, c d)));\n}\n", // "a {\n color: list-separator(((a b, c d)));\n}\n",
// "a {\n color: comma;\n}\n" // "a {\n color: comma;\n}\n"
// ); // );
test!(
set_nth_named_args,
"a {\n color: set-nth($list: 1 2 3, $n: 2, $value: foo);\n}\n",
"a {\n color: 1 foo 3;\n}\n"
);
test!(
set_nth_non_list,
"a {\n color: set-nth(c, 1, e);\n}\n",
"a {\n color: e;\n}\n"
);
test!(
set_nth_2_long,
"a {\n color: set-nth(c d, 1, e);\n}\n",
"a {\n color: e d;\n}\n"
);
test!(
set_nth_comma_separated,
"a {\n color: set-nth((a, b, c), 1, e);\n}\n",
"a {\n color: e, b, c;\n}\n"
);