summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luakeys/luakeys.lua
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/luakeys/luakeys.lua')
-rw-r--r--macros/luatex/generic/luakeys/luakeys.lua511
1 files changed, 338 insertions, 173 deletions
diff --git a/macros/luatex/generic/luakeys/luakeys.lua b/macros/luatex/generic/luakeys/luakeys.lua
index ae689d02c1..3221fc3efd 100644
--- a/macros/luatex/generic/luakeys/luakeys.lua
+++ b/macros/luatex/generic/luakeys/luakeys.lua
@@ -36,13 +36,59 @@ if not token then
}
end
+--- Merge two tables in the first specified table.
+--- The `merge_tables` function copies all keys from the `source` table
+--- to a target table. It returns the modified target table.
+---
+---@see https://stackoverflow.com/a/1283608/10193818
+---
+---@param target table
+---@param source table
+---
+---@return table target The modified target table.
+local function merge_tables(target, source)
+ for key, value in pairs(source) do
+ if type(value) == 'table' then
+ if type(target[key] or false) == 'table' then
+ merge_tables(target[key] or {}, source[key] or {})
+ elseif target[key] == nil then
+ target[key] = value
+ end
+ elseif target[key] == nil then
+ target[key] = value
+ end
+ end
+ return target
+end
+
+---Clone a table.
+---
+---@see http://lua-users.org/wiki/CopyTable
+---
+---@param orig table
+---
+---@return table
+local function clone_table(orig)
+ local orig_type = type(orig)
+ local copy
+ if orig_type == 'table' then
+ copy = {}
+ for orig_key, orig_value in next, orig, nil do
+ copy[clone_table(orig_key)] = clone_table(orig_value)
+ end
+ setmetatable(copy, clone_table(getmetatable(orig)))
+ else -- number, string, boolean, etc
+ copy = orig
+ end
+ return copy
+end
+
local utils = {
--- Get the size of an array like table `{ 'one', 'two', 'three' }` = 3.
- --
- -- @tparam table value A table or any input.
- --
- -- @treturn number The size of the array like table. 0 if the input is
- -- no table or the table is empty.
+ ---
+ ---@param value table # A table or any input.
+ ---
+ ---@return number # The size of the array like table. 0 if the input is no table or the table is empty.
get_array_size = function(value)
local count = 0
if type(value) == 'table' then
@@ -53,12 +99,11 @@ local utils = {
return count
end,
- --- Get the size of a table `{ one = 'one', 'two', 'three' }` = 3.
- --
- -- @tparam table value A table or any input.
- --
- -- @treturn number The size of the array like table. 0 if the input is
- -- no table or the table is empty.
+ ---Get the size of a table `{ one = 'one', 'two', 'three' }` = 3.
+ ---
+ ---@param value table|any # A table or any input.
+ ---
+ ---@return number # The size of the array like table. 0 if the input is no table or the table is empty.
get_table_size = function(value)
local count = 0
if type(value) == 'table' then
@@ -69,6 +114,10 @@ local utils = {
return count
end,
+ merge_tables = merge_tables,
+
+ clone_table = clone_table,
+
remove_from_array = function(array, element)
for index, value in pairs(array) do
if element == value then
@@ -77,58 +126,95 @@ local utils = {
end
end
end,
-}
---- https://stackoverflow.com/a/1283608/10193818
-local function merge_tables(target, t2)
- for k, v in pairs(t2) do
- if type(v) == 'table' then
- if type(target[k] or false) == 'table' then
- merge_tables(target[k] or {}, t2[k] or {})
- elseif target[k] == nil then
- target[k] = v
+ ---Scan for an optional argument.
+ ---
+ ---@param initial_delimiter? string # The character that marks the beginning of an optional argument (by default `[`).
+ ---@param end_delimiter? string # The character that marks the end of an optional argument (by default `]`).
+ ---
+ ---@return string|nil # The string that was enclosed by the delimiters. The delimiters themselves are not returned.
+ scan_oarg = function(initial_delimiter, end_delimiter)
+ if initial_delimiter == nil then
+ initial_delimiter = '['
+ end
+
+ if end_delimiter == nil then
+ end_delimiter = ']'
+ end
+
+ local function convert_token(t)
+ if t.index ~= nil then
+ return utf8.char(t.index)
+ else
+ return '\\' .. t.csname
end
- elseif target[k] == nil then
- target[k] = v
end
- end
- return target
-end
---- http://lua-users.org/wiki/CopyTable
-local function clone_table(orig)
- local orig_type = type(orig)
- local copy
- if orig_type == 'table' then
- copy = {}
- for orig_key, orig_value in next, orig, nil do
- copy[clone_table(orig_key)] = clone_table(orig_value)
+ local function get_next_char()
+ local t = token.get_next()
+ return convert_token(t), t
end
- setmetatable(copy, clone_table(getmetatable(orig)))
- else -- number, string, boolean, etc
- copy = orig
- end
- return copy
-end
---- This table stores all allowed option keys.
-local all_options = {
- convert_dimensions = false,
- debug = false,
- default = true,
- defaults = false,
- defs = false,
- format_keys = false,
- hooks = {},
- naked_as_value = false,
- no_error = false,
- postprocess = false,
- preprocess = false,
- unpack = true,
+ local char, t = get_next_char()
+ if char == initial_delimiter then
+ local oarg = {}
+ char = get_next_char()
+ while char ~= end_delimiter do
+ table.insert(oarg, char)
+ char = get_next_char()
+ end
+ return table.concat(oarg, '')
+ else
+ token.put_next(t)
+ end
+ end,
+}
+
+local namespace = {
+ opts = {
+ convert_dimensions = false,
+ debug = false,
+ default = true,
+ defaults = false,
+ defs = false,
+ format_keys = false,
+ hooks = {},
+ naked_as_value = false,
+ no_error = false,
+ unpack = true,
+ },
+
+ hooks = {
+ kv_string = true,
+ keys_before_opts = true,
+ result_before_opts = true,
+ keys_before_def = true,
+ result_before_def = true,
+ keys = true,
+ result = true,
+ },
+
+ attrs = {
+ alias = true,
+ always_present = true,
+ choices = true,
+ data_type = true,
+ default = true,
+ exclusive_group = true,
+ l3_tl_set = true,
+ macro = true,
+ match = true,
+ name = true,
+ opposite_keys = true,
+ pick = true,
+ process = true,
+ required = true,
+ sub_keys = true,
+ },
}
--- The default options.
-local default_options = clone_table(all_options)
+local default_options = clone_table(namespace.opts)
local function throw_error(message)
if type(tex.error) == 'function' then
@@ -144,16 +230,15 @@ local l3_code_cctab = 10
-- @section
--- The function `render(tbl)` reverses the function
--- `parse(kv_string)`. It takes a Lua table and converts this table
--- into a key-value string. The resulting string usually has a
--- different order as the input table. In Lua only tables with
--- 1-based consecutive integer keys (a.k.a. array tables) can be
--- parsed in order.
---
--- @tparam table result A table to be converted into a key-value string.
---
--- @treturn string A key-value string that can be passed to a TeX
--- macro.
+--- `parse(kv_string)`. It takes a Lua table and converts this table
+--- into a key-value string. The resulting string usually has a
+--- different order as the input table. In Lua only tables with
+--- 1-based consecutive integer keys (a.k.a. array tables) can be
+--- parsed in order.
+---
+---@param result table # A table to be converted into a key-value string.
+---
+---@return string # A key-value string that can be passed to a TeX macro.
local function render(result)
local function render_inner(result)
local output = {}
@@ -183,20 +268,19 @@ local function render(result)
end
--- The function `stringify(tbl, for_tex)` converts a Lua table into a
--- printable string. Stringify a table means to convert the table into
--- a string. This function is used to realize the `debug` function.
--- `stringify(tbl, true)` (`for_tex = true`) generates a string which
--- can be embeded into TeX documents. The macro `\luakeysdebug{}` uses
--- this option. `stringify(tbl, false)` or `stringify(tbl)` generate a
--- string suitable for the terminal.
---
--- @tparam table result A table to stringify.
---
--- @tparam boolean for_tex Stringify the table into a text string that
--- can be embeded inside a TeX document via tex.print(). Curly braces
--- and whites spaces are escaped.
---
--- https://stackoverflow.com/a/54593224/10193818
+--- printable string. Stringify a table means to convert the table into
+--- a string. This function is used to realize the `debug` function.
+--- `stringify(tbl, true)` (`for_tex = true`) generates a string which
+--- can be embeded into TeX documents. The macro `\luakeysdebug{}` uses
+--- this option. `stringify(tbl, false)` or `stringify(tbl)` generate a
+--- string suitable for the terminal.
+---
+---@see https://stackoverflow.com/a/54593224/10193818
+---
+---@param result table # A table to stringify.
+---@param for_tex? boolean # Stringify the table into a text string that can be embeded inside a TeX document via tex.print(). Curly braces and whites spaces are escaped.
+---
+---@return string
local function stringify(result, for_tex)
local line_break, start_bracket, end_bracket, indent
@@ -242,7 +326,8 @@ local function stringify(result, for_tex)
add(0, stringify_inner(value, depth + 1))
add(depth, end_bracket .. ',');
else
- add(depth, key .. ' = ' .. start_bracket .. end_bracket .. ',')
+ add(depth,
+ key .. ' = ' .. start_bracket .. end_bracket .. ',')
end
else
if (type(value) == 'string') then
@@ -259,19 +344,17 @@ local function stringify(result, for_tex)
return table.concat(output, line_break)
end
- return
- start_bracket .. line_break .. stringify_inner(result, 1) .. line_break ..
- end_bracket
+ return start_bracket .. line_break .. stringify_inner(result, 1) ..
+ line_break .. end_bracket
end
---- The function `debug(tbl)` pretty prints a Lua table to standard
+--- The function `debug(result)` pretty prints a Lua table to standard
-- output (stdout). It is a utility function that can be used to
-- debug and inspect the resulting Lua table of the function
-- `parse`. You have to compile your TeX document in a console to
-- see the terminal output.
--
--- @tparam table result A table to be printed to standard output for
--- debugging purposes.
+---@param result table # A table to be printed to standard output for debugging purposes.
local function debug(result)
print('\n' .. stringify(result, false))
end
@@ -280,19 +363,23 @@ end
-- @section
--- Generate the PEG parser using Lpeg.
---
--- Explanations of some LPeg notation forms:
---
--- * `patt ^ 0` = `expression *`
--- * `patt ^ 1` = `expression +`
--- * `patt ^ -1` = `expression ?`
--- * `patt1 * patt2` = `expression1 expression2`: Sequence
--- * `patt1 + patt2` = `expression1 / expression2`: Ordered choice
---
--- * [TUGboat article: Parsing complex data formats in LuaTEX with LPEG](https://tug.org/TUGboat/tb40-2/tb125menke-Patterndf)
---
--- @treturn userdata The parser.
-local function generate_parser(initial_rule, convert_dimensions)
+---
+--- Explanations of some LPeg notation forms:
+---
+--- * `patt ^ 0` = `expression *`
+--- * `patt ^ 1` = `expression +`
+--- * `patt ^ -1` = `expression ?`
+--- * `patt1 * patt2` = `expression1 expression2`: Sequence
+--- * `patt1 + patt2` = `expression1 / expression2`: Ordered choice
+---
+--- * [TUGboat article: Parsing complex data formats in LuaTEX with LPEG](https://tug.or-g/TUGboat/tb40-2/tb125menke-Patterndf)
+---
+---@param initial_rule string # The name of the first rule of the grammar table passed to the `lpeg.P(attern)` function (e. g. `list`, `number`).
+---@param convert_dimensions? boolean # Whether the dimensions should be converted to scaled points (by default `false`).
+---
+---@return userdata # The parser.
+local function generate_parser(initial_rule,
+ convert_dimensions)
if convert_dimensions == nil then
convert_dimensions = false
end
@@ -315,7 +402,17 @@ local function generate_parser(initial_rule, convert_dimensions)
return white_space ^ 0 * Pattern(match) * white_space ^ 0
end
+ --- Convert a dimension to an normalized dimension string or an
+ --- integer in the scaled points format.
+ ---
+ ---@param input string
+ ---
+ ---@return integer|string # A dimension as an integer or a dimension string.
local capture_dimension = function(input)
+ -- Remove all whitespaces
+ input = input:gsub('%s+', '')
+ -- Convert the unit string into lowercase.
+ input = input:lower()
if convert_dimensions then
return tex.sp(input)
else
@@ -325,27 +422,27 @@ local function generate_parser(initial_rule, convert_dimensions)
--- Add values to a table in two modes:
--
- -- # Key value pair
+ -- Key-value pair:
--
- -- If arg1 and arg2 are not nil, then arg1 is the key and arg2 is the
+ -- If `arg1` and `arg2` are not nil, then `arg1` is the key and `arg2` is the
-- value of a new table entry.
--
- -- # Index value
+ -- Indexed value:
--
- -- If arg2 is nil, then arg1 is the value and is added as an indexed
+ -- If `arg2` is nil, then `arg1` is the value and is added as an indexed
-- (by an integer) value.
--
- -- @tparam table table
- -- @tparam mixed arg1
- -- @tparam mixed arg2
- --
- -- @treturn table
- local add_to_table = function(table, arg1, arg2)
+ ---@param result table # The result table to which an additional key-value pair or value should to be added
+ ---@param arg1 any # The key or the value.
+ ---@param arg2? any # Always the value.
+ ---
+ ---@return table # The result table to which an additional key-value pair or value has been added.
+ local add_to_table = function(result, arg1, arg2)
if arg2 == nil then
- local index = #table + 1
- return rawset(table, index, arg1)
+ local index = #result + 1
+ return rawset(result, index, arg1)
else
- return rawset(table, arg1, arg2)
+ return rawset(result, arg1, arg2)
end
end
@@ -438,6 +535,7 @@ local function generate_parser(initial_rule, convert_dimensions)
-- 'bp' / 'BP' / 'cc' / etc.
-- https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua
+ -- https://github.com/TeX-Live/luatex/blob/51db1985f5500dafd2393aa2e403fefa57d3cb76/source/texk/web2c/luatexdir/lua/ltexlib.c#L434-L625
unit =
Pattern('bp') + Pattern('BP') +
Pattern('cc') + Pattern('CC') +
@@ -447,10 +545,12 @@ local function generate_parser(initial_rule, convert_dimensions)
Pattern('ex') + Pattern('EX') +
Pattern('in') + Pattern('IN') +
Pattern('mm') + Pattern('MM') +
+ Pattern('mu') + Pattern('MU') +
Pattern('nc') + Pattern('NC') +
Pattern('nd') + Pattern('ND') +
Pattern('pc') + Pattern('PC') +
Pattern('pt') + Pattern('PT') +
+ Pattern('px') + Pattern('PX') +
Pattern('sp') + Pattern('SP'),
-- '"' ('\"' / !'"')* '"'
@@ -483,7 +583,8 @@ local function visit_tree(tree, callback_func)
callback_func)
for key, value in pairs(current) do
if type(value) == 'table' then
- value = visit_tree_recursive(tree, value, {}, depth + 1, callback_func)
+ value = visit_tree_recursive(tree, value, {}, depth + 1,
+ callback_func)
end
key, value = callback_func(key, value, depth, current, tree)
@@ -514,7 +615,7 @@ local is = {
return true
end
local parser = generate_parser('boolean_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -523,7 +624,7 @@ local is = {
return false
end
local parser = generate_parser('dimension_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -543,7 +644,7 @@ local is = {
return true
end
local parser = generate_parser('number_only', false)
- local result = parser:match(value)
+ local result = parser:match(tostring(value))
return result ~= nil
end,
@@ -555,14 +656,13 @@ local is = {
--- Apply the key-value-pair definitions (defs) on an input table in a
--- recursive fashion.
---
----@param defs table A table containing all definitions.
----@param opts table The parse options table.
----@param input table The current input table.
----@param output table The current output table.
----@param unknown table Always the root unknown table.
----@param key_path table An array of key names leading to the current
----@param input_root table The root input table
---- input and output table.
+---@param defs table # A table containing all definitions.
+---@param opts table # The parse options table.
+---@param input table # The current input table.
+---@param output table # The current output table.
+---@param unknown table # Always the root unknown table.
+---@param key_path table # An array of key names leading to the current
+---@param input_root table # The root input table input and output table.
local function apply_definitions(defs,
opts,
input,
@@ -583,7 +683,7 @@ local function apply_definitions(defs,
return new_key_path
end
- local function set_default_value(def)
+ local function get_default_value(def)
if def.default ~= nil then
return def.default
elseif opts ~= nil and opts.default ~= nil then
@@ -599,7 +699,7 @@ local function apply_definitions(defs,
return value
-- naked keys: values with integer keys
elseif utils.remove_from_array(input, search_key) ~= nil then
- return set_default_value(def)
+ return get_default_value(def)
end
end
@@ -634,7 +734,7 @@ local function apply_definitions(defs,
always_present = function(value, key, def)
if value == nil and def.always_present then
- return set_default_value(def)
+ return get_default_value(def)
end
end,
@@ -692,9 +792,10 @@ local function apply_definitions(defs,
throw_error('Unknown data type: ' .. def.data_type)
end
if converted == nil then
- throw_error('The value “' .. value .. '” of the key “' .. key ..
- '” could not be converted into the data type “' ..
- def.data_type .. '”!')
+ throw_error(
+ 'The value “' .. value .. '” of the key “' .. key ..
+ '” could not be converted into the data type “' ..
+ def.data_type .. '”!')
else
return converted
end
@@ -723,7 +824,8 @@ local function apply_definitions(defs,
return
end
if def.l3_tl_set ~= nil then
- tex.print(l3_code_cctab, '\\tl_set:Nn \\g_' .. def.l3_tl_set .. '_tl')
+ tex.print(l3_code_cctab,
+ '\\tl_set:Nn \\g_' .. def.l3_tl_set .. '_tl')
tex.print('{' .. value .. '}')
end
end,
@@ -747,8 +849,9 @@ local function apply_definitions(defs,
end
local match = string.match(value, def.match)
if match == nil then
- throw_error('The value “' .. value .. '” of the key “' .. key ..
- '” does not match “' .. def.match .. '”!')
+ throw_error(
+ 'The value “' .. value .. '” of the key “' .. key ..
+ '” does not match “' .. def.match .. '”!')
else
return match
end
@@ -780,6 +883,41 @@ local function apply_definitions(defs,
end
end,
+ pick = function(value, key, def)
+ if def.pick then
+ if type(def.pick) == 'string' and is[def.pick] == nil then
+ throw_error(
+ 'Wrong setting. Allowed settings for the attribute “def.pick” are: true, boolean, dimension, integer, number, string. Got “' ..
+ tostring(def.pick) .. '”.')
+ end
+
+ if value ~= nil then
+ return value
+ end
+ for i, v in pairs(input) do
+ -- We can not use ipairs here. `ipairs(t)` iterates up to the
+ -- first absent index. Values are deleted from the `input`
+ -- table.
+ if type(i) == 'number' then
+ local picked_value = nil
+ -- Pick a value by type: boolean, dimension, integer, number, string
+ if is[def.pick] ~= nil then
+ if is[def.pick](v) then
+ picked_value = v
+ end
+ -- Pick every value
+ elseif v ~= nil then
+ picked_value = v
+ end
+ if picked_value ~= nil then
+ input[i] = nil
+ return picked_value
+ end
+ end
+ end
+ end
+ end,
+
required = function(value, key, def)
if def.required ~= nil and def.required and value == nil then
throw_error(string.format('Missing required key “%s”!', key))
@@ -797,8 +935,8 @@ local function apply_definitions(defs,
elseif type(value) == 'table' then
v = value
end
- v = apply_definitions(def.sub_keys, opts, v, output[key], unknown,
- add_to_key_path(key_path, key), input_root)
+ v = apply_definitions(def.sub_keys, opts, v, output[key],
+ unknown, add_to_key_path(key_path, key), input_root)
if utils.get_table_size(v) > 0 then
return v
end
@@ -821,23 +959,33 @@ local function apply_definitions(defs,
end
for index, def in pairs(defs) do
- --- Find key and def
+ -- Find key and def
local key
- if type(def) == 'table' and def.name == nil and type(index) == 'string' then
+ -- `{ key1 = { }, key2 = { } }`
+ if type(def) == 'table' and def.name == nil and type(index) ==
+ 'string' then
key = index
+ -- `{ { name = 'key1' }, { name = 'key2' } }`
elseif type(def) == 'table' and def.name ~= nil then
key = def.name
+ -- Definitions as strings in an array: `{ 'key1', 'key2' }`
elseif type(index) == 'number' and type(def) == 'string' then
key = def
- def = { default = true }
+ def = { default = get_default_value({}) }
end
if type(def) ~= 'table' then
- throw_error('Key definition must be a table')
+ throw_error('Key definition must be a table!')
+ end
+
+ for attr, _ in pairs(def) do
+ if namespace.attrs[attr] == nil then
+ throw_error('Unknown definition attribute: ' .. tostring(attr))
+ end
end
if key == nil then
- throw_error('key name couldn’t be detected!')
+ throw_error('Key name couldn’t be detected!')
end
local value = find_value(key, def)
@@ -845,6 +993,7 @@ local function apply_definitions(defs,
for _, def_opt in ipairs({
'alias',
'opposite_keys',
+ 'pick',
'always_present',
'required',
'data_type',
@@ -888,14 +1037,14 @@ end
--- Parse a LaTeX/TeX style key-value string into a Lua table.
---
----@param kv_string string A string in the TeX/LaTeX style key-value format as described above.
----@param opts table A table containing the settings:
+---@param kv_string string # A string in the TeX/LaTeX style key-value format as described above.
+---@param opts table # A table containing the settings:
--- `convert_dimensions`, `unpack`, `naked_as_value`, `converter`,
--- `debug`, `preprocess`, `postprocess`.
--
----@return table result The final result of all individual parsing and normalization steps.
----@return table unknown A table with unknown, undefinied key-value pairs.
----@return table raw The unprocessed, raw result of the LPeg parser.
+---@return table result # The final result of all individual parsing and normalization steps.
+---@return table unknown # A table with unknown, undefinied key-value pairs.
+---@return table raw # The unprocessed, raw result of the LPeg parser.
local function parse(kv_string, opts)
if kv_string == nil then
return {}
@@ -903,21 +1052,21 @@ local function parse(kv_string, opts)
--- Normalize the parse options.
---
- --- @param opts table Options in a raw format. The table may be empty or some keys are not set.
+ ---@param opts table # Options in a raw format. The table may be empty or some keys are not set.
---
- --- @return table
+ ---@return table
local function normalize_opts(opts)
if type(opts) ~= 'table' then
opts = {}
end
for key, _ in pairs(opts) do
- if all_options[key] == nil then
+ if namespace.opts[key] == nil then
throw_error('Unknown parse option: ' .. tostring(key) .. '!')
end
end
local old_opts = opts
opts = {}
- for name, _ in pairs(all_options) do
+ for name, _ in pairs(namespace.opts) do
if old_opts[name] ~= nil then
opts[name] = old_opts[name]
else
@@ -925,18 +1074,8 @@ local function parse(kv_string, opts)
end
end
- local hooks = {
- kv_string = true,
- keys_before_opts = true,
- result_before_opts = true,
- keys_before_def = true,
- result_before_def = true,
- keys = true,
- result = true,
- }
-
for hook in pairs(opts.hooks) do
- if hooks[hook] == nil then
+ if namespace.hooks[hook] == nil then
throw_error('Unknown hook: ' .. tostring(hook) .. '!')
end
end
@@ -983,8 +1122,8 @@ local function parse(kv_string, opts)
-- tasks are performed on the raw input table coming directly from
-- the PEG parser:
--
- --- @param result table The raw input table coming directly from the PEG parser
- --- @param opts table Some options.
+ ---@param result table # The raw input table coming directly from the PEG parser
+ ---@param opts table # Some options.
local function apply_opts(result, opts)
local callbacks = {
unpack = function(key, value)
@@ -1012,7 +1151,8 @@ local function parse(kv_string, opts)
elseif style == 'upper' then
key = key:upper()
else
- throw_error('Unknown style to format keys: ' .. tostring(style) ..
+ throw_error('Unknown style to format keys: ' ..
+ tostring(style) ..
' Allowed styles are: lower, snake, upper')
end
end
@@ -1031,8 +1171,9 @@ local function parse(kv_string, opts)
if opts.format_keys then
if type(opts.format_keys) ~= 'table' then
- throw_error('The option “format_keys” has to be a table not ' ..
- type(opts.format_keys))
+ throw_error(
+ 'The option “format_keys” has to be a table not ' ..
+ type(opts.format_keys))
end
result = visit_tree(result, callbacks.format_key)
end
@@ -1045,8 +1186,8 @@ local function parse(kv_string, opts)
local unknown = nil
if type(opts.defs) == 'table' then
apply_hooks('before_defs')
- result, unknown = apply_definitions(opts.defs, opts, result, {}, {}, {},
- clone_table(result))
+ result, unknown = apply_definitions(opts.defs, opts, result, {}, {},
+ {}, clone_table(result))
end
apply_hooks()
@@ -1077,6 +1218,26 @@ local result_store = {}
-- @section
local export = {
+ version = { 0, 7, 0 },
+
+ namespace = namespace,
+
+ ---This function is used in the documentation.
+ ---
+ ---@param from string # A key in the namespace table, either `opts`, `hook` or `attrs`.
+ print_names = function(from)
+ local names = {}
+ for name in pairs(namespace[from]) do
+ table.insert(names, name)
+ end
+ table.sort(names)
+ tex.print(table.concat(names, ', '))
+ end,
+
+ print_default = function(from, name)
+ tex.print(tostring(namespace[from][name]))
+ end,
+
--- @see default_options
opts = default_options,
@@ -1089,7 +1250,10 @@ local export = {
define = function(defs, opts)
return function(kv_string, inner_opts)
local options
- if inner_opts ~= nil then
+
+ if inner_opts ~= nil and opts ~= nil then
+ options = merge_tables(opts, inner_opts)
+ elseif inner_opts ~= nil then
options = inner_opts
elseif opts ~= nil then
options = opts
@@ -1116,11 +1280,9 @@ local export = {
-- Therefore, it is not necessary to pollute the global namespace to
-- store results for the later usage.
--
- -- @tparam string identifier The identifier under which the result is
- -- saved.
+ ---@param identifier string # The identifier under which the result is saved.
--
- -- @tparam table result A result to be stored and that was created by
- -- the key-value parser.
+ ---@param result table # A result to be stored and that was created by the key-value parser.
save = function(identifier, result)
result_store[identifier] = result
end,
@@ -1128,8 +1290,9 @@ local export = {
--- The function `get(identifier): table` retrieves a saved result
-- from the result store.
--
- -- @tparam string identifier The identifier under which the result was
- -- saved.
+ ---@param identifier string # The identifier under which the result was saved.
+ ---
+ ---@return table
get = function(identifier)
-- if result_store[identifier] == nil then
-- throw_error('No stored result was found for the identifier \'' .. identifier .. '\'')
@@ -1138,6 +1301,8 @@ local export = {
end,
is = is,
+
+ utils = utils,
}
return export