retex-lua 1.0.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",
                "development_id",
                "total_pages",
                "log_name",
                "shell_escape",
                "safer_option",
                "kpse_used",
                "luatex_hashtype",
                "luatex_hashchars",
                "buf_size",
                "hash_size",
                "hash_extra",
                "max_strings",
                "nest_size",
                "param_size",
                "save_size",
                "stack_size",
                "dest_names_size",
                "obj_tab_size",
                "pdf_mem_size",
            ] {
                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),
        "total_pages" => Value::Integer(with_engine(lua, |e| e.total_pages).unwrap_or(0).into()),
        "log_name" => {
            let name = with_engine(lua, |e| {
                e.files
                    .log_name
                    .as_ref()
                    .map(|p| p.to_string_lossy().into_owned())
            })
            .ok()
            .flatten();
            match name {
                Some(n) => Value::String(lua.create_string(&n)?),
                None => Value::Nil,
            }
        }
        // Fixed values of LuaTeX 1.22 as TeX Live configures it.
        "safer_option" | "luadebug_option" => Value::Integer(0),
        "kpse_used" => Value::Integer(1),
        "luatex_hashtype" => Value::String(lua.create_string("lua")?),
        "luatex_hashchars" => Value::Integer(6),
        "buf_size" | "save_size" => Value::Integer(200_000),
        "hash_size" => Value::Integer(65_536),
        "hash_extra" => Value::Integer(600_000),
        "max_strings" => Value::Integer(500_000),
        "nest_size" | "dest_names_size" | "obj_tab_size" => Value::Integer(1000),
        "param_size" => Value::Integer(20_000),
        "stack_size" | "pdf_mem_size" => Value::Integer(10_000),
        "callbacks" => Value::Integer(0),
        _ => Value::Nil,
    })
}