use mlua::{Lua, MultiValue, Table, Value};
use retex_engine::fonts::PacketCommand;
use crate::pdflib::{MODES, check_integer, coerce_bytes};
use crate::with_engine;
pub fn install(lua: &Lua) -> mlua::Result<()> {
let t = lua.create_table()?;
simple(lua, &t, "push", PacketCommand::Push)?;
simple(lua, &t, "pop", PacketCommand::Pop)?;
t.set("nop", lua.create_function(|_, _: MultiValue| Ok(()))?)?;
for name in ["right", "down"] {
let f = crate::create_function_caller_errors(lua, move |lua, args: MultiValue| {
let x = check_integer(lua, args.front(), 1, name)?;
with_engine(lua, |e| {
if let Some(x) = e.vf_scaled(x) {
let cmd = if name == "right" {
PacketCommand::Right(x)
} else {
PacketCommand::Down(x)
};
e.vf_command(&cmd);
}
})
})?;
t.set(name, f)?;
}
t.set(
"rule",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let w = check_integer(lua, args.front(), 1, "rule")?;
let h = check_integer(lua, args.get(1), 2, "rule")?;
with_engine(lua, |e| {
if let (Some(width), Some(height)) = (e.vf_scaled(w), e.vf_scaled(h)) {
e.vf_command(&PacketCommand::Rule { height, width });
}
})
})?,
)?;
t.set(
"char",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let c = check_integer(lua, args.front(), 1, "char")?;
with_engine(lua, |e| {
e.vf_command(&PacketCommand::Char(c as u32));
})
})?,
)?;
t.set(
"fontid",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let f = check_integer(lua, args.front(), 1, "fontid")?;
with_engine(lua, |e| {
if f > 0 && e.font_exists(f as i32) {
e.vf_command(&PacketCommand::FontId(f as u32));
}
})
})?,
)?;
t.set(
"special",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let Some(s) = args
.front()
.map(|v| coerce_bytes(lua, v))
.transpose()?
.flatten()
else {
return Ok(());
};
with_engine(lua, |e| {
e.vf_command(&PacketCommand::Special(s));
})
})?,
)?;
t.set(
"pdf",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let args = args.into_vec();
let (mode, text) = match args.as_slice() {
[text] => (retex_engine::pdfext::literal_mode::ORIGIN, text),
[Value::String(m), text, ..] => {
let m = m.as_bytes();
let mode = MODES
.iter()
.chain(&[("font", 5)])
.find(|(n, _)| n.as_bytes() == m.as_ref())
.map_or(retex_engine::pdfext::literal_mode::ORIGIN, |&(_, m)| m);
(mode, text)
}
_ => return Ok(()),
};
let Some(text) = coerce_bytes(lua, text)? else {
return Ok(());
};
with_engine(lua, |e| {
e.vf_command(&PacketCommand::Pdf(mode, text));
})
})?,
)?;
t.set(
"node",
crate::create_function_caller_errors(lua, |lua, args: MultiValue| {
let Some(p) = args.front().and_then(crate::nodelib::to_ref) else {
return Ok(());
};
with_engine(lua, |e| {
if !e.nodes.is_free(p) {
e.vf_command(&PacketCommand::Node(p));
}
})
})?,
)?;
t.set("image", lua.create_function(|_, _: MultiValue| Ok(()))?)?;
lua.globals().set("vf", t)
}
fn simple(lua: &Lua, t: &Table, name: &str, cmd: PacketCommand) -> mlua::Result<()> {
let f = lua.create_function(move |lua, _: MultiValue| {
with_engine(lua, |e| {
e.vf_command(&cmd);
})
})?;
t.set(name, f)
}