%% lua-placeholders.tex %% Copyright 2026 E. Nijenhuis % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status ‘maintained’. % % The Current Maintainer of this work is E. Nijenhuis. % % This work consists of the files lua-placeholders.tex % lua-placeholders-manual.pdf lua-placeholders.lua % lua-placeholders-common.lua lua-placeholders-namespace.lua % lua-placeholders-parser.lua and lua-placeholders-types.lua %% %% Defines the engine bridge macros the Lua core defers to, plus user-facing %% commands that mirror the LaTeX side without requiring \newcommand, %% \newenvironment, or any LaTeX2e package. Load with: %% %% \input lua-placeholders %% %% from a plain LuaTeX document. All macros take mandatory arguments; %% switch the active namespace with \setnamespace{name} before \param / %% \forlistitem / etc. % --- Defaults and bridges the Lua core renders into ------------------------ \def\curnamespace{\jobname} \def\paramplaceholder#1{[#1]} \def\paramnotfound#1{[ #1]} \def\paramlistconjunction{, } % --- Engine-specific hotfix wrappers (mirror tex/lua-placeholders.sty) % The .sty wires these to numprint / isodate / xspace; here we keep them % minimal -- a power user can override before \input. \def\paramnumberformat#1{#1} \def\paramdateformat#1#2#3{#1/#2/#3} \def\paramfieldterm{} % --- Boolean flag bridge: \let the if-token directly to \iftrue/\iffalse. % \newif's internal \@if/\if@ machinery requires literal CS names and breaks % when called with \expandafter\newif\csname if#1\endcsname, especially in % plain LuaTeX where @ is "other" at user time. The simpler \let approach % works identically in plain TeX and LaTeX, supports keys with spaces, and % has no package dependency. \def\paramnewbool#1{% \expandafter\ifx\csname if#1\endcsname\relax \expandafter\let\csname if#1\endcsname=\iffalse \fi} \def\paramsetbool#1#2{\csname paramsetbool#2\endcsname{#1}} \def\paramsetbooltrue#1{\expandafter\let\csname if#1\endcsname=\iftrue} \def\paramsetboolfalse#1{\expandafter\let\csname if#1\endcsname=\iffalse} % --- User-callable macros --------------------------------------------------- % No optional arguments (plain TeX has no \newcommand). Set the default % namespace via \setnamespace; per-call namespace can be passed by % temporarily re-\def-ing \curnamespace inside a group. \def\setnamespace#1{\def\curnamespace{#1}} \def\strictparams{\directlua{lua_placeholders.set_strict()}} \def\loadrecipe#1{\directlua{lua_placeholders.recipe('#1', '\curnamespace')}} \def\loadpayload#1{\directlua{lua_placeholders.payload('#1', '\curnamespace')}} \def\param#1{\directlua{lua_placeholders.param('#1', '\curnamespace')}} \def\PARAM#1{\directlua{local p = lua_placeholders.param_object('#1', '\curnamespace') if p then tex.print(p:to_upper()) end}} \def\rawparam#1{\directlua{local p = lua_placeholders.param_object('#1', '\curnamespace') if p then tex.print(p:raw_val() or p.default or p.placeholder) end}} \def\hasparam#1#2#3{% \def\paramhastrue{#2}% \def\paramhasfalse{#3}% \directlua{lua_placeholders.handle_param_is_set('#1', '\curnamespace')}} \def\ifparam#1#2#3{% \directlua{local p = lua_placeholders.param_object('#1','\curnamespace') if p then p:set_bool('#1') end}% \csname if#1\endcsname #2\else #3\fi} \def\paramfield#1#2{\directlua{lua_placeholders.field('#1','#2','\curnamespace')}} % paramobject: plain TeX has no \newenvironment, so the user wraps content % with \paramobject{key}...\endparamobject (matching \begin / \end shape). \def\paramobject#1{\directlua{lua_placeholders.with_object('#1','\curnamespace')}} \def\endparamobject{\directlua{lua_placeholders.exit_object()}} \def\forlistitem#1#2{\directlua{lua_placeholders.for_item('#1','\curnamespace','#2')}} \def\fortablerow#1#2{\directlua{lua_placeholders.with_rows('#1','\curnamespace','#2')}} % --- Load the Lua core ------------------------------------------------------ \directlua{lua_placeholders = require('lua-placeholders')} \endinput