\documentclass{ltxdoc}

\EnableCrossrefs
\CodelineIndex
\RecordChanges

\usepackage{mdframed}
\usepackage{minted}
\usepackage{luakeys}
\usepackage{luakeys-debug}
\usepackage{multicol}
\usepackage{luacode}
\usepackage{syntax}
\usepackage{graphicx}

\definecolor{bg}{rgb}{0.95,0.95,0.95}

\usemintedstyle{friendly}
\setminted{
  breaklines=true,
  fontsize=\footnotesize,
  style=manni,
}
\def\lua#1{\mintinline{lua}|#1|}
\def\latex#1{\mintinline{latex}|#1|}

\NewDocumentCommand { \InputLatex } { O{} m } {
  \inputminted[
    linenos=false,
    bgcolor=bg,
    #1
  ]{latex}{examples/#2}
}

\NewDocumentCommand { \InputLua } { O{} m } {
  \inputminted[
    linenos=false,
    bgcolor=bg,
    #1
  ]{lua}{examples/#2}
}

\catcode`_=12
\def\DefaultOpt#1{%
  \texttt{\directlua{
    tex.print(luakeys.print_default('opts', '#1'))
  }}%
}

\def\DefaultOptDescription#1{
\noindent
The default value of the option “\texttt{#1}” is:
\DefaultOpt{#1}.
}

\begin{document}

\providecommand*{\url}{\texttt}

\title{The \textsf{luakeys} package}
\author{%
  Josef Friedrich\\%
  \url{josef@friedrich.rocks}\\%
  \href{https://github.com/Josef-Friedrich/luakeys}
       {github.com/Josef-Friedrich/luakeys}%
}
\date{v0.15.0 from 2024/09/29}

\maketitle

\vfill

\InputLua[firstline=4,lastline=7]{first-page.lua}

\noindent
Result:

\begin{center}
\begin{minted}{lua}
{
  ['level1'] = {
    ['level2'] = {
      ['naked'] = true,
      ['dim'] = 1864679,
      ['bool'] = false,
      ['num'] = -0.001,
      ['str'] = 'lua,{}',
    }
  }
}
\end{minted}
\end{center}

\vfill

\strut

\newpage

\tableofcontents

\newpage

% \section{Einführung}
\section{Introduction}

\noindent
% |luakeys| ist ein Lua-Modul / Lua\TeX package, das wie die Pakete ...
% Schlüssel-Wert-Optionen analysieren kann.
|luakeys| is a Lua module / Lua\TeX{} package 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.
%
% |luakeys|, erfüllt diese Aufgabe jedoch, indem es die Sprache Lua
% verwendet und nicht auf \TeX{} angewiesen ist.
|luakeys|, however, accomplishes this task by using the Lua language and
doesn’t rely on \TeX{}.
%
% Deshalb kann dieses Paket nur mit der \TeX{}-Engine Lua\TeX{}
% verwendet werden.
Therefore this package can only be used with the
\TeX{} engine Lua\TeX{}.
%
% Da |luakeys| \href{http://www.inf.puc-rio.br/~roberto/lpeg/}{LPeg}
% verwendet, sollte der Parsing-Mechanismus ziemlich robust sein.
Since |luakeys| uses
\href{http://www.inf.puc-rio.br/~roberto/lpeg/}{LPeg}, the parsing
mechanism should be pretty robust.

% Der Artikel TUGboat
% \href{http://www.tug.org/tugboat/tb30-1/tb94wright-keyval.pdf}
% {“Implementing key–value input: An introduction” (Volume 30 (2009), No.
% 1)} von \emph{Joseph Wright} und \emph{Christian Feuersänger} gibt einen
% einen guten Überblick über die verfügbaren Key-Value-Pakete.
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 \emph{Joseph Wright} and \emph{Christian Feuersänger} gives a
good overview of the available key-value packages.
%
% Dieser Artikel geht auf eine auf tex.stackexchange.com von Will
% Robertson: gestellte Frage zurück.
This article is based on a question asked on tex.stackexchange.com by
Will Robertson:
\href{https://tex.stackexchange.com/questions/26771}
{A big list of every keyval package}.
%
% CTAN stellt auch eine Übersichtsseite zum Thema bereit.
CTAN also provides an overview page on the subject of
\href{https://www.ctan.org/topic/keyval}
{Key-Val: packages with key-value argument systems}.

% Dieses Paket wäre ohne den Artikel
% \href{https://tug.org/TUGboat/tb40-2/tb125menke-lpeg.pdf}
% {"Parsing complex data formats in LuaTEX with LPEG" (Volume 40 (2019),
% No. 2)} nicht möglich gewesen.
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)}.

\subsection{Pros of \texttt{luakeys}}

\begin{itemize}
% \item Schlüssel-Wert-Paare können unabhängig vom Makro-Paket (latex or
% context) analysiert werden.
\item Key-value pairs can be parsed independently of the macro
collection (\LaTeX{} or Con\TeX{}t).
% Sogar in Plain LuaTex können Schlüssel analysiert werden
Even in plain Lua\TeX{} keys can be parsed.

% \item |luakeys| kann mit ineinander verschachtelten listen an
% Schlüssel-Wert-Paaren umgehen, d. h. es kann mit einer rekursiven
% Datenstruktur an Schlüssel umgehen.
\item |luakeys| can handle nested lists of key-value pairs, i.e. it can
handle a recursive data structure of keys.

% \item Schlüssel müssen nicht, aber können definiert werden.
\item Keys do not have to be defined, but can they can be defined.
\end{itemize}

\subsection{Cons of \texttt{luakeys}}

\begin{itemize}
% \item Das Packet funktioniert nur in der Verbindung mit Lua\TeX.
\item The package works only in combination with Lua\TeX.

% \item Du musst zwei Sprachen beherrschen: \TeX{} und Lua.
\item You need to know two languages: \TeX{} and Lua.
\end{itemize}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

% \section{Wie das Paket geladen wird}
\section{How the package is loaded}

%%
%
%%

\subsection{Using the Lua module \texttt{luakeys.lua}}

% Die Kernfunktionalität dieses Pakets ist in Lua realisiert.
The core functionality of this package is realized in Lua.
%
% Sie können also |luakeys| auch ohne die Wrapper-Dateien
% \texttt{luakeys.sty} und \texttt{luakeys.tex} verwenden.
So you can use |luakeys| even without using the wrapper files
|luakeys.sty| and |luakeys.tex|.

\InputLatex{loading/lua.tex}

%%
%
%%

\subsection{Using the Lua\LaTeX{} wrapper \texttt{luakeys.sty}}

% Der Paketmanager MikTeX lädt beispielsweise Pakete erst bei Bedarf
% herunter.
For example, the MiK\TeX{} package manager downloads packages only when
needed.
%
% Es wurde berichtet, dass dieser automatische Download nur mit Hilfe
% der Hüll-Dateien funktioniert.
It has been reported that this automatic download only works with this
wrapper files.
%
% Wahrscheinlich hält MiK\TeX nach einem Auftreten des LaTeX macros
% “\latex{\usepackage{luakeys}} ”Ausschau.
Probably MiK\TeX{} is searching for an occurrence of the \LaTeX{} macro
“\latex{\usepackage{luakeys}}”.
%
% Die Datei \texttt{luakeys.sty} lädt das Lua-Modul in die globale
% Variable \texttt{luakeys}.
The \texttt{luakeys.sty} file loads the Lua module into the global
variable \texttt{luakeys}.

\InputLatex{loading/tex-latex.tex}

%%
%
%%

% \subsection{Verwendung des Plain-Lua\TeX{}-Hüllpakets
% \texttt{luakeys.tex}}
\subsection{Using the plain Lua\TeX{} wrapper \texttt{luakeys.tex}}

\noindent
% Es macht dasselbe wie das Lua\LaTeX{}-Hüllpacket und lädt das
% Lua-Modul \texttt{luakeys.lua} in die globale Variable
% \texttt{luakeys}.
The file \texttt{luakeys.tex} does the same as the Lua\LaTeX{} wrapper
and loads the Lua module \texttt{luakeys.lua} into the global variable
\texttt{luakeys}.

\InputLatex{loading/tex-plain.tex}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Lua interface / API}

% Luakeys exportiert nur eine Funktion, die aufgerufen werden muss, um auf
% die öffentliche API zuzugreifen
Luakeys exports only one function that must be called to access the
public API.
%
% Diese Exportfunktion gibt eine Tabelle zurück, die die öffentlichen
% Funktionen und weiteren Tabellen enthält:
This export function returns a table containing the public functions and
additional tables:

\InputLua[firstline=3,lastline=16]{export.lua}

\noindent
% Das Projekt verwendet einige wenige Abkürzungen für Variablennamen,
% die hoffentlich für externe Leser eindeutig und bekannt sind.
The project uses a few abbreviations for variable names that are
hopefully unambiguous and familiar to external readers.

\begin{center}
\begin{tabular}{lll}
Abbreviation & spelled out & Example \\\hline
\lua{kv_string} & Key-value string & \lua{'key=value'} \\
\lua{opts} & Options (for the parse function) &
\lua{ { no_error = false } } \\
\lua{defs} & Definitions \\
\lua{def} & Definition \\
\lua{attr} & Attributes (of a definition) \\
\end{tabular}
\end{center}

\noindent
% Diese nicht abgekürzten Variablennamen werden häufig verwendet.
These unabbreviated variable names are commonly used.
\begin{center}
\begin{tabular}{ll}

\lua{result} &
% Das Endergebnis aller einzelnen Übersetzungs- und
% Normalisierungsschritte
The final result of all individual parsing and normalization steps. \\

\lua{unknown} &
% Ein Tabelle mit unbekannten, nicht definierten Schlüssel-Wert-Paaren
A table with unknown, undefinied key-value pairs. \\

\lua{raw} &
% Das unbearbeitete, rohe Ergebnis der LPeg-Syntaxanalyse.
The raw result of the Lpeg grammar parser. \\
\end{tabular}
\end{center}

\noindent
% Es wird empfohlen, beim Entwickeln im Texteditor luakeys zusammen mit
% dem Lua-Language-Server zu verwenden.
It is recommended to use luakeys together with the
\href{https://github.com/sumneko/lua-language-server}{github.com/sumneko/lua-language-server}
when developing in a text editor.
%
% Luakeys unterstützt nämlich das vom Server angeboten Annotationsformat
luakeys supports the annotation format offered by the server.
% Sie sollten dann Warnungen erhalten, wenn Sie die mittlerweile
% ziemlich große API von luakeys falsch verwenden.
You should then get warnings if you misuse luakeys’ now rather large API.

%%
%
%%

\subsection{Function “\texttt{parse(kv_string, opts): result, unknown,
raw}”}
\label{parse}

% Die Function parse ist die wichtigste Funktion des Pakets.
The function \lua{parse(kv_string, opts)} is the most important function
of the package.
%
%
% Sie konvertiert eine Schlüssel-Wert-Zeichenkette in eine Lua Tabelle.
It converts a key-value string into a Lua table.

\InputLatex{functions/parse/tex-latex.tex}

\noindent
In plain \TeX:

\InputLatex{functions/parse/tex-plain.tex}

\subsection{Options to configure the \texttt{parse} function}

\noindent
% Die Funktion \lua{parse} kann mit einer Optionstabelle aufgerufen
% werden.
The \lua{parse} function can be called with an options table.
% Diese Optionen werden unterstützt:
This options are supported: \catcode`_=12
\directlua{luakeys.print_names('opts')}

\InputLua[firstline=7,lastline=99]{opts/all-opts.lua}

\subsection{Table “\texttt{opts}”}
\label{table-opts}

\noindent
% Die Optionen können auch global über die exportierte Tabelle
% \lua{opts} gesetzt werden:
The options can also be set globally using the exported table
\lua{opts}:

\InputLua[firstline=4,lastline=4]{opts/exported-default-opts.lua}

\InputLua[firstline=10,lastline=11]{opts/exported-default-opts.lua}

\noindent
% Damit es zu keinen Wechselwirkungen mit anderen Paketen kommt, die auch
% |luakeys| verwenden und die Optionen global setzen, ist es anzuraten,
% die Funktion \lua{get_private_instance()} zum Laden das Paket verwenden.
To avoid interactions with other packages that also use |luakeys| and
set the options globally, it is recommended to use the
\lua{get_private_instance()} function
(\ref{function:get-private-instance}) to load the package.

%%
%
%%

\subsubsection{Option “\texttt{accumulated_result}”}

% Streng genommen handelt es sich hier um keine Option
Strictly speaking, this is not an option.
%
% Mit der Option \lua{accumulated_result} kann eine Ergebnistabelle
% angegeben werden, die bei jedem Aufruf der \lua{parse}-Funktion weiter
% befüllt wird.
The \lua{accumulated_result} “option” can be used to specify a result
table that is filled with each call of the \lua{parse} function.

\InputLua[firstline=5,lastline=14]{opts/accumulated-result.lua}

%%
%
%%

\subsubsection{Option “\texttt{assignment_operator}”}
\label{option:assignment-operator}
\label{options-delimiter}

The option \lua{assignment_operator} configures the delimiter that
assigns a value to a key. The default value of this option is
\texttt{"="}.

The code example below demonstrates all six delimiter related options.

\InputLua[firstline=4,lastline=13]{opts/delimiters.lua}

\begin{tabular}{ll}
\textbf{Delimiter options} & \textbf{Section} \\
assignment_operator & \ref{option:assignment-operator}\\
group_begin & \ref{option:group-begin}\\
group_end & \ref{option:group-end}\\
list_separator & \ref{option:list-separator}\\
quotation_begin & \ref{option:quotation-begin}\\
quotation_end & \ref{option:quotation-end}\\
\end{tabular}

%%
%
%%

\subsubsection{Option “\texttt{convert_dimensions}”}

% Wenn Sie die Option \lua{convert_dimensions} auf \lua{true} setzen,
% erkennt |luakeys| die \TeX{}-Dimensionen und konvertiert sie mit Hilfe
% der die Funktion \lua{tex.sp(dim)} in scaled points.
If you set the option \lua{convert_dimensions} to \lua{true}, |luakeys|
detects the \TeX{} dimensions and converts them into scaled points using
the function \lua{tex.sp(dim)}.

\InputLua[firstline=4,lastline=7]{opts/convert-dimensions/true.lua}

\noindent
% Standardmäßig werden die Dimensionen nicht in skalierte Punkte
% umgewandelt.
By default the dimensions are not converted into scaled points.

\InputLua[firstline=4,lastline=9]{opts/convert-dimensions/false.lua}

\noindent
% Wenn Sie eine skalierte Punktzahl in einen Dimensionszeichenketten
% umwandeln möchten, können Sie das Modul
If you want to convert a scaled points number into a dimension string
you can use the module
\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}
{lualibs-util-dim.lua}.

\begin{minted}{lua}
require('lualibs')
tex.print(number.todimen(tex.sp('1cm'), 'cm', '%0.0F%s'))
\end{minted}

\DefaultOptDescription{convert_dimensions}

%%
%
%%

\subsubsection{Option “\texttt{debug}”}

% Wenn die Option \lua{debug} auf true gesetzt ist, wird die
% Ergebnistabelle in der Konsole ausgegeben.
If the option \lua{debug} is set to true, the result table is printed to
the console.

\InputLatex{opts/debug-latex.tex}

\begin{verbatim}
This is LuaHBTeX, Version 1.15.0 (TeX Live 2022)
...
(./debug.aux) (/usr/local/texlive/texmf-dist/tex/latex/base/ts1cmr.fd)
{
  ['three'] = true,
  ['two'] = true,
  ['one'] = true,
}
 [1{/usr/
local/texlive/2022/texmf-var/fonts/map/pdftex/updmap/pdftex.map}] (./debug.aux)
)
...
Transcript written on debug.log.
\end{verbatim}

\DefaultOptDescription{debug}

%%
%
%%

\subsubsection{Option “\texttt{default}”}
\label{option-default}

% Mit der Option \lua{default} kann angegeben werden, welchen Wert
% nackte Schlüssel (Schlüssel ohne Wert) erhalten. Diese Option hat
% keinen Einfluss auf Schlüssel mit Werten.
The option \lua{default} can be used to specify which value naked keys
(keys without a value) get. This option has no influence on keys with
values.

\InputLua[firstline=4,lastline=5]{opts/default.lua}

\noindent
% Standardmäßig erhalten nackte Schlüssel den Wert \lua{true}.
By default, naked keys get the value \lua{true}.

\InputLua[firstline=11,lastline=12]{opts/default.lua}

\DefaultOptDescription{default}

%%
%
%%

\subsubsection{Option “\texttt{defaults}”}
\label{options-defaults}

% Mit der Attribut „defaults“ kann nicht nur ein einiger Standardwert
% angegeben werden, sondern eine ganze Tabelle mit Standardwerten.
The option “defaults” can be used to specify not only one default value,
but a whole table of default values.
% Die Ergebnistabelle wird mit der Tabelle bestehend aus Standardwerten
% vereinigt.
The result table is merged into the defaults table.
% Werte aus der Tabelle mit Standardwerten werden von Werten der
% Ergebnistabelle überschrieben.
Values in the defaults table are
overwritten by values in the result table.

\InputLua[firstline=4,lastline=7]{opts/defaults.lua}

\DefaultOptDescription{defaults}

%%
%
%%

\subsubsection{Option “\texttt{defs}”}

% Für mehr Information wie Schlüssel definiert werden, lesen sie das
% kapitel 3.2
For more informations on how keys are defined, see section \ref{define}.
% Wenn sie die Option \lua{defs} verwenden, können sie auf den
% Aufruf der Funktion \lua{define} verzichten.
If you use the \lua{defs} option, you don't need to call the
\lua{define} function.
%
% Anstatt
Instead of ...

\InputLua[firstline=4,lastline=5]{opts/defs.lua}

\noindent
% können wir schreiben ..
we can write ...

\InputLua[firstline=11,lastline=13]{opts/defs.lua}

\DefaultOptDescription{defs}

%%
%
%%

\subsubsection{Option “\texttt{false_aliases}”}
\label{option:false-aliases}

% Mit den den Optionen \lua{true_aliases} and \lua{false_aliases} können
% die Zeichenketten festgelegt werden, die vom Parser als Wahrheitswerte
% erkannt werden.
The \lua{true_aliases} and \lua{false_aliases} options can be used to
specify the strings that will be recognized as boolean values by the
parser.
% Standardmäßig sind folgende Zeichenketten konfiguriert
The following strings are configured by default.

\InputLua[firstline=4,lastline=8]{opts/boolean-aliases.lua}

\InputLua[firstline=14,lastline=18]{opts/boolean-aliases.lua}

\InputLua[firstline=24,lastline=28]{opts/boolean-aliases.lua}

% Siehe Abschnitt \label{option:true-aliases} für die entsprechende
% Option.
See section \ref{option:true-aliases} for the corresponding option.

%%
%
%%

\subsubsection{Option “\texttt{format_keys}”}

% Mit Hilfe der Option \lua{format_keys} können die Schlüssel formatiert
% werden.
With the help of the option \lua{format_keys} the keys can be formatted.
% Die Werte dieser Option müssen in einer Tabelle angegeben werden.
The values of this option must be specified in a table.

\begin{description}
\item[lower]

% Um alle Schlüssel in \emph{Kleinbuchstaben} umzuwandeln, geben sie in
% der Optionentabelle \lua{lower} an.
To convert all keys to \emph{lowercase}, specify \lua{lower} in the
options table.

\InputLua[firstline=4,lastline=5]{opts/format-keys.lua}

\item[snake]

% Um alle Schlüssel in \emph{snake case} (Die Wörter sind durch
% Unterstriche getrennt) umzuwandeln, geben sie in der Optionentabelle
% \lua{snake} an.
To make all keys \emph{snake case} (The words are separated by
underscores), specify \lua{snake} in the options
table.

\InputLua[firstline=11,lastline=12]{opts/format-keys.lua}

\item[upper]

% Um alle Schlüssel in \emph{Grossbuchstaben} umzuwandeln, geben sie in
% der Optionentabelle \lua{upper} an.
To convert all keys to \emph{uppercase}, specify \lua{upper} in the
options table.

\InputLua[firstline=18,lastline=19]{opts/format-keys.lua}
\end{description}

% Sie können auch mehrere Formatierungsarten kombinieren.
You can also combine several types of formatting.

\InputLua[firstline=25,lastline=26]{opts/format-keys.lua}

\DefaultOptDescription{format_keys}

%%
%
%%

\subsubsection{Option “\texttt{group_begin}”}
\label{option:group-begin}

The option \lua{group_begin} configures the delimiter that marks the
beginning of a group. The default value of this option is \texttt{"\{"}.
A code example can be found in section \ref{options-delimiter}.

%%
%
%%

\subsubsection{Option “\texttt{group_end}”}
\label{option:group-end}

The option \lua{group_end} configures the delimiter that marks the end
of a group. The default value of this option is \texttt{"\}"}. A code
example can be found in section \ref{options-delimiter}.

%%
%
%%

\subsubsection{Option “\texttt{invert_flag}”}

% Wird ein nackter Schlüssel mit einem vorangestellten Ausrufezeichen versehen, so wird sein Standardwert invertiert.
If a naked key is prefixed with an exclamation mark, its default value
is inverted.
% Statt \lua{true} nimmt der Schlüssel jetzt den Wert \lua{falsch} an.
Instead of \lua{true} the key now takes the value \lua{false}.

\InputLua[firstline=4,lastline=5]{opts/invert-flat.lua}

\noindent
% Mit der Option \lua{invert_flag} kann dieses Invertierungszeichen
% geändert werden.
The \lua{invert_flag} option can be used to change this inversion
character.

\InputLua[firstline=11,lastline=12]{opts/invert-flat.lua}

\noindent
% Ist der Standardwert für nackte Schlüssel beispielweise auf \lua{false}
% gesetzt, so nehmen die mit dem Umkehrungszeichen versehenen nackten
% Schlüssel den Wert \lua{true} an.
For example, if the default value for naked keys is set to \lua{false},
the naked keys prefixed with the invert flat take the value \lua{true}.

\InputLua[firstline=18,lastline=19]{opts/invert-flat.lua}

\noindent
% Setzen sie die Option \lua{invert_flag} auf \lua{false}, um diese
% automatische Wertumkehrung zu deaktivieren.
Set the \lua{invert_flag} option to \lua{false} to disable this
automatic boolean value inversion.

\InputLua[firstline=25,lastline=26]{opts/invert-flat.lua}

%%
%
%%

\subsubsection{Option “\texttt{hooks}”}

% Die folgenden Hooks bzw. Callback-Funktionen ermöglichen es in den
% Verarbeitungsprozess der \lua{parse}-Function einzugreifen.
The following hooks or callback functions allow to intervene in the
processing of the \lua{parse} function.
%
% Die Funktionen sind in der Verarbeitungsreihenfolge aufgelistet.
The functions are listed in processing order.
%
% \lua{*_before_opts} bedeutet, dass die Hooks nach der LPeg
% Syntaxanalyse und vor dem Anwenden der Optionen ausgeführt
\lua{*_before_opts} means that the hooks are executed after the LPeg
syntax analysis and before the options are applied.
%
% Die Hooks \lua{*_before_defs} werden vor dem Anwenden der
% Schlüssel-Wert-Definitionen ausgeführt
The \lua{*_before_defs} hooks are executed before applying the key value
definitions.

\def\TmpSignature#1{
  {
    \scriptsize\texttt{ = #1}
  }
}

\def\TmpKeySignature{
  \TmpSignature{function(key, value, depth, current, result): key, value}
}
\def\TmpResultSignature{
  \TmpSignature{function(result): void}
}

\begin{enumerate}
\item \lua{kv_string} \TmpSignature{function(kv_string): kv_string}
\item \lua{keys_before_opts} \TmpKeySignature
\item \lua{result_before_opts} \TmpResultSignature
\item \lua{keys_before_def} \TmpKeySignature
\item \lua{result_before_def} \TmpResultSignature
\item (\lua{process}) (has to be definied using defs, see \ref{attr-process})
\item \lua{keys} \TmpKeySignature
\item \lua{result} \TmpResultSignature
\end{enumerate}

\paragraph{\texttt{kv_string}}

% Der Hook \lua{kv_string} wird als erste
% der Hook-Funktionen noch vor der LPeg-Syntax-Analyse aufgerufen.
The \lua{kv_string} hook is called as the first of the hook functions
before the LPeg syntax parser is executed.

\InputLua[firstline=4,lastline=11]{hooks/kv-string.lua}

\paragraph{\texttt{keys_*}}

% Die Hooks \lua{keys_*} werden rekursiv auf jeden Schlüssel in der
% aktuellen Ergebnistabelle aufgerufen.
The hooks \lua{keys_*} are called recursively on each key in the current
result table.
% Die Hook-Funktion muss zwei Werte zurückgeben: \lua{key, value}
The hook function must return two values: \lua{key, value}.
%
% Das folgende Beispiel gibt \lua{key} und \lua{value} unverändert
% zurück, sodass die Ergebnistabelle nicht verändert wird.
The following example returns \lua{key} and \lua{value} unchanged, so
the result table is not changed.

\InputLua[firstline=4,lastline=11]{hooks/keys-unchanged.lua}

\noindent
% Das nächste Beispiel demonstriert den dritten Parameter \lua{depth}
% der Hook-Funktion.
The next example demonstrates the third parameter \lua{depth} of the
hook function.

\InputLua[firstline=4,lastline=16]{hooks/keys-depth.lua}

\paragraph{\texttt{result_*}}

% Die Hooks \lua{result_*} werden einmal mit der aktuellen
% Ergebnistabelle als Parameter aufgerufen.
The hooks \lua{result_*} are called once with the current result table
as a parameter.

%%
%
%%

\subsubsection{Option “\texttt{list_separator}”}
\label{option:list-separator}

The option \lua{list_separator} configures the delimiter that separates
list items from each other. The default value of this option is
\texttt{","}. A code example can be found in section
\ref{options-delimiter}.

%%
%
%%

\subsubsection{Option “\texttt{naked_as_value}”}

% Mit Hilfe der Option \lua{naked_as_value} werden nackte Schlüssel
% nicht mit einem Standardwert versehen, sondern als Werte in die
% Lua-Tabelle abgelegt.
With the help of the option \lua{naked_as_value}, naked keys are not
given a default value, but are stored as values in a Lua table.

\InputLua[firstline=4,lastline=5]{opts/naked-as-value.lua}

\noindent
If we set the option \lua{naked_as_value} to \lua{true}:

\InputLua[firstline=11,lastline=14]{opts/naked-as-value.lua}

\DefaultOptDescription{naked_as_value}

%%
%
%%

\subsubsection{Option “\texttt{no_error}”}

% Standardmaßig wirft parse-Funktion einen Fehler, wenn es unbekannte
% Schlüssel gibt.
By default the parse function throws an error if there are unknown keys.
% Mit Hilfe der Option \lua{no_error} kann dies unterbunden werden.
This can be prevented with the help of the \lua{no_error} option.

\InputLua[firstline=5,lastline=6]{opts/no-error.lua}

\noindent
If we set the option \lua{no_error} to \lua{true}:

\InputLua[firstline=9,lastline=10]{opts/no-error.lua}

\DefaultOptDescription{no_error}

%%
%
%%

\subsubsection{Option “\texttt{quotation_begin}”}
\label{option:quotation-begin}

The option \lua{quotation_begin} configures the delimiter that marks the
beginning of a string. The default value of this option is
\texttt{'"'} (double quotes). A code example can be found in section
\ref{options-delimiter}.

%%
%
%%

\subsubsection{Option “\texttt{quotation_end}”}
\label{option:quotation-end}

The option \lua{quotation_end} configures the delimiter that marks the
end of a string. The default value of this option is \texttt{'"'}
(double quotes). A code example can be found in section
\ref{options-delimiter}.

%%
%
%%

\subsubsection{Option “\texttt{true_aliases}”}
\label{option:true-aliases}

See section \ref{option:false-aliases}.

%%
%
%%

\subsubsection{Option “\texttt{unpack}”}

% Mit Hilfe der Option \lua{unpack} werden alle Tabellen, die nur aus
% einem einzigen nackten Schlüssel bzw. einen einzigen alleinstehenden
% Wert bestehen, aufgelöst.
With the help of the option \lua{unpack}, all tables that consist of
only a single naked key or a single standalone value are unpacked.

\InputLua[firstline=4,lastline=5]{opts/unpack.lua}

\InputLua[firstline=11,lastline=12]{opts/unpack.lua}

\DefaultOptDescription{unpack}

%%
%
%%

\subsection{Function “\texttt{define(defs, opts): parse}”}
\label{define}

The \lua{define} function returns a \lua{parse} function (see
\ref{parse}).
The name of a key can be specified in three ways:

\begin{enumerate}
\item as a string.
\item as a key in a Lua table. The definition of the corresponding
key-value pair is then stored under this key.
\item by the “name” attribute.
\end{enumerate}

\InputLua[firstline=4,lastline=16]{functions/define.lua}

\noindent
% Bei verschachtelten Definitionen können nur die letzten beiden
% Möglichkeiten zur Angabe der Schlüsselnamen verwendet werden.
For nested definitions, only the last two ways of specifying the key
names can be used.

\InputLua[firstline=26,lastline=33]{functions/define.lua}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\subsection{Attributes to define a key-value pair}

% Die Definition eines Schlüssel-Wert-Paares kann mit Hilfe von
% verschiedenen Attributen vorgenommen werden.
The definition of a key-value pair can be made with the help of various
attributes.
%
% Der Name „Attribut“ für eine Option, einen Schlüssel, eine Eigenschaft
% (um nur einige Benennungsmöglichkeiten aufzuzählen) zur
% Schlüssel-Definition, wurde bewusst gewählt, um sie von den Optionen
% der Funktion \lua{parse} zu unterscheiden.
The name \emph{“attribute”} for an option, a key, a property ... (to
list just a few naming possibilities) to define keys, was deliberately
chosen to distinguish them from the options of the \lua{parse} function.
%
% Diese Attribute sind erlaubt.
These attributes are allowed:
\directlua{luakeys.print_names('attrs')}.
%
% Das folgende Codebeispiel listet alle Attribute auf, die verwendet
% werden können, um Schlüssel-Wert-Paare zu definieren.
The code example below lists all the attributes that can be used to
define key-value pairs.

\InputLua[firstline=5,lastline=62]{defs/all-attrs.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{alias}”}

With the help of the \lua{alias} attribute, other key names can be used.
The value is always stored under the original key name. A single alias
name can be specified by a string ...

\InputLua[firstline=4,lastline=7]{defs/attrs/alias.lua}

\noindent
multiple aliases by a list of strings.

\InputLua[firstline=13,lastline=16]{defs/attrs/alias.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{always_present}”}

% Die Option \lua{default} wird nur bei nackten Schlüsseln verwendet.
The \lua{default} attribute is used only for naked keys.

\InputLua[firstline=4,lastline=5]{defs/attrs/always-present.lua}

\noindent
% Wird die Option \lua{always_present} auf wahr gesetzt, wird der
% Schlüssel immer ins Ergebnis mit übernommen.
If the attribute \lua{always_present} is set to true, the key is always
included in the result. If no default value is definied, true is taken
as the value.

\InputLua[firstline=11,lastline=12]{defs/attrs/always-present.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{choices}”}

% source: Python argparse documentation.
Some key values should be selected from a restricted set of choices.
These can be handled by passing an array table containing choices.

\InputLua[firstline=4,lastline=5]{defs/attrs/choices.lua}

\noindent
When the key-value pair is parsed, values will be checked, and an error
message will be displayed if the value was not one of the acceptable
choices:

\InputLua[firstline=13,lastline=15]{defs/attrs/choices.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{data_type}”}

% source: Python argparse documentation.
The \lua{data_type} attribute allows type-checking and type conversions
to be performed.
%
% Folgende Datentypen werden unterstützt:
The following data types are supported:
\lua{'boolean'},
\lua{'dimension'},
\lua{'integer'},
\lua{'number'},
\lua{'string'},
\lua{'list'}.
%
% Bei den drei Datentypen integer, number, dimension kann eine
% Typenumwandlung scheitern.
A type conversion can fail with the three data types
\lua{'dimension'},
\lua{'integer'},
\lua{'number'}.
%
% Dann wird eine Fehlermeldung ausgegeben.
Then an error message is displayed.

\InputLua[firstline=4,lastline=8]{defs/attrs/data-type.lua}
\InputLua[firstline=11,lastline=15]{defs/attrs/data-type.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{default}”}

% Verwenden Sie das Attribut „\lua{default}“, um für jeden nackten Schlüssel
% einzeln einen Standardwert bereit zu stellen.
Use the \lua{default} attribute to provide a default value for each naked
key individually.
%
% Mit der globalen \lua{default} Option kann für alle nackten Schlüssel ein
% Standardwert vorgegeben werden.
With the global \lua{default} attribute (\ref{option-default}) a default
value can be specified for all naked keys.

\InputLua[firstline=4,lastline=9]{defs/attrs/default.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{description}”}

% Dieses Attribut wird momentan nicht weiterverarbeitet.
This attribute is currently not processed further.
% Es kann als Kommentar dienen.
It can serve as a comment.

%%
%
%%

\subsubsection{Attribute “\texttt{exclusive_group}”}

% Alle Schlüssel, die der gleichen ausschließenden Gruppe angehören,
% dürfen nicht gemeinsam angegeben werden.
All keys belonging to the same exclusive group must not be specified
together.
%
% Nur ein Schlüssel aus dieser Gruppe ist erlaubt.
Only one key from this group is allowed.
%
% Als Name für diese ausschließende Gruppe kann irgend ein beliebiger
% Wert verwendet werden.
Any value can be used as a name for this exclusive group.

\InputLua[firstline=4,lastline=9]{defs/attrs/exclusive-group.lua}

\noindent
% Werden mehrer Schlüssel der Gruppe angegeben, so wird eine
% Fehlermeldung geworfen.
If more than one key of the group is specified, an error message is
thrown.

\InputLua[firstline=21,lastline=23]{defs/attrs/exclusive-group.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{macro}”}

The attribute \texttt{macro} stores the value in a \TeX{} macro.

\begin{minted}{lua}
local parse = luakeys.define({
  key = {
    macro = 'MyMacro'
  }
})
parse('key=value')
\end{minted}

\begin{minted}{latex}
\MyMacro % expands to “value”
\end{minted}

%%
%
%%

\subsubsection{Attribute “\texttt{match}”}

% Der Wert des Schlüssel wird zuerst der Lua Funktion
% \lua{string.match(value, match)} übergeben, bevor er dem Schlüssel
% zugewiesen wird.
The value of the key is first passed to the Lua function
\lua{string.match(value, match)}
(\url{http://www.lua.org/manual/5.3/manual.html#pdf-string.match})
before being assigned to the key.
%
% Du kannst das Attribut \lua{match} deshalb mit einer Pattern-Matching-
% Zeichenkette konfigurieren, wie sie in Lua zu Einsatz kommt.
You can therefore configure the \lua{match} attribute with a pattern
matching string used in Lua.
%
% Werfe einen Blick in das Lua-Handbuch, wie man Patterns schreibt.
Take a look at the Lua manual on how to write patterns
(\url{http://www.lua.org/manual/5.3/manual.html#6.4.1}).

\InputLua[firstline=4,lastline=7]{defs/attrs/match/birthday.lua}

\noindent
% Kann das Pattern im Wert nicht gefunden werden, wird eine
% Fehlermeldung ausgegeben.
If the pattern cannot be found in the value, an error message is issued.

\InputLua[firstline=15,lastline=18]{defs/attrs/match/birthday.lua}

\noindent
% Der Schlüssel erhält das Ergebnis der Funktion \lua{string.match(value,
% match)}, dass bedeutet, dass der ursprüngliche Wert unter
% Umständen nicht vollständig in den Schlüssel gespeichert wird.
The key receives the result of the function \lua{string.match(value,
match)}, which means that the original value may not be stored
completely in the key.
%
% Im nächsten Beispiel wird der gesamte Eingabewert akzeptiert:
In the next example, the entire input value is accepted:

\InputLua[firstline=4,lastline=5]{defs/attrs/match/year.lua}

\noindent
% Das Präfix “waste ” und das Suffix “ rubbisch” der Zeichenketten wird
% verworfen.
The prefix “waste ” and the suffix “ rubbisch” of the string are
discarded.

\InputLua[firstline=11,lastline=11]{defs/attrs/match/year.lua}

\noindent
% Da Funktion \lua{string.match(value, match)} immer eine Zeichenkette
% zurückgibt, ist der Wert des Schlüssel auch immer eine Zeichenkette.
Since function \lua{string.match(value, match)} always returns a string,
the value of the key is also always a string.

%%
%
%%

\subsubsection{Attribute “\texttt{name}”}

% Die Option \lua{name} ermöglicht eine alternative Notation von
% Schlüsselnamen.
The \lua{name} attribute allows an alternative notation of key names.
%
% Anstatt ...
Instead of ...

\InputLua[firstline=4,lastline=8]{defs/attrs/name/as-key.lua}

\noindent
% ... können wir schreiben:
... we can write:

\InputLua[firstline=4,lastline=8]{defs/attrs/name/name-attr.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{opposite_keys}”}

% Die Option \lua{opposite_keys} ermöglicht es, gegensätzliche (nackte)
% Schlüssel in Wahrheitswerte umzuwandeln und diesen Wahrheitswert unter
% einem Zielschlüssel zu speichern.
The \lua{opposite_keys} attribute allows to convert opposite (naked)
keys into a boolean value and store this boolean under a target key.
%
% Lua erlaubt es in Tabellen Wahrheitswerte als Schlüssel zu verwenden.
% Es müssen jedoch eckige Klammern verwendet werden.
Lua allows boolean values to be used as keys in tables.
%
% Die Wahrheitswerte müssen jedoch in eckige Klammern geschrieben werden.
However, the boolean values must be written in square brackets, e. g.
\lua{{ opposite_keys = { [true] = 'show', [false] = 'hide' } }}.
%
% Beispiele für gegensätzliche Schlüssel sind:
Examples of opposing keys are: \lua{show} and \lua{hide}, \lua{dark} and
\lua{light}, \lua{question} and \lua{solution}.
%
% Das untenstehende Beispiel verwendet als gegensätzliches Schlüsselpaar
% die Schlüssel \lua{show} und \lua{hide}.
The example below uses the \lua{show} and \lua{hide} keys as the
opposite key pair.
%
% Wird der Schlüssel \lua{show} von der Funktion \lua{parse} gelesen,
% dann erhält der Zielschlüssel \lua{visibility} den Wert \lua{true}.
If the key \lua{show} is parsed by the \lua{parse} function, then the
target key \lua{visibility} receives the value \lua{true}.

\InputLua[firstline=4,lastline=7]{defs/attrs/opposite-keys.lua}

% Wird der Schlüssel \lua{hide} gelesen, dann \lua{falsch}.
\noindent
If the key \lua{hide} is parsed, then \lua{false}.

\InputLua[firstline=13,lastline=13]{defs/attrs/opposite-keys.lua}

\noindent
% Gegensätzliche Schlüsselpaare können in einer Kurzschreibweise
% angegeben werden, nämlich als Liste
Opposing key pairs can be specified in a short form, namely as a list:
% Der gegensätzliche Schlüssel, der den Wahrwert repräsentiert, muss in
% dieser Liste zuerst angegeben werden, dann folgt der Falschwert.
The opposite key, which represents the true value, must be specified
first in this list, followed by the false value.

\InputLua[firstline=19,lastline=21]{defs/attrs/opposite-keys.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{pick}”}

% Das Attribut \lua{pick} sucht nach einem Wert, der keinem Schlüssel
% zugeordnet ist.
The attribute \lua{pick} searches for a value not assigned to a key.
% Der zuerst gefundene Wert, d. h. der weiter links stehende Wert, wird
% einem Schlüssel zugewiesen.
The first value found, i.e. the one further to the left, is assigned to
a key.

\InputLua[firstline=4,lastline=6]{defs/attrs/pick/dimension.lua}

\noindent
% Es wird nur in der aktuellen Ergebnistabelle gesucht und nicht auf
% anderen Ebenen in der rekursiven Datenstruktur.
Only the current result table is searched, not other levels in the
recursive data structure.

\InputLua[firstline=4,lastline=11]{defs/attrs/pick/different-levels.lua}

\noindent
% Die Suche nach Werte wird aktiviert, wenn das Attribut \lua{pick} auf
% \lua{true} gesetzt wird.
The search for values is activated when the attribute \lua{pick} is set
to a data type.
% Mit diesen Datentypen kann nach Werten gesucht werden
These data types can be used to search for values:
string, number, dimension, integer, boolean, any.
% Verwendet den Datentyp any um jeden beliebigen Wert zu akzeptieren.
Use the data type “any” to accept any value.
% Wird einem Schlüssel bereits bei der Eingabe ein Wert zugewiesen, dann
% wird nicht weiter nach Werten gesucht.
If a value is already assigned to a key when it is entered, then no
further search for values is performed.
\InputLua[firstline=4,lastline=8]{defs/attrs/pick/value-set.lua}

\noindent
% Das Attribut \lua{pick} akzeptiert auch mehrere Datentypen, die in
% einer Tabelle angegeben werden.
The \lua{pick} attribute also accepts multiple data types
specified in a table.

\InputLua[firstline=4,lastline=10]{defs/attrs/pick/multiple-data-types.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{process}”}
\label{attr-process}

% Das Attribut \lua{process} kann dazu verwendet werden, um eine Funktion
% zu definieren, deren Rückgabewert an den Schlüssel übergeben wird.
The \lua{process} attribute can be used to define a function whose
return value is passed to the key.
%
% Beim Aufruf der Funktion werden vier Parameter übergeben:
Four parameters are passed when the function is called:

\begin{enumerate}
\item \lua{value}:
% Der zum Schlüssel gehörende aktuelle Wert.
The current value asssociated with the key.

\item \lua{input}:
% Die Ergebnis-Tabelle, die vor dem Zeitpunkt geklont wurde, als mit dem
% Anwenden der Definitionen begonnen wurde.
The result table cloned before the time the definitions started to be
applied.

\item \lua{result}: The table in which the final result will be saved.

\item \lua{unknown}: The table in which the unknown key-value pairs
are stored.
\end{enumerate}

\noindent
% Das folgende Beispiel demonstriert den Parameter \lua{value}:
The following example demonstrates the \lua{value} parameter:
\InputLua[firstline=4,lastline=14]{defs/attrs/process/parameter-value.lua}

\noindent
% Das folgende Beispiel demonstriert den Parameter \lua{input}:
The following example demonstrates the \lua{input} parameter:

\InputLua[firstline=4,lastline=16]{defs/attrs/process/parameter-input.lua}

\noindent
% Das folgende Beispiel demonstriert den Parameter \lua{result}:
The following example demonstrates the \lua{result} parameter:

\InputLua[firstline=4,lastline=12]{defs/attrs/process/parameter-result.lua}

\noindent
% Das folgende Beispiel demonstriert den Parameter \lua{unknown}:
The following example demonstrates the \lua{unknown} parameter:

\InputLua[firstline=4,lastline=11]{defs/attrs/process/parameter-unknown.lua}
\InputLua[firstline=15,lastline=15]{defs/attrs/process/parameter-unknown.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{required}”}

% Durch das Attribut \lua{required} kann erzwungen werden, dass ein
% bestimmter Schlüssel angegeben werden muss.
The \lua{required} attribute can be used to enforce that a specific key
must be specified.
%
% Im untenstehenden Beispiel wird der Schlüssel \lua{important} als
% zwingend notwendig definiert.
In the example below, the key \lua{important} is defined as mandatory.

\InputLua[firstline=4,lastline=5]{defs/attrs/required.lua}

\noindent
% Fehlt der Schlüssel \lua{important} in der Eingabe, so tritt eine
% Fehlermeldung auf.
If the key \lua{important} is missing in the input, an error message
occurs.

\InputLua[firstline=13,lastline=14]{defs/attrs/required.lua}

\noindent
A recursive example:

\InputLua[firstline=18,lastline=23]{defs/attrs/required.lua}

\noindent
% Der Schlüssel \lua{important2} auf der Ebene 2 fehlt.
The \lua{important2} key on level 2 is missing.

\InputLua[firstline=29,lastline=30]{defs/attrs/required.lua}

\noindent
% Der Schlüssel \lua{important1} auf der untersten Schlüssel-Ebene fehlt.
The \lua{important1} key at the lowest key level is missing.

\InputLua[firstline=38,lastline=39]{defs/attrs/required.lua}

%%
%
%%

\subsubsection{Attribute “\texttt{sub_keys}”}

% Mit dem Attribut \lua{sub_keys} können ineinander verschachtelte
% Schlüssel-Wert-Paar-Definitionen aufgebaut werden.
The \lua{sub_keys} attribute can be used to build nested key-value pair
definitions.

\InputLua[firstline=4,lastline=16]{defs/attrs/sub-keys.lua}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\subsection{Function “\texttt{render(result): string}”}

The function \lua{render(result)} 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.

\InputLua[firstline=4,lastline=10]{functions/render.lua}

\noindent
In Lua only tables with 1-based consecutive integer keys (a.k.a. array
tables) can be parsed in order.

\InputLua[firstline=16,lastline=17]{functions/render.lua}

%%
%
%%

\subsection{Function “\texttt{debug(result): void}”}

The function \lua{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 \lua{parse}. You have to
compile your \TeX{} document in a console to see the terminal output.

\InputLua[firstline=4,lastline=5]{functions/debug.lua}

\noindent
The output should look like this:

\begin{minted}{md}
{
  ['level1'] = {
      ['level2'] = {
        ['key'] = 'value',
    },
  }
}
\end{minted}

%%
%
%%

\subsection{Function “\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{Function “\texttt{get(identifier): result}”}

The function \lua{get(identifier)} retrieves a saved result from the
result store.

%%
%
%%

\subsection{Class “\texttt{DefinitionManager()}”}

% Die Klasse DefinitionManager ermöglicht es Schlüssel-Wert-Definitionen
% in einem Objekt abzulegen.
The DefinitionManager class makes it possible to store key-value
definitions in a central location.
% Über die Methoden \lua{include} und \lue{exclude} können auf Basis der
% gespeicherten Definitionen neue Teilmengen an Definitionen gebildet
% werden.
New subsets of definitions can be formed based on the saved definitions
using the \lua{include} and \lua{exclude} methods.

\InputLua[firstline=4]{definition-manager.lua}

%%
%
%%

\subsection{Table “\texttt{is}”}

% In der Tabelle \lua{is} werden einige Funktionen zusammengefasst, die
% überprüft ob eine Eingabe einem bestimmen Datentyp entspricht.
In the table \lua{is} some functions are summarized, which check whether
an input corresponds to a certain data type.
%
% Einige Funktionen akzeptieren nicht nur die entsprechenden
% Lua-Datentypen, sondern auch Eingaben als Zeichenketten.
Some functions accept not only the corresponding Lua data types, but also
input as strings.
%
% Beispielsweise wird die Zeichenkette \lua{'true'} von der
% \lua{is.boolean()}-Funktion als Wahrheitswert erkannt.
For example, the string \lua{'true'} is recognized by the
\lua{is.boolean()} function as a boolean value.

\subsubsection{Function “\texttt{is.boolean(value): boolean}”}
\InputLua[firstline=6,lastline=23]{functions/is/boolean.lua}

\subsubsection{Function “\texttt{is.dimension(value): boolean}”}
\InputLua[firstline=6,lastline=16]{functions/is/dimension.lua}

\subsubsection{Function “\texttt{is.integer(value): boolean}”}
\InputLua[firstline=6,lastline=11]{functions/is/integer.lua}

\subsubsection{Function “\texttt{is.number(value): boolean}”}
\InputLua[firstline=6,lastline=13]{functions/is/number.lua}

\subsubsection{Function “\texttt{is.string(value): boolean}”}
\InputLua[firstline=6,lastline=12]{functions/is/string.lua}

\subsubsection{Function “\texttt{is.list(value): boolean}”}
\InputLua[firstline=6,lastline=16]{functions/is/list.lua}

\subsubsection{Function “\texttt{is.any(value): boolean}”}

% Die Funktion \lua{is.any(value)}  gibt immer wahr zurück und
% akzeptiert deshalb jeden Datentyp.
The function \lua{is.any(value)} always returns \lua{true} and
therefore accepts any data type.

%%
%
%%

\subsection{Table “\texttt{utils}”}

% In der Tabelle \lua{utils} sind einige Hilfsfunktionen gebündelt.
The \lua{utils} table bundles some auxiliary functions.

\InputLua[firstline=3,lastline=35]{utils/all.lua}

%%
%
%%

\subsubsection{Function “\texttt{utils.merge_tables(target, source, overwrite): table}”}

% Die Funktion \lua{merge_tables} führt zwei Tabellen in die erste
% angegebene Tabelle zusammen. Sie kopiert Schlüssel aus der
% `source` Tabelle in die `target`-Tabelle. Sie gibt die geänderte
% Zieltabelle zurück.
The function \lua{merge_tables} merges two tables into the first
specified table. It copies keys from the `source` table into the
`target` table. It returns the target table.

% Wird der Parameter \lua{overwrite} auf wahr gesetzten, so werden Werte
% in der Zieltabelle überschrieben
If the \lua{overwrite} parameter is set to \lua{true}, values in the
target table are overwritten.

\InputLua[firstline=4,lastline=8]{utils/merge-tables.lua}

\noindent
% Geben sie dem Parameter \lua{overwrite} den Wert \lua{false}, um Werte
% in der Zieltabelle zu überschreiben.
Give the parameter \lua{overwrite} the value \lua{false} to overwrite
values in the target table.

\InputLua[firstline=14,lastline=18]{utils/merge-tables.lua}

%%
%
%%

\subsection{Table “version”}

% Das luakeys Projekt verwendet semantic versioning
The luakeys project uses semantic versioning.
% Die drei Versionenzahlen des Semantic Versioning Schemas werden in
% einer Tabelle in der Reihenfolge MAJOR, MINOR, PATCH als Ganzzahlen
% abgelegt.
The three version numbers of the semantic versioning scheme are stored
in a table as integers in the order MAJOR, MINOR, PATCH.
% Mit Hilfe dieser Tabelle kann überprüft werden, ob die richtige
% Version installiert ist.
This table can be used to check whether the correct version is
installed.

\InputLua[firstline=4,lastline=10]{version.lua}

%%
%
%%

\subsection{Table “error_messages”}

\InputLua[firstline=4,lastline=17]{error-messages.lua}

\begin{description}
\directlua{luakeys.print_error_messages()}
\end{description}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\section{Syntax of the recognized key-value format}

%%
%
%%

\subsection{An 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 keys without values (naked keys) are lined up
with commas (\texttt{key=value,naked}) 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,naked\}\}}).

%%
%
%%

\subsection{An (incomplete) attempt to put the syntax into the Extended Backus-Naur Form}

\begin{grammar}
<list> ::= \{ <list-item> \}

<list-container> ::= `{' <list> `}'

<list-item> ::= ( <list-container> | <key-value-pair> | <value> ) [ `,' ]

<key-value-pair> ::= <value> `=' ( <list-container> | <value> )

<value> ::= <boolean>
  \alt <dimension>
  \alt <number>
  \alt <string-quoted>
  \alt <string-unquoted>

<dimension> ::= <number> <unit>

<number> ::= <sign> ( <integer> [ <fractional> ] | <fractional> )

<fractional> ::= `.' <integer>

<sign> ::= `-' | `+'

<integer> ::= <digit> \{ <digit> \}

<digit> ::= `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 `mu' | `MU'
  \alt `nc' | `NC'
  \alt `nd' | `ND'
  \alt `pc' | `PC'
  \alt `pt' | `PT'
  \alt `px' | `PX'
  \alt `sp' | `SP'

<boolean> ::= <boolean-true> | <boolean-false>

<boolean-true> ::= `true' | `TRUE' | `True'

<boolean-false> ::= `false' | `FALSE' | `False'
\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}
\InputLatex[firstline=5,lastline=12]{luakeysdebug/boolean-latex.tex}

\columnbreak

\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}

%%
%
%%

\subsubsection{number}

\begin{multicols}{2}
\InputLatex[firstline=5,lastline=13]{luakeysdebug/number-latex.tex}

\columnbreak

\begin{minted}{lua}
{
  ['num0'] = 42,
  ['num1'] = 42,
  ['num2'] = -42,
  ['num3'] = 4.2,
  ['num4'] = 0.42,
  ['num5'] = 0.42,
  ['num6'] = '0 . 42', -- string
}
\end{minted}
\end{multicols}

%%
%
%%

\subsubsection{dimension}

% Luakeys versucht alle Einheiten zu erkennen, die in der TeX-Welt
% verwendet werden.
|luakeys| tries to recognize all units used in the \TeX{} world.
%
% Nach dem Lua\TeX-Quellcode .
According to the Lua\TeX{} source code
(\href{https://github.com/TeX-Live/luatex/blob/51db1985f5500dafd2393aa2e403fefa57d3cb76/source/texk/web2c/luatexdir/lua/ltexlib.c#L434-L625}
{source/texk/web2c/luatexdir/lua/ltexlib.c})
%
% und nach dem Dimensionen-Modul der lulibs-Bibliothek
and the dimension module of the lualibs library
(\href{https://raw.githubusercontent.com/latex3/lualibs/master/lualibs-util-dim.lua}
{lualibs-util-dim.lua}),
%
% müssten alle Einheiten erkannt werden
all units should be recognized.
\begin{multicols}{3}
\tiny
\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 \\
mu & math unit \\
nc & new cicero \\
nd & new didot \\
pc & pica \\
pt & point \\
px & x height current font \\
sp & scaledpoint \\
\end{tabular}
\end{center}

\columnbreak

\InputLatex[firstline=5,lastline=21]{luakeysdebug/dimension/all-latex.tex}

\columnbreak

\begin{minted}{lua}
{
  ['bp'] = 65781,
  ['cc'] = 841489,
  ['cm'] = 1864679,
  ['dd'] = 70124,
  ['em'] = 655360,
  ['ex'] = 282460,
  ['in'] = 4736286,
  ['mm'] = 186467,
  ['mu'] = 65536,
  ['nc'] = 839105,
  ['nd'] = 69925,
  ['pc'] = 786432,
  ['pt'] = 65536,
  ['px'] = 65781,
  ['sp'] = 1,
}
\end{minted}
\end{multicols}

\noindent
% Im nächsten Beispiel werden die unterschiedlichen Notationsformen der
% Dimensionen illustriert.
The next example illustrates the different notations of the dimensions.

\begin{multicols}{2}
\InputLatex[firstline=5,lastline=12]{luakeysdebug/dimension/notations-latex.tex}

\columnbreak

\begin{minted}{lua}
{
  ['upper'] = 1864679,
  ['lower'] = 1864679,
  ['space'] = 1864679,
  ['plus'] = 1864679,
  ['minus'] = -1864679,
  ['nodim'] = '1 c m', -- string
}
\end{minted}
\end{multicols}

%%
%
%%

\subsubsection{string}

% Es gibt zwei Möglichkeiten Zeichenketten anzugeben:
There are two ways to specify strings:
%
% Mit oder ohne doppelte Anführungszeichen.
With or without double quotes.
%
% Wenn der Text Kommas, geschweifte Klammern oder Gleichheitszeichen
% enthalten soll, müssen doppelte Anführungszeichen verwendet werden.
If the text have to contain commas, curly braces or equal signs, then
double quotes must be used.

\InputLua[firstline=4,lastline=17]{data-types/string.lua}

\subsubsection{Naked keys}

% Nackte Schlüssel sind Schlüssel ohne Wert.
Naked keys are keys without a value.
%
% Mit der Option \lua{naked_as_value} können sie als Werte in ein Feld
% übernommen werden.
Using the option \lua{naked_as_value} they can be converted into values
and stored into an array.
%
% In Lua ist ein Feld eine Tabelle mit numerischen Indizes (der erste
% Index ist 1).
In Lua an array is a table with numeric indexes (The first index is 1).

\InputLatex[firstline=5,lastline=12]{luakeysdebug/naked-keys-latex.tex}

\noindent
% Alle erkannten Datentypen können als eigenständige Werte verwendet
% werden.
All recognized data types can be used as standalone values.

\InputLatex[firstline=14,lastline=19]{luakeysdebug/naked-keys-latex.tex}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\clearpage

\section{Examples}

%%
%
%%

\subsection{Extend and modify keys of existing macros}

Extend the includegraphics macro with a new key named \latex{caption}
and change the accepted values of the \latex{width} key. A number
between 0 and 1 is allowed and converted into
\latex{width=0.5\linewidth}

\InputLua{extend-includegraphics/extend-keys.lua}
\InputLatex{extend-includegraphics/extend-keys-latex.tex}

%%
%
%%

\subsection{Process document class options}

% Auf die Optionen einer \LaTeX{} Dokumentenklasse kann über das Macro
% \latex{\LuakeysGetClassOptions} zu gegriffen werden.
The options of a \LaTeX{} document class can be accessed via the
\latex{\LuakeysGetClassOptions} macro.
%
% \latex{\LuakeysGetClassOptions} ist ein anderer Name für
\latex{\LuakeysGetClassOptions} is an alias for

\begin{center}
\latex{\luaescapestring{\@raw@classoptionslist}}.
\end{center}

\InputLatex{class-options/test-class.cls}
\InputLatex{class-options/use-test-class-latex.tex}

%%
%
%%

\subsection{Process package options}

\noindent
% Auf die Optionen eines \LaTeX{}-Pakets kann über das Macro
% \latex{\LuakeysGetPackageOptions} zu gegriffen werden.
The options of a \LaTeX{} package can be accessed via the
\latex{\LuakeysGetPackageOptions} macro.
% \latex{\LuakeysGetPackageOptions} ist ein anderer Name für
\latex{\LuakeysGetPackageOptions} is an alias for

\begin{center}
\latex{\luaescapestring{\@ptionlist{\@currname.\@currext}}}.
\end{center}

\InputLatex{package-options/test-package.sty}
\InputLatex{package-options/use-test-package-latex.tex}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\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=false,
  convert dimensions=false
]{one,two,three}
\end{document}
\end{minted}

\section{Activity diagramm of the parsing process}

\begin{center}
\includegraphics[width=0.8\linewidth]{Activity-Diagramm.eps}
\end{center}

%-----------------------------------------------------------------------
%
%-----------------------------------------------------------------------

\clearpage

\section{Implementation}

%%
%
%%

\subsection{luakeys.lua}

\inputminted[linenos=true]{lua}{luakeys.lua}

%%
%
%%

\clearpage

\subsection{luakeys.tex}

\inputminted[linenos=true]{latex}{luakeys.tex}

%%
%
%%

\clearpage

\subsection{luakeys.sty}

\inputminted[linenos=true]{latex}{luakeys.sty}

%%
%
%%

\clearpage

\subsection{luakeys-debug.tex}

\inputminted[linenos=true]{latex}{luakeys-debug.tex}

%%
%
%%

\clearpage

\subsection{luakeys-debug.sty}

\inputminted[linenos=true]{latex}{luakeys-debug.sty}

\pagebreak
\PrintIndex
\end{document}