Add (variable|function|mixin)-exists builtin functions
This commit is contained in:
parent
cbec684052
commit
4585558266
@ -10,7 +10,7 @@ use crate::units::Unit;
|
||||
use crate::value::Value;
|
||||
|
||||
pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
decl!(f "rgb", |args| {
|
||||
decl!(f "rgb", |args, _| {
|
||||
let channels = args.get("channels").unwrap_or(&Value::Null);
|
||||
if channels.is_null() {
|
||||
let red: u16 = arg!(args, 0, "red").clone().try_into().unwrap();
|
||||
@ -21,19 +21,19 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
todo!("channels variable in `rgb`")
|
||||
}
|
||||
});
|
||||
decl!(f "red", |args| {
|
||||
decl!(f "red", |args, _| {
|
||||
match arg!(args, 0, "red") {
|
||||
Value::Color(c) => Some(Value::Dimension(BigRational::from_integer(BigInt::from(c.red())), Unit::None)),
|
||||
_ => todo!("non-color given to builtin function `red()`")
|
||||
}
|
||||
});
|
||||
decl!(f "green", |args| {
|
||||
decl!(f "green", |args, _| {
|
||||
match arg!(args, 0, "green") {
|
||||
Value::Color(c) => Some(Value::Dimension(BigRational::from_integer(BigInt::from(c.green())), Unit::None)),
|
||||
_ => todo!("non-color given to builtin function `green()`")
|
||||
}
|
||||
});
|
||||
decl!(f "blue", |args| {
|
||||
decl!(f "blue", |args, _| {
|
||||
match arg!(args, 0, "blue") {
|
||||
Value::Color(c) => Some(Value::Dimension(BigRational::from_integer(BigInt::from(c.blue())), Unit::None)),
|
||||
_ => todo!("non-color given to builtin function `blue()`")
|
||||
|
@ -6,7 +6,7 @@ use crate::units::Unit;
|
||||
use crate::value::Value;
|
||||
|
||||
pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
decl!(f "if", |args| {
|
||||
decl!(f "if", |args, _| {
|
||||
let cond: &Value = arg!(args, 0, "condition");
|
||||
let if_true = arg!(args, 1, "if-true").clone();
|
||||
let if_false = arg!(args, 2, "if-false").clone();
|
||||
@ -16,7 +16,7 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
Some(if_false)
|
||||
}
|
||||
});
|
||||
decl!(f "feature-exists", |args| {
|
||||
decl!(f "feature-exists", |args, _| {
|
||||
let feature: &Value = arg!(args, 0, "feature");
|
||||
match feature.clone().unquote().to_string().as_str() {
|
||||
// A local variable will shadow a global variable unless
|
||||
@ -37,7 +37,7 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
_ => Some(Value::False),
|
||||
}
|
||||
});
|
||||
decl!(f "unit", |args| {
|
||||
decl!(f "unit", |args, _| {
|
||||
let number = arg!(args, 0, "number");
|
||||
let unit = match number {
|
||||
Value::Dimension(_, u) => u.to_string(),
|
||||
@ -45,11 +45,11 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
};
|
||||
Some(Value::Ident(unit, QuoteKind::Double))
|
||||
});
|
||||
decl!(f "type-of", |args| {
|
||||
decl!(f "type-of", |args, _| {
|
||||
let value = arg!(args, 0, "value");
|
||||
Some(Value::Ident(value.kind().to_owned(), QuoteKind::None))
|
||||
});
|
||||
decl!(f "unitless", |args| {
|
||||
decl!(f "unitless", |args, _| {
|
||||
let number = arg!(args, 0, "number");
|
||||
match number {
|
||||
Value::Dimension(_, Unit::None) => Some(Value::True),
|
||||
@ -57,8 +57,20 @@ pub(crate) fn register(f: &mut BTreeMap<String, Builtin>) {
|
||||
_ => Some(Value::True)
|
||||
}
|
||||
});
|
||||
decl!(f "inspect", |args| {
|
||||
decl!(f "inspect", |args, _| {
|
||||
let value = arg!(args, 0, "value");
|
||||
Some(Value::Ident(value.to_string(), QuoteKind::None))
|
||||
});
|
||||
decl!(f "variable-exists", |args, scope| {
|
||||
let value = arg!(args, 0, "name");
|
||||
Some(Value::bool(scope.var_exists(&value.to_string())))
|
||||
});
|
||||
decl!(f "mixin-exists", |args, scope| {
|
||||
let value = arg!(args, 0, "name");
|
||||
Some(Value::bool(scope.mixin_exists(&value.to_string())))
|
||||
});
|
||||
decl!(f "function-exists", |args, scope| {
|
||||
let value = arg!(args, 0, "name");
|
||||
Some(Value::bool(scope.fn_exists(&value.to_string())))
|
||||
});
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use lazy_static::lazy_static;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::args::CallArgs;
|
||||
use crate::common::Scope;
|
||||
use crate::value::Value;
|
||||
|
||||
#[macro_use]
|
||||
@ -15,7 +16,7 @@ mod meta;
|
||||
mod selector;
|
||||
mod string;
|
||||
|
||||
pub(crate) type Builtin = Box<dyn Fn(&CallArgs) -> Option<Value> + Send + Sync>;
|
||||
pub(crate) type Builtin = Box<dyn Fn(&CallArgs, &Scope) -> Option<Value> + Send + Sync>;
|
||||
|
||||
lazy_static! {
|
||||
pub(crate) static ref GLOBAL_FUNCTIONS: BTreeMap<String, Builtin> = {
|
||||
|
@ -200,7 +200,7 @@ impl Value {
|
||||
let func = match scope.get_fn(&s) {
|
||||
Ok(f) => f,
|
||||
Err(_) => match GLOBAL_FUNCTIONS.get(&s) {
|
||||
Some(f) => return f(&args),
|
||||
Some(f) => return f(&args, scope),
|
||||
None => todo!("called undefined function"),
|
||||
},
|
||||
};
|
||||
|
@ -229,6 +229,51 @@ test!(
|
||||
"a {\n color: inspect(null)\n}\n",
|
||||
"a {\n color: null;\n}\n"
|
||||
);
|
||||
test!(
|
||||
variable_does_exist,
|
||||
"$a: red; a {\n color: variable-exists(a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
variable_does_not_exist,
|
||||
"a {\n color: variable-exists(a)\n}\n",
|
||||
"a {\n color: false;\n}\n"
|
||||
);
|
||||
test!(
|
||||
variable_exists_named,
|
||||
"$a: red; a {\n color: variable-exists($name: a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
mixin_does_exist,
|
||||
"@mixin a{} a {\n color: mixin-exists(a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
mixin_does_not_exist,
|
||||
"a {\n color: mixin-exists(a)\n}\n",
|
||||
"a {\n color: false;\n}\n"
|
||||
);
|
||||
test!(
|
||||
mixin_exists_named,
|
||||
"@mixin a{} a {\n color: mixin-exists($name: a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
function_does_exist,
|
||||
"@function a(){} a {\n color: function-exists(a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
test!(
|
||||
function_does_not_exist,
|
||||
"a {\n color: function-exists(a)\n}\n",
|
||||
"a {\n color: false;\n}\n"
|
||||
);
|
||||
test!(
|
||||
function_exists_named,
|
||||
"@function a(){} a {\n color: function-exists($name: a)\n}\n",
|
||||
"a {\n color: true;\n}\n"
|
||||
);
|
||||
// test!(
|
||||
// inspect_empty_list,
|
||||
// "a {\n color: inspect(())\n}\n",
|
||||
|
Loading…
x
Reference in New Issue
Block a user