summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua')
-rw-r--r--macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua217
1 files changed, 217 insertions, 0 deletions
diff --git a/macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua b/macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua
new file mode 100644
index 0000000000..255b4d1f26
--- /dev/null
+++ b/macros/luatex/latex/lua-placeholders/scripts/lua-placeholders.lua
@@ -0,0 +1,217 @@
+-- lua-placeholders.lua
+-- Copyright 2024 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.sty
+-- lua-placeholders-manual.pdf lua-placeholders.lua
+-- lua-placeholders-common.lua lua-placeholders-namespace.lua
+-- lua-placeholders-parser.lua and lua-placeholders-types.lua
+
+if not modules then
+ modules = {}
+end
+
+modules.lua_placeholders = {
+ version = "0.1.0",
+ date = "2024/01/12",
+ comment = 'Extended LaTeX Parameter Interface — for specifying and inserting document parameters',
+ author = 'Erik Nijenhuis',
+ license = 'free'
+}
+
+local api = {
+ namespaces = {},
+ parameters = {},
+ strict = false,
+ toks = {
+ is_set_true = token.create('has@param@true'),
+ is_set_false = token.create('has@param@false'),
+ }
+}
+local lua_placeholders = {}
+local lua_placeholders_mt = {
+ __index = api,
+ __newindex = function()
+ tex.error('Cannot override or set actions for this module...')
+ end
+}
+
+setmetatable(lua_placeholders, lua_placeholders_mt)
+
+local lua_placeholders_namespace = require('lua-placeholders-namespace')
+local load_resource = require('lua-placeholders-parser')
+
+local function get_param(key, namespace)
+ namespace = namespace or tex.jobname
+ local _namespace = api.namespaces[namespace]
+ return _namespace and _namespace:param(key)
+end
+
+function api.set_strict()
+ api.strict = true
+end
+
+function api.recipe(path, namespace_name)
+ if namespace_name == '' then
+ namespace_name = nil
+ end
+ local filename, abs_path = lua_placeholders_namespace.parse_filename(path)
+ local raw_recipe = load_resource(abs_path)
+ local name = namespace_name or raw_recipe.namespace or filename
+ local namespace = api.namespaces[name] or lua_placeholders_namespace:new { recipe_file = abs_path, strict = api.strict }
+ if not api.namespaces[name] then
+ api.namespaces[name] = namespace
+ end
+ if raw_recipe.namespace then
+ namespace:load_recipe(raw_recipe.parameters)
+ else
+ namespace:load_recipe(raw_recipe)
+ end
+ tex.print('\\UseOneTimeHook{namespace/' .. name .. '}')
+ if namespace.payload_file and not namespace.payload_loaded then
+ local raw_payload = load_resource(namespace.payload_file)
+ if raw_payload.namespace then
+ namespace:load_payload(raw_payload.parameters)
+ else
+ namespace:load_payload(raw_payload)
+ end
+ tex.print('\\UseOneTimeHook{namespace/' .. name .. '/loaded}')
+ end
+end
+
+function api.payload(path, namespace_name)
+ if namespace_name == '' then
+ namespace_name = nil
+ end
+ local filename, abs_path = lua_placeholders_namespace.parse_filename(path)
+ local raw_payload = load_resource(abs_path)
+ local name = namespace_name or raw_payload.namespace or filename
+ local namespace = api.namespaces[name] or lua_placeholders_namespace:new { payload_file = abs_path, strict = api.strict }
+ if not api.namespaces[name] then
+ api.namespaces[name] = namespace
+ end
+ if namespace.recipe_loaded then
+ if raw_payload.namespace then
+ namespace:load_payload(raw_payload.parameters)
+ else
+ namespace:load_payload(raw_payload)
+ end
+ tex.print('\\UseOneTimeHook{namespace/' .. name .. '/loaded}')
+ end
+end
+
+function api.param_object(key, namespace)
+ return get_param(key, namespace)
+end
+
+function api.param(key, namespace)
+ local param = get_param(key, namespace)
+ if param then
+ param:print_val()
+ elseif api.strict then
+ tex.error('Error: Parameter not set "' .. key .. '" in namespace "' .. namespace .. '".')
+ else
+ tex.sprint(lua_placeholders_toks.unknown_format, '{', key, '}')
+ end
+end
+
+function api.handle_param_is_set(key, namespace)
+ local param = get_param(key, namespace)
+ if param and param:is_set() then
+ tex.sprint(token.create('has@param@true'))
+ else
+ tex.sprint(token.create('has@param@false'))
+ end
+end
+
+function api.field(object_key, field, namespace)
+ local param = get_param(object_key, namespace)
+ if param then
+ local object = param.fields or param.default or {}
+ local f = object[field]
+ if f then
+ f:print_val()
+ else
+ tex.sprint(lua_placeholders_toks.unknown_format, '{', field, '}')
+ end
+ else
+ tex.error('No such object', object_key)
+ end
+end
+
+function api.with_object(object_key, namespace)
+ local object = get_param(object_key, namespace)
+ for key, param in pairs(object.fields) do
+ local val = param:val()
+ if val then
+ token.set_macro(key, param:val() .. '\\xspace')
+ else
+ token.set_macro(key, '\\paramplaceholder{' .. (param.placeholder or key) .. '}\\xspace')
+ end
+ end
+end
+
+function api.for_item(list_key, namespace, csname)
+ local param = get_param(list_key, namespace)
+ local list = param:val()
+ if #list > 0 then
+ if token.is_defined(csname) then
+ local tok = token.create(csname)
+ for _, item in ipairs(list) do
+ if param.values then
+ tex.sprint(tok, '{', item:val(), '}')
+ else
+ tex.sprint(tok, '{', lua_placeholders_toks.placeholder_format, '{', item:val(), '}}')
+ end
+ end
+ else
+ tex.error('No such command ', csname or 'nil')
+ end
+ end
+end
+
+function api.with_rows(key, namespace, csname)
+ local param = get_param(key, namespace)
+ if token.is_defined(csname) then
+ local row_content = token.get_macro(csname)
+ if param then
+ if param.values or api.strict then
+ if #param.values > 0 then
+ for _, row in ipairs(param.values) do
+ local format = row_content
+ for col_key, cell in pairs(row) do
+ format = format:gsub('\\' .. col_key, cell:val())
+ end
+ tex.print(format)
+ end
+ end
+ elseif param.columns then
+ texio.write_nl("Warning: no values set for " .. param.key)
+ local format = row_content
+ for col_key, col in pairs(param.columns) do
+ format = format:gsub('\\' .. col_key, '{\\paramplaceholder{' .. (col.placeholder or col_key) .. '}}')
+ end
+ tex.print(format)
+ else
+ tex.error('No values either columns available')
+ end
+ else
+ tex.error('Error: no such parameter')
+ end
+ else
+ tex.error('Error: no such command: ', csname or 'nil')
+ end
+end
+
+return lua_placeholders