texlive[57463] Master: luakeys (18jan21)

commits+karl at tug.org commits+karl at tug.org
Mon Jan 18 23:15:49 CET 2021


Revision: 57463
          http://tug.org/svn/texlive?view=revision&revision=57463
Author:   karl
Date:     2021-01-18 23:15:49 +0100 (Mon, 18 Jan 2021)
Log Message:
-----------
luakeys (18jan21)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/libexec/ctan2tds
    trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/luatex/luakeys/
    trunk/Master/texmf-dist/doc/luatex/luakeys/README.md
    trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys-debug.tex
    trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf
    trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.tex
    trunk/Master/texmf-dist/tex/luatex/luakeys/
    trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys-debug.sty
    trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys.lua
    trunk/Master/tlpkg/tlpsrc/luakeys.tlpsrc

Added: trunk/Master/texmf-dist/doc/luatex/luakeys/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luakeys/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luakeys/README.md	2021-01-18 22:15:49 UTC (rev 57463)
@@ -0,0 +1,52 @@
+# luakeys
+
+`luakeys` is a Lua module that can parse key-value options like the
+TeX packages [keyval](https://www.ctan.org/pkg/keyval),
+[kvsetkeys](https://www.ctan.org/pkg/kvsetkeys),
+[kvoptions](https://www.ctan.org/pkg/kvoptions),
+[xkeyval](https://www.ctan.org/pkg/xkeyval),
+[pgfkeys](https://www.ctan.org/pkg/pgfkeys) etc. do. `luakeys`,
+however, accompilshes this task entirely, by using the Lua language and
+doesn’t rely on TeX. Therefore this package can only be used with the
+TeX engine LuaTeX. Since `luakeys` uses
+[LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/), the parsing
+mechanism should be pretty robust.
+
+## License
+
+Copyright 2021 Josef Friedrich
+
+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 2008/05/04 or later.
+
+This work has the LPPL maintenance status `maintained`.
+
+The Current Maintainer of this work is Josef Friedrich.
+
+## Tasks
+
+### Installing
+
+```
+make install
+```
+
+### Testing
+
+```
+luarocks install luaunit
+lua test/tests.lua
+```
+
+or
+
+```
+make test
+```


Property changes on: trunk/Master/texmf-dist/doc/luatex/luakeys/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys-debug.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys-debug.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys-debug.tex	2021-01-18 22:15:49 UTC (rev 57463)
@@ -0,0 +1,33 @@
+%% luakeys-debug.tex
+%% Copyright 2021 Josef Friedrich
+%
+% 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 2008/05/04 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Josef Friedrich.
+%
+% This work consists of the files luakeys.lua, luakeys-debug.sty
+% and luakeys-debug.tex.
+
+\directlua{
+  luakeys = require('luakeys')
+}
+
+\def\luakeysdebug#1{
+  {
+    \tt
+    \parindent=0pt
+    \directlua{
+      local result = luakeys.parse('#1')
+      tex.print(luakeys.stringify(result, true))
+      luakeys.print(result)
+    }
+  }
+}


Property changes on: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys-debug.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf	2021-01-18 22:13:42 UTC (rev 57462)
+++ trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf	2021-01-18 22:15:49 UTC (rev 57463)

Property changes on: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.tex	2021-01-18 22:15:49 UTC (rev 57463)
@@ -0,0 +1,544 @@
+\documentclass{ltxdoc}
+
+\usepackage{hyperref}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+
+\usepackage{mdframed}
+\usepackage{minted}
+\usepackage{luakeys-debug}
+\usepackage{multicol}
+\usepackage{luacode}
+\usepackage{syntax}
+\usemintedstyle{friendly}
+\BeforeBeginEnvironment{minted}{\begin{mdframed}}
+\AfterEndEnvironment{minted}{\end{mdframed}}
+\setminted{
+  breaklines=true,
+  fontsize=\footnotesize,
+}
+\def\lua#1{\mintinline{lua}|#1|}
+
+\begin{document}
+
+\providecommand*{\url}{\texttt}
+
+\title{The \textsf{luakeys} package}
+\author{%
+  Josef Friedrich\\%
+  \url{josef at friedrich.rocks}\\%
+  \href{https://github.com/Josef-Friedrich/nodetree}{github.com/Josef-Friedrich/luakeys}%
+}
+\date{v0.1 from 2021/01/18}
+
+\maketitle
+
+\vfill
+
+%\luakeysdebug{level1={level2={level3={dim=1cm,bool=true,num=-1e-03,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}}}')
+luakeys.print(kv)
+\end{minted}
+
+\noindent
+Result:
+
+\begin{center}
+\begin{minted}{lua}
+{
+  ['level1'] = {
+    ['level2'] = {
+      ['level3'] = {
+        ['dim'] = 1864679,
+        ['bool'] = true,
+        ['num'] = -0.001
+        ['str'] = 'lua',
+      }
+    }
+  }
+}
+\end{minted}
+\end{center}
+
+\vfill
+
+\strut
+
+\newpage
+
+\tableofcontents
+
+\newpage
+
+\section{Introduction}
+
+\noindent
+|luakeys| is a Lua module that can parse key-value options like the
+\TeX{} packages \href{https://www.ctan.org/pkg/keyval}{keyval},
+\href{https://www.ctan.org/pkg/kvsetkeys}{kvsetkeys},
+\href{https://www.ctan.org/pkg/kvoptions}{kvoptions},
+\href{https://www.ctan.org/pkg/xkeyval}{xkeyval},
+\href{https://www.ctan.org/pkg/pgfkeys}{pgfkeys} etc. do. |luakeys|,
+however, accompilshes this task entirely, by using the Lua language and
+doesn’t rely on \TeX{}. Therefore this package can only be used with the
+\TeX{} engine Lua\TeX{}. Since |luakeys| uses
+\href{http://www.inf.puc-rio.br/~roberto/lpeg/}{LPeg}, the parsing
+mechanism should be pretty robust.
+
+The TUGboat article
+\href{http://www.tug.org/tugboat/tb30-1/tb94wright-keyval.pdf}
+{“Implementing key–value input: An introduction” (Volume 30 (2009), No. 1)}
+by Joseph Wright and Christian Feuersänger gives a good overview of the
+available key-value packages.
+
+This package would not be possible without the article
+\href{https://tug.org/TUGboat/tb40-2/tb125menke-lpeg.pdf}
+{Parsing complex data formats in LuaTEX with LPEG (Volume 40 (2019), No. 2)}.
+
+%-----------------------------------------------------------------------
+%
+%-----------------------------------------------------------------------
+
+\clearpage
+
+\section{Syntax of the recognized key-value format}
+
+%%
+%
+%%
+
+\subsection{A attempt to put the syntax into words}
+
+A key-value pair is definied by an equal sign (\texttt{key=value}).
+Several key-value pairs or values without keys are lined up with commas
+(\texttt{key=value,value}) and build a key-value list. Curly brackets
+can be used to create a recursive data structure of nested key-value
+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-item> ::= ( <key-value-pair> | <value-without-key> ) [ `,' ]
+
+<list-container> ::== `{' <list> `}'
+
+<value> ::= <boolean>
+  \alt <dimension>
+  \alt <number>
+  \alt <string-quoted>
+  \alt <string-unquoted>
+\end{grammar}
+
+... to be continued
+
+%%
+%
+%%
+
+\subsection{Recognized data types}
+
+\subsubsection{boolean}
+
+The strings \texttt{true}, \texttt{TRUE} and \texttt{True} are converted
+into Lua’s boolean type \lua{true}, the strings \texttt{false},
+\texttt{FALSE} and \texttt{False} into \lua{false}.
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{
+  lower case true = true,
+  upper case true = TRUE,
+  title case true = True
+  lower case false = false,
+  upper case false = FALSE,
+  title case false = False,
+}
+\end{minted}
+\begin{minted}{lua}
+{
+  ['lower case true'] = true,
+  ['upper case true'] = true,
+  ['title case true'] = true,
+  ['lower case false'] = false,
+  ['upper case false'] = false
+  ['title case false'] = false,
+}
+\end{minted}
+\end{multicols}
+
+%%
+%
+%%
+
+\clearpage
+
+\subsubsection{number}
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{
+  num1 = 4,
+  num2 = -4,
+  num3 = 0.4,
+  num4 = 4.57e-3,
+  num5 = 0.3e12,
+  num6 = 5e+20
+}
+\end{minted}
+\begin{minted}{lua}
+{
+  ['num1'] = 4,
+  ['num2'] = -4,
+  ['num3'] = 0.4,
+  ['num4'] = 0.00457,
+  ['num5'] = 300000000000.0,
+  ['num6'] = 5e+20
+}
+\end{minted}
+\end{multicols}
+
+%%
+%
+%%
+
+\clearpage
+
+\subsubsection{dimension}
+
+|luakeys| detects \TeX{} dimensions and automatically converts the
+dimensions into scaled points using the function \lua{tex.sp(dim)}. Use
+the option \lua{convert_dimensions} of the function
+\lua{parse(kv_string, options)} to disalbe the automatic conversion.
+
+\begin{minted}{lua}
+local result = parse('dim=1cm', {
+  convert_dimensions = false,
+})
+\end{minted}
+
+If you want to convert a scale point into a unit string you can used the module
+\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}{lualibs-util-dim.lua}.
+
+\begin{minted}{latex}
+\begin{luacode}
+require('lualibs')
+tex.print(number.todimen(tex.sp('1cm'), 'cm', '%0.0F%s'))
+\end{luacode}
+\end{minted}
+
+\begin{center}
+\begin{tabular}{rl}
+\textbf{Unit name} & \textbf{Description} \\\hline
+bp & big point \\
+cc & cicero \\
+cm & centimeter \\
+dd & didot \\
+em & horizontal measure of \emph{M} \\
+ex & vertical measure of \emph{x} \\
+in & inch \\
+mm & milimeter \\
+nc & new cicero \\
+nd & new didot \\
+pc & pica \\
+pt & point \\
+sp & scaledpoint \\
+\end{tabular}
+\end{center}
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{
+  bp = 1bp,
+  cc = 1cc,
+  cm = 1cm,
+  dd = 1dd,
+  em = 1em,
+  ex = 1ex,
+  in = 1in,
+  mm = 1mm,
+  nc = 1nc,
+  nd = 1nd,
+  pc = 1pc,
+  pt = 1pt,
+  sp = 1sp,
+}
+\end{minted}
+\begin{minted}{lua}
+{
+  ['bp'] = 65781,
+  ['cc'] = 841489,
+  ['cm'] = 1864679,
+  ['dd'] = 70124,
+  ['em'] = 655360,
+  ['ex'] = 282460,
+  ['in'] = 4736286,
+  ['mm'] = 186467,
+  ['nc'] = 839105,
+  ['nd'] = 69925,
+  ['pc'] = 786432,
+  ['pt'] = 65536,
+  ['sp'] = 1,
+}
+\end{minted}
+\end{multicols}
+
+%%
+%
+%%
+
+\subsubsection{string}
+
+There are two ways to specify strings: With or without quotes. If the
+text have to contain commas or equal signs, then double quotation
+marks must be used.
+
+\begin{multicols}{2}
+\begin{minted}{latex}
+\luakeysdebug{
+  without quotes = no commas and equal signs are allowed,
+  with double quotes = ", and = are allowed",
+}
+\end{minted}
+\begin{minted}{lua}
+{
+  ['without quotes'] = 'no commas and equal signs are allowed',
+  ['with double quotes'] = ', and = are allowed',
+}
+\end{minted}
+\end{multicols}
+
+%-----------------------------------------------------------------------
+%
+%-----------------------------------------------------------------------
+
+\clearpage
+
+\section{Exported functions of the Lua module \texttt{luakeys.lua}}
+
+To learn more about the individual functions (local functions), pleasecommand
+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
+this functions:
+
+\begin{minted}{lua}
+local luakeys = require('luakeys')
+local parse = luakeys.parse
+local render = luakeys.render
+--local print = luakeys.print -- That would overwrite the built-in Lua function
+\end{minted}
+
+%%
+%
+%%
+
+\subsection{\texttt{parse(kv\_string, options)}: table}
+
+The function \lua{parse(input_string, options)} is the main method of
+this module. It parses a key-value string into a Lua table.
+
+\begin{minted}{latex}
+\newcommand{\mykeyvalcmd}[1][]{
+  \directlua{
+    result = luakeys.parse('#1')
+    luakeys.print(result)
+  }
+  #2
+}
+\mykeyvalcmd[one=1]{test}
+\end{minted}
+
+\noindent
+In plain \TeX:
+
+\begin{minted}{latex}
+\def\mykeyvalcommand#1{
+  \directlua{
+    result = luakeys.parse('#1')
+    luakeys.print(result)
+  }
+}
+\mykeyvalcmd{one=1}
+\end{minted}
+
+\noindent
+The function can be called with a options table. This two options are
+supported.
+
+\begin{minted}{lua}
+local result = parse('one,two,three', {
+  convert_dimensions = false,
+  unpack_single_array_value = false
+})
+\end{minted}
+
+%%
+%
+%%
+
+\subsection{\texttt{render(tbl)}: string}
+
+The function \lua{render(tbl)} reverses the function
+\lua{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.
+
+\begin{minted}{lua}
+result = luakeys.parse('one=1,two=2,tree=3,')
+print(luakeys.render(result))
+--- one=1,two=2,tree=3,
+--- or:
+--- two=2,one=1,tree=3,
+--- or:
+--- ...
+\end{minted}
+
+\noindent
+In Lua only tables with 1-based consecutive integer keys (a.k.a. array
+tables) can be parsed in order.
+
+\begin{minted}{lua}
+result = luakeys.parse('one,two,three')
+print(luakeys.render(result))
+--- one,two,three, (always)
+\end{minted}
+
+%%
+%
+%%
+
+\subsection{\texttt{print(tbl): void}}
+
+The function \lua{print(tbl)} 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 \lua{parse}. You have to
+compile your \TeX{} document in a console to see the terminal output.
+
+%\luakeysdebug{level1={level2={key=value}}}
+
+\begin{minted}{lua}
+result = luakeys.parse('level1={level2={key=value}}')
+luakeys.print(result)
+\end{minted}
+
+\noindent
+The output should look like this:
+
+\begin{minted}{md}
+{
+  ['level1'] = {
+    ['level2'] = {
+      ['key'] = 'value',
+  },
+}
+\end{minted}
+
+%-----------------------------------------------------------------------
+%
+%-----------------------------------------------------------------------
+
+\clearpage
+
+\section{Debug packages}
+
+Two small debug packages are included in |luakeys|. One debug package
+can be used in \LaTeX{} (luakeys-debug.sty) and one can be used in plain
+\TeX{} (luakeys-debug.tex). Both packages provide only one command:
+|\luakeysdebug{kv-string}|
+
+\begin{minted}{latex}
+\luakeysdebug{one,two,three}
+\end{minted}
+
+\noindent
+Then the following output should appear in the document:
+\bigskip
+
+\luakeysdebug{one,two,three}
+
+%%
+%
+%%
+
+\subsection{For plain \TeX: luakeys-debug.tex}
+
+An example of how to use the command in plain \TeX:
+
+\begin{minted}{latex}
+\input luakeys-debug.tex
+\luakeysdebug{one,two,three}
+\bye
+\end{minted}
+
+%%
+%
+%%
+
+\subsection{For \LaTeX: luakeys-debug.sty}
+
+An example of how to use the command in \LaTeX:
+
+\begin{minted}{latex}
+\documentclass{article}
+\usepackage{luakeys-debug}
+\begin{document}
+\luakeysdebug[
+  unpack single array values=false,
+  convert dimensions=false
+]{one,two,three}
+\end{document}
+\end{minted}
+
+%-----------------------------------------------------------------------
+%
+%-----------------------------------------------------------------------
+
+\clearpage
+
+\section{Implementation}
+
+%%
+%
+%%
+
+\subsection{luakeys.lua}
+
+\inputminted[linenos=true]{lua}{luakeys.lua}
+
+%%
+%
+%%
+
+\clearpage
+
+\subsection{luakeys-debug.tex}
+
+\inputminted[linenos=true]{latex}{luakeys-debug.tex}
+
+%%
+%
+%%
+
+\clearpage
+
+\subsection{luakeys-debug.sty}
+
+\inputminted[linenos=true]{latex}{luakeys-debug.sty}
+
+\changes{v0.1}{2020/01/17}{Inital release}
+
+\pagebreak
+\PrintChanges
+\pagebreak
+\PrintIndex
+\end{document}


Property changes on: trunk/Master/texmf-dist/doc/luatex/luakeys/luakeys.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys-debug.sty
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys-debug.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys-debug.sty	2021-01-18 22:15:49 UTC (rev 57463)
@@ -0,0 +1,39 @@
+%% luakeys-debug.sty
+%% Copyright 2021 Josef Friedrich
+%
+% 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 2008/05/04 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Josef Friedrich.
+%
+% This work consists of the files luakeys.lua, luakeys-debug.sty
+% and luakeys-debug.tex.
+
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{luakeys-debug}[2021/01/18 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)
+    }
+  }
+}


Property changes on: trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys-debug.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys.lua	2021-01-18 22:15:49 UTC (rev 57463)
@@ -0,0 +1,483 @@
+-- luakeys-debug.tex
+-- Copyright 2021 Josef Friedrich
+--
+-- 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 2008/05/04 or later.
+--
+-- This work has the LPPL maintenance status `maintained'.
+--
+-- The Current Maintainer of this work is Josef Friedrich.
+--
+-- This work consists of the files luakeys.lua, luakeys-debug.sty
+-- and luakeys-debug.tex.
+
+--- A key-value parser written with 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-lpeg.pdf)
+--
+-- @module luakeys
+
+local lpeg = require('lpeg')
+
+if not tex then
+  tex = {}
+
+  -- Dummy function for the tests.
+  tex['sp'] = function (input)
+    return 1234567
+  end
+end
+
+--- Generate the PEG parser using Lpeg.
+--
+-- @treturn userdata The parser
+local function generate_parser(options)
+  -- Optional whitespace
+  local white_space = lpeg.S(' \t\n\r')^0
+
+  --- Match literal string surrounded by whitespace
+  local ws = function(match)
+    return white_space * lpeg.P(match) * white_space
+  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)
+    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)
+
+    if options.convert_dimensions then
+      return dimension / tex.sp
+    else
+      return lpeg.C(dimension)
+    end
+  end
+
+  --- Add values to a table in a two modes:
+  --
+  -- # Key value pair
+  --
+  -- If arg1 and arg2 are not nil, then arg1 is the key and arg2 is the
+  -- value of a new table entry.
+  --
+  -- # Index value
+  --
+  -- 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)
+    if arg2 == nil then
+      local index = #table + 1
+      return rawset(table, index, arg1)
+    else
+      return rawset(table, arg1, arg2)
+    end
+  end
+
+  return lpeg.P({
+    'list',
+
+    list = lpeg.Cf(
+      lpeg.Ct('') * lpeg.V('list_item')^0,
+      add_to_table
+    ),
+
+    list_container =
+      ws('{') * lpeg.V('list') * ws('}'),
+
+    list_item =
+      lpeg.Cg(
+        lpeg.V('key_value_pair') +
+        lpeg.V('value')
+      ) * 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,
+
+    value =
+      lpeg.V('boolean') +
+      lpeg.V('dimension') +
+      lpeg.V('number') +
+      lpeg.V('string_quoted') +
+      lpeg.V('string_unquoted'),
+
+    boolean =
+      boolean_true * lpeg.Cc(true) +
+      boolean_false * lpeg.Cc(false),
+
+    dimension = build_dimension_pattern(),
+
+    string_quoted =
+      white_space * lpeg.P('"') *
+      lpeg.C((lpeg.P('\\"') + 1 - lpeg.P('"'))^0) *
+      lpeg.P('"') * white_space,
+
+    string_unquoted =
+      white_space *
+      lpeg.C((1 - lpeg.S('{},='))^1) *
+      white_space,
+
+    number =
+      white_space * (number / tonumber) * white_space,
+
+  })
+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.
+--
+-- @treturn number The size of the array like table. 0 if the input is
+-- no table or the table is empty.
+local function get_array_size(value)
+  local count = 0
+  if type(value) == 'table' then
+    for _ in ipairs(value) do count = count + 1 end
+  end
+  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.
+local function get_table_size(value)
+  local count = 0
+  if type(value) == 'table' then
+    for _ in pairs(value) do count = count + 1 end
+  end
+  return count
+end
+
+--- Unpack a single valued array table like `{ 'one' }` into `one` or
+-- `{ 1 }` into `into`.
+--
+-- @treturn If the value is a array like table with one non table typed
+-- value in it, the unpacked value, else the unchanged input.
+local function unpack_single_valued_array_table(value)
+  if
+    type(value) == 'table' and
+    get_array_size(value) == 1 and
+    get_table_size(value) == 1 and
+    type(value[1]) ~= 'table'
+  then
+    return value[1]
+  end
+  return value
+end
+
+--- 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`
+--
+-- @tparam table raw The raw input table coming directly from the PEG
+--   parser
+--
+-- @treturn table A normalized table ready for the outside world.
+local function normalize(raw, options)
+  local function normalize_recursive(raw, result, options)
+    for key, value in pairs(raw) do
+      if options.unpack_single_array_values then
+        value = unpack_single_valued_array_table(value)
+      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
+    end
+    return result
+  end
+  return normalize_recursive(raw, {}, options)
+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 `print` 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 input 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
+local function stringify(input, for_tex)
+  local line_break, start_bracket, end_bracket, indent
+
+  if for_tex then
+    line_break = '\\par'
+    start_bracket = '\\{'
+    end_bracket = '\\}'
+    indent = '\\ \\ '
+  else
+    line_break = '\n'
+    start_bracket = '{'
+    end_bracket = '}'
+    indent = '  '
+  end
+
+  local function stringify_inner(input, depth)
+    local output = {}
+    depth = depth or 0;
+
+    local function add(depth, text)
+      table.insert(output, string.rep(indent, depth) .. text)
+    end
+
+    for key, value in pairs(input) do
+      if (key and type(key) == 'number' or type(key) == 'string') then
+        key = string.format('[\'%s\']', 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, end_bracket .. ',');
+          else
+            add(depth, key .. ' = ' .. start_bracket .. end_bracket .. ',');
+          end
+        else
+          if (type(value) == 'string') then
+            value = string.format('\'%s\'', value);
+          else
+            value = tostring(value);
+          end
+
+          add(depth, key .. ' = ' .. value .. ',');
+        end
+      end
+    end
+
+    return table.concat(output, line_break)
+  end
+
+  return start_bracket .. line_break .. stringify_inner(input, 1) .. line_break .. end_bracket
+end
+
+--- For the LaTeX version of the macro
+--  `\luakeysdebug[options]{kv-string}`.
+--
+-- @tparam table options_raw Options in a raw format. The table may be
+-- empty or some keys are not set.
+--
+-- @treturn table
+local function normalize_parse_options (options_raw)
+  if options_raw == nil then
+    options_raw = {}
+  end
+  local options = {}
+
+  if options_raw['unpack single array values'] ~= nil then
+    options['unpack_single_array_values'] = options_raw['unpack single array values']
+  end
+
+  if options_raw['convert dimensions'] ~= nil then
+    options['convert_dimensions'] = options_raw['convert dimensions']
+  end
+
+  if options.convert_dimensions == nil then
+    options.convert_dimensions = true
+  end
+
+  if options.unpack_single_array_values == nil then
+    options.unpack_single_array_values = true
+  end
+
+  return options
+end
+
+return {
+  stringify = stringify,
+
+  --- Parse a LaTeX/TeX style key-value string into a Lua table. With
+  -- this function you should be able to parse key-value strings like
+  -- this example:
+  --
+  --     show,
+  --     hide,
+  --     key with spaces = String without quotes,
+  --     string="String with double quotes: ,{}=",
+  --     dimension = 1cm,
+  --     number = -1.2,
+  --     list = {one,two,three},
+  --     key value list = {one=one,two=two,three=three},
+  --     nested key = {
+  --       nested key 2= {
+  --         key = value,
+  --       },
+  --     },
+  --
+  -- The string above results in this Lua table:
+  --
+  --     {
+  --       'show',
+  --       'hide',
+  --       ['key with spaces'] = 'String without quotes',
+  --       string = 'String with double quotes: ,{}=',
+  --       dimension = 1864679,
+  --       number = -1.2,
+  --       list = {'one', 'two', 'three'},
+  --       key value list = {
+  --         one = 'one',
+  --         three = 'three',
+  --         two = 'two'
+  --       },
+  --       ['nested key'] = {
+  --         ['nested key 2'] = {
+  --           key = 'value'
+  --         }
+  --       },
+  --     }
+  --
+  -- @tparam string kv_string A string in the TeX/LaTeX style key-value
+  --   format as described above.
+  --
+  -- @tparam table options A table containing
+  -- settings: `convert_dimensions` `unpack_single_array_values`
+  --
+  -- @treturn table A hopefully properly parsed table you can do
+  -- something useful with.
+  parse = function (kv_string, options)
+    if kv_string == nil then
+      return {}
+    end
+    options = normalize_parse_options()
+
+    local parser = generate_parser(options)
+    return normalize(parser:match(kv_string), options)
+  end,
+
+  --- 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 tbl A table to be converted into a key-value string.
+  --
+  -- @treturn string A key-value string that can be passed to a TeX
+  -- macro.
+  render = function (tbl)
+    local function render_inner(tbl)
+      local output = {}
+      local function add(text)
+        table.insert(output, text)
+      end
+      for key, value in pairs(tbl) do
+        if (key and type(key) == 'string') then
+          if (type(value) == 'table') then
+            if (next(value)) then
+              add(key .. '={');
+              add(render_inner(value));
+              add('},');
+            else
+              add(key .. '={},');
+            end
+          else
+            add(key .. '=' .. tostring(value) .. ',');
+          end
+        else
+          add(tostring(value) .. ',')
+        end
+      end
+      return table.concat(output)
+    end
+    return render_inner(tbl)
+  end,
+
+  --- The function `print(tbl)` 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 tbl A table to be printed to standard output for
+  -- debugging purposes.
+  print = function(tbl)
+    print(stringify(tbl, false))
+  end,
+
+}


Property changes on: trunk/Master/texmf-dist/tex/luatex/luakeys/luakeys.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-01-18 22:13:42 UTC (rev 57462)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2021-01-18 22:15:49 UTC (rev 57463)
@@ -471,7 +471,8 @@
     lua-alt-getopt lua-check-hyphen lua-physical lua-uca lua-ul
     lua-uni-algos lua-visual-debug
     luabibentry luabidi luacode luacolor luahyphenrules
-    luaimageembed luaindex luainputenc luaintro lualatex-doc lualatex-doc-de
+    luaimageembed luaindex luainputenc luaintro luakeys
+    lualatex-doc lualatex-doc-de
     lualatex-math lualatex-truncate lualibs
     luamesh luamplib luaotfload luapackageloader luaprogtable luarandom
     luasseq luatex85 luatexbase luatexja luatexko luatextra

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2021-01-18 22:13:42 UTC (rev 57462)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2021-01-18 22:15:49 UTC (rev 57463)
@@ -2024,6 +2024,7 @@
  'lua2dox',     'NULL',         # .def is lua code
  'luabidi',	'(arabmaths|footnoterule)|' . $standardtex,
  'luaintro',    'NULL',         # doc pkg
+ 'luakeys',	'\.lua|' . $standardtex,
  'lualatex-math', '\.sty',      # not phst-doc.cls
  'luamesh',	'\.sty',        # not lltxdoc.cls
  'luapackageloader', '\.lua|' . $standardtex,

Modified: trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc	2021-01-18 22:13:42 UTC (rev 57462)
+++ trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc	2021-01-18 22:15:49 UTC (rev 57463)
@@ -33,6 +33,7 @@
 depend luaindex
 depend luainputenc
 depend luaintro
+depend luakeys
 depend lualatex-doc
 depend lualatex-math
 depend lualatex-truncate

Added: trunk/Master/tlpkg/tlpsrc/luakeys.tlpsrc
===================================================================


More information about the tex-live-commits mailing list.