summaryrefslogtreecommitdiff
path: root/obsolete/macros/generic/expkv-def/expkv-def.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'obsolete/macros/generic/expkv-def/expkv-def.dtx')
-rw-r--r--obsolete/macros/generic/expkv-def/expkv-def.dtx2493
1 files changed, 2493 insertions, 0 deletions
diff --git a/obsolete/macros/generic/expkv-def/expkv-def.dtx b/obsolete/macros/generic/expkv-def/expkv-def.dtx
new file mode 100644
index 0000000000..059c7dda01
--- /dev/null
+++ b/obsolete/macros/generic/expkv-def/expkv-def.dtx
@@ -0,0 +1,2493 @@
+% \iffalse meta-comment
+%
+% File: expkv-def.dtx Copyright (C) 2020-2022 Jonathan P. Spratte
+%
+% This work may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this license or
+% (at your option) any later version. The latest version of this license is in
+% the file:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% ------------------------------------------------------------------------------
+%
+%<*driver>^^A>>=
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+ \expandafter\begingroup
+\fi
+\input l3docstrip.tex
+\askforoverwritefalse
+\preamble
+
+--------------------------------------------------------------
+expkv-def -- a key-defining frontend for expkv
+E-mail: jspratte@yahoo.de
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+--------------------------------------------------------------
+
+Copyright (C) 2020-2022 Jonathan P. Spratte
+
+This work may be distributed and/or modified under the conditions of the
+LaTeX Project Public License (LPPL), either version 1.3c of this license or
+(at your option) any later version. The latest version of this license is in
+the file:
+
+ http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+ Jonathan P. Spratte.
+
+This work consists of the file expkv-def.dtx
+and the derived files expkv-def.pdf
+ expkv-def.sty
+ expkv-def.tex
+ t-expkv-def.tex
+
+\endpreamble
+% stop docstrip adding \endinput
+\postamble
+\endpostamble
+\generate{\file{expkv-def.sty}{\from{expkv-def.dtx}{pkg}}}
+\generate{\file{expkv-def.tex}{\from{expkv-def.dtx}{tex}}}
+\generate{\file{t-expkv-def.tex}{\from{expkv-def.dtx}{ctx}}}
+\ifx\fmtname\nameofplainTeX
+ \expandafter\endbatchfile
+\else
+ \expandafter\endgroup
+\fi
+%
+\IfFileExists{expkv-def.tex}{\input{expkv-def.tex}}{}
+\ProvidesFile{expkv-def.dtx}
+ [\csname ekvdDate\endcsname\ a key-defining frontend for expkv]
+\PassOptionsToPackage{full}{textcomp}
+\documentclass{l3doc}
+\RequirePackage[oldstylenums,nott]{kpfonts}
+\input{glyphtounicode}
+\pdfgentounicode=1
+\RequirePackage{tcolorbox}
+\newtcolorbox{exresult}[2][]
+ {colback=expkvgrey!10!white,colframe=expkvgrey,fontupper=\small,width={#2},#1}
+\newtcbox\exres[1][]
+ {
+ colback=expkvgrey!10!white
+ ,colframe=expkvgrey
+ ,size=small
+ ,nobeforeafter
+ ,tcbox raise base
+ ,fontupper=\small
+ ,#1
+ }
+\RequirePackage{listings}
+\RequirePackage{booktabs}
+\RequirePackage{array}
+\RequirePackage{collcell}
+\RequirePackage{siunitx}
+\RequirePackage{xcolor}
+\RequirePackage{caption}
+\RequirePackage{microtype}
+\RequirePackage{accsupp}
+\lstdefinelanguage{expkvd}[primitive]{TeX}
+ {
+ ,moretexcs=[4]^^A e-TeX
+ {
+ expanded,
+ numexpr,
+ protected,
+ }
+ ,moretexcs=[5]^^A plain/LaTeX
+ {
+ approx,
+ begin,
+ empty,
+ item,
+ LaTeX,
+ makeatletter,makeatother,
+ newcommand,newdimen,
+ RequirePackage,
+ rule,
+ TeX,
+ textit,texttt,
+ usepackage,
+ }
+ ,moretexcs=[6]^^A used packages
+ {
+ ^^A xfp
+ fpeval,
+ ^^A keyval
+ setkeys,
+ ^^A yax
+ defactiveparameter,storevalue,setparameterlist
+ }
+ ,moretexcs=[2]^^A expkv-def macros
+ {
+ ekvdefinekeys
+ }
+ ,moretexcs=[3]^^A expkv-pkg macros
+ {
+ ^^A expkv
+ ekvdef,ekvdefNoVal,^^A
+ ekvlet,ekvletNoVal,ekvletkv,ekvletkvNoVal,^^A
+ ekvdefunknown,ekvdefunknownNoVal,^^A
+ ekvredirectunknown,ekvredirectunknownNoVal,^^A
+ ekvset,ekvsetSneaked,^^A
+ ekvsetdef,ekvsetSneakeddef,ekvsetdefSneaked,^^A
+ ekvparse,^^A
+ ekvVersion,ekvDate,^^A
+ ekvifdefined,ekvifdefinedNoVal,ekvifdefinedset,^^A
+ ekvbreak,ekvbreakPreSneak,ekvbreakPostSneak,^^A
+ ekvsneak,ekvsneakPre,^^A
+ ekvchangeset,^^A
+ ekvoptarg,ekvoptargTF,^^A
+ ekverr,
+ ^^A expkv-cs
+ ekvcSecondaryKeys,ekvcSplitAndForward,
+ }
+ }
+\colorlet{codeparam}{cyan!65!black}
+\def\mylstwd{.55em}
+\lstset
+ {
+ ,language=expkvd
+ ,flexiblecolumns=false
+ ,basewidth=\mylstwd
+ ,gobble=2
+ ,basicstyle=\fontfamily{jkp}\itshape
+ ,texcsstyle=*[1]{\bfseries\color{expkvgrey}} ^^A primitives
+ ,texcsstyle=*[2]{\bfseries\color{expkvred}} ^^A expkv
+ ,texcsstyle=*[3]{\color{expkvred}} ^^A expkv-pkg
+ ,texcsstyle=*[4]{\bfseries\color{expkvgrey}} ^^A e-TeX
+ ,texcsstyle=*[5]{\bfseries\color{expkvgrey}} ^^A plain/LaTeX macros
+ ,texcsstyle=*[6]{} ^^A macros of other packages
+ ,commentstyle=\color[gray]{0.4}
+ ,literate=
+ {\{} {{\CodeUpBf\{}}{1}
+ {\}} {{\CodeUpBf\}}}{1}
+ {$} {{\CodeUpBf\$}}{1}
+ {[} {{\CodeUp[}}{1}
+ {]} {{\CodeUp]}}{1}
+ {(} {{\CodeUp(}}{1}
+ {)} {{\CodeUp)}}{1}
+ {*} {{$*$}}{1}
+ {1} {{\CodeUp{1}}}{1}
+ {2} {{\CodeUp{2}}}{1}
+ {3} {{\CodeUp{3}}}{1}
+ {4} {{\CodeUp{4}}}{1}
+ {5} {{\CodeUp{5}}}{1}
+ {6} {{\CodeUp{6}}}{1}
+ {7} {{\CodeUp{7}}}{1}
+ {8} {{\CodeUp{8}}}{1}
+ {9} {{\CodeUp{9}}}{1}
+ {0} {{\CodeUp{0}}}{1}
+ {##} {{\CodeColored{codeparam}{1}{\#}}}{1}
+ {##1}{{\CodeColored{codeparam}{2}{\#1}}}{2}
+ {##2}{{\CodeColored{codeparam}{2}{\#2}}}{2}
+ {##3}{{\CodeColored{codeparam}{2}{\#3}}}{2}
+ {##4}{{\CodeColored{codeparam}{2}{\#4}}}{2}
+ {##5}{{\CodeColored{codeparam}{2}{\#5}}}{2}
+ {##6}{{\CodeColored{codeparam}{2}{\#6}}}{2}
+ {##7}{{\CodeColored{codeparam}{2}{\#7}}}{2}
+ {##8}{{\CodeColored{codeparam}{2}{\#8}}}{2}
+ {##9}{{\CodeColored{codeparam}{2}{\#9}}}{2}
+ {<key>}{{$\langle$}key{$\rangle$}}{5}
+ {<set>}{{$\langle$}set{$\rangle$}}{5}
+ {<set1>}{{$\langle$}set1{$\rangle$}}{6}
+ {<set2>}{{$\langle$}set2{$\rangle$}}{6}
+ ^^A,literate=*{<key>}{\key}{4}{<set>}{\set}{4}
+ }
+\newcommand*\CodeColored[3]{\textcolor{#1}{\makebox[\dimexpr\mylstwd*#2]{#3}}}
+\newcommand*\CodeUpBf[1]{\makebox[\mylstwd]{\textup{\textbf{#1}}}}
+\newcommand*\CodeUp[1]{\makebox[\mylstwd]{\textup{#1}}}
+\RequirePackage{randtext}
+\let\metaORIG\meta
+\protected\def\meta #1{\texttt{\metaORIG{#1}}}
+\renewcommand*\thefootnote{\fnsymbol{footnote}}
+\definecolor{expkvred}{HTML}{9F393D}
+\colorlet{expkvgrey}{black!75}
+\makeatletter
+\newcommand*\expkv
+ {^^A
+ \texorpdfstring
+ {^^A
+ \mbox
+ {^^A
+ \BeginAccSupp{ActualText=expkv}^^A
+ \href{https://github.com/Skillmon/tex_expkv}
+ {^^A
+ \rmfamily
+ \bfseries
+ {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
+ \lower.493ex
+ \hbox{{\color{expkvgrey}P}\kern-.1em{\color{expkvred}k}}^^A
+ \kern-.18em{\color{expkvred}v}^^A
+ }^^A
+ \EndAccSupp{}^^A
+ }^^A
+ }
+ {expkv}^^A
+ }
+\newcommand*\expkvd
+ {^^A
+ \texorpdfstring
+ {^^A
+ \mbox
+ {^^A
+ \BeginAccSupp{ActualText=expkv-def}^^A
+ \href{https://github.com/Skillmon/tex_expkv-def}
+ {^^A
+ \rmfamily
+ \bfseries
+ {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A
+ \lower.493ex
+ \hbox{{\color{expkvgrey}P}\kern-.1em{\color{expkvred}k}}^^A
+ \kern-.18em{\color{expkvred}v}^^A
+ {\color{expkvgrey}^^A
+ \kern.05em\rule[-.1ex]{.08em}{1.2ex}\kern.05em\textsc{def}^^A
+ }^^A
+ }^^A
+ \EndAccSupp{}^^A
+ }^^A
+ }
+ {expkv-def}^^A
+ }
+\newcommand\kv{\meta{key}=\meta{value}}
+\newcommand\key{\meta{key}}
+\newcommand\val{\meta{value}}
+\newcommand\set{\meta{set}}
+\newcommand\enfprefix{\textcolor{black}}
+\newcommand\allprefix{\textcolor{gray}}
+\newcommand\notprefix{\textcolor{red!80!black}}
+\newcommand\printprefix[2]
+ {^^A
+ \ifcase\numexpr#1\relax\or
+ \enfprefix{#2}\or
+ \allprefix{#2}\or
+ \notprefix{#2}\fi
+ }
+\newcommand\prefixes[4]
+ {^^A
+ \hfill
+ \printprefix{#1}{new}
+ \printprefix{#2}{also}
+ \printprefix{#3}{protected}
+ \printprefix{#4}{long}^^A
+ }
+\hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black}
+\DoNotIndex{\def,\edef,\,,\=,\begingroup,\catcode,\chardef,\csname,\endcsname}
+\DoNotIndex{\endgroup,\endinput,\errmessage,\expandafter,\input,\let,\long}
+\DoNotIndex{\protected,\ProvidesFile,\ProvidesPackage,\relax,\space}
+\DoNotIndex{\@,\unexpanded,\string,\expanded,\dimexpr,\global,\glueexpr,\hbox}
+\DoNotIndex{\numexpr,\RequirePackage,\setbox,\the,\unless,\xdef,\@firstofone}
+\DoNotIndex{\@firstoftwo,\@gobble,\@secondoftwo,\meaning,\detokenize}
+\DoNotIndex{\romannumeral,\^}
+\DoNotIndex{\ifcsname}
+\DoNotIndex{\ifx}
+\DoNotIndex{\ifdefined}
+\DoNotIndex{\iffalse}
+\DoNotIndex{\iftrue}
+\DoNotIndex{\else}
+\DoNotIndex{\fi}
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@gobble\fi ^^A ignoring \ifx, \ifcsname, etc., but only one \fi
+\@ifdefinable\gobbledocstriptag{\def\gobbledocstriptag#1>{}}
+\makeatother
+\begin{document}
+ \title
+ {^^A
+ \texorpdfstring
+ {^^A
+ \huge\expkvd
+ \\[\medskipamount]
+ \Large a key-defining frontend for \expkv
+ }{expkv-def - a key-defining frontend for expkv}^^A
+ }
+ \date{\ekvdDate\space v\ekvdVersion}
+ \author{Jonathan P. Spratte\thanks{\protect\randomize{jspratte@yahoo.de}}}
+ \DocInput{expkv-def.dtx}
+\end{document}
+%</driver>^^A=<<
+% \fi
+%
+% \maketitle
+% \renewcommand*\thefootnote{\arabic{footnote}}
+%
+% \begin{abstract}
+% \noindent\parfillskip=0pt
+% \expkvd\ provides a small \kv\ interface to define keys for \expkv. Key-types
+% are declared using prefixes, similar to static typed languages. The stylised
+% name is \expkvd\ but the files use \file{expkv-def}, this is due to CTAN-rules
+% which don't allow \string| in package names since that is the pipe symbol in
+% *nix shells.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \begin{documentation}^^A>>=
+%
+% \section{Documentation}
+%
+% Since the trend for the last couple of years goes to defining keys for a \kv\
+% interface using a \kv\ interface, I thought that maybe providing such an
+% interface for \expkv\ will make it more attractive for actual use, besides its
+% unique selling points of being fully expandable, and fast and reliable. But at
+% the same time I don't want to widen \expkv's initial scope. So here it is
+% \expkvd, go define \kv\ interfaces with \kv\ interfaces.
+%
+% Unlike many of the other established \kv\ interfaces to define keys, \expkvd\
+% works using prefixes instead of suffixes (\emph{e.g.}, |.tl_set:N| of
+% \pkg{l3keys}) or directory like handlers (\emph{e.g.}, |/.store in| of
+% \pkg{pgfkeys}). This was decided as a personal preference, more over in \TeX\
+% parsing for the first space is way easier than parsing for the last one.
+% \expkvd's prefixes are sorted into two categories: |p|-type, which are
+% equivalent to \TeX's prefixes like |\long|, and |t|-type defining the type of
+% the key. For a description of the available |p|-prefixes take a look at
+% \autoref{sec:prefix:p}, the |t|-prefixes are described in
+% \autoref{sec:prefix:t}.
+%
+% \expkvd\ is usable as generic code, as a \LaTeX\ package, and as a \ConTeXt\
+% module. It'll automatically load \expkv\ in the same mode as well. To use it,
+% just use one of
+% \begin{lstlisting}
+% \input expkv-def % plainTeX
+% \usepackage{expkv-def} % LaTeX
+% \usemodule[expkv-def] % ConTeXt
+% \end{lstlisting}
+%
+% \subsection{Macros}
+% Apart from version and date containers there is only a single user-facing
+% macro, and that should be used to define keys.
+%
+% \begin{function}{\ekvdefinekeys}
+% \begin{syntax}
+% \cs{ekvdefinekeys}\marg{set}\{\kv, \ldots\}
+% \end{syntax}
+% In \set, define \key\ to have definition \val. The general syntax for \key\
+% should be
+% \begin{quote}\ttfamily\small
+% \meta{prefix} \meta{name}
+% \end{quote}
+% Where \meta{prefix} is a space separated list of optional |p|-type prefixes
+% followed by one |t|-type prefix. The syntax of \val\ is dependent on the
+% used |t|-prefix.
+% \end{function}
+%
+% \begin{function}{\ekvdDate,\ekvdVersion}
+% These two macros store the version and date of the package.
+% \end{function}
+%
+% \subsection{Prefixes}
+% As already said there are |p|-prefixes and |t|-prefixes. Not every |p|-prefix
+% is allowed for all |t|-prefixes.
+%
+% \subsubsection{\texttt{p}-Prefixes}\label{sec:prefix:p}
+% The two |p|-type prefixes |long| and |protected| are pretty simple by nature,
+% so their description is pretty simple. They affect the \key\ at use-time, so
+% omitting |long| doesn't mean that a \meta{definition} can't contain a |\par|
+% token, only that the \key\ will not accept a |\par| in \val. On the other
+% hand |new| and |also| might be simple on first sight as well, but their rules
+% are a bit more complicated.
+%
+% \begin{function}{also}
+% The following key type will be \emph{added} to an existing \key's
+% definition. You can't add a type taking an argument at use time to an
+% existing key which doesn't take an argument and vice versa. Also you'll get
+% an error if you try to add an action which isn't allowed to be either |long|
+% or |protected| to a key which already is |long| or |protected| (the opposite
+% order would be suboptimal as well, but can't be really captured with the
+% current code).
+%
+% A key already defined as |long| or |protected| will stay |long| or
+% |protected|, but you can as well add |long| or |protected| with the |also|
+% definition.
+%
+% As a small example, suppose you want to create a boolean key, but
+% additionally to setting a boolean value you want to execute some more code
+% as well, you can use the following
+% \begin{lstlisting}
+% \ekvdefinekeys{also-example}
+% {
+% bool key = \ifmybool
+% ,also code key = \domystuff{#1}
+% }
+% \end{lstlisting}
+%
+% If you use |also| on a |choice|, |bool|, |invbool|, or |boolpair| key it is
+% tried to determine if the key already is of one of those types. If this test
+% is true the declared choices will be added to the possible choices but the
+% key's definition will not be changed other than that. If that wouldn't have
+% been done, the callbacks of the different choices could get called multiple
+% times.
+% \end{function}
+%
+% \begin{function}{protected,protect}
+% The following key will be defined |\protected|. Note that key-types which
+% can't be defined expandable will always use |\protected|.
+% \end{function}
+%
+% \begin{function}{long}
+% The following key will be defined |\long|.
+% \end{function}
+%
+% \begin{function}{new}
+% The following key must be new (so previously undefined). An error is thrown
+% if it is already defined and the new definition is ignored. |new| only
+% asserts that there are no conflicts between |NoVal| keys and other |NoVal|
+% keys or value taking keys and other value taking keys. For example you can
+% use the following without an error:
+% \begin{lstlisting}
+% \ekvdefinekeys{new-example}
+% {
+% code key = \domystuffwitharg{#1}
+% ,new noval key = \domystuffwithoutarg
+% }
+% \end{lstlisting}
+% \end{function}
+%
+% \subsubsection{\texttt{t}-Prefixes}\label{sec:prefix:t}
+% Since the |p|-type prefixes apply to some of the |t|-prefixes automatically
+% but sometimes one might be disallowed we need some way to highlight this
+% behaviour. In the following an enforced prefix will be printed black
+% (\texttt{\enfprefix{protected}}), allowed prefixes will be grey
+% (\texttt{\allprefix{protected}}), and disallowed prefixes will be red
+% (\texttt{\notprefix{protected}}). This will be put flush-right in the syntax
+% showing line.
+%
+% \begin{function}{code,ecode}
+% \begin{syntax}
+% code \key\ = \marg{definition} \prefixes2222
+% \end{syntax}
+% Define \key\ to expand to \meta{definition}. The \key\ will require a \val\
+% for which you can use |#1| inside \meta{definition}. The |ecode| variant
+% will fully expand \meta{definition} inside an |\edef|.
+% \end{function}
+%
+% \begin{function}{noval,enoval}
+% \begin{syntax}
+% noval \key\ = \marg{definition} \prefixes2223
+% \end{syntax}
+% The |noval| type defines \key\ to expand to \meta{definition}. The \key\
+% will not take a \val. |enoval| fully expands \meta{definition} inside an
+% |\edef|.
+% \end{function}
+%
+% \begin{function}{default,qdefault,odefault,fdefault,edefault}
+% \begin{syntax}
+% default \key\ = \marg{definition} \prefixes3223
+% \end{syntax}
+% This serves to place a default \val\ for a \key\ that takes an argument, the
+% \key\ can be of any argument-grabbing kind, and when used without a \val\
+% it will be passed \meta{definition} instead. The |qdefault| variant will
+% expand the \key's code once, so will be slightly quicker, but not change if
+% you redefine \key. |odefault| is just another name for |qdefault|. The
+% |fdefault| version will expand the key code until a non-expandable token or
+% a space is found, a space would be gobbled.\footnotemark{} The |edefault| on
+% the other hand fully expands the \key-code with \meta{definition} as its
+% argument inside of an |\edef|.
+% \end{function}
+% \footnotetext
+% {^^A
+% For those familiar with \TeX-coding: This uses a
+% \cs[no-index]{romannumeral}-expansion.
+% }
+%
+% \begin{function}{initial,oinitial,finitial,einitial}
+% \begin{syntax}
+% initial \key\ = \{\val\} \prefixes3333
+% initial \key
+% \end{syntax}
+% With |initial| you can set an initial \val\ for an already defined argument
+% taking \key. It'll just call the key-macro of \key\ and pass it \val. The
+% |einitial| variant will expand \val\ using an |\edef| expansion prior to
+% passing it to the key-macro and the |oinitial| variant will expand the first
+% token in \val\ once. |finitial| will expand \val\ until a non-expandable
+% token or a space is found, a space would be
+% gobbled.\footnotemark
+%
+% If you don't provide a value (and no equals sign) a |noval| \key\ of the
+% same name is called once (or, if you specified a |default| for a value
+% taking key that would be used).
+% \end{function}
+% \footnotetext{Again using \cs[no-index]{romannumeral}.}
+%
+% \begin{function}{bool,gbool,boolTF,gboolTF}
+% \begin{syntax}
+% bool \key\ = \meta{cs} \prefixes2223
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\iffoo|.
+% This will define \key\ to be a boolean key, which only takes the values
+% |true| or |false| and will throw an error for other values. If the key is
+% used without a \val\ it'll have the same effect as if you use
+% \texttt{\key=true}. |bool| and |gbool| will behave like \TeX-ifs so either
+% be |\iftrue| or |\iffalse|. The |boolTF| and |gboolTF| variants will both
+% take two arguments and if true the first will be used else the second, so
+% they are always either |\@firstoftwo| or |\@secondoftwo|. The variants with
+% a leading |g| will set the control sequence globally, the others locally. If
+% \meta{cs} is not yet defined it'll be initialised as the |false| version.
+% Note that the initialisation is \emph{not} done with |\newif|, so you will
+% not be able to do |\footrue| outside of the \kv\ interface, but you could
+% use |\newif| yourself. Even if the \key\ will not be |\protected| the
+% commands which execute the |true| or |false| choice will be, so the usage
+% should be safe in an expansion context (\emph{e.g.}, you can use
+% \texttt{edefault \key\ = false} without an issue to change the default
+% behaviour to execute the |false| choice). Internally a |bool| \key\ is the
+% same as a |choice| key which is set up to handle |true| and |false| as
+% choices.
+% \end{function}
+%
+% \begin{function}{invbool,ginvbool,invboolTF,ginvboolTF}
+% \begin{syntax}
+% bool \key\ = \meta{cs} \prefixes2223
+% \end{syntax}
+% These are inverse boolean keys, they behave like |bool| and friends but set
+% the opposite meaning to the macro \meta{cs} in each case. So if
+% \texttt{key=true} is used |invbool| will set \meta{cs} to |\iffalse| and
+% vice versa.
+% \end{function}
+%
+% \begin{function}{boolpair,gboolpair,boolpairTF,gboolpairTF}
+% \begin{syntax}
+% boolpair \key\ = \meta{cs_1}\meta{cs_2} \prefixes2223
+% \end{syntax}
+% The |boolpair| key type behaves like both |bool| and |invbool|, the
+% \meta{cs_1} will be set to the meaning according to the rules of |bool|, and
+% \meta{cs_2} will be set to the opposite.
+% \end{function}
+%
+% \begin{function}{store,estore,gstore,xstore}
+% \begin{syntax}
+% store \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% This will define \key\ to store \val\ inside of the control sequence. If
+% \meta{cs} isn't yet defined it will be initialised as empty. The variants
+% behave similarly to their |\def|, |\edef|, |\gdef|, and |\xdef|
+% counterparts, but |store| and |gstore| will allow you to store macro
+% parameters inside of them by using |\unexpanded|.
+% \end{function}
+%
+% \begin{function}{data,edata,gdata,xdata}
+% \begin{syntax}
+% data \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|. This will
+% define \key\ to store \val\ inside of the control sequence. But unlike the
+% |store| type, the macro \meta{cs} will be a switch at the same time, it'll
+% take two arguments and if \key\ was used expands to the first argument
+% followed by \val\ in braces, if \key\ was not used \meta{cs} will expand to
+% the second argument (so behave like |\@secondoftwo|). The idea is that with
+% this type you can define a key which should be typeset formatted. The
+% |edata| and |xdata| variants will fully expand \val, the |gdata| and |xdata|
+% variants will store \val\ inside \meta{cs} globally. The |p|-prefixes will
+% only affect the key-macro, \meta{cs} will always be expandable and |\long|.
+% \end{function}
+%
+% \begin{function}{dataT,edataT,gdataT,xdataT}
+% \begin{syntax}
+% dataT \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% Just like |data|, but instead of \meta{cs} grabbing two arguments it'll only
+% grab one, so by default it'll behave like |\@gobble|, and if a \val\ was
+% given to \key\ the \meta{cs} will behave like |\@firstofone| appended by
+% \marg{value}.
+% \end{function}
+%
+% \begin{function}{int,eint,gint,xint}
+% \begin{syntax}
+% int \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% An |int| key will be a \TeX-count register. If \meta{cs} isn't defined yet,
+% |\newcount| will be used to initialise it. The |eint| and |xint| versions
+% will use |\numexpr| to allow basic computations in their \val. The |gint|
+% and |xint| variants set the register globally.
+% \end{function}
+%
+% \begin{function}{dimen,edimen,gdimen,xdimen}
+% \begin{syntax}
+% dimen \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% This is just like |int| but uses a dimen register, |\newdimen| and
+% |\dimexpr| instead.
+% \end{function}
+%
+% \begin{function}{skip,eskip,gskip,xskip}
+% \begin{syntax}
+% skip \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% This is just like |int| but uses a skip register, |\newskip| and |\glueexpr|
+% instead.
+% \end{function}
+%
+% \begin{function}{toks,gtoks,apptoks,gapptoks,pretoks,gpretoks}
+% \begin{syntax}
+% toks \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% Store \val\ inside of a toks-register. The |g| variants use |\global|, the
+% |app| variants append \val\ to the contents of that register, the |pre|
+% variants will prepend \val. If \meta{cs} is not yet defined it will be
+% initialised with |\newtoks|.
+% \end{function}
+%
+% \begin{function}{box,gbox}
+% \begin{syntax}
+% box \key\ = \meta{cs} \prefixes2212
+% \end{syntax}
+% The \meta{cs} should be a single control sequence, such as |\foo|.
+% Typesets \val\ into a |\hbox| and stores the result in a box register. The
+% boxes are colour safe. \expkvd\ doesn't provide a |vbox| type.
+% \end{function}
+%
+% \begin{function}{meta}
+% \begin{syntax}
+% meta \key\ = \{\kv, \ldots\} \prefixes2222
+% \end{syntax}
+% This key type can set other keys, you can access the \val\ which was passed
+% to \key\ inside the \kv\ list with |#1|. It works by calling a sub-|\ekvset|
+% on the \kv\ list, so a |set| key will only affect that \kv\ list and not the
+% current |\ekvset|. Since it runs in a separate |\ekvset| you can't use
+% |\ekvsneak| using keys or similar macros in the way you normally could.
+% \end{function}
+%
+% \begin{function}{nmeta}
+% \begin{syntax}
+% nmeta \key\ = \{\kv, \ldots\} \prefixes2223
+% \end{syntax}
+% This key type can set other keys, the difference to |meta| is, that this key
+% doesn't take a value, so the \kv\ list is static.
+% \end{function}
+%
+% \begin{function}{smeta}
+% \begin{syntax}
+% smeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes2222
+% \end{syntax}
+% Yet another |meta| variant. An |smeta| key will take a \val\ which you can
+% access using |#1|, but it sets the \kv\ list inside of \set, so is equal to
+% \texttt{\cs[no-index]{ekvset}\marg{set}\{\kv, \ldots\}}.
+% \end{function}
+%
+% \begin{function}{snmeta}
+% \begin{syntax}
+% snmeta \key\ = \marg{set}\{\kv, \ldots\} \prefixes2223
+% \end{syntax}
+% And the last |meta| variant. |snmeta| is a combination of |smeta| and
+% |nmeta|. It doesn't take an argument and sets the \kv\ list inside of \set.
+% \end{function}
+%
+% \begin{function}{set}
+% \begin{syntax}
+% set \key\ = \marg{set} \prefixes2233
+% \end{syntax}
+% This will define \key\ to change the set of the current |\ekvset|
+% invocation to \set. You can omit \set\ (including the equals sign),
+% which is the same as using \texttt{set \key\ = \{\key\}}. The created |set|
+% key will not take a \val. Note that just like in \expkv\ it'll not be
+% checked whether \set\ is defined and you'll get a low-level \TeX\ error if
+% you use an undefined \set.
+% \end{function}
+%
+% \begin{function}{choice}
+% \begin{syntax}
+% choice \key\ = \{\val=\meta{definition}, \ldots\} \prefixes2223
+% \end{syntax}
+% Defines \key\ to be a |choice| key, meaning it will only accept a limited
+% set of values. You should define each possible \val\ inside of the
+% \val=\meta{definition} list. If a defined \val\ is passed to \key\ the
+% \meta{definition} will be left in the input stream. You can make
+% individual values |protected| inside the \val=\meta{definition} list. By
+% default a |choice| key is expandable, an undefined \val\ will throw an error
+% in an expandable way (but see the |unknown-choice| prefix). You can add
+% additional choices after the \key\ was created by using |choice| again for
+% the same \key, redefining choices is possible the same way, but there is no
+% interface to remove certain choices.
+% \end{function}
+%
+% \begin{function}{choice-store}
+% \begin{syntax}
+% choice-store \key\ = \meta{cs}\{\val, \ldots\} \prefixes2223
+% \end{syntax}
+% This is defines a special type of |choice| key that'll store the given
+% choice inside the macro \meta{cs} (so \meta{cs} should be a single control
+% sequence name such as |\foo|). Since storing inside a macro can't be done
+% expandably every choice-code is |\protected|, you might define the
+% |choice-store| key itself as |protected| as well if you want. Since the
+% definition of each choice is predefined with this key type the choice list
+% should just be a comma separated list of valid choices.
+% \end{function}
+% This means that the following |choice| and |choice-store| keys are equivalent
+% at use time:
+% \begin{lstlisting}
+% \newcommand*\mya{}
+% \ekvdefinekeys{example}
+% {
+% choice key1 = {a=\def\mya{a}, b=\def\mya{b}, c=\def\mya{c}}
+% ,choice-store key2 = \mya{a,b,c}
+% }
+% \end{lstlisting}
+%
+% \begin{function}{choice-enum}
+% \begin{syntax}
+% choice-enum \key\ = \meta{cs}\{\val, \ldots\} \prefixes2223
+% \end{syntax}
+% This is similar to |choice-store|, the differences are: \meta{cs} should be
+% a count-register or is initialised as such if the \meta{cs} is undefined
+% (via |\newcount|); instead of the value the position of the value in the
+% given list is stored in this register (zero-based).
+% \end{function}
+% This means that the following |choice| and |choice-enum| keys are equivalent
+% at use time:
+% \begin{lstlisting}
+% \newcount\myb
+% \ekvdefinekeys{example}
+% {
+% choice key1 = {a={\myb=0 }, b={\myb=1 }, c={\myb=2 }}
+% ,choice-enum key2 = \myb{a,b,c}
+% }
+% \end{lstlisting}
+%
+% \begin{function}{unknown-choice}
+% \begin{syntax}
+% unknown-choice \key\ = \marg{definition} \prefixes2323
+% \end{syntax}
+% By default an unknown \val\ passed to a |choice| or |bool| key will throw an
+% error. However, with this prefix you can define an alternative action which
+% should be executed if \key\ received an unknown choice. In \meta{definition}
+% you can refer to the choice which was passed in with |#1|.
+% \end{function}
+%
+% \begin{function}{unknown code}
+% \begin{syntax}
+% unknown code = \marg{definition} \prefixes2322
+% \end{syntax}
+% By default \expkv\ throws errors when it encounters unknown keys in a set.
+% With the |unknown| prefix you can define handlers that deal with undefined
+% keys, instead of a \key\ name you have to specify a subtype for this prefix,
+% here the subtype is |code|.\par
+% With |unknown code| the \meta{definition} is used for unknown keys which
+% were provided a value (so corresponds to |\ekvdefunknown|), you can access
+% the key name with |#1| and the value with |#2|.\footnotemark
+% \end{function}
+% \footnotetext
+% {^^A
+% There is some trickery involved to get this more intuitive argument order
+% without any performance hit if you compare this to
+% \cs[no-index]{ekvdefunknown} directly.^^A
+% }
+%
+% \begin{function}{unknown noval}
+% \begin{syntax}
+% unknown noval = \marg{definition} \prefixes2323
+% \end{syntax}
+% This is like |unknown code| but uses \meta{definition} for unknown keys to
+% which no value was passed (so corresponds to |\ekvdefunknownNoVal|). You can
+% access the key name with |#1|.
+% \end{function}
+%
+% \begin{function}{unknown redirect-code}
+% \begin{syntax}
+% unknown redirect-code = \marg{set-list} \prefixes2331
+% \end{syntax}
+% This uses a predefined action for |unknown code|. Instead of throwing an
+% error, it is tried to find the \key\ in each \set\ in the comma separated
+% \meta{set-list}. The first found match will be used and the remaining
+% options from the list discarded. If the \key\ isn't found in any \set\ an
+% expandable error will be thrown eventually. Internally \expkv's
+% |\ekvredirectunknown| will be used.
+% \end{function}
+%
+% \begin{function}{unknown redirect-noval}
+% \begin{syntax}
+% unknown redirect-noval = \marg{set-list} \prefixes2333
+% \end{syntax}
+% This behaves just like |unknown redirect-code| but will set up means to
+% forward keys for |unknown noval|. Internally \expkv's
+% |\ekvredirectunknownNoVal| will be used.
+% \end{function}
+%
+% \begin{function}{unknown redirect}
+% \begin{syntax}
+% unknown redirect = \marg{set-list} \prefixes2333
+% \end{syntax}
+% This is a short cut to apply both, |unknown redirect-code| and
+% |unknown redirect-noval|, as a result you might get doubled error messages,
+% one from each.
+% \end{function}
+%
+% \subsection{Bugs}
+% I don't think there are any (but every developer says that), if you find some
+% please let me know, either via the email address on the first page or on
+% GitHub:
+% \url{https://github.com/Skillmon/tex_expkv-def}
+%
+% \subsection{Example}
+% The following is an example code defining each base key-type once. Please
+% admire the very creative key-name examples.
+%
+% \begin{lstlisting}
+% \ekvdefinekeys{example}
+% {
+% long code keyA = #1
+% ,noval keyA = NoVal given
+% ,bool keyB = \keyB
+% ,boolTF keyC = \keyC
+% ,store keyD = \keyD
+% ,data keyE = \keyE
+% ,dataT keyF = \keyF
+% ,int keyG = \keyG
+% ,dimen keyH = \keyH
+% ,skip keyI = \keyI
+% ,toks keyJ = \keyJ
+% ,default keyJ = \empty test
+% ,new box keyK = \keyK
+% ,qdefault keyK = K
+% ,choice keyL =
+% {
+% protected 1 = \texttt{a}
+% ,2 = b
+% ,3 = c
+% ,4 = d
+% ,5 = e
+% }
+% ,edefault keyL = 2
+% ,meta keyM = {keyA={#1},keyB=false}
+% ,invbool keyN = \keyN
+% ,boolpair keyO = \keyOa\keyOb
+% }
+% \end{lstlisting}
+%
+% \bigskip
+% Since the |data| type might be a bit strange, here is another usage example
+% for it.
+% \begin{lstlisting}
+% \ekvdefinekeys{ex}
+% {
+% data name = \Pname
+% ,data age = \Page
+% ,dataT hobby = \Phobby
+% }
+% \newcommand\Person[1]
+% {%
+% \begingroup
+% \ekvset{ex}{#1}%
+% \begin{description}
+% \item[\Pname{}{\errmessage{A person requires a name}}]
+% \item[Age] \Page{\textit}{\errmessage{A person requires an age}}
+% \Phobby{\item[Hobbies]}
+% \end{description}
+% \endgroup
+% }
+% \Person{name=Jonathan P. Spratte, age=young, hobby=\TeX\ coding}
+% \Person{name=Some User, age=unknown, hobby=Reading Documentation}
+% \Person{name=Anybody, age=any}
+% \end{lstlisting}
+% In this example a person should have a name and an age, but doesn't have to
+% have hobbies. The name will be displayed as the description item and the age
+% in Italics. If a person has no hobbies the description item will be silently
+% left out. The result of the above code looks like this:
+%
+% \begin{exresult}{\linewidth}
+% \ekvdefinekeys{ex}
+% {
+% data name = \Pname
+% ,data age = \Page
+% ,dataT hobby = \Phobby
+% }
+% \newcommand\Person[1]
+% {%
+% \begingroup
+% \ekvset{ex}{#1}%
+% \begin{description}
+% \item[\Pname{}{\errmessage{A person requires a name}}]
+% \item[Age] \Page{\textit}{\errmessage{A person requires an age}}
+% \Phobby{\item[Hobbies]}
+% \end{description}
+% \endgroup
+% }
+% \Person{name=Jonathan P. Spratte, age=young, hobby=\TeX\ coding}
+% \Person{name=Some User, age=unknown, hobby=Reading Documentation}
+% \Person{name=Anybody, age=any}
+% \end{exresult}
+%
+% \subsection{License}
+%
+% Copyright \textcopyright\ 2020\unless\ifnum\year=2020--\the\year\fi\
+% Jonathan P. Spratte
+%
+% \medskip\noindent
+% This work may be distributed and/or modified under the conditions of the
+% \LaTeX\ Project Public License (LPPL), either version 1.3c of this license or
+% (at your option) any later version. The latest version of this license is in
+% the file:
+%
+% \url{http://www.latex-project.org/lppl.txt}
+%
+% \noindent
+% This work is ``maintained'' (as per LPPL maintenance status) by
+%
+% \mbox{Jonathan P. Spratte}.
+%
+% \end{documentation}^^A=<<
+%
+% \begin{implementation}^^A>>=
+%
+% \clearpage
+%
+% \section{Implementation}^^A>>=
+%^^A the LaTeX package >>=
+% \subsection{The \LaTeX\ Package}
+% Just like for \expkv\ we provide a small \LaTeX\ package that sets up things
+% such that we behave nicely on \LaTeX\ packages and files system. It'll
+% |\input| the generic code which implements the functionality.
+% \gobbledocstriptag
+%<*pkg>
+% \begin{macrocode}
+\RequirePackage{expkv}
+\def\ekvd@tmp
+ {%
+ \ProvidesFile{expkv-def.tex}%
+ [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]%
+ }
+\input{expkv-def.tex}
+\ProvidesPackage{expkv-def}%
+ [\ekvdDate\space v\ekvdVersion\space a key-defining frontend for expkv]
+% \end{macrocode}
+% \gobbledocstriptag
+%</pkg>
+%^^A=<<
+%^^A the ConTeXt module >>=
+% \subsection{The \ConTeXt\ module}
+% \gobbledocstriptag
+%<*ctx>
+% \begin{macrocode}
+\writestatus{loading}{ConTeXt User Module / expkv-def}
+\usemodule[expkv]
+\unprotect
+\input expkv-def.tex
+\writestatus{loading}
+ {ConTeXt User Module / expkv-def / Version \ekvdVersion\space loaded}
+\protect\endinput
+% \end{macrocode}
+% \gobbledocstriptag
+%</ctx>
+%^^A=<<
+%^^A main file >>=
+% \subsection{The Generic Code}
+% The rest of this implementation will be the generic code.
+% \gobbledocstriptag
+%<*tex>
+%
+% Load \expkv\ if the package didn't already do so -- since \expkv\ has
+% safeguards against being loaded twice this does no harm and the overhead
+% isn't that big. Also we reuse some of the internals of \expkv\ to save us from
+% retyping them.
+% \begin{macrocode}
+\input expkv
+% \end{macrocode}
+%
+% We make sure that \file{expkv-def.tex} is only input once:
+% \begin{macrocode}
+\expandafter\ifx\csname ekvdVersion\endcsname\relax
+\else
+ \expandafter\endinput
+\fi
+% \end{macrocode}
+%
+% \begin{macro}{\ekvdVersion,\ekvdDate}
+% We're on our first input, so lets store the version and date in a macro.
+% \begin{macrocode}
+\def\ekvdVersion{0.9}
+\def\ekvdDate{2022-01-29}
+% \end{macrocode}
+% \end{macro}
+%
+% If the \LaTeX\ format is loaded we want to be a good file and report back who
+% we are, for this the package will have defined |\ekvd@tmp| to use
+% |\ProvidesFile|, else this will expand to a |\relax| and do no harm.
+% \begin{macrocode}
+\csname ekvd@tmp\endcsname
+% \end{macrocode}
+%
+% Store the category code of |@| to later be able to reset it and change it to
+% 11 for now.
+% \begin{macrocode}
+\expandafter\chardef\csname ekvd@tmp\endcsname=\catcode`\@
+\catcode`\@=11
+% \end{macrocode}
+% |\ekvd@tmp| will be reused later to handle expansion during the key
+% defining. But we don't need it to ever store information long-term after
+% \expkvd\ was initialized.
+%
+% \begin{macro}[internal]{\ekvd@ifprimitive}
+% \begin{macrocode}
+\protected\long\def\ekvd@ifprimitive#1%
+ {%
+ \begingroup
+ \edef\ekvd@tmpa{\string #1}%
+ \edef\ekvd@tmpb{\meaning#1}%
+ \expandafter
+ \endgroup
+ \ifx\ekvd@tmpa\ekvd@tmpb
+ \ekv@fi@firstoftwo
+ \fi
+ \@secondoftwo
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@long,\ekvd@prot,\ekvd@clear@prefixes,\ekvd@ifalso}
+% \expkvd\ will use |\ekvd@long|, |\ekvd@prot|, and |\ekvd@ifalso| to store
+% whether a key should be defined as |\long| or |\protected| or adds an action
+% to an existing key, and we have to clear them for every new key. By default
+% |long| and |protected| will just be empty, |ifalso| will be
+% |\@secondoftwo|, and |ifnew| will just use its third argument.
+% \begin{macrocode}
+\protected\def\ekvd@clear@prefixes
+ {%
+ \let\ekvd@long\ekv@empty
+ \let\ekvd@prot\ekv@empty
+ \let\ekvd@ifalso\@secondoftwo
+ \long\def\ekvd@ifnew##1##2##3{##3}%
+ }
+\ekvd@clear@prefixes
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\ekvdefinekeys}
+% This is the one front-facing macro which provides the interface to define
+% keys. It's using |\ekvparse| to handle the \kv\ list, the interpretation will
+% be done by |\ekvd@noarg| and |\ekvd@|. The \set\ for which the keys should be
+% defined is stored in |\ekvd@set|.
+% \begin{macrocode}
+\protected\def\ekvdefinekeys#1%
+ {%
+ \def\ekvd@set{#1}%
+ \ekvparse\ekvd@noarg\ekvd@arg
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@noarg,\ekvd@arg,\ekvd@handle}
+% |\ekvd@noarg| and |\ekvd@arg| store whether there was a value in the \kv\
+% pair. |\ekvd@handle| has to test whether there is a space inside the key and
+% if so calls the prefix grabbing routine, else we throw an error and ignore the
+% key.
+% \begin{macrocode}
+\protected\long\def\ekvd@noarg#1%
+ {%
+ \let\ekvd@ifnoarg\@firstoftwo
+ \expandafter\ekvd@handle\detokenize{#1}\ekvd@stop{}%
+ }
+\protected\long\def\ekvd@arg#1%
+ {%
+ \let\ekvd@ifnoarg\@secondoftwo
+ \expandafter\ekvd@handle\detokenize{#1}\ekvd@stop
+ }
+\protected\long\def\ekvd@handle#1\ekvd@stop#2%
+ {%
+ \ekvd@clear@prefixes
+ \def\ekvd@cur{#1}%
+ \ekvd@ifspace{#1}%
+ {\ekvd@prefix\ekv@mark#1\ekv@stop{#2}}%
+ \ekvd@err@missing@type
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@prefix,\ekvd@prefix@}
+% \expkvd\ separates prefixes into two groups, the first being prefixes in the
+% \TeX\ sense (|long| and |protected|) which use |@p@| in their name, the other
+% being key-types (|code|, |int|, \emph{etc.}) which use |@t@| instead.
+% |\ekvd@prefix| splits at the first space and checks whether its a |@p@|
+% or |@t@| type prefix. If it is neither throw an error and gobble the
+% definition (the value).
+% \begin{macrocode}
+\protected\def\ekvd@prefix#1 {\ekv@strip{#1}\ekvd@prefix@\ekv@mark}
+\protected\def\ekvd@prefix@#1#2\ekv@stop
+ {%
+ \ekv@ifdefined{ekvd@t@#1}%
+ {\ekv@strip{#2}{\csname ekvd@t@#1\endcsname}}%
+ {%
+ \ekv@ifdefined{ekvd@p@#1}%
+ {\csname ekvd@p@#1\endcsname\ekvd@prefix@after@p{#2}}%
+ {\ekvd@err@undefined@prefix{#1}\@gobble}%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@prefix@after@p}
+% The |@p@| type prefixes are all just modifying a following |@t@| type, so they
+% will need to search for another prefix. This is true for all of them, so we
+% use a macro to handle this. It'll throw an error if there is no other prefix.
+% \begin{macrocode}
+\protected\def\ekvd@prefix@after@p#1%
+ {%
+ \ekvd@ifspace{#1}%
+ {\ekvd@prefix#1\ekv@stop}%
+ {\ekvd@err@missing@type\@gobble}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@p@long,\ekvd@p@protected,\ekvd@p@protect,\ekvd@p@also,\ekvd@p@new}
+% Define the |@p@| type prefixes, they all just store some information in a
+% temporary macro.
+% \begin{macrocode}
+\protected\def\ekvd@p@long{\let\ekvd@long\long}
+\protected\def\ekvd@p@protected{\let\ekvd@prot\protected}
+\let\ekvd@p@protect\ekvd@p@protected
+\protected\def\ekvd@p@also{\let\ekvd@ifalso\@firstoftwo}
+\protected\def\ekvd@p@new{\let\ekvd@ifnew\ekvd@assert@new}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Key Types}
+%
+% \begin{macro}[internal]{\ekvd@type@set,\ekvd@t@set}
+% The |set| type is quite straight forward, just define a |NoVal| key to call
+% |\ekvchangeset|.
+% \begin{macrocode}
+\protected\def\ekvd@type@set#1#2%
+ {%
+ \ekvd@assert@not@long
+ \ekvd@assert@not@protected
+ \ekvd@ifnew{NoVal}{#1}%
+ {%
+ \ekv@ifempty{#2}%
+ {\ekvd@err@missing@definition}%
+ {%
+ \ekvd@ifalso
+ {%
+ \ekv@expargtwice{\ekvd@add@noval{#1}}%
+ {\ekvchangeset{#2}}%
+ \ekvd@assert@not@protected@also
+ }%
+ {\ekv@expargtwice{\ekvdefNoVal\ekvd@set{#1}}{\ekvchangeset{#2}}}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@set#1#2%
+ {%
+ \ekvd@ifnoarg
+ {\ekvd@type@set{#1}{#1}}%
+ {\ekvd@type@set{#1}{#2}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@noval,\ekvd@t@noval,\ekvd@t@enoval}
+% Another pretty simple type, |noval| just needs to assert that there is a
+% definition and that |long| wasn't specified.
+% There are types where the difference in the variants is so small, that we
+% define a common handler for them, those common handlers are named with
+% |@type@|. |noval| and |enoval| are so similar that we can use such a |@type@|
+% macro, even if we could've done |noval| in a slightly faster way without it.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@noval#1#2#3%
+ {%
+ \ekvd@ifnew{NoVal}{#2}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@long
+ \ekvd@prot#1\ekvd@tmp{#3}%
+ \ekvd@ifalso
+ {\ekv@exparg{\ekvd@add@noval{#2}}\ekvd@tmp{}}%
+ {\ekvletNoVal\ekvd@set{#2}\ekvd@tmp}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@noval{\ekvd@type@noval\def}
+\protected\def\ekvd@t@enoval{\ekvd@type@noval\edef}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@code,\ekvd@t@code,\ekvd@t@ecode}
+% |code| is simple as well, |ecode| has to use |\edef| on a temporary macro,
+% since \expkv\ doesn't provide an |\ekvedef|.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@code#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@prot\ekvd@long#1\ekvd@tmp##1{#3}%
+ \ekvd@ifalso
+ {\ekv@exparg{\ekvd@add@val{#2}}{\ekvd@tmp{##1}}{}}%
+ {\ekvlet\ekvd@set{#2}\ekvd@tmp}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@code{\ekvd@type@code\def}
+\protected\def\ekvd@t@ecode{\ekvd@type@code\edef}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@default,\ekvd@t@default,\ekvd@t@qdefault,\ekvd@t@odefault,
+% \ekvd@t@fdefault
+% }
+% |\ekvd@type@default| asserts there was an argument, also the key for which one
+% wants to set a default has to be already defined (this is not so important for
+% |default|, but |qdefault| requires is). If everything is good, |\edef| a
+% temporary macro that expands |\ekvd@set| and the |\csname| for the key, and in
+% the case of |qdefault| does the first expansion step of the key-macro.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@default#1#2#3#4%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvifdefined\ekvd@set{#3}%
+ {%
+ \ekvd@assert@not@new
+ \ekvd@assert@not@long
+ \ekvd@prot\edef\ekvd@tmp
+ {%
+ \ekv@unexpanded\expandafter#1%
+ {#2\csname\ekv@name\ekvd@set{#3}\endcsname{#4}}%
+ }%
+ \ekvd@ifalso
+ {\ekv@exparg{\ekvd@add@noval{#3}}\ekvd@tmp{}}%
+ {\ekvletNoVal\ekvd@set{#3}\ekvd@tmp}%
+ }%
+ {\ekvd@err@undefined@key{#3}}%
+ }%
+ }
+\protected\def\ekvd@t@default{\ekvd@type@default{}{}}
+\protected\def\ekvd@t@qdefault{\ekvd@type@default{\expandafter\expandafter}{}}
+\let\ekvd@t@odefault\ekvd@t@qdefault
+\protected\def\ekvd@t@fdefault{\ekvd@type@default{}{\romannumeral`\^^@}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@t@edefault}
+% |edefault| is too different from |default| and |qdefault| to reuse the
+% |@type@| macro, as it doesn't need |\unexpanded| inside of |\edef|.
+% \begin{macrocode}
+\protected\long\def\ekvd@t@edefault#1#2%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvifdefined\ekvd@set{#1}%
+ {%
+ \ekvd@assert@not@new
+ \ekvd@assert@not@long
+ \ekvd@prot\edef\ekvd@tmp
+ {\csname\ekv@name\ekvd@set{#1}\endcsname{#2}}%
+ \ekvd@ifalso
+ {\ekv@exparg{\ekvd@add@noval{#1}}\ekvd@tmp{}}%
+ {\ekvletNoVal\ekvd@set{#1}\ekvd@tmp}%
+ }%
+ {\ekvd@err@undefined@key{#1}}%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@t@initial,\ekvd@t@oinitial,\ekvd@t@finitial,\ekvd@t@einitial}
+% \begin{macrocode}
+\long\def\ekvd@type@initial#1#2#3#4%
+ {%
+ \ekvd@assert@not@new
+ \ekvd@assert@not@also
+ \ekvd@assert@not@long
+ \ekvd@assert@not@protected
+ \ekvd@ifnoarg
+ {%
+ \ekvifdefinedNoVal\ekvd@set{#3}%
+ {\csname\ekv@name\ekvd@set{#3}N\endcsname}%
+ {\ekvd@err@undefined@noval{#3}}%
+ }%
+ {%
+ \ekvifdefined\ekvd@set{#3}%
+ {%
+ #1{#2#4}%
+ \csname\ekv@name\ekvd@set{#3}\expandafter\endcsname\expandafter
+ {\ekvd@tmp}%
+ }%
+ {\ekvd@err@undefined@key{#3}}%
+ }%
+ }
+\def\ekvd@t@initial{\ekvd@type@initial{\def\ekvd@tmp}{}}
+\def\ekvd@t@oinitial{\ekvd@type@initial{\ekv@exparg{\def\ekvd@tmp}}{}}
+\def\ekvd@t@einitial{\ekvd@type@initial{\edef\ekvd@tmp}{}}
+\def\ekvd@t@finitial
+ {\ekvd@type@initial{\ekv@exparg{\def\ekvd@tmp}}{\romannumeral`\^^@}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@bool,\ekvd@t@bool,\ekvd@t@gbool,\ekvd@t@boolTF,\ekvd@t@gboolTF,
+% \ekvd@t@invbool,\ekvd@t@ginvbool,\ekvd@t@invboolTF,\ekvd@t@ginvboolTF,
+% }
+% The boolean types are a quicker version of a |choice| that accept |true| and
+% |false|, and set up the |NoVal| action to be identical to \texttt{\key=true}.
+% The |true| and |false| actions are always just |\let|ting the macro in |#7| to
+% some other macro (\emph{e.g.}, \cs[no-index]{iftrue}).
+% \begin{macrocode}
+\protected\def\ekvd@type@bool#1#2#3#4#5%
+ {%
+ \ekvd@ifnew{}{#4}%
+ {%
+ \ekvd@ifnew{NoVal}{#4}%
+ {%
+ \ekvd@assert@filledarg{#5}%
+ {%
+ \ekvd@newlet#5#3%
+ \ekvd@type@choice{#4}%
+ \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2}%
+ \protected\expandafter\def
+ \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname
+ {#1\let#5#2}%
+ \protected\expandafter\def
+ \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname
+ {#1\let#5#3}%
+ }%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@bool{\ekvd@type@bool{}\iftrue\iffalse}
+\protected\def\ekvd@t@gbool{\ekvd@type@bool\global\iftrue\iffalse}
+\protected\def\ekvd@t@boolTF{\ekvd@type@bool{}\@firstoftwo\@secondoftwo}
+\protected\def\ekvd@t@gboolTF{\ekvd@type@bool\global\@firstoftwo\@secondoftwo}
+\protected\def\ekvd@t@invbool{\ekvd@type@bool{}\iffalse\iftrue}
+\protected\def\ekvd@t@ginvbool{\ekvd@type@bool\global\iffalse\iftrue}
+\protected\def\ekvd@t@invboolTF{\ekvd@type@bool{}\@secondoftwo\@firstoftwo}
+\protected\def\ekvd@t@ginvboolTF
+ {\ekvd@type@bool\global\@secondoftwo\@firstoftwo}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@boolpair,
+% \ekvd@t@boolpair,\ekvd@t@gboolpair,\ekvd@t@boolpairTF,\ekvd@t@gboolpairTF
+% }
+% The boolean pair types are essentially the same as the boolean types, but set
+% two macros instead of one.
+% \begin{macrocode}
+\protected\def\ekvd@type@boolpair#1#2#3#4#5#6%
+ {%
+ \ekvd@ifnew{}{#4}%
+ {%
+ \ekvd@ifnew{NoVal}{#4}%
+ {%
+ \ekvd@newlet#5#3%
+ \ekvd@newlet#6#2%
+ \ekvd@type@choice{#4}%
+ \protected\ekvdefNoVal\ekvd@set{#4}{#1\let#5#2#1\let#6#3}%
+ \protected\expandafter\def
+ \csname\ekvd@choice@name\ekvd@set{#4}{true}\endcsname
+ {#1\let#5#2#1\let#6#3}%
+ \protected\expandafter\def
+ \csname\ekvd@choice@name\ekvd@set{#4}{false}\endcsname
+ {#1\let#5#3#1\let#6#2}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@boolpair#1#2%
+ {\ekvd@assert@twoargs{#2}{\ekvd@type@boolpair{}\iftrue\iffalse{#1}#2}}
+\protected\def\ekvd@t@gboolpair#1#2%
+ {\ekvd@assert@twoargs{#2}{\ekvd@type@boolpair\global\iftrue\iffalse{#1}#2}}
+\protected\def\ekvd@t@boolpairTF#1#2%
+ {%
+ \ekvd@assert@twoargs{#2}%
+ {\ekvd@type@boolpair{}\@firstoftwo\@secondoftwo{#1}#2}%
+ }
+\protected\def\ekvd@t@gboolpairTF#1#2%
+ {%
+ \ekvd@assert@twoargs{#2}%
+ {\ekvd@type@boolpair\global\@firstoftwo\@secondoftwo{#1}#2}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@data,\ekvd@t@data,\ekvd@t@gdata,\ekvd@t@dataT,\ekvd@t@gdataT
+% }
+% \begin{macrocode}
+\protected\def\ekvd@type@data#1#2#3#4#5#6%
+ {%
+ \ekvd@ifnew{}{#5}%
+ {%
+ \ekvd@assert@filledarg{#6}%
+ {%
+ \ekvd@newlet#6#1%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#5}{\long#2#6####1#3{####1{#4}}}{}%
+ }%
+ {%
+ \protected\ekvd@long\ekvdef\ekvd@set{#5}%
+ {\long#2#6####1#3{####1{#4}}}%
+ }%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@data
+ {\ekvd@type@data\@secondoftwo\edef{####2}{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@edata{\ekvd@type@data\@secondoftwo\edef{####2}{##1}}
+\protected\def\ekvd@t@gdata
+ {\ekvd@type@data\@secondoftwo\xdef{####2}{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@xdata{\ekvd@type@data\@secondoftwo\xdef{####2}{##1}}
+\protected\def\ekvd@t@dataT
+ {\ekvd@type@data\@gobble\edef{}{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@edataT{\ekvd@type@data\@gobble\edef{}{##1}}
+\protected\def\ekvd@t@gdataT
+ {\ekvd@type@data\@gobble\xdef{}{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@xdataT{\ekvd@type@data\@gobble\xdef{}{##1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@box,\ekvd@t@box,\ekvd@t@gbox}
+% Set up our boxes. Though we're a generic package we want to be colour safe, so
+% we put an additional grouping level inside the box contents, for the case that
+% someone uses \pkg{color}. |\ekvd@newreg| is a small wrapper which tests
+% whether the first argument is defined and if not does
+% |\csname new#2\endcsname#1|.
+% \begin{macrocode}
+\protected\def\ekvd@type@box#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@filledarg{#3}%
+ {%
+ \ekvd@newreg#3{box}%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#2}{#1\setbox#3=\hbox{\begingroup##1\endgroup}}{}%
+ }%
+ {%
+ \protected\ekvd@long\ekvdef\ekvd@set{#2}%
+ {#1\setbox#3=\hbox{\begingroup##1\endgroup}}%
+ }%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@box{\ekvd@type@box{}}
+\protected\def\ekvd@t@gbox{\ekvd@type@box\global}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@toks,\ekvd@t@toks,\ekvd@t@gtoks}
+% Similar to |box|, but set the |toks|.
+% \begin{macrocode}
+\protected\def\ekvd@type@toks#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@filledarg{#3}%
+ {%
+ \ekvd@newreg#3{toks}%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#2}{#1#3={##1}}{}%
+ }%
+ {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3={##1}}}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@toks{\ekvd@type@toks{}}
+\protected\def\ekvd@t@gtoks{\ekvd@type@toks\global}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@preapptoks,\ekvd@t@apptoks,\ekvd@t@gapptoks}
+% Just like |toks|, but expand the current contents of the |toks| register to
+% append the new contents.
+% \begin{macrocode}
+\ekvd@ifprimitive\toksapp
+ {%
+ \protected\def\ekvd@type@preapptoks#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@filledarg{#3}%
+ {%
+ \ekvd@newreg#3{toks}%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#2}{#1#3{##1}}{}%
+ }%
+ {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3{##1}}}%
+ }%
+ }%
+ }
+ \protected\def\ekvd@t@apptoks{\ekvd@type@preapptoks\toksapp}
+ \protected\def\ekvd@t@gapptoks{\ekvd@type@preapptoks\gtoksapp}
+ \protected\def\ekvd@t@pretoks{\ekvd@type@preapptoks\tokspre}
+ \protected\def\ekvd@t@gpretoks{\ekvd@type@preapptoks\gtokspre}
+ }
+ {%
+ \protected\def\ekvd@type@apptoks#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@filledarg{#3}%
+ {%
+ \ekvd@newreg#3{toks}%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#2}{#1#3=\expandafter{\the#3##1}}{}%
+ }%
+ {%
+ \protected\ekvd@long\ekvdef\ekvd@set{#2}%
+ {#1#3=\expandafter{\the#3##1}}%
+ }%
+ }%
+ }%
+ }
+ \protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}}
+ \protected\def\ekvd@t@gapptoks{\ekvd@type@apptoks\global}
+ \newtoks\ekvd@toks
+ \protected\def\ekvd@type@pretoks#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@filledarg{#3}%
+ {%
+ \ekvd@newreg#3{toks}%
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#2}%
+ {%
+ \ekvd@toks={##1}%
+ #1#3=\expandafter{\the\expandafter\ekvd@toks\the#3}%
+ }%
+ {}%
+ }%
+ {%
+ \protected\ekvd@long\ekvdef\ekvd@set{#2}%
+ {%
+ \ekvd@toks={##1}%
+ #1#3=\expandafter{\the\expandafter\ekvd@toks\the#3}%
+ }%
+ }%
+ }%
+ }%
+ }
+ \protected\def\ekvd@t@pretoks{\ekvd@type@pretoks{}}
+ \protected\def\ekvd@t@gpretoks{\ekvd@type@pretoks\global}
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@reg,\ekvd@t@int,\ekvd@t@eint,\ekvd@t@gint,\ekvd@t@xint,
+% \ekvd@t@dimen,\ekvd@t@edimen,\ekvd@t@gdimen,\ekvd@t@xdimen,
+% \ekvd@t@skip,\ekvd@t@eskip,\ekvd@t@gskip,\ekvd@t@xskip
+% }
+% The |\ekvd@type@reg| can handle all the types for which the assignment will
+% just be \texttt{\meta{register}=\meta{value}}.
+% \begin{macrocode}
+\protected\def\ekvd@type@reg#1#2#3#4#5#6%
+ {%
+ \ekvd@ifnew{}{#5}%
+ {%
+ \ekvd@assert@filledarg{#6}%
+ {%
+ \ekvd@newreg#6{#1}%
+ \ekvd@ifalso
+ {%
+ \let\evkd@prot\protected
+ \ekvd@add@val{#5}{#2#6=#3##1#4\relax}{}%
+ }%
+ {\protected\ekvd@long\ekvdef\ekvd@set{#5}{#2#6=#3##1#4\relax}}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@int{\ekvd@type@reg{count}{}{}{}}
+\protected\def\ekvd@t@eint{\ekvd@type@reg{count}{}\numexpr\relax}
+\protected\def\ekvd@t@gint{\ekvd@type@reg{count}\global{}{}}
+\protected\def\ekvd@t@xint{\ekvd@type@reg{count}\global\numexpr\relax}
+\protected\def\ekvd@t@dimen{\ekvd@type@reg{dimen}{}{}{}}
+\protected\def\ekvd@t@edimen{\ekvd@type@reg{dimen}{}\dimexpr\relax}
+\protected\def\ekvd@t@gdimen{\ekvd@type@reg{dimen}\global{}{}}
+\protected\def\ekvd@t@xdimen{\ekvd@type@reg{dimen}\global\dimexpr\relax}
+\protected\def\ekvd@t@skip{\ekvd@type@reg{skip}{}{}{}}
+\protected\def\ekvd@t@eskip{\ekvd@type@reg{skip}{}\glueexpr\relax}
+\protected\def\ekvd@t@gskip{\ekvd@type@reg{skip}\global{}{}}
+\protected\def\ekvd@t@xskip{\ekvd@type@reg{skip}\global\glueexpr\relax}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@type@store,\ekvd@t@store,\ekvd@t@gstore}
+% The none-expanding |store| types use an |\edef| or |\xdef| and |\unexpanded|
+% to be able to also store |#| easily.
+% \begin{macrocode}
+\protected\def\ekvd@type@store#1#2#3#4%
+ {%
+ \ekvd@ifnew{}{#3}%
+ {%
+ \ekvd@assert@filledarg{#4}%
+ {%
+ \ekvd@newlet#4\ekv@empty
+ \ekvd@ifalso
+ {%
+ \let\ekvd@prot\protected
+ \ekvd@add@val{#3}{#1#4{#2}}{}%
+ }%
+ {\protected\ekvd@long\ekvdef\ekvd@set{#3}{#1#4{#2}}}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@store{\ekvd@type@store\edef{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@gstore{\ekvd@type@store\xdef{\ekv@unexpanded{##1}}}
+\protected\def\ekvd@t@estore{\ekvd@type@store\edef{##1}}
+\protected\def\ekvd@t@xstore{\ekvd@type@store\xdef{##1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@meta,\ekvd@type@meta@a,\ekvd@type@meta@b,\ekvd@type@meta@c,
+% \ekvd@t@meta,\ekvd@t@nmeta
+% }
+% |meta| sets up things such that another instance of |\ekvset| will be run on
+% the argument, with the same \set.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@meta#1#2#3#4#5#6#7%
+ {%
+ \ekvd@ifnew{#1}{#6}%
+ {%
+ \ekvd@assert@filledarg{#7}%
+ {%
+ \edef\ekvd@tmp{\ekvd@set}%
+ \expandafter\ekvd@type@meta@a\expandafter{\ekvd@tmp}{#7}{#2}%
+ \ekvd@ifalso
+ {\ekv@exparg{#3{#6}}{\ekvd@tmp#4}{#5}}%
+ {\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}%
+ }%
+ }%
+ }
+\protected\long\def\ekvd@type@meta@a#1#2%
+ {%
+ \expandafter\ekvd@type@meta@b\expandafter{\ekvset{#1}{#2}}%
+ }
+\protected\def\ekvd@type@meta@b
+ {%
+ \expandafter\ekvd@type@meta@c\expandafter
+ }
+\protected\long\def\ekvd@type@meta@c#1#2%
+ {%
+ \ekvd@prot\ekvd@long\def\ekvd@tmp#2{#1}%
+ }
+\protected\def\ekvd@t@meta{\ekvd@type@meta{}{##1}\ekvd@add@val{{##1}}{}}
+\protected\def\ekvd@t@nmeta
+ {%
+ \ekvd@assert@not@long
+ \ekvd@type@meta{NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@type@smeta,\ekvd@type@smeta@,\ekvd@t@smeta,\ekvd@t@snmeta}
+% |smeta| is pretty similar to |meta|, but needs two arguments inside of \val,
+% such that the first is the \set\ for which the sub-|\ekvset| and the second is
+% the \kv\ list.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@smeta#1#2#3#4#5#6#7%
+ {%
+ \ekvd@ifnew{#1}{#6}%
+ {%
+ \ekvd@assert@twoargs{#7}%
+ {%
+ \ekvd@type@meta@a#7{#2}%
+ \ekvd@ifalso
+ {\ekv@exparg{#3{#6}}{\ekvd@tmp#4}{#5}}%
+ {\csname ekvlet#1\endcsname\ekvd@set{#6}\ekvd@tmp}%
+ }%
+ }%
+ }
+\protected\def\ekvd@t@smeta{\ekvd@type@smeta{}{##1}\ekvd@add@val{{##1}}{}}
+\protected\def\ekvd@t@snmeta
+ {%
+ \ekvd@assert@not@long
+ \ekvd@type@smeta{NoVal}{}\ekvd@add@noval{}\ekvd@assert@not@long@also
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@choice,
+% \ekvd@populate@choice,\ekvd@populate@choice@,\ekvd@populate@choice@noarg,
+% \ekvd@choice@prefix,\ekvd@choice@prefix@,\ekvd@choice@prefix@done,
+% \ekvd@choice@p@protected,\ekvd@choice@p@protect,
+% \ekvd@choice@p@long,\ekvd@choice@p@long@,
+% \ekvd@t@choice
+% }
+% The |choice| type is by far the most complex type, as we have to run a
+% sub-parser on the choice-definition list, which should support the |@p@| type
+% prefixes as well (but |long| will always throw an error, as they are not
+% allowed to be long). |\ekvd@type@choice| will just define the choice-key, the
+% handling of the choices definition will be done by |\ekvd@populate@choice|.
+% \begin{macrocode}
+\protected\def\ekvd@type@choice#1%
+ {%
+ \ekvd@assert@not@long
+ \ekv@expargtwice{\ekvd@prot\def\ekvd@tmp##1}%
+ {%
+ \expandafter\expandafter\expandafter
+ \ekvd@h@choice
+ \expandafter\expandafter\expandafter
+ {\expandafter\ekvd@choice@name\expandafter{\ekvd@set}{#1}{##1}}%
+ }%
+ \ekvd@ifalso
+ {%
+ \ekvd@assert@val{#1}%
+ {%
+ \ekvd@if@not@already@choice{#1}%
+ {%
+ \ekv@exparg
+ {%
+ \expandafter\ekvd@add@aux
+ \csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}{#1}%
+ }%
+ {\ekvd@tmp{##1}}%
+ {\ekvd@long\ekvdef}\ekvd@assert@not@long@also
+ }%
+ }%
+ }%
+ {\ekvlet\ekvd@set{#1}\ekvd@tmp}%
+ }
+% \end{macrocode}
+% |\ekvd@populate@choice| just uses |\ekvparse| and then gives control to
+% |\ekvd@populate@choice@noarg|, which throws an error, and
+% |\ekvd@populate@choice@|.
+% \begin{macrocode}
+\protected\def\ekvd@populate@choice
+ {%
+ \ekvparse\ekvd@populate@choice@noarg\ekvd@populate@choice@
+ }
+\protected\long\def\ekvd@populate@choice@noarg#1%
+ {%
+ \expandafter\ekvd@err@missing@definition@msg\expandafter{\ekvd@cur : #1}%
+ }
+% \end{macrocode}
+% |\ekvd@populate@choice@| runs the prefix-test, if there is none we can
+% directly define the choice, for that |\ekvd@set@choice| will expand to the
+% current choice-key's name, which will have been defined by |\ekvd@t@choice|.
+% If there is a prefix run the prefix grabbing routine, which was altered for
+% |@type@choice|.
+% \begin{macrocode}
+\protected\long\def\ekvd@populate@choice@#1#2%
+ {%
+ \ekvd@clear@prefixes
+ \ekvd@ifspace{#1}%
+ {\ekvd@choice@prefix{\ekv@mark#1}\ekv@mark#1\ekv@stop}%
+ {%
+ \expandafter\edef
+ \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#1}\endcsname
+ }%
+ {\unexpanded{#2}}%
+ }
+\protected\def\ekvd@choice@prefix#1#2
+ {%
+ \ekv@strip{#2}{\ekvd@choice@prefix@{#1}}\ekv@mark
+ }
+\protected\def\ekvd@choice@prefix@#1#2#3\ekv@stop
+ {%
+ \ekv@ifdefined{ekvd@choice@p@#2}%
+ {%
+ \csname ekvd@choice@p@#2\endcsname
+ \ekvd@ifspace{#3}%
+ {\ekvd@choice@prefix{#3}#3\ekv@stop}%
+ {\ekvd@choice@prefix@done{#3}}%
+ }%
+ {\ekvd@choice@prefix@done{#1}}%
+ }
+\protected\def\ekvd@choice@prefix@done#1%
+ {%
+ \ekvd@prot\expandafter\edef
+ \csname
+ \ekv@strip{#1}{\ekvd@choice@name\ekvd@set\ekvd@set@choice}%
+ \endcsname
+ }
+\protected\def\ekvd@choice@p@protected{\let\ekvd@prot\protected}
+\let\ekvd@choice@p@protect\ekvd@choice@p@protected
+\protected\def\ekvd@choice@invalid@p#1\ekvd@ifspace#2%
+ {%
+ \expandafter\ekvd@choice@invalid@p@\expandafter{\ekv@gobble@mark#2}{#1}%
+ \ekvd@ifspace{#2}%
+ }
+\protected\def\ekvd@choice@invalid@p@#1#2%
+ {%
+ \expandafter\ekvd@err@no@prefix@msg\expandafter{\ekvd@cur : #2 #1}{#2}%
+ }
+\protected\def\ekvd@choice@p@long{\ekvd@choice@invalid@p{long}}%
+\protected\def\ekvd@choice@p@also{\ekvd@choice@invalid@p{also}}%
+\protected\def\ekvd@choice@p@new{\ekvd@choice@invalid@p{new}}%
+% \end{macrocode}
+% Finally we're able to set up the |@t@choice| macro, which has to store the
+% current choice-key's name, define the key, and parse the available choices.
+% \begin{macrocode}
+\protected\long\def\ekvd@t@choice#1#2%
+ {%
+ \ekvd@ifnew{}{#1}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@type@choice{#1}%
+ \def\ekvd@set@choice{#1}%
+ \ekvd@populate@choice{#2}%
+ }%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@t@choice-store,\ekvd@t@choice-enum}
+% These two types define a special kind of |choice| key and are quite similar,
+% the only difference is what the different choices do (hence they use a
+% shared initialisation which differs in the chosen |populate| step).
+% \begin{macrocode}
+\protected\long\expandafter\def\csname ekvd@t@choice-store\endcsname
+ {\ekvd@type@choicespecial\ekvd@populate@choicestore}
+\protected\long\expandafter\def\csname ekvd@t@choice-enum\endcsname
+ {\ekvd@type@choicespecial\ekvd@populate@choiceenum}
+% \end{macrocode}
+% \begin{macro}[internal]{\ekvd@type@choicespecial}
+% Initialise similar to a |choice| key. The difference is that we require two
+% arguments (which we assert), a macro to store things in, and a |csv|-list
+% containing the allowed values. |#1| is the |populate| macro according to the
+% type used.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@choicespecial#1#2#3%
+ {%
+ \ekvd@ifnew{}{#2}%
+ {%
+ \ekvd@assert@twoargs{#3}%
+ {%
+ \ekvd@type@choice{#2}%
+ \def\ekvd@set@choice{#2}%
+ #1#3%
+ }%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+% {\ekvd@populate@choicestore,\ekvd@populate@choicestore@}
+% We initialise the storing macro if it doesn't yet exist, and then we loop
+% over the value list. The |\edef|s with |\unexpanded| are both necessary to
+% be able to store macro parameter tokens (the outer protects at define time,
+% the inner at use time).
+% \begin{macrocode}
+\protected\long\def\ekvd@populate@choicestore#1%
+ {%
+ \ekvd@newlet#1\ekv@empty
+ \ekvcsvloop{\ekvd@populate@choicestore@#1}%
+ }
+\protected\long\def\ekvd@populate@choicestore@#1#2%
+ {%
+ \protected\expandafter\edef
+ \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#2}\endcsname
+ {\unexpanded{\edef#1{\unexpanded{#2}}}}%
+ }
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}[internal]
+% {\ekvd@populate@choiceenum,\ekvd@populate@choiceenum@}
+% This is similar to the population of a |choice-store| type, but instead of
+% storing the values in a macro this initialises a count and stores the
+% position of the value in the list inside that count (zero-indexed). The
+% space is necessary to terminate the number scanning, which is the reason we
+% use |\@firstofone| (so that the space after the macro name isn't gobbled by
+% \TeX).
+% \begin{macrocode}
+\protected\long\def\ekvd@populate@choiceenum#1%
+ {%
+ \ekvd@newreg#1{count}%
+ \def\ekvd@tmp{0}%
+ \ekvcsvloop{\ekvd@populate@choiceenum@#1}%
+ }
+\protected\long\def\ekvd@populate@choiceenum@#1#2%
+ {%
+ \protected\expandafter\edef
+ \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#2}\endcsname
+ {#1=\@firstofone{\ekvd@tmp} }%
+ \edef\ekvd@tmp{\the\numexpr\ekvd@tmp+1\relax}%
+ }
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@t@unknown-choice}
+% \begin{macrocode}
+\protected\long\expandafter\def\csname ekvd@t@unknown-choice\endcsname#1#2%
+ {%
+ \ekvd@assert@new@for@name{\ekvd@unknown@choice@name\ekvd@set{#1}}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@long
+ \ekvd@assert@not@also
+ \ekvd@prot\expandafter
+ \def\csname\ekvd@unknown@choice@name\ekvd@set{#1}\endcsname##1{#2}%
+ }%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@t@unknown,\ekvd@type@unknown@code,\ekvd@type@unknown@noval}
+% The |unknown| type has different subtypes which would be the key names for
+% other types. It is first checked whether that subtype is defined, if it
+% isn't throw an error, else use that subtype.
+% \begin{macrocode}
+\protected\long\def\ekvd@t@unknown#1#2%
+ {%
+ \ekv@ifdefined{ekvd@type@unknown@\detokenize{#1}}%
+ {\csname ekvd@type@unknown@\detokenize{#1}\endcsname{#2}}%
+ \ekvd@err@misused@unknown
+ }
+% \end{macrocode}
+% The |unknown noval| type can use |\ekvdefunknownNoVal| directly (after
+% asserting some prefixes).
+% \begin{macrocode}
+\protected\long\def\ekvd@type@unknown@noval#1%
+ {%
+ \ekvd@assert@new@for@name{\ekv@name\ekvd@set{}uN}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@also
+ \ekvd@assert@not@long
+ \ekvd@prot\ekvdefunknownNoVal\ekvd@set{#1}%
+ }%
+ }%
+ }
+% \end{macrocode}
+% The |unknown code| type uses some trickery during the definition in order to
+% swap out |#1| and |#2| in the user supplied definition. This is done via a
+% temporary macro that stores the definition but gets the parameter numbers
+% reversed while the real definition is done.
+% \begin{macrocode}
+\protected\long\def\ekvd@type@unknown@code#1%
+ {%
+ \ekvd@assert@new@for@name{\ekv@name\ekvd@set{}u}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@also
+ \begingroup
+ \def\ekvd@tmp##1##2{#1}%
+ \ekv@exparg
+ {%
+ \endgroup
+ \ekvd@prot\ekvd@long\ekvdefunknown\ekvd@set
+ }%
+ {\ekvd@tmp{##2}{##1}}%
+ }%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@type@unknown@redirect,
+% \ekvd@type@unknown@redirect-code,
+% \ekvd@type@unknown@redirect-noval
+% }
+% The |unknown redirect| types also just forward to |\ekvredirectunknown|
+% after asserting some prefixes.
+% \begin{macrocode}
+\protected\edef\ekvd@type@unknown@redirect#1%
+ {%
+ \expandafter\noexpand\csname ekvd@type@unknown@redirect-code\endcsname{#1}%
+ \expandafter\noexpand\csname ekvd@type@unknown@redirect-noval\endcsname{#1}%
+ }
+\protected\expandafter\def\csname ekvd@type@unknown@redirect-code\endcsname#1%
+ {%
+ \ekvd@assert@new@for@name{\ekv@name\ekvd@set{}u}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@also
+ \ekvd@assert@not@protected
+ \expandafter\ekvredirectunknown\expandafter{\ekvd@set}{#1}%
+ }%
+ }%
+ }
+\protected\expandafter\def\csname ekvd@type@unknown@redirect-noval\endcsname#1%
+ {%
+ \ekvd@assert@new@for@name{\ekv@name\ekvd@set{}uN}%
+ {%
+ \ekvd@assert@arg
+ {%
+ \ekvd@assert@not@also
+ \ekvd@assert@not@protected
+ \ekvd@assert@not@long
+ \expandafter\ekvredirectunknownNoVal\expandafter{\ekvd@set}{#1}%
+ }%
+ }%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Key Type Helpers}
+% There are some keys that might need helpers during their execution (not during
+% their definition, which are gathered as |@type@| macros). These helpers are
+% named |@h@|.
+%
+% \begin{macro}[internal]{\ekvd@h@choice,\ekvd@h@choice@}
+% The |choice| helper will just test whether the given choice was defined, if
+% not throw an error expandably, else call the macro which stores the code for
+% this choice.
+% \begin{macrocode}
+\def\ekvd@h@choice#1%
+ {%
+ \expandafter\ekvd@h@choice@
+ \csname\ifcsname#1\endcsname#1\else relax\fi\endcsname
+ {#1}%
+ }
+\def\ekvd@h@choice@#1#2%
+ {%
+ \ifx#1\relax
+ \ekvd@err@choice@invalid{#2}%
+ \expandafter\@gobble
+ \fi
+ #1%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Handling \texttt{also}}
+%
+% \begin{macro}[internal]
+% {\ekvd@add@val,\ekvd@add@noval,\ekvd@add@aux,\ekvd@add@aux@}
+% \begin{macrocode}
+\protected\long\def\ekvd@add@val#1#2#3%
+ {%
+ \ekvd@assert@val{#1}%
+ {%
+ \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}\endcsname{{##1}}%
+ {#1}{#2}{\ekvd@long\ekvdef}{#3}%
+ }%
+ }
+\protected\long\def\ekvd@add@noval#1#2#3%
+ {%
+ \ekvd@assert@noval{#1}%
+ {%
+ \expandafter\ekvd@add@aux\csname\ekv@name\ekvd@set{#1}N\endcsname{}%
+ {#1}{#2}\ekvdefNoVal{#3}%
+ }%
+ }
+\protected\long\def\ekvd@add@aux#1#2%
+ {%
+ \ekvd@extract@prefixes#1%
+ \expandafter\ekvd@add@aux@\expandafter{#1#2}%
+ }
+\protected\long\def\ekvd@add@aux@#1#2#3#4#5%
+ {%
+ #5%
+ \ekvd@prot#4\ekvd@set{#2}{#1#3}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@extract@prefixes,\ekvd@extract@prefixes@,
+% \ekvd@extract@prefixes@long,\ekvd@extract@prefixes@prot
+% }
+% This macro checks which prefixes were used for the definition of a macro and
+% sets |\ekvd@long| and |\ekvd@prot| accordingly.
+% \begin{macrocode}
+\protected\def\ekvd@extract@prefixes#1%
+ {%
+ \expandafter\ekvd@extract@prefixes@\meaning#1\ekvd@stop
+ }
+% \end{macrocode}
+% In the following definition |#1| will get replaced by |macro:|, |#2| by
+% |\long| and |#3| by |\protected| (in each, all tokens will have category
+% other). This allows us to parse the |\meaning| of a macro for those strings.
+% \begin{macrocode}
+\protected\def\ekvd@extract@prefixes@#1#2#3%
+ {%
+ \protected\def\ekvd@extract@prefixes@##1#1##2\ekvd@stop
+ {%
+ \ekvd@extract@prefixes@long
+ ##1\ekvd@mark\@firstofone#2\ekvd@mark\@gobble\ekvd@stop
+ {\let\ekvd@long\long}%
+ \ekvd@extract@prefixes@prot
+ ##1\ekvd@mark\@firstofone#3\ekvd@mark\@gobble\ekvd@stop
+ {\let\ekvd@prot\protected}%
+ }%
+ \protected\def\ekvd@extract@prefixes@long##1#2##2\ekvd@mark##3##4\ekvd@stop
+ {##3}%
+ \protected\def\ekvd@extract@prefixes@prot##1#3##2\ekvd@mark##3##4\ekvd@stop
+ {##3}%
+ }
+% \end{macrocode}
+% We use a temporary macro to expand the three arguments of
+% |\ekvd@extract@prefixes@|, which will set up the real meaning of itself and
+% the parsing for |\long| and |\protected|.
+% \begin{macrocode}
+\begingroup
+\edef\ekvd@tmp
+ {%
+ \endgroup
+ \ekvd@extract@prefixes@
+ {\detokenize{macro:}}%
+ {\string\long}%
+ {\string\protected}%
+ }
+\ekvd@tmp
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \subsubsection{Tests}
+%
+% \begin{macro}[internal]{\ekvd@newlet,\ekvd@newreg}
+% These macros test whether a control sequence is defined, if it isn't they
+% define it, either via |\let| or via the correct \cs[no-index]{new\meta{reg}}.
+% \begin{macrocode}
+\protected\def\ekvd@newlet#1#2%
+ {%
+ \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\let#1#2}%
+ }
+\protected\def\ekvd@newreg#1#2%
+ {%
+ \ifdefined#1\ekv@fi@gobble\fi\@firstofone{\csname new#2\endcsname#1}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {\ekvd@assert@twoargs,\ekvd@ifnottwoargs,\ekvd@ifempty@gtwo}
+% A test for exactly two tokens can be reduced for an empty-test after gobbling
+% two tokens, in the case that there are fewer tokens than two in the argument,
+% only macros will be gobbled that are needed for the true branch, which doesn't
+% hurt, and if there are more this will not be empty.
+% \begin{macrocode}
+\long\def\ekvd@assert@twoargs#1%
+ {%
+ \ekvd@ifnottwoargs{#1}{\ekvd@err@missing@definition}%
+ }
+\long\def\ekvd@ifnottwoargs#1%
+ {%
+ \ekvd@ifempty@gtwo#1\ekv@ifempty@B
+ \ekv@ifempty@false\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ }
+\long\def\ekvd@ifempty@gtwo#1#2{\ekv@ifempty@\ekv@ifempty@A}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@assert@val,\ekvd@assert@val@,\ekvd@assert@noval,\ekvd@assert@noval@,
+% \ekvd@extract@args,\ekvd@extracted@args,\ekvd@one@arg@string
+% }
+% Assert that a given key is defined as a value taking key or a |NoVal| key with
+% the correct argument structure, respectively.
+% \begin{macrocode}
+\protected\def\ekvd@assert@val#1%
+ {%
+ \ekvifdefined\ekvd@set{#1}%
+ {\expandafter\ekvd@assert@val@\csname\ekv@name\ekvd@set{#1}\endcsname}%
+ {%
+ \ekvifdefinedNoVal\ekvd@set{#1}%
+ \ekvd@err@add@val@on@noval
+ {\ekvd@err@undefined@key{#1}}%
+ \@gobble
+ }%
+ }
+\protected\def\ekvd@assert@val@#1%
+ {%
+ \expandafter\ekvd@extract@args\meaning#1\ekvd@stop
+ \unless\ifx\ekvd@extracted@args\ekvd@one@arg@string
+ \ekvd@err@unsupported@arg
+ \fi
+ \@firstofone
+ }%
+\protected\def\ekvd@assert@noval#1%
+ {%
+ \ekvifdefinedNoVal\ekvd@set{#1}%
+ {\expandafter\ekvd@assert@noval@\csname\ekv@name\ekvd@set{#1}N\endcsname}%
+ {%
+ \ekvifdefined\ekvd@set{#1}%
+ \ekvd@err@add@noval@on@val
+ {\ekvd@err@undefined@key{#1}}%
+ \@gobble
+ }%
+ }
+\protected\def\ekvd@assert@noval@#1%
+ {%
+ \expandafter\ekvd@extract@args\meaning#1\ekvd@stop
+ \unless\ifx\ekvd@extracted@args\ekv@empty
+ \ekvd@err@unsupported@arg
+ \fi
+ \@firstofone
+ }
+\protected\def\ekvd@extract@args#1%
+ {%
+ \protected\def\ekvd@extract@args##1#1##2->##3\ekvd@stop
+ {\def\ekvd@extracted@args{##2}}%
+ }
+\expandafter\ekvd@extract@args\expandafter{\detokenize{macro:}}
+\edef\ekvd@one@arg@string{\string#1}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@assert@arg,\ekvd@assert@arg@msg,\ekvd@ifnoarg}
+% There is no need to actually define |\ekvd@ifnoarg| here, as it will be set by
+% either |\ekvd@arg| or |\ekvd@noarg|.
+% \begin{macrocode}
+\def\ekvd@assert@arg{\ekvd@ifnoarg\ekvd@err@missing@definition}
+\long\def\ekvd@assert@arg@msg#1%
+ {%
+ \ekvd@ifnoarg{\ekvd@err@missing@definition@msg{#1}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@assert@filledarg,\ekvd@ifnoarg@or@empty}
+% \begin{macrocode}
+\long\def\ekvd@assert@filledarg#1%
+ {%
+ \ekvd@ifnoarg@or@empty{#1}\ekvd@err@missing@definition
+ }
+\long\def\ekvd@ifnoarg@or@empty#1%
+ {%
+ \ekvd@ifnoarg
+ \@firstoftwo
+ {\ekv@ifempty{#1}}%
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@assert@not@long,\ekvd@assert@not@protected,\ekvd@assert@not@also
+% \ekvd@assert@not@long@also,\ekvd@assert@not@protected@also,
+% \ekvd@assert@new,\ekvd@assert@not@new
+% }
+% Some key-types don't want to be |also|, |\long| or |\protected|, so we provide
+% macros to test this and throw an error, this could be silently ignored but now
+% users will learn to not use unnecessary stuff which slows the compilation
+% down.
+% \begin{macrocode}
+\def\ekvd@assert@not@long{\ifx\ekvd@long\long\ekvd@err@no@prefix{long}\fi}
+\def\ekvd@assert@not@protected
+ {\ifx\ekvd@prot\protected\ekvd@err@no@prefix{protected}\fi}
+\def\ekvd@assert@not@also{\ekvd@ifalso{\ekvd@err@no@prefix{also}}{}}
+\def\ekvd@assert@not@long@also
+ {\ifx\ekvd@long\long\ekvd@err@no@prefix@also{long}\fi}
+\def\ekvd@assert@not@protected@also
+ {\ifx\ekvd@prot\protected\ekvd@err@no@prefix@also{protected}\fi}
+\def\ekvd@assert@new#1#2%
+ {\csname ekvifdefined#1\endcsname\ekvd@set{#2}{\ekvd@err@not@new}}
+\def\ekvd@assert@not@new
+ {\ifx\ekvd@ifnew\ekvd@assert@new\ekvd@err@no@prefix{new}\fi}
+\def\ekvd@assert@new@for@name#1%
+ {%
+ \ifx\ekvd@ifnew\ekvd@assert@new
+ \ekv@fi@firstoftwo
+ \fi
+ \@secondoftwo
+ {\ekv@ifdefined{#1}\ekvd@err@not@new}%
+ \@firstofone
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@if@not@already@choice, \ekvd@if@not@already@choice@a,
+% \ekvd@if@not@already@choice@b
+% }
+% It is bad to use |also| on a key that already contains a |choice|, as both
+% choices would share the same valid values and thus lead to each callback being
+% used twice. The following is a rudimentary test against this.
+% \begin{macrocode}
+\protected\def\ekvd@if@not@already@choice#1%
+ {%
+ \expandafter\ekvd@if@not@already@choice@a
+ \csname\ekv@name\ekvd@set{#1}\endcsname
+ {}\ekvd@h@choice\ekvd@stop
+ }
+\protected\def\ekvd@if@not@already@choice@a
+ {%
+ \expandafter\ekvd@if@not@already@choice@b
+ }
+\long\protected\def\ekvd@if@not@already@choice@b#1\ekvd@h@choice#2\ekvd@stop
+ {%
+ \ekv@ifempty{#2}\@firstofone\@gobble
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@ifspace,\ekvd@ifspace@}
+% Yet another test which can be reduced to an if-empty, this time by gobbling
+% everything up to the first space.
+% \begin{macrocode}
+\long\def\ekvd@ifspace#1%
+ {%
+ \ekvd@ifspace@#1 \ekv@ifempty@B
+ \ekv@ifempty@false\ekv@ifempty@A\ekv@ifempty@B\@firstoftwo
+ }
+\long\def\ekvd@ifspace@#1 % keep this space
+ {%
+ \ekv@ifempty@\ekv@ifempty@A
+ }
+% \end{macrocode}
+% \end{macro}
+%
+% \subsubsection{Messages}
+%
+% Most messages of \expkvd\ are not expandable, since they only appear during
+% key-definition, which is not expandable anyway.
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@errm,\ekvd@err@missing@definition,\ekvd@err@missing@definition@msg,
+% \ekvd@err@missing@type,\ekvd@err@undefined@prefix,\ekvd@err@undefined@key,
+% \ekvd@err@no@prefix,\ekvd@err@no@prefix@msg,\ekvd@err@no@prefix@also,
+% \ekvd@err@add@val@on@noval,\ekvd@err@add@noval@on@val,
+% \ekvd@err@unsupported@arg,\ekvd@err@not@new
+% }
+% The non-expandable error messages are boring, so here they are:
+% \begin{macrocode}
+\protected\def\ekvd@errm#1{\errmessage{expkv-def Error: #1}}
+\protected\def\ekvd@err@missing@definition
+ {\ekvd@errm{Missing definition for key `\ekvd@cur'}}
+\protected\def\ekvd@err@missing@definition@msg#1%
+ {\ekvd@errm{Missing definition for key `\ekv@unexpanded{#1}'}}
+\protected\def\ekvd@err@missing@type
+ {\ekvd@errm{Missing type prefix for key `\ekvd@cur'}}
+\protected\def\ekvd@err@undefined@prefix#1%
+ {%
+ \ekvd@errm
+ {%
+ Undefined prefix `\ekv@unexpanded{#1}' found while processing
+ `\ekvd@cur'%
+ }%
+ }
+\protected\def\ekvd@err@undefined@key#1%
+ {%
+ \ekvd@errm
+ {Undefined key `\ekv@unexpanded{#1}' found while processing `\ekvd@cur'}%
+ }
+\protected\def\ekvd@err@undefined@noval#1%
+ {%
+ \ekvd@errm
+ {%
+ Undefined noval key `\unexpanded{#1}' found while processing
+ `\ekvd@cur'%
+ }%
+ }
+\protected\def\ekvd@err@no@prefix#1%
+ {\ekvd@errm{prefix `#1' not accepted in `\ekvd@cur'}}
+\protected\def\ekvd@err@no@prefix@msg#1#2%
+ {\ekvd@errm{prefix `#2' not accepted in `\ekv@unexpanded{#1}'}}
+\protected\def\ekvd@err@no@prefix@also#1%
+ {\ekvd@errm{`\ekvd@cur' not allowed with a `#1' key}}
+\protected\def\ekvd@err@add@val@on@noval
+ {\ekvd@errm{`\ekvd@cur' not allowed with a NoVal key}}
+\protected\def\ekvd@err@add@noval@on@val
+ {\ekvd@errm{`\ekvd@cur' not allowed with a value taking key}}
+\protected\def\ekvd@err@unsupported@arg\fi\@firstofone#1%
+ {%
+ \fi
+ \ekvd@errm
+ {%
+ Existing key-macro has the unsupported argument string
+ `\ekvd@extracted@args' for key `\ekvd@cur'%
+ }%
+ }
+\protected\def\ekvd@err@not@new
+ {\ekvd@errm{The key for `\ekvd@cur' is already defined}}
+\protected\long\def\ekvd@err@misused@unknown
+ {\ekvd@errm{Misuse of the unknown type found while processing `\ekvd@cur'}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]
+% {
+% \ekvd@err@choice@invalid,\ekvd@err@choice@invalid@,\ekvd@choice@name,
+% \ekvd@unknown@choice@name
+% }
+% |\ekvd@err@choice@invalid| will have to use this mechanism to throw its
+% message. Also we have to retrieve the name parts of the choice in an easy way,
+% so we use parentheses of catcode 8 here, which should suffice in most cases to
+% allow for a correct separation.
+% \begin{macrocode}
+\def\ekvd@err@choice@invalid#1%
+ {%
+ \ekvd@err@choice@invalid@#1%
+ }
+\begingroup
+\catcode40=8
+\catcode41=8
+\@firstofone{\endgroup
+\def\ekvd@choice@name#1#2#3%
+ {%
+ ekvd#1(#2)\detokenize{#3}%
+ }
+\def\ekvd@unknown@choice@name#1#2%
+ {%
+ ekvd:u:#1(#2)%
+ }
+\def\ekvd@err@choice@invalid@ ekvd#1(#2)\detokenize#3%
+ {%
+ \ekv@ifdefined{\ekvd@unknown@choice@name{#1}{#2}}%
+ {\csname\ekvd@unknown@choice@name{#1}{#2}\endcsname{#3}}%
+ {\ekvd@err{invalid choice `#3' for `#2' in set `#1'}}%
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[internal]{\ekvd@err}
+% The expandable error messages use |\ekvd@err|, which is just like |\ekv@err|
+% from \expkv. It uses a runaway argument to start the error message.
+% \begin{macrocode}
+\ekv@exparg{\long\def\ekvd@err#1}{\ekverr{expkv-def}{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+% Now everything that's left is to reset the category code of |@|.
+% \begin{macrocode}
+\catcode`\@=\ekvd@tmp
+% \end{macrocode}
+%
+% \gobbledocstriptag
+%</tex>
+%^^A=<<
+%
+%^^A=<<
+%
+% \end{implementation}^^A=<<
+%
+% \clearpage
+% \PrintIndex
+%
+\endinput
+%
+^^A vim: ft=tex fdm=marker fmr=>>=,=<<