summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/luakeys
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-01-01 03:00:53 +0000
committerNorbert Preining <norbert@preining.info>2022-01-01 03:00:53 +0000
commit39877769ecfa442af71b4ddd1c266f401957cdd8 (patch)
tree06aaa106eb40b7e0b2ee91073f636bb5975e502c /macros/luatex/generic/luakeys
parent2c09a813df08895666d3755db66718dcd501aee5 (diff)
CTAN sync 202201010300
Diffstat (limited to 'macros/luatex/generic/luakeys')
-rw-r--r--macros/luatex/generic/luakeys/README.md18
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.sty4
-rw-r--r--macros/luatex/generic/luakeys/luakeys-debug.tex2
-rw-r--r--macros/luatex/generic/luakeys/luakeys-doc.pdfbin157648 -> 159798 bytes
-rw-r--r--macros/luatex/generic/luakeys/luakeys-doc.tex35
-rw-r--r--macros/luatex/generic/luakeys/luakeys.lua227
-rw-r--r--macros/luatex/generic/luakeys/luakeys.sty4
-rw-r--r--macros/luatex/generic/luakeys/luakeys.tex2
8 files changed, 162 insertions, 130 deletions
diff --git a/macros/luatex/generic/luakeys/README.md b/macros/luatex/generic/luakeys/README.md
index 8c2e5cf8db..10793d353e 100644
--- a/macros/luatex/generic/luakeys/README.md
+++ b/macros/luatex/generic/luakeys/README.md
@@ -14,7 +14,7 @@ mechanism should be pretty robust.
## License
-Copyright 2021 Josef Friedrich
+Copyright 2021-2022 Josef Friedrich
This work may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either version 1.3c
@@ -41,8 +41,8 @@ make install
### Testing
```
-luarocks install luaunit
-lua test/tests.lua
+luarocks install busted
+busted --exclude-tags=skip test/lua/*.lua
```
or
@@ -53,6 +53,12 @@ make test
### Release a new version
+Update version in:
+
+* luakeys-doc.tex
+* luakeys-debug.sty
+* luakeys.sty
+
Update copyright in:
* LICENSE
@@ -63,12 +69,6 @@ Update copyright in:
* luakeys.tex
* README.md
-Update version in:
-
-* luakeys-doc.tex
-* luakeys-debug.sty
-* luakeys.sty
-
Summarize the changes in the luakeys-doc.tex as changes.
Create a new git tag `git tag -sa v0.3`. Prefix the version with “v”.
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.sty b/macros/luatex/generic/luakeys/luakeys-debug.sty
index ca800bfad7..56e3329ac4 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.sty
+++ b/macros/luatex/generic/luakeys/luakeys-debug.sty
@@ -1,5 +1,5 @@
%% luakeys-debug.sty
-%% Copyright 2021 Josef Friedrich
+%% Copyright 2021-2022 Josef Friedrich
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
@@ -17,6 +17,6 @@
% luakeys-debug.sty and luakeys-debug.tex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{luakeys-debug}[2021/11/05 v0.3 Debug package for luakeys.]
+\ProvidesPackage{luakeys-debug}[2021/12/31 v0.4 Debug package for luakeys.]
\input luakeys-debug.tex
diff --git a/macros/luatex/generic/luakeys/luakeys-debug.tex b/macros/luatex/generic/luakeys/luakeys-debug.tex
index a6cd7c85c2..ffc449ac9b 100644
--- a/macros/luatex/generic/luakeys/luakeys-debug.tex
+++ b/macros/luatex/generic/luakeys/luakeys-debug.tex
@@ -1,5 +1,5 @@
%% luakeys-debug.tex
-%% Copyright 2021 Josef Friedrich
+%% Copyright 2021-2022 Josef Friedrich
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
diff --git a/macros/luatex/generic/luakeys/luakeys-doc.pdf b/macros/luatex/generic/luakeys/luakeys-doc.pdf
index 3c28176a7d..0f796cc12c 100644
--- a/macros/luatex/generic/luakeys/luakeys-doc.pdf
+++ b/macros/luatex/generic/luakeys/luakeys-doc.pdf
Binary files differ
diff --git a/macros/luatex/generic/luakeys/luakeys-doc.tex b/macros/luatex/generic/luakeys/luakeys-doc.tex
index b7e525fc4b..99dfa6805b 100644
--- a/macros/luatex/generic/luakeys/luakeys-doc.tex
+++ b/macros/luatex/generic/luakeys/luakeys-doc.tex
@@ -30,17 +30,17 @@
\url{josef@friedrich.rocks}\\%
\href{https://github.com/Josef-Friedrich/luakeys}{github.com/Josef-Friedrich/luakeys}%
}
-\date{v0.3 from 2021/11/05}
+\date{v0.4 from 2021/12/31}
\maketitle
\vfill
-%\luakeysdebug{level1={level2={level3={dim=1cm,bool=true,num=-1e-03,str=lua}}}}
+%level1={level2={level3={dim=1cm,bool=true,num=-0.001,str=lua}}}
\begin{minted}{lua}
local luakeys = require('luakeys')
-local kv = luakeys.parse('level1={level2={level3={dim=1cm,bool=true,num=-1e-03,str=lua}}}')
+local kv = luakeys.parse('level1={level2={level3={dim=1cm,bool=true,num=-0.001,str=lua}}}')
luakeys.print(kv)
\end{minted}
@@ -217,11 +217,13 @@ lists (\texttt{level1=\{level2=\{key=value,value\}\}}).
\subsection{An (incomplete) attempt to put the syntax into the Extended Backus-Naur Form}
\begin{grammar}
-<list> ::= <list-item> | <list-item> <list>
+<list> ::= \{ <list-item> \}
-<list-item> ::= ( <key-value-pair> | <value-without-key> ) [ `,' ]
+<list-container> ::= `{' <list> `}'
-<list-container> ::== `{' <list> `}'
+<list-item> ::= ( <list-container> | <key-value-pair> | <value> ) [ `,' ]
+
+<key-value-pair> ::= <value> `=' ( <list-container> | <value> )
<value> ::= <boolean>
\alt <dimension>
@@ -247,6 +249,11 @@ lists (\texttt{level1=\{level2=\{key=value,value\}\}}).
\alt `pt' | `PT'
\alt `sp' | `SP'
+<boolean> ::= <boolean-true> | <boolean-false>
+
+<boolean-true> ::= `true' | `TRUE' | `True'
+
+<boolean-false> ::= `false' | `FALSE' | `False'
\end{grammar}
... to be continued
@@ -299,20 +306,14 @@ into Lua’s boolean type \lua{true}, the strings \texttt{false},
\luakeysdebug{
num1 = 4,
num2 = -4,
- num3 = 0.4,
- num4 = 4.57e-3,
- num5 = 0.3e12,
- num6 = 5e+20
+ num3 = 0.4
}
\end{minted}
\begin{minted}{lua}
{
['num1'] = 4,
['num2'] = -4,
- ['num3'] = 0.4,
- ['num4'] = 0.00457,
- ['num5'] = 300000000000.0,
- ['num6'] = 5e+20
+ ['num3'] = 0.4
}
\end{minted}
\end{multicols}
@@ -719,6 +720,12 @@ An example of how to use the command in \LaTeX:
* Add a plain LuaTeX wrapper “luakeys.tex”
* Rename the previous documentation file “luakeys.tex” to luakeys-doc.tex”
}
+\changes{v0.4}{2021/12/31}{
+* Parser: Add support for nested tables (for example {{'a', 'b'}})
+* Parser: Allow only strings and numbers as keys
+* Parser: Remove support from Lua numbers with exponents (for example '5e+20')
+* Switch the Lua testing framework to busted
+}
\pagebreak
\PrintChanges
\pagebreak
diff --git a/macros/luatex/generic/luakeys/luakeys.lua b/macros/luatex/generic/luakeys/luakeys.lua
index 05b3d94e1f..c5f51fcfad 100644
--- a/macros/luatex/generic/luakeys/luakeys.lua
+++ b/macros/luatex/generic/luakeys/luakeys.lua
@@ -1,5 +1,5 @@
-- luakeys.lua
--- Copyright 2021 Josef Friedrich
+-- Copyright 2021-2022 Josef Friedrich
--
-- This work may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either version 1.3c
@@ -26,11 +26,20 @@
-- * `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-lpeg.pdf)
+-- * [TUGboat article: Parsing complex data formats in LuaTEX with LPEG](https://tug.org/TUGboat/tb40-2/tb125menke-Patterndf)
--
-- @module luakeys
local lpeg = require('lpeg')
+local Variable = lpeg.V
+local Pattern = lpeg.P
+local Set = lpeg.S
+local Range = lpeg.R
+local CaptureGroup = lpeg.Cg
+local CaptureFolding = lpeg.Cf
+local CaptureTable = lpeg.Ct
+local CaptureConstant = lpeg.Cc
+local CaptureSimple = lpeg.C
if not tex then
tex = {}
@@ -49,70 +58,18 @@ local result_store = {}
-- @treturn userdata The parser.
local function generate_parser(options)
-- Optional whitespace
- local white_space = lpeg.S(' \t\n\r')
+ local white_space = Set(' \t\n\r')
--- Match literal string surrounded by whitespace
local ws = function(match)
- return white_space^0 * lpeg.P(match) * white_space^0
+ return white_space^0 * Pattern(match) * white_space^0
end
- local boolean_true =
- lpeg.P('true') +
- lpeg.P('TRUE') +
- lpeg.P('True')
-
- local boolean_false =
- lpeg.P('false') +
- lpeg.P('FALSE') +
- lpeg.P('False')
-
- local number = lpeg.P({'number',
- number =
- lpeg.V('int') *
- lpeg.V('frac')^-1 *
- lpeg.V('exp')^-1,
-
- int = lpeg.V('sign')^-1 * (
- lpeg.R('19') * lpeg.V('digits') + lpeg.V('digit')
- ),
-
- sign = lpeg.S('+-'),
- digit = lpeg.R('09'),
- digits = lpeg.V('digit') * lpeg.V('digits') + lpeg.V('digit'),
- frac = lpeg.P('.') * lpeg.V('digits'),
- exp = lpeg.S('eE') * lpeg.V('sign')^-1 * lpeg.V('digits'),
- })
-
- --- Define data type dimension.
- --
- -- @return Lpeg patterns
- local function build_dimension_pattern()
- local sign = lpeg.S('-+')
- local integer = lpeg.R('09')^1
- local tex_number = (integer^1 * (lpeg.P('.') * integer^1)^0) + (lpeg.P('.') * integer^1)
-
- -- 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)
-
+ local capture_dimension = function (input)
if options.convert_dimensions then
- return dimension / tex.sp
+ return tex.sp(input)
else
- return lpeg.C(dimension)
+ return input
end
end
@@ -142,59 +99,119 @@ local function generate_parser(options)
end
end
- return lpeg.P({
+ return Pattern({
'list',
- list = lpeg.Cf(
- lpeg.Ct('') * lpeg.V('list_item')^0,
+ -- list_item*
+ list = CaptureFolding(
+ CaptureTable('') * Variable('list_item')^0,
add_to_table
),
+ -- '{' list '}'
list_container =
- ws('{') * lpeg.V('list') * ws('}'),
+ ws('{') * Variable('list') * ws('}'),
+ -- ( list_container / key_value_pair / value ) ','?
list_item =
- lpeg.Cg(
- lpeg.V('key_value_pair') +
- lpeg.V('value')
+ CaptureGroup(
+ Variable('list_container') +
+ Variable('key_value_pair') +
+ Variable('value')
) * ws(',')^-1,
+ -- key '=' (list_container / value)
key_value_pair =
- (lpeg.V('value') * ws('=')) * (lpeg.V('list_container') + lpeg.V('value')),
+ (Variable('key') * ws('=')) * (Variable('list_container') + Variable('value')),
- value =
- lpeg.V('boolean') +
- lpeg.V('dimension') +
- lpeg.V('number') +
- lpeg.V('string_quoted') +
- lpeg.V('string_unquoted') +
- lpeg.V('array'),
+ -- number / string_quoted / string_unquoted
+ key =
+ Variable('number') +
+ Variable('string_quoted') +
+ Variable('string_unquoted'),
- array =
- ws('{') * lpeg.Ct((lpeg.V('value') * ws(',')^-1)^0) * ws('}'),
+ -- boolean !value / dimension !value / number !value / string_quoted !value / string_unquoted
+ -- !value -> Not-predicate -> * -Variable('value')
+ value =
+ Variable('boolean') * -Variable('value') +
+ Variable('dimension') * -Variable('value') +
+ Variable('number') * -Variable('value') +
+ Variable('string_quoted') * -Variable('value') +
+ Variable('string_unquoted'),
+ -- boolean_true / boolean_false
boolean =
- boolean_true * lpeg.Cc(true) +
- boolean_false * lpeg.Cc(false),
-
- dimension = build_dimension_pattern(),
+ (
+ Variable('boolean_true') * CaptureConstant(true) +
+ Variable('boolean_false') * CaptureConstant(false)
+ ),
+
+ boolean_true =
+ Pattern('true') +
+ Pattern('TRUE') +
+ Pattern('True'),
+
+ boolean_false =
+ Pattern('false') +
+ Pattern('FALSE') +
+ Pattern('False'),
+
+ dimension = (
+ Variable('sign')^0 * white_space^0 *
+ Variable('tex_number') * white_space^0 *
+ Variable('unit')
+ ) / capture_dimension,
number =
- white_space^0 * (number / tonumber) * white_space^0,
+ (white_space^0 * (Variable('lua_number') / tonumber) * white_space^0) ,
+
+ tex_number =
+ (Variable('integer')^1 * (Pattern('.') * Variable('integer')^1)^0) +
+ (Pattern('.') * Variable('integer')^1),
+
+ -- 'bp' / 'BP' / 'cc' / etc.
+ -- https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua
+ unit =
+ Pattern('bp') + Pattern('BP') +
+ Pattern('cc') + Pattern('CC') +
+ Pattern('cm') + Pattern('CM') +
+ Pattern('dd') + Pattern('DD') +
+ Pattern('em') + Pattern('EM') +
+ Pattern('ex') + Pattern('EX') +
+ Pattern('in') + Pattern('IN') +
+ Pattern('mm') + Pattern('MM') +
+ Pattern('nc') + Pattern('NC') +
+ Pattern('nd') + Pattern('ND') +
+ Pattern('pc') + Pattern('PC') +
+ Pattern('pt') + Pattern('PT') +
+ Pattern('sp') + Pattern('SP'),
+
+ lua_number =
+ Variable('int') *
+ Variable('frac')^-1,
+
+ int = Variable('sign')^-1 * (
+ Range('19') * Variable('integer') + Variable('integer')
+ ),
+
+ frac = Pattern('.') * Variable('integer'),
+ sign = Set('-+'),
+ integer = Range('09')^1,
+ -- '"' ('\"' / !'"')* '"'
string_quoted =
- white_space^0 * lpeg.P('"') *
- lpeg.C((lpeg.P('\\"') + 1 - lpeg.P('"'))^0) *
- lpeg.P('"') * white_space^0,
+ white_space^0 * Pattern('"') *
+ CaptureSimple((Pattern('\\"') + 1 - Pattern('"'))^0) *
+ Pattern('"') * white_space^0,
string_unquoted =
white_space^0 *
- lpeg.C(
- lpeg.V('word_unquoted')^1 *
- (lpeg.S(' \t')^1 * lpeg.V('word_unquoted')^1)^0) *
+ CaptureSimple(
+ Variable('word_unquoted')^1 *
+ (Set(' \t')^1 * Variable('word_unquoted')^1)^0) *
white_space^0,
- word_unquoted = (1 - white_space - lpeg.S('{},='))^1;
+ word_unquoted = (1 - white_space - Set('{},='))^1
})
end
@@ -306,36 +323,44 @@ local function stringify(input, for_tex)
local function stringify_inner(input, depth)
local output = {}
- depth = depth or 0;
+ depth = depth or 0
local function add(depth, text)
table.insert(output, string.rep(indent, depth) .. text)
end
+ local function format_key(key)
+ if (type(key) == 'number') then
+ return string.format('[%s]', key)
+ else
+ return string.format('[\'%s\']', key)
+ end
+ 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);
+ key = format_key(key)
if (type(value) == 'table') then
if (next(value)) then
- add(depth, key .. ' = ' .. start_bracket);
- add(0, stringify_inner(value, depth + 1, for_tex));
+ add(depth, key .. ' = ' .. start_bracket)
+ 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
- value = string.format('\'%s\'', value);
+ value = string.format('\'%s\'', value)
else
- value = tostring(value);
+ value = tostring(value)
end
- add(depth, key .. ' = ' .. value .. ',');
+ add(depth, key .. ' = ' .. value .. ',')
end
end
end
@@ -460,14 +485,14 @@ return {
if (key and type(key) == 'string') then
if (type(value) == 'table') then
if (next(value)) then
- add(key .. '={');
- add(render_inner(value));
- add('},');
+ add(key .. '={')
+ add(render_inner(value))
+ add('},')
else
- add(key .. '={},');
+ add(key .. '={},')
end
else
- add(key .. '=' .. tostring(value) .. ',');
+ add(key .. '=' .. tostring(value) .. ',')
end
else
add(tostring(value) .. ',')
diff --git a/macros/luatex/generic/luakeys/luakeys.sty b/macros/luatex/generic/luakeys/luakeys.sty
index 6717b85b57..31d56854f3 100644
--- a/macros/luatex/generic/luakeys/luakeys.sty
+++ b/macros/luatex/generic/luakeys/luakeys.sty
@@ -1,5 +1,5 @@
%% luakeys.sty
-%% Copyright 2021 Josef Friedrich
+%% Copyright 2021-2022 Josef Friedrich
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
@@ -17,5 +17,5 @@
% luakeys-debug.sty and luakeys-debug.tex.
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{luakeys}[2021/11/05 v0.3 Parsing key-value options using Lua.]
+\ProvidesPackage{luakeys}[2021/12/31 v0.4 Parsing key-value options using Lua.]
\directlua{luakeys = require('luakeys')}
diff --git a/macros/luatex/generic/luakeys/luakeys.tex b/macros/luatex/generic/luakeys/luakeys.tex
index 68fc92d8ee..c3c69a0ba3 100644
--- a/macros/luatex/generic/luakeys/luakeys.tex
+++ b/macros/luatex/generic/luakeys/luakeys.tex
@@ -1,5 +1,5 @@
%% luakeys.tex
-%% Copyright 2021 Josef Friedrich
+%% Copyright 2021-2022 Josef Friedrich
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c