summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luakeys
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/generic/luakeys')
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.sty21
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.tex35
-rw-r--r--macros/luatex/generic/luakeys/luakeys.lua114
-rw-r--r--macros/luatex/generic/luakeys/luakeys.pdfbin140586 -> 153582 bytes
-rw-r--r--macros/luatex/generic/luakeys/luakeys.tex121
5 files changed, 220 insertions, 71 deletions
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.sty b/macros/luatex/generic/luakeys/luakeys-debug.sty
index 77dfa0063e..a96d2d51c6 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.sty
+++ b/macros/luatex/generic/luakeys/luakeys-debug.sty
@@ -17,23 +17,6 @@
% and luakeys-debug.tex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{luakeys-debug}[2021/01/18 Debug package for luakeys.]
+\ProvidesPackage{luakeys-debug}[2021/09/19 Debug package for luakeys.]
-%\input luakeys-debug.tex
-
-\directlua{
- luakeys = require('luakeys')
-}
-
-\newcommand{\luakeysdebug}[2][]{
- {
- \tt
- \parindent=0pt
- \directlua{
- local options_raw = luakeys.parse('#1')
- local result = luakeys.parse('#2', options_raw)
- tex.print(luakeys.stringify(result, true))
- luakeys.print(result)
- }
- }
-}
+\input luakeys-debug.tex
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.tex b/macros/luatex/generic/luakeys/luakeys-debug.tex
index 499b1305f6..b63e67e050 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.tex
+++ b/macros/luatex/generic/luakeys/luakeys-debug.tex
@@ -20,14 +20,43 @@
luakeys = require('luakeys')
}
-\def\luakeysdebug#1{
+% https://tex.stackexchange.com/a/418401/42311
+\catcode`\@=11
+\long\def\LuaKeysIfNextChar#1#2#3{%
+ \let\@tmpa=#1%
+ \def\@tmpb{#2}%
+ \def\@tmpc{#3}%
+ \futurelet\@future\LuaKeysIfNextChar@i%
+}%
+\def\LuaKeysIfNextChar@i{%
+ \ifx\@tmpa\@future%
+ \expandafter\@tmpb
+ \else
+ \expandafter\@tmpc
+ \fi
+}%
+\def\luakeysdebug@parse@options#1{
+ \directlua{
+ luakeys.save('debug_options', luakeys.parse('#1'))
+ }
+}%
+\def\luakeysdebug@output#1{
{
\tt
\parindent=0pt
\directlua{
- local result = luakeys.parse('#1')
+ local result = luakeys.parse('\luaescapestring{\unexpanded{#1}}', luakeys.get('debug_options'))
tex.print(luakeys.stringify(result, true))
luakeys.print(result)
}
}
-}
+}%
+\def\luakeysdebug@oarg[#1]#2{%
+ \luakeysdebug@parse@options{#1}%
+ \luakeysdebug@output{#2}%
+}%
+\def\luakeysdebug@marg#1{%
+ \luakeysdebug@output{#1}%
+}%
+\def\luakeysdebug{\LuaKeysIfNextChar[{\luakeysdebug@oarg}{\luakeysdebug@marg}}%
+\catcode`\@=12
diff --git a/macros/luatex/generic/luakeys/luakeys.lua b/macros/luatex/generic/luakeys/luakeys.lua
index e4ecaab7f7..b026413800 100644
--- a/macros/luatex/generic/luakeys/luakeys.lua
+++ b/macros/luatex/generic/luakeys/luakeys.lua
@@ -41,16 +41,19 @@ if not tex then
end
end
+--- A table to store parsed key-value results.
+local result_store = {}
+
--- Generate the PEG parser using Lpeg.
--
--- @treturn userdata The parser
+-- @treturn userdata The parser.
local function generate_parser(options)
-- Optional whitespace
- local white_space = lpeg.S(' \t\n\r')^0
+ local white_space = lpeg.S(' \t\n\r')
--- Match literal string surrounded by whitespace
local ws = function(match)
- return white_space * lpeg.P(match) * white_space
+ return white_space^0 * lpeg.P(match) * white_space^0
end
local boolean_true =
@@ -87,17 +90,24 @@ local function generate_parser(options)
local sign = lpeg.S('-+')
local integer = lpeg.R('09')^1
local tex_number = (integer^1 * (lpeg.P('.') * integer^1)^0) + (lpeg.P('.') * integer^1)
- local unit
- -- https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua
- for _, dimension_extension in ipairs({'bp', 'cc', 'cm', 'dd', 'em', 'ex', 'in', 'mm', 'nc', 'nd', 'pc', 'pt', 'sp'}) do
- if unit then
- unit = unit + lpeg.P(dimension_extension)
- else
- unit = lpeg.P(dimension_extension)
- end
- end
- local dimension = (sign^0 * tex_number * unit)
+ -- https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua
+ local unit =
+ lpeg.P('bp') + lpeg.P('BP') +
+ lpeg.P('cc') + lpeg.P('CC') +
+ lpeg.P('cm') + lpeg.P('CM') +
+ lpeg.P('dd') + lpeg.P('DD') +
+ lpeg.P('em') + lpeg.P('EM') +
+ lpeg.P('ex') + lpeg.P('EX') +
+ lpeg.P('in') + lpeg.P('IN') +
+ lpeg.P('mm') + lpeg.P('MM') +
+ lpeg.P('nc') + lpeg.P('NC') +
+ lpeg.P('nd') + lpeg.P('ND') +
+ lpeg.P('pc') + lpeg.P('PC') +
+ lpeg.P('pt') + lpeg.P('PT') +
+ lpeg.P('sp') + lpeg.P('SP')
+
+ local dimension = (sign^0 * white_space^0 * tex_number * white_space^0 * unit)
if options.convert_dimensions then
return dimension / tex.sp
@@ -106,7 +116,7 @@ local function generate_parser(options)
end
end
- --- Add values to a table in a two modes:
+ --- Add values to a table in two modes:
--
-- # Key value pair
--
@@ -150,15 +160,7 @@ local function generate_parser(options)
) * ws(',')^-1,
key_value_pair =
- (lpeg.V('key') * ws('=')) * (lpeg.V('list_container') + lpeg.V('value')),
-
- -- ./ for tikz style keys
- key_word = lpeg.R('az', 'AZ', '09', './'),
-
- key = white_space * lpeg.C(
- lpeg.V('key_word')^1 *
- (lpeg.P(' ')^1 * lpeg.V('key_word')^1)^0
- ) * white_space,
+ (lpeg.V('value') * ws('=')) * (lpeg.V('list_container') + lpeg.V('value')),
value =
lpeg.V('boolean') +
@@ -174,25 +176,25 @@ local function generate_parser(options)
dimension = build_dimension_pattern(),
string_quoted =
- white_space * lpeg.P('"') *
+ white_space^0 * lpeg.P('"') *
lpeg.C((lpeg.P('\\"') + 1 - lpeg.P('"'))^0) *
- lpeg.P('"') * white_space,
+ lpeg.P('"') * white_space^0,
string_unquoted =
- white_space *
- lpeg.C((1 - lpeg.S('{},='))^1) *
- white_space,
+ white_space^0 *
+ lpeg.C(
+ lpeg.V('word_unquoted')^1 *
+ (lpeg.S(' \t')^1 * lpeg.V('word_unquoted')^1)^0) *
+ white_space^0,
+
+ word_unquoted = (1 - white_space - lpeg.S('{},='))^1;
number =
- white_space * (number / tonumber) * white_space,
+ white_space^0 * (number / tonumber) * white_space^0,
})
end
-local function trim(input_string)
- return input_string:gsub('^%s*(.-)%s*$', '%1')
-end
-
--- Get the size of an array like table `{ 'one', 'two', 'three' }` = 3.
--
-- @tparam table value A table or any input.
@@ -238,16 +240,19 @@ local function unpack_single_valued_array_table(value)
return value
end
---- This normalization tasks are performed on the raw input table
--- coming directly from the PEG parser:
+--- This normalization tasks are performed on the raw input table coming
+-- directly from the PEG parser:
--
-- 1. Trim all strings: ` text \n` into `text`
--- 2. Unpack all single valued array like tables: `{ 'text' }`
--- into `text`
+-- 2. Unpack all single valued array like tables: `{ 'text' }` into
+-- `text`
--
-- @tparam table raw The raw input table coming directly from the PEG
-- parser
--
+-- @tparam table options Some options. A table with the key
+-- `unpack_single_array_values`
+--
-- @treturn table A normalized table ready for the outside world.
local function normalize(raw, options)
local function normalize_recursive(raw, result, options)
@@ -257,8 +262,6 @@ local function normalize(raw, options)
end
if type(value) == 'table' then
result[key] = normalize_recursive(value, {}, options)
- elseif type(value) == 'string' then
- result[key] = trim(value)
else
result[key] = value
end
@@ -288,8 +291,8 @@ local function stringify(input, for_tex)
if for_tex then
line_break = '\\par'
- start_bracket = '\\{'
- end_bracket = '\\}'
+ start_bracket = '$\\{$'
+ end_bracket = '$\\}$'
indent = '\\ \\ '
else
line_break = '\n'
@@ -306,6 +309,10 @@ local function stringify(input, for_tex)
table.insert(output, string.rep(indent, depth) .. text)
end
+ if type(input) ~= 'table' then
+ return tostring(input)
+ end
+
for key, value in pairs(input) do
if (key and type(key) == 'number' or type(key) == 'string') then
key = string.format('[\'%s\']', key);
@@ -423,7 +430,7 @@ return {
if kv_string == nil then
return {}
end
- options = normalize_parse_options()
+ options = normalize_parse_options(options)
local parser = generate_parser(options)
return normalize(parser:match(kv_string), options)
@@ -480,4 +487,27 @@ return {
print(stringify(tbl, false))
end,
+ --- The function `save(identifier, result): void` saves a result (a
+ -- table from a previous run of `parse`) under an identifier.
+ -- 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.
+ --
+ -- @tparam table result A result to be stored and that was created by
+ -- the key-value parser.
+ save = function(identifier, result)
+ result_store[identifier] = result
+ end,
+
+ --- The function `get(identifier): table` retrieves a saved result
+ -- from the result store.
+ --
+ -- @tparam string identifier The identifier under which the result was
+ -- saved.
+ get = function(identifier)
+ return result_store[identifier]
+ end,
+
}
diff --git a/macros/luatex/generic/luakeys/luakeys.pdf b/macros/luatex/generic/luakeys/luakeys.pdf
index ceaebbee04..c65765d5b9 100644
--- a/macros/luatex/generic/luakeys/luakeys.pdf
+++ b/macros/luatex/generic/luakeys/luakeys.pdf
Binary files differ
diff --git a/macros/luatex/generic/luakeys/luakeys.tex b/macros/luatex/generic/luakeys/luakeys.tex
index 75ffbc8c70..fc465f46ae 100644
--- a/macros/luatex/generic/luakeys/luakeys.tex
+++ b/macros/luatex/generic/luakeys/luakeys.tex
@@ -28,9 +28,9 @@
\author{%
Josef Friedrich\\%
\url{josef@friedrich.rocks}\\%
- \href{https://github.com/Josef-Friedrich/nodetree}{github.com/Josef-Friedrich/luakeys}%
+ \href{https://github.com/Josef-Friedrich/luakeys}{github.com/Josef-Friedrich/luakeys}%
}
-\date{v0.1 from 2021/01/18}
+\date{v0.2 from 2021/09/19}
\maketitle
@@ -105,6 +105,27 @@ This package would not be possible without the article
\clearpage
+\section{Usage}
+
+\begin{minted}{latex}
+\documentclass{article}
+\directlua{
+ luakeys = require('luakeys')
+}
+
+\newcommand{\helloworld}[2][]{
+ \directlua{
+ local keys = luakeys.parse('\luaescapestring{\unexpanded{#1}}')
+ luakeys.print(keys)
+ local marg = '#2'
+ tex.print(keys.greeting .. ', ' .. marg .. keys.punctuation)
+ }
+}
+\begin{document}
+\helloworld[greeting=hello,punctuation=!]{world}
+\end{document}
+\end{minted}
+
\section{Syntax of the recognized key-value format}
%%
@@ -123,7 +144,7 @@ lists (\texttt{level1=\{level2=\{key=value,value\}\}}).
%
%%
-\subsection{An (incomplete) attempt to put the syntax into the (Extended) Backus-Naur form}
+\subsection{An (incomplete) attempt to put the syntax into the Extended Backus-Naur Form}
\begin{grammar}
<list> ::= <list-item> | <list-item> <list>
@@ -137,6 +158,25 @@ lists (\texttt{level1=\{level2=\{key=value,value\}\}}).
\alt <number>
\alt <string-quoted>
\alt <string-unquoted>
+
+<sign> ::= `-' | `+'
+
+<integer> ::= `0' | `1' | `2' | `3' | `4' | `5' | `6' | `7' | `8' | `9'
+
+<unit> ::= `bp' | `BP'
+ \alt `cc' | `CC'
+ \alt `cm' | `CM'
+ \alt `dd' | `DD'
+ \alt `em' | `EM'
+ \alt `ex' | `EX'
+ \alt `in' | `IN'
+ \alt `mm' | `MM'
+ \alt `nc' | `NC'
+ \alt `nd' | `ND'
+ \alt `pc' | `PC'
+ \alt `pt' | `PT'
+ \alt `sp' | `SP'
+
\end{grammar}
... to be continued
@@ -226,7 +266,8 @@ local result = parse('dim=1cm', {
})
\end{minted}
-If you want to convert a scale point into a unit string you can used the module
+\noindent
+If you want to convert a scale point into a unit string you can use the module
\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}{lualibs-util-dim.lua}.
\begin{minted}{latex}
@@ -317,6 +358,46 @@ marks must be used.
\end{minted}
\end{multicols}
+\subsubsection{Standalone values}
+
+Standalone values are values without a key. They are converted into an
+array. In Lua an array is a table with numeric indexes (The first index
+is 1).
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{one,two,three}
+\end{minted}
+\columnbreak
+\begin{minted}{lua}
+{ 'one', 'two', 'three' }
+\end{minted}
+
+\noindent
+is equivalent to
+
+\begin{minted}{lua}
+{
+ [1] = 'one',
+ [2] = 'two',
+ [3] = 'three',
+}
+\end{minted}
+\end{multicols}
+
+\noindent
+All recognized data types can be used as standalone values.
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{one,2,3cm}
+\end{minted}
+\columnbreak
+\begin{minted}{lua}
+{ 'one', 2, 5594039 }
+\end{minted}
+\end{multicols}
+
%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------
@@ -325,7 +406,7 @@ marks must be used.
\section{Exported functions of the Lua module \texttt{luakeys.lua}}
-To learn more about the individual functions (local functions), pleasecommand
+To learn more about the individual functions (local functions), please
read the \href{https://josef-friedrich.github.io/luakeys/}{source code
documentation}, which was created with
\href{http://stevedonovan.github.io/ldoc/}{LDoc}. The Lua module exports
@@ -336,6 +417,8 @@ local luakeys = require('luakeys')
local parse = luakeys.parse
local render = luakeys.render
--local print = luakeys.print -- That would overwrite the built-in Lua function
+local save = luakeys.save
+local get = luakeys.get
\end{minted}
%%
@@ -443,6 +526,26 @@ The output should look like this:
}
\end{minted}
+%%
+%
+%%
+
+\subsection{\texttt{save(identifier, result): void}}
+
+The function \lua{save(identifier, result)} saves a result (a
+table from a previous run of \lua{parse}) under an identifier.
+Therefore, it is not necessary to pollute the global namespace to
+store results for the later usage.
+
+%%
+%
+%%
+
+\subsection{\texttt{get(identifier): table}}
+
+The function \lua{get(identifier)} retrieves a saved result from the
+result store.
+
%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------
@@ -535,8 +638,12 @@ An example of how to use the command in \LaTeX:
\inputminted[linenos=true]{latex}{luakeys-debug.sty}
-\changes{v0.1}{2020/01/17}{Inital release}
-
+\changes{v0.1}{2021/01/18}{Inital release}
+\changes{v0.2}{2021/09/19}{
+* Allow all recognized data types as keys
+* Allow TeX macros in the values
+* New public Lua functions: save(identifier, result), get(identifier)
+}
\pagebreak
\PrintChanges
\pagebreak