\documentclass{ltxdoc}

\EnableCrossrefs
\CodelineIndex
\RecordChanges

\usepackage{mdframed}
\usepackage{minted}
\usepackage{multicol}
\usepackage{luacode}
\usepackage{syntax}
\usepackage{color}

\definecolor{gray}{gray}{0.75}

\usemintedstyle{friendly}
\BeforeBeginEnvironment{minted}{\begin{mdframed}}
\AfterEndEnvironment{minted}{\end{mdframed}}
\setminted{
  breaklines=true,
  fontsize=\footnotesize,
  style=manni,
}
\def\lua#1{\mintinline{lua}|#1|}
\def\latex#1{\mintinline{latex}|#1|}

% File names must not contain underscores
\NewDocumentCommand { \InputLatex } { O{} m } {
  \begin{mdframed}
  \inputminted[linenos=false,#1]{latex}{examples/#2}
  \end{mdframed}
}

\NewDocumentCommand { \InputTex } { O{} m } {
  \begin{mdframed}
  \inputminted[linenos=false,#1]{tex}{examples/#2}
  \end{mdframed}
}

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

\begin{document}

\providecommand*{\url}{\texttt}

\title{The \textsf{lparse} package}
\author{%
  Josef Friedrich\\%
  \url{josef@friedrich.rocks}\\%
  \href{https://github.com/Josef-Friedrich/lparse}
       {github.com/Josef-Friedrich/lparse}%
}
\date{0.3.0 from 2025/07/02}

\maketitle

\InputLatex[firstline=5,lastline=14]{lualatex/title-page.tex}

\newpage

\tableofcontents

\newpage

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

% Der Name |lparse| ist von |xparse| abgeleitet.
The name |lparse| is derived from |xparse|.
%
% Das |x| wurde durch |l| ersetzt, da dieses Packet nur zusammen mit
% Lua\TeX{} funktioniert.
The |x| has been replaced by |l| because this package only works with Lua\TeX{}.
%
% |l| steht für \emph{Lua}
|l| stands for \emph{Lua}.
%
% Ebenso wie bei dem Paket |xparse| ist es möglich, die Argumente eines
% Makros mit Hilfe einer speziellen Syntax bestehend aus einzelnen
% Buchstaben zu beschreiben.
Just as with |xparse|, it is possible to use a special syntax consisting
of single letters to express the arguments of a macro.
%
% |lparse| ist jedoch im Stande unabhängig von der verwendeten
% Makrosammlung - ob LaTeX oder ConTeXt oder sogar Plain TeX - Argumente
% einzulesen.
However, |lparse| is able to read arguments regardless of the macro
systemd used - whether \LaTeX{} or Con\TeX{}t or even plain \TeX.
%
% Als Engine musst natürlich immer LuaTeX verwendet werden.
Of course, Lua\TeX{} must always be used as the engine.

\subsection*{Similar projects}

% Für ConTeXt gibt es einen ähnlichen Argumenten scanner.
For Con\TeX{}t there is a similar argument scanner (see Con\TeX{}t Lua
Document
\href{http://www.pragma-ade.nl/general/manuals/cld-mkiv.pdf}{cld-mkiv}).
%
% Dieser Scanner ist in folgenden Dateien implementiert
This scanner is implemented in the following files:
\href{https://github.com/contextgarden/context/blob/main/tex/context/base/mkiv/toks-scn.lua}{toks-scn.lua}
\href{https://github.com/contextgarden/context/blob/main/tex/context/base/mkiv/toks-aux.lua}{toks-aux.lua}
\href{https://github.com/contextgarden/context/blob/main/tex/context/base/mkiv/toks-ini.lua}{toks-ini.lua}
% Con\TeX{}t scanner verwendet offenbar die Token Bibliothek des LuaTeX Nachfolgeprojekts luametaTeX
%
Con\TeX{}t scanner apparently uses the token library of the LuaTeX
successor project luameta\TeX:
\href{https://github.com/contextgarden/context/blob/main/source/luametatex/source/lua/lmttokenlib.c}{lmttokenlib.c}

\section{The Lua API of \texttt{lparse}}

\subsection{Description of the argument specification}
%
% Folgende Listen, die die Argumenttypen beschreiben, entstammen den
% Handbücher usrguide bzw. xparse.
The following lists describing the argument types are
taken from the manuals
\href{http://mirrors.ctan.org/macros/latex/base/usrguide.pdf}{usrguide}
and
\href{http://mirrors.ctan.org/macros/latex/contrib/l3packages/xparse.pdf}{xparse}.
%
% Die Beschreibungstexte der einzelnen Argumententypen wurden nur leicht angepasst.
The descriptive texts of the individual argument types have only been
slightly adjusted.
%
% Die noch nicht unterstützen Argumentypen sind eingeklammert.
The argument types that are not yet supported are bracketed.

% /usr/local/texlive/texmf-dist/source/latex/l3packages/xparse/xparse.dtx
\begin{itemize}
  \item[m] A standard mandatory argument, which can either be a single
    token alone or multiple tokens surrounded by curly braces |{}|.
    Regardless of the input, the argument will be passed to the
    internal code without the outer braces. This is the \pkg{lparse}
    type specifier for a normal \TeX{} argument.

  \item[r] Given as \texttt{r}\meta{token1}\meta{token2}, this denotes a
    \enquote{required} delimited argument, where the delimiters are
    \meta{token1} and \meta{token2}. If the opening delimiter
    \meta{token1} is missing, |nil| will be
    returned after a suitable error.

  \item[R] Given as \texttt{R}\meta{token1}\meta{token2}\marg{default},
    this is a \enquote{required} delimited argument as for~\texttt{r},
    but it has a user-definable recovery \meta{default} instead of
    |nil|.

  \item[v] Reads an argument \enquote{verbatim}, between the following
    character and its next occurrence.

  \color{gray}

  \item[(b)] Not implemented! Only suitable in the argument specification of an
    environment, it denotes the body of the environment, between
    |\begin|\marg{environment} and |\end|\marg{environment}.

\end{itemize}
The types which define optional arguments are:
\begin{itemize}
  \item[o] A standard \LaTeX{} optional argument, surrounded with square
    brackets, which will supply
    |nil| if not given (as described later).

  \item[d] Given as \texttt{d}\meta{token1}\meta{token2}, an optional
    argument which is delimited by \meta{token1} and \meta{token2}.
    As with \texttt{o}, if no
    value is given |nil| is returned.

  \item[O] Given as \texttt{O}\marg{default}, is like \texttt{o}, but
    returns \meta{default} if no value is given.

  \item[D] Given as \texttt{D}\meta{token1}\meta{token2}\marg{default},
    it is as for \texttt{d}, but returns \meta{default} if no value is given.
    Internally, the \texttt{o}, \texttt{d} and \texttt{O} types are
    short-cuts to an appropriated-constructed \texttt{D} type argument.

  \item[s] An optional star, which will result in a value
    |true| if a star is present and |false|
    otherwise (as described later).

  \item[t] An optional \meta{token}, which will result in a value
    |true| if \meta{token} is present and |false|
    otherwise. Given as \texttt{t}\meta{token}.

  \color{gray}

  \item[(e)] Not implemented! Given as \texttt{e}\marg{tokens}, a set of optional
    \emph{embellishments}, each of which requires a \emph{value}.
    If an embellishment is not present, |-NoValue-| is returned.  Each
    embellishment gives one argument, ordered as for the list of
    \meta{tokens} in the argument specification.  All \meta{tokens}
    must be distinct.  \emph{This is an experimental type}.
  \item[(E)] Not implemented! As for \texttt{e} but returns one or more \meta{defaults}
    if values are not given: \texttt{E}\marg{tokens}\marg{defaults}.
\end{itemize}

\subsection{Function: \texttt{scan}}

\InputTex{luatex/function-scan.tex}

\subsection{Function: \texttt{register_csname(csname, fn, opts)}}

The function \lua{register_csname(csname, fn, opts)} registers a Lua
function under a control sequence name (csname). The first argument is
the control sequence name without the leading backslash. The second
argument is the Lua function to be called when the command name is
called in the TeX code.

\InputTex{luatex/function-register-csname.tex}


% Hilfsfunktionen
\subsection{Auxiliary functions}

%
% Einige Hilfsfunktionen werden in der Tabelle utils exportiert.
Some auxiliary functions are exported in the \lua{utils} table:

\begin{minted}{lua}
local lparse = require('lparse')

local parse_spec = lparse.utils.parse_spec
local scan_oarg = lparse.utils.scan_oarg
\end{minted}

%%
%
%%

\subsubsection*{Function: \texttt{utils.scan_oarg(init_delim, end_delim)}}

% Plain \TeX{} kennt keine optionalen Argumente (oarg).
Plain \TeX{} does not know optional arguments \oarg{oarg}.
%
% Die Funktion ermöglicht es nicht nur in \LaTeX{}, sondern auch in
% Plain \TeX{} nach optionalen Argumenten zu suchen.
The function \lua{scan_oarg} allows to search for optional arguments not only
in \LaTeX{} but also in Plain \TeX.
%
% Die Funktion basiert auf der Token-Bibliothek.
The function uses the token library built into Lua\TeX{}.
%
% Die beiden Parameter \lua{initial_delimiter} und \lua{end_delimiter}
% können weggelassen werden.
The two parameters \lua{init_delim} and \lua{end_delim} can
be omitted.
%
% Dann werden eckige Klammern als Begrenzungszeichen angenommen.
Then square brackets are assumed to be delimiters.
%
% \lua{utils.scan_oarg('(', ')')} sucht beispielsweise nach an einem
% optionalen Argument in runden Klammern.
\lua{utils.scan_oarg('(', ')')} searches for an optional argument in
round brackets, for example.
%
% Die Funktion gibt die Zeichenkette zwischen den Begrenzungszeichen
% zurück, oder nil wenn Begrenzungszeichen gefunden werden konnten.
The function returns the string between the delimiters or \lua{nil} if
no delimiters could be found.
%
% Die Begrenzungszeichen sind im Ergebnis nicht enthalten.
The delimiters themselves are not included in the result.
%
% Nach dem \latex{\directlua{}} darf das Makro, indem
% \lua{utils.scan_oarg} eingesetzt wird, zu keinen Zeichen expandieren.
After the \latex{\directlua{}}, the macro using \lua{scan_oarg}
must not expand to any characters.

\InputTex{luatex/function-utils.scan-oarg.tex}

\section{Known limitations}

% Im einigen Lua\LaTeX{} Umgebungen funktioniert das Scannen nach
% optionalen Argument (oargs) nicht.
In some Lua\LaTeX{} environments, scanning for optional arguments
(oargs) does not work.
% Ich weiß leider nicht warum.
Unfortunately I don't know why.
% Über Hilfe wäre ich sehr dankbar.
I would be very grateful for help.

\subsection{In tabular environment}

% Steht in einer |tabular|-Umgebung vor einem Kommando, der mit |lparse|
% gescannt wird, ein beliebert Text funktioniert es nicht, sonst schon.
In a |tabular| environment, if a command that is scanned with |lparse| is
preceded by any text, it does not work, otherwise it does.

\InputTex{lualatex/error-tabular.tex}

\subsection{In multline environment}

\InputTex{lualatex/error-multline.tex}

\clearpage

\section{Implementation}

The source code is hosted on
\href{https://github.com/Josef-Friedrich/lparse}{Github}. The
following links will take you to the individual files:

\begin{itemize}
\item \href{https://github.com/Josef-Friedrich/lparse/blob/main/lparse.lua}{lparse.lua}

\item \href{https://github.com/Josef-Friedrich/lparse/blob/main/lparse.sty}{lparse.sty}

\item \href{https://github.com/Josef-Friedrich/lparse/blob/main/lparse.tex}{lparse.tex}
\end{itemize}

\pagebreak
\PrintIndex
\end{document}
