From e8abb8d95794509452efd78015e313f61cee603a Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sat, 29 Jan 2022 21:47:48 +0000 Subject: expkv-def/ (29jan22) git-svn-id: svn://tug.org/texlive/trunk@61796 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/expkv-def/expkv-def.dtx | 319 +++++++++++++++++---- 1 file changed, 258 insertions(+), 61 deletions(-) (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx b/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx index c9d6ebe5b7f..059c7dda015 100644 --- a/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx +++ b/Master/texmf-dist/source/latex/expkv-def/expkv-def.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% File: expkv-def.dtx Copyright (C) 2020-2021 Jonathan P. Spratte +% 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 @@ -27,7 +27,7 @@ Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt -------------------------------------------------------------- -Copyright (C) 2020-2021 Jonathan P. Spratte +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 @@ -623,14 +623,15 @@ and the derived files expkv-def.pdf % instead. % \end{function} % -% \begin{function}{toks,gtoks,apptoks,gapptoks} +% \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. If \meta{cs} -% is not yet defined it will be initialised with |\newtoks|. +% |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} @@ -706,6 +707,49 @@ and the derived files expkv-def.pdf % 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 @@ -956,8 +1000,8 @@ and the derived files expkv-def.pdf % \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.8c} -\def\ekvdDate{2021-09-20} +\def\ekvdVersion{0.9} +\def\ekvdDate{2022-01-29} % \end{macrocode} % \end{macro} % @@ -978,19 +1022,35 @@ and the derived files expkv-def.pdf % 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@empty,\ekvd@ifalso} +% {\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} -\def\ekvd@empty{} \protected\def\ekvd@clear@prefixes {% - \let\ekvd@long\ekvd@empty - \let\ekvd@prot\ekvd@empty + \let\ekvd@long\ekv@empty + \let\ekvd@prot\ekv@empty \let\ekvd@ifalso\@secondoftwo \long\def\ekvd@ifnew##1##2##3{##3}% } @@ -1031,7 +1091,7 @@ and the derived files expkv-def.pdf \protected\long\def\ekvd@handle#1\ekvd@stop#2% {% \ekvd@clear@prefixes - \edef\ekvd@cur{\detokenize{#1}}% + \def\ekvd@cur{#1}% \ekvd@ifspace{#1}% {\ekvd@prefix\ekv@mark#1\ekv@stop{#2}}% \ekvd@err@missing@type @@ -1409,11 +1469,11 @@ and the derived files expkv-def.pdf \ekvd@ifalso {% \let\ekvd@prot\protected - \ekvd@add@val{#2}{#1\setbox#3\hbox{\begingroup##1\endgroup}}{}% + \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}}% + {#1\setbox#3=\hbox{\begingroup##1\endgroup}}% }% }% }% @@ -1436,9 +1496,9 @@ and the derived files expkv-def.pdf \ekvd@ifalso {% \let\ekvd@prot\protected - \ekvd@add@val{#2}{#1#3{##1}}{}% + \ekvd@add@val{#2}{#1#3={##1}}{}% }% - {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3{##1}}}% + {\protected\ekvd@long\ekvdef\ekvd@set{#2}{#1#3={##1}}}% }% }% } @@ -1447,31 +1507,86 @@ and the derived files expkv-def.pdf % \end{macrocode} % \end{macro} % -% \begin{macro}[internal]{\ekvd@type@apptoks,\ekvd@t@apptoks,\ekvd@t@gapptoks} +% \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} -\protected\def\ekvd@type@apptoks#1#2#3% +\ekvd@ifprimitive\toksapp {% - \ekvd@ifnew{}{#2}% + \protected\def\ekvd@type@preapptoks#1#2#3% {% - \ekvd@assert@filledarg{#3}% + \ekvd@ifnew{}{#2}% {% - \ekvd@newreg#3{toks}% - \ekvd@ifalso + \ekvd@assert@filledarg{#3}% {% - \let\ekvd@prot\protected - \ekvd@add@val{#2}{#1#3\expandafter{\the#3##1}}{}% + \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}% {% - \protected\ekvd@long\ekvdef\ekvd@set{#2}% - {#1#3\expandafter{\the#3##1}}% + \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} } -\protected\def\ekvd@t@apptoks{\ekvd@type@apptoks{}} -\protected\def\ekvd@t@gapptoks{\ekvd@type@apptoks\global} % \end{macrocode} % \end{macro} % @@ -1525,7 +1640,7 @@ and the derived files expkv-def.pdf {% \ekvd@assert@filledarg{#4}% {% - \ekvd@newlet#4\ekvd@empty + \ekvd@newlet#4\ekv@empty \ekvd@ifalso {% \let\ekvd@prot\protected @@ -1615,10 +1730,12 @@ and the derived files expkv-def.pdf % % \begin{macro}[internal] % { -% \ekvd@type@choice,\ekvd@populate@choice,\ekvd@populate@choice@, -% \ekvd@populate@choice@noarg,\ekvd@choice@prefix,\ekvd@choice@prefix@, +% \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 +% \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 @@ -1629,8 +1746,13 @@ and the derived files expkv-def.pdf \protected\def\ekvd@type@choice#1% {% \ekvd@assert@not@long - \ekvd@prot\edef\ekvd@tmp##1% - {\ekv@unexpanded{\ekvd@h@choice}{\ekvd@choice@name\ekvd@set{#1}{##1}}}% + \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}% @@ -1672,36 +1794,35 @@ and the derived files expkv-def.pdf \protected\long\def\ekvd@populate@choice@#1#2% {% \ekvd@clear@prefixes - \expandafter\ekvd@assert@arg@msg\expandafter{\ekvd@cur : #1}% + \ekvd@ifspace{#1}% + {\ekvd@choice@prefix{\ekv@mark#1}\ekv@mark#1\ekv@stop}% {% - \ekvd@ifspace{#1}% - {\ekvd@choice@prefix\ekv@mark#1\ekv@stop}% - {% - \expandafter\def - \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#1}\endcsname - }% - {#2}% + \expandafter\edef + \csname\ekvd@choice@name\ekvd@set\ekvd@set@choice{#1}\endcsname }% + {\unexpanded{#2}}% } -\protected\def\ekvd@choice@prefix#1 +\protected\def\ekvd@choice@prefix#1#2 {% - \ekv@strip{#1}\ekvd@choice@prefix@\ekv@mark + \ekv@strip{#2}{\ekvd@choice@prefix@{#1}}\ekv@mark } -\protected\def\ekvd@choice@prefix@#1#2\ekv@stop +\protected\def\ekvd@choice@prefix@#1#2#3\ekv@stop {% - \ekv@ifdefined{ekvd@choice@p@#1}% + \ekv@ifdefined{ekvd@choice@p@#2}% {% - \csname ekvd@choice@p@#1\endcsname - \ekvd@ifspace{#2}% - {\ekvd@choice@prefix#2\ekv@stop}% - {% - \ekvd@prot\expandafter\def - \csname - \ekv@strip{#2}{\ekvd@choice@name\ekvd@set\ekvd@set@choice}% - \endcsname - }% + \csname ekvd@choice@p@#2\endcsname + \ekvd@ifspace{#3}% + {\ekvd@choice@prefix{#3}#3\ekv@stop}% + {\ekvd@choice@prefix@done{#3}}% }% - {\ekvd@err@undefined@prefix{#1}\@gobble}% + {\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 @@ -1736,6 +1857,82 @@ and the derived files expkv-def.pdf % \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% @@ -2043,7 +2240,7 @@ and the derived files expkv-def.pdf \protected\def\ekvd@assert@noval@#1% {% \expandafter\ekvd@extract@args\meaning#1\ekvd@stop - \unless\ifx\ekvd@extracted@args\ekvd@empty + \unless\ifx\ekvd@extracted@args\ekv@empty \ekvd@err@unsupported@arg \fi \@firstofone @@ -2243,7 +2440,7 @@ and the derived files expkv-def.pdf % \begin{macrocode} \def\ekvd@err@choice@invalid#1% {% - \ekvd@err@choice@invalid@#1\ekv@stop + \ekvd@err@choice@invalid@#1% } \begingroup \catcode40=8 @@ -2251,13 +2448,13 @@ and the derived files expkv-def.pdf \@firstofone{\endgroup \def\ekvd@choice@name#1#2#3% {% - ekvd#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)#3\ekv@stop% +\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}}% -- cgit v1.2.3