retex-lua 0.9.0

Embedded Lua and the LuaTeX Lua API for retex
Documentation
//! The `status` library (LuaTeX manual ยง10.2).

use mlua::{Lua, Table, Value};

use crate::with_engine;

/// Installs `status`.
pub fn install(lua: &Lua) -> mlua::Result<()> {
    let t = lua.create_table()?;
    let mt = lua.create_table()?;
    mt.set(
        "__index",
        lua.create_function(|lua, (_t, k): (Table, String)| get(lua, &k))?,
    )?;
    t.set_metatable(Some(mt))?;
    t.raw_set(
        "list",
        lua.create_function(|lua, ()| {
            let out = lua.create_table()?;
            for k in [
                "filename",
                "linenumber",
                "luatex_version",
                "luatex_revision",
                "luatex_engine",
                "ini_version",
                "banner",
                "output_active",
                "callbacks",
            ] {
                out.set(k, get(lua, k)?)?;
            }
            Ok(out)
        })?,
    )?;
    lua.globals().set("status", t)?;
    Ok(())
}

fn get(lua: &Lua, k: &str) -> mlua::Result<Value> {
    Ok(match k {
        "luatex_version" => Value::Integer(122),
        "luatex_revision" => Value::String(lua.create_string("0")?),
        "luatex_engine" => Value::String(lua.create_string("luahbtex")?),
        "luatex_verbose" => Value::Integer(0),
        "development_id" => Value::Integer(7673),
        "banner" => Value::String(lua.create_string("This is LuaTeX, Version 1.22.0")?),
        "shell_escape" => Value::Integer(with_engine(lua, |e| e.shell_escape).unwrap_or(2).into()),
        "ini_version" => Value::Boolean(with_engine(lua, |e| e.ini_version).unwrap_or(false)),
        "linenumber" => Value::Integer(with_engine(lua, |e| e.input.line()).unwrap_or(0).into()),
        "filename" => {
            let name = with_engine(lua, |e| {
                e.input
                    .stack
                    .iter()
                    .rev()
                    .find_map(|l| match l {
                        retex_engine::input::Level::Text(t) if t.is_input_file => {
                            Some(t.name.clone())
                        }
                        _ => None,
                    })
                    .unwrap_or_default()
            })
            .unwrap_or_default();
            Value::String(lua.create_string(&name)?)
        }
        "output_active" => Value::Boolean(false),
        "callbacks" => Value::Integer(0),
        _ => Value::Nil,
    })
}