mdvault_core/scripting/
bindings.rs1use mlua::{Function, Lua, Result as LuaResult, Table, Value};
7use std::collections::HashMap;
8
9use crate::templates::engine::{RenderContext, render_string};
10use crate::vars::datemath::{evaluate_date_expr, is_date_expr, parse_date_expr};
11
12pub fn register_mdv_table(lua: &Lua) -> LuaResult<()> {
19 let mdv = lua.create_table()?;
20
21 mdv.set("date", create_date_fn(lua)?)?;
22 mdv.set("render", create_render_fn(lua)?)?;
23 mdv.set("is_date_expr", create_is_date_expr_fn(lua)?)?;
24
25 lua.globals().set("mdv", mdv)?;
26 Ok(())
27}
28
29fn create_date_fn(lua: &Lua) -> LuaResult<Function> {
40 lua.create_function(|_, args: (String, Option<String>)| {
41 let (expr, format_override) = args;
42
43 let mut parsed =
45 parse_date_expr(&expr).map_err(|e| mlua::Error::runtime(e.to_string()))?;
46
47 if let Some(fmt) = format_override {
49 parsed.format = Some(fmt);
50 }
51
52 Ok(evaluate_date_expr(&parsed))
53 })
54}
55
56fn create_render_fn(lua: &Lua) -> LuaResult<Function> {
65 lua.create_function(|_, args: (String, Table)| {
66 let (template, ctx_table) = args;
67
68 let mut ctx: RenderContext = HashMap::new();
70
71 for pair in ctx_table.pairs::<String, Value>() {
72 let (key, value) = pair?;
73 let str_value = lua_value_to_string(&key, value)?;
74 ctx.insert(key, str_value);
75 }
76
77 render_string(&template, &ctx).map_err(|e| mlua::Error::runtime(e.to_string()))
78 })
79}
80
81fn create_is_date_expr_fn(lua: &Lua) -> LuaResult<Function> {
90 lua.create_function(|_, s: String| Ok(is_date_expr(&s)))
91}
92
93fn lua_value_to_string(key: &str, value: Value) -> LuaResult<String> {
95 match value {
96 Value::String(s) => Ok(s.to_str()?.to_string()),
97 Value::Integer(i) => Ok(i.to_string()),
98 Value::Number(n) => Ok(n.to_string()),
99 Value::Boolean(b) => Ok(b.to_string()),
100 Value::Nil => Ok(String::new()),
101 _ => Err(mlua::Error::runtime(format!(
102 "context value for '{}' must be string, number, boolean, or nil",
103 key
104 ))),
105 }
106}