diff options
Diffstat (limited to 'macros/latex/contrib/ltxkeys/ltxkeys.sty')
-rw-r--r-- | macros/latex/contrib/ltxkeys/ltxkeys.sty | 4317 |
1 files changed, 4317 insertions, 0 deletions
diff --git a/macros/latex/contrib/ltxkeys/ltxkeys.sty b/macros/latex/contrib/ltxkeys/ltxkeys.sty new file mode 100644 index 0000000000..8109dd19a3 --- /dev/null +++ b/macros/latex/contrib/ltxkeys/ltxkeys.sty @@ -0,0 +1,4317 @@ +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% +% This is file 'ltxkeys.sty', version 0.0.3c, 2012/11/17. % +% % +% This package and accompanying files may be distributed and/or % +% modified under the conditions of the LaTeX Project Public License, % +% either version 1.3 of this license or any later version. The latest % +% version of this license is in http://www.latex-project.org/lppl.txt % +% and version 1.3 or later is part of all distributions of LaTeX % +% version 2005/12/01 or later. % +% % +% The LPPL maintenance status of this software is 'author-maintained'. % +% % +% This software is provided 'as it is', without warranty of any kind, % +% either expressed or implied, including, but not limited to, the % +% implied warranties of merchantability and fitness for a particular % +% purpose. % +% % +% Copyright (c) 2011-2012 Ahmed Musa (amusa22@gmail.com). % +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% + +\@ifpackageloaded{catoptions}{% + \@ifpackagelater{catoptions}{2012/10/14}{}{% + \@latex@error{Loaded version of catoptions package is + not current}\@ehd + }% +}{% + \RequirePackage{catoptions}[2012/10/14]% +} +\UseNormalCatcodes +\StyleFilePurpose{A robust key-value parser (AM)} +\StyleFileRCSInfo +$Id: ltxkeys.sty,v 0.0.3c 2012/11/17 09:00:00 Ahmed Musa Exp $ +\ProvidesPackage{ltxkeys}[\StyleFileInfo] +\NeedsTeXFormat{LaTeX2e}[2011/06/27] +\SetStyleFileMessages[ltxkeys@]{info}{warn}{err} +\cpt@setupsafeactivesedef +\catcode`\&=3\relax +\new@def\ltxkeys@afterfi#1\fi{\fi#1} +\new@def\ltxkeys@afterelsei#1\else#2\fi{\fi#1} +\new@def\ltxkeys@afterelseii#1\else#2\fi{\fi#2} +\new@def*\ltxkeys@ehd{% + \ifx\protect\string\ltxkeys@afterfi + A serious error has occurred.\MsgBrk + Try typing <return>\space to proceed.\MsgBrk + If that fails, type X and then <return>\space to quit. + \fi +} +\new@def*\ltxkeys@truetoks{true} +\new@def*\ltxkeys@falsetoks{false} +\robust@def*\ltxkeys@specialhandler{% + \cpt@testopt\ltxkeys@sp@cialhandler{}% +} +\robust@def*\ltxkeys@sp@cialhandler[#1]#2{% + \begingroup + \toks1{\endgroup\newcsnpdef*{#1@#2@handler}##1##2}% + \def\reserved@a{\the\toks\expandafter1\expandafter{\the\toks0}}% + \afterassignment\reserved@a\toks0=% +} +\newletcs\ltxkeys@nil\relax +\new@def*\ltxkeys@nnil{\ltxkeys@nil} +\new@def*\ltxkeys@quark{\@gobble\ltxkeys@quark} +\new@def*\ltxkeys@antiquark{\@gobble\ltxkeys@antiquark} +\new@def*\ltxkeys@cdr#1#2\ltxkeys@nil{#2} +\new@def*\ltxkeys@spcdr#1#2#3\ltxkeys@nil{\detokenize{#2}} +\new@def\ltxkeys@ifxFT#1#2{\ltxkeys@ifxTF{#1}{#2}\cptiiofii\cptiofii} +\new@def\ltxkeys@ifxTF#1#2{% + \expandafter\cptswap\cpt@car#1\ltxkeys@quark\car@nil + {\expandafter\ifx\cpt@car#2\ltxkeys@antiquark\car@nil}% + \expandafter\cptiofii\else\expandafter\cptiiofii\fi +} +\new@def*\ltxkeys@ifcsemptyTF#1{% + \expandafter\ltxkeys@ifxTF\cpt@car#1\ltxkeys@quark\car@nil\@empty +} +\robust@def*\ltxkeys@letmanytocs#1#2{\cptfor#1\dofor{\let##1= #2}} +\robust@def*\ltxkeys@error#1#2{\ltxkeys@err{#1}{#2}\@gobble} +\robust@def*\ltxkeys@debug#1#{% + \ifboolTF{ltxkeys@tracingkeys}{% + \ifstrcmpTF{#1}{*}{% + \cpt@sttrue\ltxkeys@d@bug + }{% + \cpt@stfalse\ltxkeys@d@bug + }% + }{% + \@gobbletwo + }% +} +\robust@def*\ltxkeys@d@bug#1#2{% + \wlog{\ifcpt@st^^J\fi ltxkeys debug [#1] #2.}% +} +\cptnewvariables{if}[ltxkeys@]{break,st,pl,cl,sw,sv,nv,novalue,pxop,exop, + preset,disable,ini,kf,rm,ssk,dec,dep,twk,tracingkeys,useempty,chdef, + swa,reservenopath,global,protected,inkeycmd}[false] +\cptnewvariables{if}{inputvalid}[false] +\cptnewvariables{switch}{infdpointers,infdp@inters}[false] +\cptnewvariables{count}[ltxkeys@]{csvdepth,keydepth}[\z@pt] +\robust@def*\setslavewithmaster{\global\ltxkeys@ssktrue} +\robust@def*\setnoslavewithmaster{\global\ltxkeys@sskfalse} +\setnoslavewithmaster +\robust@def*\allowemptykeypath{\global\ltxkeys@useemptytrue} +\robust@def*\disallowemptykeypath{\global\ltxkeys@useemptyfalse} +\DefSuffixChecker\ltxkeys@suffixcheck{*}{+}{!} +\newletcs\ltxkeys@documentclass\cpt@undefined +\robust@def*\ltxkeys@getdocumentclass{% + \def\csv@do##1{% + \filename@parse{##1}% + \ifx\filename@ext\@clsextension + \ifcsndefFT{opt@\filename@area\filename@base.\filename@ext}{}{% + \xdef\ltxkeys@documentclass{% + \filename@area\filename@base.\filename@ext + }% + \loopbreak + }% + \fi + }% + \csv@@parse*\@filelist + \ifdefTF\ltxkeys@documentclass{}{% + \ltxkeys@debug{==}{'ltxkeys' package loaded before + \string\documentclass:\MsgBrk no problem}% + }% +} +\cptpassunexpanded{% + \ifdefFT\@filelist{}{% + \ltxkeys@ifxTF\@filelist\@gobble{}{% + \ltxkeys@ifcsemptyTF\@filelist{}\ltxkeys@getdocumentclass + }% + }% + \ifdefFT\ltxkeys@documentclass{% + \let\ltxkeys@classoptionslist\@empty + }{% + \ifdefFT\@classoptionslist{}{% + \ltxkeys@ifcsemptyTF\@classoptionslist{}{% + \kv@@normalize*\@classoptionslist + }% + }% + \let\ltxkeys@classoptionslist\@classoptionslist + \def\csv@do##1{% + \ifinsetTF{=}{##1}{}{% + \cptgaddtolist\@classoptionslist{##1}% + }% + }% + \cptexpandbracenext + {\def\@classoptionslist{}\csv@@loop}\@classoptionslist + \def\@fileswith@ptions##1[##2]##3{% + \edef\ltxkeys@tempa{\cptcommanormalize{##3}}% + \cptfor xkeyval,kvoptions,catoptions\dofor{% + \xifinsetFT{,####1,}{,\ltxkeys@tempa,}{}{% + \let\@classoptionslist\ltxkeys@classoptionslist + \forbreaktrue + }% + }% + \cpt@ifbrack{\@fileswith@pti@ns##1[##2]##3}% + {\@fileswith@pti@ns##1[##2]##3[]}% + }% + }% +} +\robust@def*\ltxkeys@striplaststar#1*\@empty#2\ltxkeys@nil#3{\edef#3{#1}} +\robust@def*\ltxkeys@ifrejname#1{% + \ifcase0\ifx\key@type\ltxkeys@rej1\else + \ifx\key@name\ltxkeys@rej1\fi\fi\relax + \else + #1% + \fi +} +\robust@def*\ltxkeys@testst#1{% + \cpt@ifstar{\ltxkeys@sttrue#1}{\ltxkeys@stfalse#1}% +} +\robust@def*\ltxkeys@testpl#1{% + \cpt@ifplus{\ltxkeys@pltrue#1}{\ltxkeys@plfalse#1}% +} +\robust@def*\ltxkeys@testcl#1{% + \cpt@ifclam{\ltxkeys@cltrue#1}{\ltxkeys@clfalse#1}% +} +\robust@def*\ltxkeys@teststpl#1{\ltxkeys@testst{\ltxkeys@testpl{#1}}} +\robust@def*\ltxkeys@state{% + \\\ltxkeys@keys\\\ltxkeys@prefs\\\ltxkeys@fams\\\ltxkeys@nakeys + \\\ltxkeys@tpref\\\ltxkeys@ttpref\\\ltxkeys@tfam\\\ltxkeys@tkey + \\\ltxkeys@tval\\\ifltxkeys@st\\\ifltxkeys@pl\\\ifltxkeys@cl + \\\ifltxkeys@kf\\\ifltxkeys@pxop\\\ifltxkeys@exop\\\ifltxkeys@ini + \\\CurrentKeyval\\\CurrentKey\\\CurrentVal +} +\robust@def\ltxkeys@trimspacesincs#1{% + \expandafter\ltxkeys@trimspaces\expandafter{#1}{#1}% +} +\robust@def\ltxkeys@trimspaces#1#2{% + \begingroup + \ifcase0% + % 1. When #2 of \ltxkeys@trimspaces is empty token, #1, #2, #3 of + % \ltxkeys@spcdr will be '.', 'x', <empty>. + % 2. No one will give #2 of \ltxkeys@trimspaces as a dot (.). So + % the test is fairly robust. + \if.\ltxkeys@spcdr#2.x\ltxkeys@nil\else1\fi + \if\expandafter\cpt@car\string#2\car@nil\@backslashchar\else1\fi\relax + \else + \ltxkeys@err{'\detokenize{#2}' has illegal form}\ltxkeys@ehd + \fi + \ltxkeys@tr@mspaces{#1}{#2}% +} +\robust@def\ltxkeys@tr@mspaces#1#2{% + \edef\ltxkeys@trimmed{\cpttrimspace{#1}}% + \ltxkeys@ifxTF#2\ltxkeys@trimmed{% + \expandafter\endgroup\expandafter\edef\expandafter + #2\expandafter{\expandafter\unexpanded\expandafter{#2}}% + }{% + \let#2=\ltxkeys@trimmed + \expandafter\ltxkeys@tr@mspaces\expandafter{#2}#2% + }% +} +\robust@def*\ltxkeys@trimspacesset#1{% + \def\@do##1##2,{% + \ifnot@nil{##1}{\ltxkeys@trimspaces{##1}##2\@do}% + }% + \@do#1,\@nil\@nil,% +} +\new@def*\ltxkeys@iffirstnull#1#2{\ltxkeys@ifcsemptyTF#1{}{#1#2}} +\robust@def*\ltxkeys@remdottrimspaces#1#2{% + \cptexpandbracenext\ltxkeys@trimspaces{\@gobble#1}#2% +} +\robust@def*\ltxkeys@simplesplitkeyval#1{% + \expandafter\ltxkeys@simplespl@tkeyval#1=^?^=^?^=\ltxkeys@nil +} +\robust@def*\ltxkeys@simplespl@tkeyval#1={% + \def\reserved@a##1={% + \def\reserved@a####1=####2\ltxkeys@nil{% + \ltxkeys@trimspaces{#1}\key@name + \ltxkeys@remdottrimspaces{##1}\key@value + \ltxkeys@remdottrimspaces{####1}\remainder + }% + \reserved@a.% + }% + \reserved@a.% +} +\robust@def*\ltxkeys@splitkeyattrib#1{% + \begingroup + \def\ltxkeys@splita##1/##2/{% + \ltxkeys@trimspacesset{{##1}\key@type,{##2}\key@name}% + \ltxkeys@ifrejname{% + \ltxkeys@err{Wrong syntax for attributes of a key}\ltxkeys@ehd + }% + \ltxkeys@splitb.% + }% + \def\ltxkeys@splitb##1/{% + \ltxkeys@remdottrimspaces{##1}\key@default + \ltxkeys@splitc.% + }% + \def\ltxkeys@splitc##1/{% + \edef\key@callback{\unexpanded\expandafter{\@gobble##1}}% + \ltxkeys@stripdotcode\key@callback + \ltxkeys@splitd.% + }% + \def\ltxkeys@splitd##1/##2\ltxkeys@nil{% + \ltxkeys@remdottrimspaces{##1}\key@dependants + }% + \ltxkeys@splita#1/^?^/^?^/^?^/^?^/^?^/\ltxkeys@nil + \let\do\cpt@csexit + \cptexpanded{\endgroup + \do\key@type\do\key@name\do\key@default\do\key@callback + \do\key@dependants + }% +} +\new@def*\ltxkeys@rej{^?^} +% Does #1 start with '.code'? If it does, remove '.code': +\robust@def*\ltxkeys@stripdotcode#1{% + \ltxkeys@trimspacesincs#1% + \xifinsetTF{\relax\detokenize{.code=}}{\relax\cptoxdetok{#1}}{% + \def\reserved@a##1.code=##2\ltxkeys@nil{% + \def\reserved@a####1.\ltxkeys@nil{% + \ltxkeys@remdottrimspaces{####1}#1% + }% + \reserved@a.##2\ltxkeys@nil + }% + \expandafter\reserved@a#1.\ltxkeys@nil + }{}% +} +\robust@def*\ltxkeys@removedotcode#1#2{% + \ltxkeys@trimspaces{#1}#2% + \xifinsetTF{\detokenize{/.code=}}{\detokenize{#1}}{% + \def\reserved@a##1/.code=##2\ltxkeys@nil{% + \def\reserved@a####1.\ltxkeys@nil{% + \ltxkeys@remdottrimspaces{####1}\reserved@a + \edef#2{\expandcsonce{\@gobble##1}/\expandcsonce\reserved@a}% + }% + \reserved@a.##2\ltxkeys@nil + }% + \expandafter\reserved@a\expandafter.#2.\ltxkeys@nil + }{}% +} +\robust@def*\ltxkeys@in{\cpt@testst\ltxkeys@in@a} +\robust@def*\ltxkeys@in@a#1#2{% + \def\in@@##1#1##2\in@@{% + \ifblankTF{##2}\in@false\in@true + \ifboolTF{cpt@st}{\ifboolTF{in@}}{}% + }% + \in@@#2{\in@@}#1\in@@ +} +\robust@def*\ltxkeys@iffound#1\in#2\then{% + \ltxkeys@trimspaces{#1}\reserved@a + \ltxkeys@trimspaces{#2}\reserved@b + \ltxkeys@stfalse + \cptexpandtwoargsonce\ltxkeys@in@a\reserved@a\reserved@b + \ifin@ +} +\robust@def*\ltxkeys@ifchcfd#1\endgroup{% + % Don't make \@firstoftwo and \@secondoftwo equal to \relax + % here since \ifbool needs \ifnull, which in turn needs + % \@firstoftwo and \@secondoftwo. + \cptpassexpanded{% + \endgroup + \ifcase#1\relax + \ifdefboolTF{cpt@choicefd} + {\noexpand\@firstoftwo}{\noexpand\@secondoftwo}% + \or + \ifdefboolTF{cpt@choicefd} + {\noexpand\@secondoftwo}{\noexpand\@firstoftwo}% + \else + \ltxkeys@err{Invalid number '#1'}\ltxkeys@ehd + \fi + }% +} +\robust@def*\ltxkeys@getlasttoken#1{% + \def\ltxkeys@resttokens{}% + \ltxkeys@g@tlasttoken#1\ltxkeys@g@tlasttoken + \ltxkeys@g@tlasttoken\ltxkeys@getlasttoken +} +\robust@def*\ltxkeys@g@tlasttoken#1#2{% + \ifx#2\ltxkeys@g@tlasttoken + \edef\ltxkeys@lasttoken{\unexpanded{#1}}% + \def\reserved@a##1\ltxkeys@getlasttoken{}% + \expandafter\reserved@a + \else + \edef\ltxkeys@resttokens + {\expandcsonce\ltxkeys@resttokens\unexpanded{#1}}% + \expandafter\ltxkeys@g@tlasttoken + \fi + #2% +} +\new@def\ltxkeys@stripNouterbraces#1#2{% + \romannumeral\expandafter\ltxkeys@str@pNouterbraces + \expandafter{\romannumeral\number#1000m}\strip@nil#2\strip@nil +} +\new@def\ltxkeys@str@pNouterbraces#1\strip@nil#2\strip@nil{% + \ifbracedTF{#2}{% + \expandafter\ifnullTF\expandafter{\@gobble#2}{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{0 #2}{% + \cptexpandbracenext\ltxkeys@str@pNouterbraces{\@gobble#1}% + \strip@nil#2\strip@nil + }% + }{0 #2}% + }{0 #2}% +} +\new@def*\ltxkeys@stripallouterbraces#1{\ltxkeys@stripNouterbraces\@m{#1}} +\new@def*\ltxkeys@stripallouterbracesincs#1{% + \ifmacroTF{#1}{% + \edef#1{\cptexpandbracenext{\ltxkeys@stripNouterbraces\@m}{#1}}% + }{% + \cpt@notcserr{#1}% + }% +} +\robust@def*\ltxkeys@getbasechars{\cpt@teststopt\ltxkeys@g@tchars{1}} +\robust@def*\ltxkeys@g@tchars[#1]#2#3{% + \begingroup + \def#3{}\gdef\ltxkeys@charcount{0}% + \def\siso@do##1{% + \edef#3{#3##1}% + \xdef\ltxkeys@charcount{\the\numexpr\ltxkeys@charcount+1}% + \ifnum\ltxkeys@charcount>#1\relax\loopbreak\fi + }% + \cptexpandarg\siso@@loop + {\ifboolTF{cpt@st}\cptoxdetok\detokenize{#2}}% + \postgroupdef#3\endgroup +} +\robust@def*\ltxkeys@getorder{\cpt@teststopt\ltxkeys@g@torder,} +\robust@def*\ltxkeys@g@torder[#1]#2#3{% + \def\ltxkeys@order{-1}% + \begintoksgroup + \cpt@stchoose{cpt@st}{#3}\ltxkeys@tempa\ltxkeys@getorder + \lowercase{\ltxkeys@trimspaces{#2}\ltxkeys@tempb}% + \@tempcnta\z@pt + \def\ltxkeys@do##1{% + \oifstrcmpFT\ltxkeys@tempb{##1}{}{% + \cptexpanded{% + \toks@{\def\noexpand\ltxkeys@order{\the\@tempcnta}}% + }% + \loopbreaktrue + }% + \advance\@tempcnta\@ne + }% + \ltxkeys@listparse*1[;]\ltxkeys@tempa + \endtoksgroup +} +\robust@def*\ltxkeys@ifeltcountTF{\cpt@teststopt\ltxkeys@ifeltcount,} +\robust@def*\ltxkeys@ifeltcount[#1]{% + \cpt@testpnopt{\ltxkeys@ifeltc@unt{#1}}{=}% +} +\robust@def*\ltxkeys@ifeltc@unt#1(#2)#3#4{% + \begingroup + \edef\reserved@a{\ifcpt@st*\fi}% + \def\eltnum{0}% + \def\ltxkeys@do##1{% + \cptpushnumber\eltnum + }% + \expandafter\ltxkeys@listparse\reserved@a1[#1]{#4}% + \aftercsname\endgroup{@\ifnum\eltnum#2\numexpr#3% + first\else second\fi oftwo}% +} +\robust@def*\ltxkeys@findmatch#1#2#3{% + \def\currmatch{}% + \ltxkeys@trimspaces{#1}\reserved@a + \ltxkeys@f@ndmatch#2,:,\ltxkeys@nil{#3}% +} +\robust@def*\ltxkeys@f@ndmatch#1:#2,#3\ltxkeys@nil#4{% + \ifblankTF{#3}{% + #4% + }{% + \ltxkeys@trimspaces{#1}\reserved@b + \ifx\reserved@a\reserved@b + \edef\currmatch{\unexpanded{#2}}% + \expandafter\@gobble + \else + \expandafter\@iden + \fi + {\ltxkeys@f@ndmatch#3\ltxkeys@nil{#4}}% + }% +} +\robust@def*\ltxkeys@ifcase#1#2{% + \def\currmatch{}% + \ltxkeys@trimspaces{#1}\reserved@a + \ltxkeys@ifc@se#2,:,\ltxkeys@nil +} +\robust@def*\ltxkeys@ifc@se#1:#2,#3\ltxkeys@nil{% + \ifblankTF{#3}{% + \@secondoftwo + }{% + \ltxkeys@trimspaces{#1}\reserved@b + \ltxkeys@ifxTF\reserved@a\reserved@b{% + \edef\currmatch{\unexpanded{#2}}% + \@firstoftwo + }{% + \ltxkeys@ifc@se#3\ltxkeys@nil + }% + }% +} +\new@def\ltxkeys@alltoendif#1\endif{#1} +\new@def\ltxkeys@firsttoendif#1#2\endif{#1} +\new@def*\ltxkeys@ifcassenumcmpTF#1#2#3{% + \ifdim#1pt#2pt % + \expandafter\cptiofii\else\expandafter\cptiiofii\fi +} +\new@def\ltxkeys@ifcasse#1{% + \ifstrcmpTF{#1}\elseif{% + \ltxkeys@alltoendif + }{% + \ifstrcmpTF{#1}\endif{}{\ltxkeys@ifcasse@a{#1}}% + }% +} +\new@def\ltxkeys@ifcasse@a#1#2{% + \ifstrcmpTF{#2}\elseif{% + \ltxkeys@alltoendif + }{% + \ifstrcmpTF{#2}\endif{}{% + \ltxkeystestcmd{#1}{#2}\ltxkeys@firsttoendif{\ltxkeys@ifcasse@b{#1}}% + }% + }% +} +\new@def\ltxkeys@ifcasse@b#1#2{% + \ifstrcmpTF{#2}\endif{}{\ltxkeys@ifcasse@a{#1}}% +} +\robust@def*\ltxkeys@removeelements{\cpt@teststopt\ltxkeys@rem@veelements,} +\robust@def*\ltxkeys@rem@veelements[#1]{% + \cpt@testpnopt{\ltxkeys@rem@veelem@nts{#1}}\@ne +} +\robust@def\ltxkeys@rem@veelem@nts#1(#2)#3#4{% + \let\ltxkeys@tempa#3% + \ifcpt@st\else + \ifnum#2=\z@pt\cptthreexp\cptgobbletorelax\fi + \fi + \iflacus#4\dolacus + \expandafter\cptgobbletorelax + \fi + \begingroup + \let\detk\detokenize + \let\if@remvst\ifcpt@st + \ifmacroTF{#3}{}{\cpt@notcserr{#3}}% + \csv@@normalize*[#1]#3% + \def\ltxkeys@remove@a##1{% + \def\ltxkeys@do####1{% + \@tempcnta\z@pt + \def\ltxkeys@remove@a########1##1####1##1########2&{% + \edef#3{\unexpanded{########1##1########2}}% + }% + \def\ltxkeys@remove@b########1{% + \xifinsetTF{##1\detk{####1}##1}{##1\detk{########1}##1}{% + \ltxkeys@remove@a##1########1##1&% + \ifboolTF{@remvst}{% + \s@expandarg\ltxkeys@remove@b#3% + }{% + \advance\@tempcnta\@ne + \ifnumcmpTF\@tempcnta<#2{% + \s@expandarg\ltxkeys@remove@b#3% + }{}% + }% + }{}% + }% + \s@expandarg\ltxkeys@remove@b#3% + }% + \ltxkeys@listparse1[##1]{#4}% + \csv@@normalize*[##1]#3% + }% + \s@expandarg\ltxkeys@remove@a{\detk{#1}}% + \postgroupdef#3\endgroup + \cpt@relax + \ltxkeys@ifxFT#3\ltxkeys@tempa +} +\robust@def*\ltxkeys@replaceelements{% + \cpt@teststopt\ltxkeys@r@placeelements,% +} +\robust@def*\ltxkeys@r@placeelements[#1]{% + \cpt@testpnopt{\ltxkeys@r@pl@ceelements{#1}}\@ne +} +\robust@def\ltxkeys@r@pl@ceelements#1(#2)#3#4{% + \let\ltxkeys@tempa#3% + \ifcpt@st\else + \ifnum#2=\z@pt\cptthreexp\cptgobbletorelax\fi + \fi + \iflacus#4\dolacus + \expandafter\cptgobbletorelax + \fi + \begingroup + \let\if@replst\ifcpt@st + \ifmacroTF{#3}{}{\cpt@notcserr{#3}}% + \edef\ltxkeys@sublist{\unexpanded{#4}}% + \ltxkeys@n@rmalizecsset[#1]{#3,\ltxkeys@sublist}% + \def\ltxkeys@replace@a##1{% + \def\ltxkeys@replace@a####1####2##1####3&{% + \ltxkeys@r@pl@ceelement[##1](#2)#3{####1}{####2}% + \ifblankTF{####3}{}{\ltxkeys@replace@a####3&}% + }% + \expandafter\ltxkeys@replace@a\ltxkeys@sublist##1&% + \csv@@normalize*[##1]#3% + }% + \s@expandarg\ltxkeys@replace@a{\detokenize{#1}}% + \postgroupdef#3\endgroup + \cpt@relax + \ltxkeys@ifxFT#3\ltxkeys@tempa +} +\robust@def\ltxkeys@r@pl@ceelement[#1](#2)#3#4#5{% + \begingroup + \@tempcnta\z@pt + \def\ltxkeys@replace@a##1#1#4#1##2&{% + \edef#3{\unexpanded{##1#1#5#1##2}}% + }% + \def\ltxkeys@replace@b##1{% + \xifinsetTF{#1\detokenize{#4}#1}{#1\detokenize{##1}#1}{% + \ltxkeys@replace@a#1##1#1&% + \ifboolTF{@replst}{% + \s@expandarg\ltxkeys@replace@b#3% + }{% + \advance\@tempcnta\@ne + \ifnumcmpTF\@tempcnta<#2{% + \s@expandarg\ltxkeys@remove@b#3% + }{}% + }% + }{}% + }% + \s@expandarg\ltxkeys@replace@b{#3}% + \postgroupdef#3\endgroup +} +\robust@def*\ltxkeys@checkchoice{% + \cpt@teststpl{\cpt@testopt\ltxkeys@cc@a,}% +} +\robust@def*\ltxkeys@cc@a[#1]{% + \cpt@checklistparser{#1}{}% + \cpt@testpnopt{\ltxkeys@cc@b#1}{}% +} +\robust@def*\ltxkeys@commacheckchoice{% + \cpt@teststpl{\cpt@testpnopt{\ltxkeys@cc@b,}{}}% +} +\robust@def*\ltxkeys@checkinput#1#2{% + \lowercase{\edef\nominations{\unexpanded{#2}}}% + \cpt@sttrue\cpt@pltrue + \ltxkeys@cc@b,(\userinput\order){#1}{#2}{% + \@firstoftwo + }{% + \@secondoftwo + }% +} +\robust@def*\CheckUserInput#1#2{% + \lowercase{\edef\nominations{\unexpanded{#2}}}% + \cpt@sttrue\cpt@pltrue + \ltxkeys@cc@b,(\userinput\order){#1}{#2}{% + \inputvalidtrue + }{% + \inputvalidfalse + }% +} +\robust@def*\ltxkeys@cc@b#1(#2)#3#4{% + \begingroup + \ifcpt@st\lowercase{\fi + \ltxkeys@trimspaces{#3}\ltxkeys@userinput + \edef\ltxkeys@nominations{\unexpanded{#4}}% + \ifcpt@st}\fi + \def\ltxkeys@ccparser{#1}% + \csv@@normalize*[#1]\ltxkeys@nominations + \cptexpandsecond{% + \ifblankTF{#2}\ltxkeys@cc@d{\ltxkeys@cc@c#2}\ltxkeys@nil + }{% + {\expandcsonce\ltxkeys@userinput}% + {\expandcsonce\ltxkeys@nominations}% + }% +} +\robust@def*\ltxkeys@cc@c#1#2\ltxkeys@nil#3#4{% + \ifblankTF{#2}{\ltxkeys@cc@d#1}{\ltxkeys@cc@e#1#2}{#3}{#4}% +} +\robust@def*\ltxkeys@cc@d#1#2#3{% + \def\reserved@a{#1}% + \ltxkeys@ifxTF\reserved@a\ltxkeys@nnil{% + \def\ltxkeys@tempa{}% + }{% + \def\ltxkeys@tempa{\def#1{#2}}% + }% + \edef\x{\cptoxdetok\ltxkeys@ccparser}% + \edef\x{{\x\detokenize{#2}\x}{\x\detokenize{#3}\x}}% + \expandafter\ifinsetTF\x{% + \ifboolTF{cpt@pl}{% + \rightaddtocs\ltxkeys@tempa\@firstoftwo + }{% + \rightaddtocs\ltxkeys@tempa\@firstofone + }% + }{% + \ifboolTF{cpt@pl}{% + \rightaddtocs\ltxkeys@tempa\@secondoftwo + }{% + \rightaddtocs\ltxkeys@tempa{% + \expandafter\ltxkeys@nomatcherr\@gobble + }% + }% + }% + \cptpassexpanded{% + \endgroup + \cpt@csexit\ltxkeys@userinput + \cpt@csexit\ltxkeys@nominations + \expandcsonce\ltxkeys@tempa + }% +} +\robust@def*\ltxkeys@cc@e#1#2#3#4{% + \chardef#2\z@pt + \cpt@choicefdfalse + \def\ltxkeys@do##1{% + \def#1{##1}% + \ifstrcmpTF{##1}{#3}{% + \cpt@choicefdtrue\loopbreak + }{% + \cptpushnumber#2% + }% + }% + \cptexpandsecond{\ltxkeys@listparse0}{[\ltxkeys@ccparser]}{#4}% + \cptpassexpanded{% + \endgroup + \cpt@csexit\ltxkeys@userinput + \cpt@csexit\ltxkeys@nominations + \ifcpt@choicefd + \def\noexpand#1{\expandcsonce#1}% + \def\noexpand#2{\the\numexpr#2}% + \ifcpt@pl\noexpand\@firstoftwo\else\noexpand\@firstofone\fi + \else + \def\noexpand#1{\unexpanded{#3}}% + \def\noexpand#2{-1}% + \ifcpt@pl + \noexpand\@secondoftwo + \else + \unexpanded{\expandafter\ltxkeys@nomatcherr\@gobble}% + \fi + \fi + }% +} +\robust@def*\ltxkeys@nomatcherr{% + \ltxkeys@error{User input '\ltxkeys@userinput' not in list + of nominations ||\ltxkeys@nominations||}\ltxkeys@ehd +} +\robust@def*\ltxkeys@ifoneincsvlist{\cpt@teststopt\ltxkeys@ifoneincsvl@st,} +\robust@def*\ltxkeys@ifoneincsvl@st[#1]#2#3{% + \begingroup + \ifcpt@st + \let\test@list#2% + \let\master@list#3% + \else + \edef\test@list{\unexpanded{#2}}% + \edef\master@list{\unexpanded{#3}}% + \fi + \csv@@normalize*[#1]\master@list + \cpt@choicefdfalse + \def\csv@do##1{% + \oifinset@sp@TF#1{##1}\master@list{\cpt@choicefdtrue\loopbreak}{}% + }% + \csv@@parse*[#1]\test@list + \expandafter\endgroup + \ifcpt@choicefd\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\robust@def*\ltxkeys@ifincsvlistTF{\cpt@teststopt\ltxkeys@ifincsvlist,} +\robust@def*\ltxkeys@ifincsvlist[#1]{% + \cpt@testpnopt{\ltxkeys@if@ncsvlist#1}{1}% +} +\robust@def*\ltxkeys@if@ncsvlist#1(#2)#3#4{% + \begingroup + \edef\parser{\detokenize{#1}}% + \ifcpt@st\lowercase{\fi + \edef\ltxkeys@tempa{\unexpanded{#3}}% + \edef\ltxkeys@tempb{\unexpanded{#4}}% + \ifcpt@st}\fi + \cpt@sttrue\cpt@csvnormalize[#1]\ltxkeys@tempb + \cpt@cnta\z@pt + \def\ltxkeys@itemspresent{}% + \def\ltxkeys@do##1{% + \xifinsetFT{\detokenize{#1##1#1}}% + {\parser\cptoxdetok\ltxkeys@tempb\parser}{}{% + \edef\ltxkeys@itemspresent + {\csliststack,\ltxkeys@itemspresent\unexpanded{##1}}% + \advance\cpt@cnta\@ne + }% + \ifnum\cpt@cnta>\numexpr#2-1\relax\loopbreak\fi + }% + \ltxkeys@listparse*1[#1]\ltxkeys@tempa + \ifnum\cpt@cnta>\numexpr#2-1\relax + \edef\ltxkeys@nritems{\the\cpt@cnta}% + \else + \def\ltxkeys@itemspresent{}% + \def\ltxkeys@nritems{-1}% + \fi + \cptexpandsecond\endgroup{% + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ifx\ltxkeys@itemspresent\@empty\noexpand\@secondoftwo\else + \noexpand\@firstoftwo\fi + }% +} +\robust@def*\ltxkeys@ifoneintokenlist{\cpt@testst\ltxkeys@ifoneint@kenlist} +\robust@def*\ltxkeys@ifoneint@kenlist#1#2{% + \begingroup + \ifcpt@st + \let\test@list#1% + \let\master@list#2% + \else + \edef\test@list{\unexpanded{#1}}% + \edef\master@list{\unexpanded{#2}}% + \fi + \cpt@choicefdfalse + \def\tsv@do##1{% + \edef\reserved@a{\ltxkeys@stripNouterbraces{1}{##1}}% + \xifinsetTF{\cptoxdetok\reserved@a} + {\cptoxdetok\master@list}{\cpt@choicefdtrue\loopbreak}{}% + }% + \tsv@@parse*\test@list + \expandafter\endgroup + \ifcpt@choicefd\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\robust@def*\ltxkeys@ifintsvlistTF{% + \cpt@testst{\cpt@testpnopt\ltxkeys@ifintsvlist{1}}% +} +\robust@def*\ltxkeys@ifintsvlist(#1)#2#3{% + \begingroup + \ifcpt@st\lowercase{\fi + \edef\ltxkeys@tempa{\unexpanded{#2}}% + \edef\ltxkeys@tempb{\unexpanded{#3}}% + \ifcpt@st}\fi + \def\ltxkeys@itemspresent{}% + \cpt@cnta\z@pt + \def\tsv@do##1{% + \xifinsetFT{\detokenize{##1}}{\cptoxdetok\ltxkeys@tempb}{}{% + \edef\ltxkeys@itemspresent + {\csliststack{}\ltxkeys@itemspresent\unexpanded{##1}}% + \advance\cpt@cnta\@ne + }% + \ifnum\cpt@cnta>\numexpr#1-1\relax\loopbreak\fi + }% + \s@expandarg\tsv@@parse\ltxkeys@tempa + \ifnum\cpt@cnta>\numexpr#1-1\relax + \edef\ltxkeys@nritems{\the\cpt@cnta}% + \else + \def\ltxkeys@itemspresent{}% + \def\ltxkeys@nritems{-1}% + \fi + \cptexpandsecond\endgroup{% + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ifx\ltxkeys@itemspresent\@empty\noexpand\@secondoftwo\else + \noexpand\@firstoftwo\fi + }% +} +\robust@def*\ltxkeys@ifinlistTF{% + \cpt@testst{\cpt@testpnopt\ltxkeys@ifinlist{1}}% +} +\robust@def*\ltxkeys@ifinlist(#1)#2#3{% + \begingroup + \ifcpt@st\lowercase{\fi + \edef\ltxkeys@tempa{\unexpanded{#2}}% + \edef\ltxkeys@tempb{\unexpanded{#3}}% + \ifcpt@st}\fi + \def\ltxkeys@itemspresent{}% + \cpt@cnta\z@pt + \def\ltxkeys@do##1{% + \xifinsetTF{\detokenize{##1}}{\cptoxdetok\ltxkeys@tempb}{% + \edef\ltxkeys@itemspresent + {\csliststack,\ltxkeys@itemspresent\unexpanded{##1}}% + \advance\cpt@cnta\@ne + }{}% + \ifnum\cpt@cnta>\numexpr#1-1\relax\loopbreak\fi + }% + \ltxkeys@listparse*1\ltxkeys@tempa + \ifnum\cpt@cnta>\numexpr#1-1\relax + \edef\ltxkeys@nritems{\the\cpt@cnta}% + \else + \def\ltxkeys@itemspresent{}\def\ltxkeys@nritems{-1}% + \fi + \cptexpandsecond\endgroup{% + \cpt@csexit\ltxkeys@itemspresent + \cpt@csexit\ltxkeys@nritems + \ltxkeys@ifcsemptyTF\ltxkeys@itemspresent + {\noexpand\@secondoftwo}{\noexpand\@firstoftwo}% + }% +} +\robust@def*\ltxkeys@notinpkgclserr#1{% + \ifinstylefileTF{}{% + \ltxkeys@err{Command '\detokenize{#1}' issued + \MsgBrk outside style or class file} + {Command '\detokenize{#1}' is available + only in style files.}% + }% +} +\robust@def*\ltxkeys@commanormalize#1#2{\edef#2{\cptcommanormalize{#1}}} +\robust@def*\ltxkeys@commanormalizeset{% + \let\normelt\ltxkeys@commanormalize + \ltxkeys@normalizeset +} +\robust@def*\ltxkeys@kvnormalize#1#2{% + \edef#2{\unexpanded{#1}}% + \kv@@normalize*[,]#2% +} +\robust@def*\ltxkeys@kvnormalizeset{% + \let\normelt\ltxkeys@kvnormalize + \ltxkeys@normalizeset +} +\robust@def*\ltxkeys@normalizeset#1{% + \edef\reserved@a{\cptcommanormalize{#1}}% + \def\@do##1##2,{% + \ifnot@nil{##1}{\normelt{##1}##2\@do}% + }% + \expandafter\@do\reserved@a,\@nil,% + \undefcs\normelt +} +\robust@def*\ltxkeys@normalizecsset{\cpt@testopt\ltxkeys@n@rmalizecsset,} +\robust@def*\ltxkeys@n@rmalizecsset[#1]#2{% + \cptfor#2\dofor{\csv@@normalize[#1]##1}% +} +\new@def*\ltxkeys@parser@nil{\@gobble\ltxkeys@parser@nil} + +\begingroup +\catcode`\?=3 +\robust@gdef*\ltxkeys@declarelistparser#1#2{% + \ifcsdefinable{#1}\relax + \begingroup + \ltxkeys@letmanytocs{#1,\ifstrcmpTF,\cptexpandnext, + \ltxkeys@ifxTF,\listbreak,\ltxkeys@parser@nil}\relax + \def\elta##1{\noexpandcsn{\cptgobblescape#1@list@##1}}% + \def\eltb##1{\cptexpandnext{\elta{b}##1}{########1}% + #2\ltxkeys@parser@nil#2?{}}% + \def\eltc{\ltxkeys@ifxTF!\unexpanded{{####1}{####4}{\unexpanded{####4}}}}% + \cptexpanded{\endgroup + \def#1####1{\ifstrcmpTF!{####1}{\elta{a}}{\eltb+}}% + \def\elta{a}####1{\eltb!}% + \def\elta{b}####1####2#2####3?####4####5{% + \ltxkeys@ifxTF\ltxkeys@parser@nil{####2}{\eltc}{% + \ifstrcmpTF{####2}{\listbreak}{\eltc}{% + \elta{b}{####1}####3?{####4####5{####2}}{####5}% + }% + }% + }% + }% +} +\endgroup + +% Break out of the loop using \loopbreak. +\robust@def*\ltxkeys@listparse{\cpt@testst\ltxkeys@listparse@a} +\robust@def*\ltxkeys@listparse@a#1{% + \begingroup + \def\reserved@a##1##2{\endgroup + \def\ltxkeys@nlz{##1}\def\ltxkeys@inkv{##2}% + }% + \cptexpandsecond\reserved@a{% + \ifcase#1{01}{01}\or{00}{01}\or{01}{00}\or{00}{00}\else{01}{01}\fi + }% + \cpt@testopt\ltxkeys@listparse@b,% +} +\robust@def*\ltxkeys@listparse@b[#1]#2{% + \cpt@stchoose{cpt@st}{#2}\ltxkeys@listitem\ltxkeys@listparse + \cptpushfunctions\ltxkeys@listparse{% + \\\ifloopbreak\\\ifltxkeys@useempty\\\ltxkeys@doo + \\\ltxkeys@listparse@c\\\ltxkeys@listparse@d\\\ltxkeys@loopcbk + \\\stopprocessinglistkey + }\cpt@csvdepth + \let\stopprocessinglistkey\loopbreak + \ifdefTF\ltxkeys@do + {\let\ltxkeys@doo\ltxkeys@do}{\cpt@notdeferr\ltxkeys@do}% + \def\ltxkeys@listparse@c{% + \ifboolTF{loopbreak} + {\gobble@to@sentinel\ltxkeys@nil#1}{\ltxkeys@listparse@d.}% + }% + \def\ltxkeys@listparse@d##1#1{% + \edef\ltxkeys@listitem{\expandcsonce{\@gobble##1}}% + \ltxkeys@ifxTF\ltxkeys@listitem\ltxkeys@nnil{}{% + \ltxkeys@ifcsemptyTF\ltxkeys@listitem{% + \ifboolFT{ltxkeys@useempty}{}{\ltxkeys@doo{}}% + }{% + \s@expandarg\ltxkeys@doo\ltxkeys@listitem + }% + \relax\ltxkeys@listparse@c + }% + }% + \ifswitchTF{ltxkeys@nlz}{% + \usename{\if\ltxkeys@inkv kv\else csv\fi @@normalize}*[#1]% + \ltxkeys@listitem + }{}% + \loopbreakfalse + \expandafter\ltxkeys@listparse@c\ltxkeys@listitem#1\ltxkeys@nil#1% + \cptpopfunctions\ltxkeys@listparse\cpt@csvdepth + \ifnum\cpt@csvdepth=\z@pt\undefcs\ltxkeys@do\fi +} +\def\ltxkeys@keyprefixhook{} +\def\ltxkeys@macroprefixhook{} +\def\ltxkeys@keyfamilyhook{} +\robust@def*\ltxkeys@reservekeyprefix{% + \cpt@testst\ltxkeys@res@rvekeyprefix +} +\robust@def*\ltxkeys@res@rvekeyprefix#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfiltermergecsv[,]\unexpanded{% + \ltxkeys@keyprefixhook{#1}\nofilter + \globalize\ltxkeys@keyprefixhook + }% + \ifcpt@st}\fi + }% +} +\robust@def*\ltxkeys@reservekeyfamily{% + \cpt@testst\ltxkeys@res@rvekeyfamily +} +\robust@def*\ltxkeys@res@rvekeyfamily#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfiltermergecsv[,]\unexpanded{% + \ltxkeys@keyfamilyhook{#1}\nofilter + \globalize\ltxkeys@keyfamilyhook + }% + \ifcpt@st}\fi + }% +} +\robust@def*\ltxkeys@reservemacroprefix{% + \cpt@testst\ltxkeys@res@rvemacroprefix +} +\robust@def*\ltxkeys@res@rvemacroprefix#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfiltermergecsv[,]\unexpanded{% + \ltxkeys@macroprefixhook{#1}\nofilter + \globalize\ltxkeys@macroprefixhook + }% + \ifcpt@st}\fi + }% +} +\ltxkeys@reservekeyfamily*{ltxkeys} +\ltxkeys@reservemacroprefix*{ltxkeys@} + +\robust@def*\ltxkeys@unreservekeyprefix{% + \cpt@testst\ltxkeys@unres@rvekeyprefix +} +\robust@def*\ltxkeys@unres@rvekeyprefix#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfilterremovecsv[,]\unexpanded{% + \ltxkeys@keyprefixhook{#1}\nofilter + \globalize\ltxkeys@keyprefixhook + }% + \ifcpt@st}\fi + }% +} +\robust@def*\ltxkeys@unreservekeyfamily{% + \cpt@testst\ltxkeys@unres@rvekeyfamily +} +\robust@def*\ltxkeys@unres@rvekeyfamily#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfilterremovecsv[,]\unexpanded{% + \ltxkeys@keyfamilyhook{#1}\nofilter + \globalize\ltxkeys@keyfamilyhook + }% + \ifcpt@st}\fi + }% +} +\robust@def*\ltxkeys@unreservemacroprefix{% + \cpt@testst\ltxkeys@unres@rvemacroprefix +} +\robust@def*\ltxkeys@unres@rvemacroprefix#1{% + \cptexpanded{% + \ifcpt@st\AfterEndOfStyleFile{\fi + \cptfilterremovecsv[,]\unexpanded{% + \ltxkeys@macroprefixhook{#1}\nofilter + \globalize\ltxkeys@macroprefixhook + }% + \ifcpt@st}\fi + }% +} +\robust@def*\ltxkeys@testopt@a#1{\cpt@testopt{\ltxkeys@testopt@b#1}{KV}} +\robust@def*\ltxkeys@testopt@b#1[#2]#3{% + \ifltxkeys@useempty\else + \iflacus#3\dolacus + \ltxkeys@warn{Empty key family encountered\on@line}% + \fi + \fi + \ltxkeys@makepf{#2}% + \ltxkeys@makehdr{#3}% + #1% +} +\robust@def*\ltxkeys@testopt@c#1{% + \begingroup + \catcode`\,=12\relax + \cpt@testopt{\ltxkeys@testopt@d#1}{KV}% +} +\robust@def*\ltxkeys@testopt@d#1[#2]#3{% + \ifltxkeys@pl\else + \def\temp@err##1{% + \ltxkeys@err{Multiple ##1 in \noexpandcsn + {ltxkeys@set\ifltxkeys@rm rm\fi keys}% + without '+' suffix}\ltxkeys@ehd + }% + \ltxkeys@ifeltcountTF[,](>)\@ne{#2}{% + \temp@err{prefixes}% + }{% + \ltxkeys@ifeltcountTF[,](>)\@ne{#3}{% + \temp@err{families}% + }{}% + }% + \fi + \endgroup + \ltxkeys@commanormalizeset{{#2}\ltxkeys@prefs,{#3}\ltxkeys@fams}% + \cpt@testopt{#1}{}% +} +\robust@def*\ltxkeys@testopt@e#1#2{% + \ltxkeys@testopt@a{% + \cptexpandarg{\cpt@testopt{\ltxkeys@testopt@f#1}}{#2\ltxkeys@hdr}% + }% +} +\robust@def*\ltxkeys@testopt@f#1[#2]#3{% + \ifboolTF{ltxkeys@sw}{% + \cpt@ifbrack{\ltxkeys@sttrue#1{#2}{#3}}{\ltxkeys@stfalse#1{#2}{#3}[]}% + }{% + \cpt@ifbrack{\ltxkeys@bracedefault{\ltxkeys@sttrue#1{#2}{#3}}}% + {\ltxkeys@stfalse#1{#2}{#3}[]}% + }% +} +\robust@def*\ltxkeys@testopt@g#1#2{% + \cptexpandarg\ltxkeys@testopt@a{\noexpandcsn{ltxkeys@#1}{#2}}% +} +\robust@def*\ltxkeys@bracedefault#1[{% + \begingroup + \toks@{#1}% + \defpass\ltxkeys@tempa##1]{% + \toks1\expandafter{\@gobble##1}% + \cptexpandsecond\endgroup{\the\toks@[{\the\toks1}]}% + }.% +} +\robust@def*\ltxkeys@testopt@@a#1{\ltxkeys@testst{\ltxkeys@testopt@@b#1}} +\robust@def*\ltxkeys@testopt@@b#1{\cpt@testopt{\ltxkeys@testopt@@c#1}{KV}} +\robust@def*\ltxkeys@testopt@@c#1[#2]{% + \ltxkeys@commanormalize{#2}\ltxkeys@prefs + \cpt@testfam{\ltxkeys@testopt@@d#1}% +} +\robust@def*\ltxkeys@testopt@@d#1<#2>{% + \expandafter\ltxkeys@commanormalize + \expandafter{\romannumeral-`\q#2}\ltxkeys@fams + \cpt@testopt{#1}{}% +} +\robust@def*\ltxkeys@findpointers#1{% + \ltxkeys@svfalse\ltxkeys@nvfalse + \let\infdpointers\cptswtrue + \let\infdp@inters\cptswfalse + \ltxkeys@findp@inters{\savevalue\needvalue}{#1}\ltxkeys@tkey{% + \ltxkeys@svtrue\ltxkeys@nvtrue + \ltxkeys@addtopointedkeys{savevalue}\ltxkeys@tkey + \ltxkeys@addtopointedkeys{needvalue}\ltxkeys@tkey + }{% + \ltxkeys@findp@inters{\needvalue\savevalue}{#1}\ltxkeys@tkey{% + \ltxkeys@svtrue\ltxkeys@nvtrue + \ltxkeys@addtopointedkeys{needvalue}\ltxkeys@tkey + \ltxkeys@addtopointedkeys{savevalue}\ltxkeys@tkey + }{% + \ltxkeys@findp@inters{\needvalue}{#1}\ltxkeys@tkey{% + \ltxkeys@svfalse\ltxkeys@nvtrue + \ltxkeys@addtopointedkeys{needvalue}\ltxkeys@tkey + }{% + \let\infdp@inters\cptswtrue + \ltxkeys@findp@inters{\savevalue}{#1}\ltxkeys@tkey{% + \ltxkeys@svtrue\ltxkeys@nvfalse + \ltxkeys@addtopointedkeys{savevalue}\ltxkeys@tkey + }{% + \ltxkeys@debug{==}{Key '\ltxkeys@tkey' has no pointer}% + }% + }% + }% + }% + \let\infdpointers\cptswfalse +} +\robust@def*\ltxkeys@findp@inters#1#2#3{% + \def\reserved@a##1#1##2##3\ltxkeys@nil{% + \edef#3{\unexpanded{##2}}% + \ltxkeys@ifxTF#3\ltxkeys@nnil{% + \edef#3{\unexpanded{##1}}% + \if\infdpointers + \if\infdp@inters + \ltxkeys@trimspacesincs#3% + \fi + \else + \ltxkeys@trimspacesincs#3% + \fi + \@secondoftwo + }{% + \ltxkeys@trimspacesincs#3% + \@firstoftwo + }% + }% + \reserved@a#2#1{\ltxkeys@nil}\ltxkeys@nil +} +\robust@def*\ltxkeys@addtopointedkeys#1#2{% + \letcstocsn\reserved@e{\ltxkeys@hdr#1keys}% + \ifdefTF\reserved@e{% + \xifinsetTF{,\cptoxdetok{#2},}{,\cptoxdetok\reserved@e,}{}{% + \csn@xdef{\ltxkeys@hdr#1keys}{% + \csliststack,\reserved@e\expandcsonce{#2}% + }% + }% + }{% + \csn@xdef{\ltxkeys@hdr#1keys}{\expandcsonce{#2}}% + }% +} +\robust@def*\ltxkeys@addtosavedvalue#1#2{% + \edef\ltxkeys@tempa{#1{\expandcsonce{#2}}}% + \letcstocsn\reserved@e{\ltxkeys@hdr @savedvaluelist}% + \ifdefTF\reserved@e{% + \oifinset@sp@TF,\ltxkeys@tempa\reserved@e{}{% + \csn@xdef{\ltxkeys@hdr @savedvaluelist}{% + \csliststack,\reserved@e\expandcsonce\ltxkeys@tempa + }% + }% + }{% + \csn@xdef{\ltxkeys@hdr @savedvaluelist}{% + \expandcsonce\ltxkeys@tempa + }% + }% +} +\new@def*\ltxkeys@currtriple{% + \ltxkeys@ifcsemptyTF\ltxkeys@ttpref{???}\ltxkeys@ttpref,% + \ltxkeys@ifcsemptyTF\ltxkeys@tfam{???}\ltxkeys@tfam,% + \ltxkeys@tkey +} +\robust@def*\ltxkeys@makepf#1{% + \s@expandarg\ltxkeys@trimspaces{#1}\ltxkeys@ttpref + \edef\ltxkeys@tpref{% + \ltxkeys@ifcsemptyTF\ltxkeys@ttpref{}{\ltxkeys@ttpref @}% + }% +} +\robust@def*\ltxkeys@makehdr#1{% + \s@expandarg\ltxkeys@trimspaces{#1}\ltxkeys@tfam + \edef\ltxkeys@hdr{% + \ltxkeys@tpref\ltxkeys@ifcsemptyTF\ltxkeys@tfam{}{\ltxkeys@tfam @}% + }% +} +\new@def*\ltxkeys@badkeynamelist{} +\robust@def*\ltxkeys@badkeynames#1{% + \ltxkeys@ifcsemptyTF\ltxkeys@badkeynamelist{% + \expandafter\ltxkeys@commanormalize\expandafter + {\detokenize{#1}}\ltxkeys@badkeynamelist + }{% + \cptexpandsecond{\cptfiltermergecsv[,]} + {\noexpand\ltxkeys@badkeynamelist{\detokenize{#1}}}\nofilter + }% +} +\newletcs\ltxkeys@addbadkeynames\ltxkeys@badkeynames +\robust@def*\ltxkeys@removebadkeynames#1{% + \ltxkeys@ifcsemptyTF\ltxkeys@badkeynamelist{% + \ltxkeys@info{Couldn't delete from empty + \string\ltxkeys@badkeynamelist}% + }{% + \cptexpandsecond{\cptfilterremovecsv[,]} + {\noexpand\ltxkeys@badkeynamelist{\detokenize{#1}}}\nofilter + }% +} +\ltxkeys@badkeynames{.code,ordkey,cmdkey,choicekey,boolkey,% + handledkeys,presetkeys,postsetkeys,rmkeys,executedkeys,bool,% + boolean,tog,toggle,switch,true,false,on,off,count,% + savevaluekeys,xfamilykeys,needvalue,savevalue,usevalue% +} +\robust@def*\ltxkeys@findbadkeyname#1{% + \begingroup + \edef\ltxkeys@tempa{\cpttrimspaces{#1}}% + \oifinset@sp@TF,\ltxkeys@tempa\ltxkeys@badkeynamelist{% + \ltxkeys@err{Bad key name '\ltxkeys@tempb'}\ltxkeys@ehd + }{}% + \endgroup +} +\robust@def*\ltxkeys@saveinitialkeyvals#1#2#3{% + \ifltxkeys@disable\else + \ifltxkeys@tracingkeys + \s@expandarg\ltxkeys@findbadkeyname{#2}% + \fi + \ifltxkeys@twk\else + \letcstocsn\ltxkeys@tempa{\ltxkeys@hdr initialkeyvals}% + \csn@xdef{\ltxkeys@hdr initialkeyvals}{% + \csliststack,\ltxkeys@tempa\expandcsonce{#2}=% + \ifstrcmpTF{#1}{bool}{false}{% + \ifstrcmpTF{#1}{switch}{false}{\unexpanded{#3}}% + }% + }% + \fi + \ifboolTF{ltxkeys@tracingkeys}{% + \ltxkeys@getbasechars[20]{#3}\ltxkeys@tempa + \ltxkeys@debug{==}{Definition done: + \ltxkeys@currtriple,\ltxkeys@tempa}% + }{}% + \fi +} +\robust@def*\ltxkeys@checkdefkey{% + \ifcsndefTF{\ltxkeys@hdr\ltxkeys@tkey}{% + \ifltxkeys@disable\else + \ifltxkeys@chdef + \ltxkeys@error{Key already exists: \ltxkeys@currtriple} + {Defining only new keys: key '\ltxkeys@currtriple' + already exists.}% + \else + \ltxkeys@debug{!!}{Key already exists: \ltxkeys@currtriple}% + \fi + \fi + }{% + \ltxkeys@debug{==}{This is a new key: \ltxkeys@currtriple}% + }% + \ltxkeys@chdeffalse + \ifltxkeys@reservenopath\else + \ltxkeys@checkreserved + \fi +} +\robust@def*\ltxkeys@checkreserved{% + \ltxkeys@debug{==}{Checking reserved key paths}% + \def\@do##1,##2,##3;{% + \ifnot@nil{##1}{% + \ifnum\numexpr + \ifdefTF##2{0}{-1}\ltxkeys@ifcsemptyTF##2{-1}{+0}% + \ifdefTF##3{+0}{-1}\ltxkeys@ifcsemptyTF##3{-1}{+0}<\z@pt + \else + \oifinset@sp@FT,##2##3{}{% + \ltxkeys@error{##1 '##2' is reserved} + {You have used a reserved ##1: '##2'.}% + }% + \fi + \@do + }% + }% + \@do key prefix,\ltxkeys@ttpref,\ltxkeys@keyprefixhook;% + key family,\ltxkeys@tfam,\ltxkeys@keyfamilyhook;% + macro prefix,\ltxkeys@macpref,\ltxkeys@macroprefixhook;\@nil,,;% + \ltxkeys@debug{==}{No clash with reserved key paths}% +} +\robust@def*\ltxkeys@ordkey{% + \ltxkeys@swfalse + \def\ltxkeys@macpref{}% + \ltxkeys@testopt@a\ltxkeys@ordkey@a +} +\newletcs\ltxkeys@ordkeys\ltxkeys@ordkey +\robust@def*\ltxkeys@newordkey{\ltxkeys@chdeftrue\ltxkeys@ordkey} +\newletcs\ltxkeys@newordkeys\ltxkeys@newordkey +\robust@def*\ltxkeys@ordkey@a#1{% + \ltxkeys@debug{==}{Ordinary key '\ltxkeys@tkey' is being defined}% + \cpt@ifbrack{% + \ltxkeys@bracedefault{\ltxkeys@sttrue\ltxkeys@ordkey@b{#1}}% + }{% + \ltxkeys@stfalse\ltxkeys@ordkey@b{#1}[]% + }% +} +\robust@def*\ltxkeys@ordkey@b#1[#2]#3{% + \let\ifltxkeys@keyst\ifltxkeys@st + \edef\ltxkeys@loopcbk##1{{##1}\unexpanded{{#2}{#3}}}% + \ifinsetTF,{#1}{% + \def\ltxkeys@do##1{% + \expandafter\ltxkeys@ordkey@c\ltxkeys@loopcbk{##1}% + }% + \ltxkeys@listparse1{#1}% + }{% + \ltxkeys@ordkey@c{#1}{#2}{#3}% + }% +} +\robust@def*\ltxkeys@ordkey@c#1#2#3{% + \ltxkeys@findpointers{#1}% + \ltxkeys@checkdefkey + \ifdefboolFT{ltxkeys@keyst}{}{% + \ltxkeys@definedefault\ltxkeys@tkey{#2}% + }% + \ltxkeys@saveinitialkeyvals{}\ltxkeys@tkey{#2}% + \@namedef{\ltxkeys@hdr\ltxkeys@tkey}##1{#3}% +} + +\robust@def*\ltxkeys@denyusevaluepointer#1{% + \xifinsetTF{\detokenize{\usevalue}}{\detokenize{#1}}{% + \ltxkeys@err{Pointer '\string\usevalue' not allowed when + defining keys}\@ehd + }{}% +} +% List processor keys: +\robust@def*\ltxkeys@getlistseparator#1{% + \xifinsetTF{\detokenize{\listsep}}{\detokenize{#1}}{% + \def\reserved@a##1\listsep##2##3\ltxkeys@nil{% + \ifblankTF{##2}{% + \def\ltxkeys@listsep{,}% + }{% + \edef\ltxkeys@listsep{\cpttrimspace{##2}}% + }% + \edef\ltxkeys@tempb{\cpttrimspace{##1}\cpttrimspace{##3}}% + }% + \reserved@a#1\ltxkeys@nil + }{% + \def\ltxkeys@listsep{,}% + \edef\ltxkeys@tempb{\cpttrimspace{#1}}% + }% +} +% \ltxkeyslistkey[<pref>]{<fam>}{<key>}[<dft>]{<fn>} +\robust@def*\ltxkeys@listkey{% + \ltxkeys@swfalse + \def\ltxkeys@macpref{}% + \ltxkeys@testopt@a\ltxkeys@listkey@a +} +\newletcs\ltxkeys@listkeys\ltxkeys@listkey +\robust@def*\ltxkeys@newlistkey{\ltxkeys@chdeftrue\ltxkeys@listkey} +\newletcs\ltxkeys@newlistkeys\ltxkeys@newlistkey +\robust@def*\ltxkeys@listkey@a#1{% + \ltxkeys@debug{==}{Lisp key '\ltxkeys@tkey' is being defined}% + \cpt@ifbrack{% + \ltxkeys@bracedefault{\ltxkeys@sttrue\ltxkeys@listkey@b{#1}}% + }{% + \ltxkeys@stfalse\ltxkeys@listkey@b{#1}[]% + }% +} +\robust@def*\ltxkeys@listkey@b#1[#2]#3{% + \let\ifltxkeys@keyst\ifltxkeys@st + \edef\ltxkeys@loopcbk##1{{##1}\unexpanded{{#2}{#3}}}% + \ifinsetTF,{#1}{% + \def\ltxkeys@do##1{% + \expandafter\ltxkeys@listkey@c\ltxkeys@loopcbk{##1}% + }% + \ltxkeys@listparse1{#1}% + }{% + \ltxkeys@listkey@c{#1}{#2}{#3}% + }% +} +\robust@def*\ltxkeys@listkey@c#1#2#3{% + \ltxkeys@denyusevaluepointer{#1}% + \ltxkeys@findpointers{#1}% + \ltxkeys@checkdefkey + \ifdefboolTF{ltxkeys@keyst}{% + \ltxkeys@definedefault\ltxkeys@tkey{#2}% + }{}% + \ltxkeys@saveinitialkeyvals{}\ltxkeys@tkey{#2}% + \ltxkeys@getlistseparator{#3}% + \def\reserved@a{\csn@def{\ltxkeys@hdr\ltxkeys@tkey @auxcbk}####1}% + \expandafter\reserved@a\expandafter{\ltxkeys@tempb}% + \csn@edef{\ltxkeys@hdr\ltxkeys@tkey}##1{% + \def\noexpand\ltxkeys@listcount{0}% + \edef\noexpand\ltxkeys@tempa{\noexpand\ltxkeys@stripallouterbraces{##1}}% + \def\noexpand\ltxkeys@do####1{% + \noexpand\cptpushnumber\noexpand\ltxkeys@listcount + \noexpandcsn{\ltxkeys@hdr\ltxkeys@tkey @auxcbk}{####1}% + }% + \ltxkeys@listparse*1[\ltxkeys@listsep]\noexpand\ltxkeys@tempa + }% +} + +\robust@def*\ltxkeys@cmdkey{% + \ltxkeys@swfalse + \ltxkeys@testopt@e\ltxkeys@cmdkey@a{cmd}% +} +\newletcs\ltxkeys@cmdkeys\ltxkeys@cmdkey +\robust@def*\ltxkeys@newcmdkey{\ltxkeys@chdeftrue\ltxkeys@cmdkey} +\newletcs\ltxkeys@newcmdkeys\ltxkeys@newcmdkey +\robust@def*\ltxkeys@cmdkey@a#1#2[#3]#4{% + \let\ifltxkeys@keyst\ifltxkeys@st + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@cmdkey@b{#1}{##1}\unexpanded{{#3}{#4}}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{\ltxkeys@loopcbk{##1}}% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@cmdkey@b{#1}{#2}{#3}{#4}% + }% +} +\robust@def*\ltxkeys@cmdkey@b#1#2#3#4{% + \def\ltxkeys@macpref{#1}% + \ltxkeys@findpointers{#2}% + \ltxkeys@debug{==}{Command key '\ltxkeys@tkey' is being defined}% + \ltxkeys@checkdefkey + \ifdefboolFT{ltxkeys@keyst}{}{\ltxkeys@definedefault\ltxkeys@tkey{#3}}% + \ltxkeys@saveinitialkeyvals{}\ltxkeys@tkey{#3}% + \begingroup + \edef\ltxkeys@tempa{\endgroup\csn@def{\ltxkeys@hdr\ltxkeys@tkey}####1}% + \edef\ltxkeys@tempb##1{% + {\csn@edef{#1\ltxkeys@tkey}{\noexpand\unexpanded{####1}}##1}% + }% + \expandafter\ltxkeys@tempa\ltxkeys@tempb{#4}% +} +\robust@def*\ltxkeys@boolkey{% + \ltxkeys@swtrue + \ltxkeys@testpl{\ltxkeys@testopt@e\ltxkeys@boolkey@a{bool}}% +} +\newletcs\ltxkeys@boolkeys\ltxkeys@boolkey +\robust@def*\ltxkeys@newboolkey{\ltxkeys@chdeftrue\ltxkeys@boolkey} +\newletcs\ltxkeys@newboolkeys\ltxkeys@newboolkey +\robust@def*\ltxkeys@boolkey@a#1#2[#3]{% + \let\ifltxkeys@keyst\ifltxkeys@st + \ifblankTF{#3}{}{% + \xifstrcmpTF{#3}{true}{}{% + \xifstrcmpTF{#3}{false}{}{% + \ltxkeys@err{Bad boolean value '#3'}\ltxkeys@ehd + }% + }% + }% + \ltxkeys@commanormalize{#2}\ltxkeys@tempa + \cptexpanded{% + \ifboolTF{ltxkeys@pl}\ltxkeys@boolkey@d + \ltxkeys@boolkey@c{#1}{\expandcsonce\ltxkeys@tempa}{#3}% + }% +} +\robust@def*\ltxkeys@boolkey@b#1#2#3{% + \ltxkeys@findpointers{#2}% + \ltxkeys@debug{==}{Boolean key '\ltxkeys@tkey' is being defined}% + \ltxkeys@saveinitialkeyvals{bool}\ltxkeys@tkey{#3}% + \edef\ltxkeys@resa##1##2{% + \ltxkeys@boolkey@e\cptmakecs{\ltxkeys@hdr\ltxkeys@tkey}% + {\ltxkeys@tkey}{#1\ltxkeys@tkey}\unexpanded{{#3}}% + {{\ltxkeys@setbool\noexpand\ltxkeys@resa\noexpand + \usename{#1\ltxkeys@tkey\noexpand\ltxkeys@resa}##1}% + \gobble@or@empty{##2}}% + }% +} +\robust@def*\ltxkeys@boolkey@c#1#2#3#4{% + \let\gobble@or@empty\@gobble + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@boolkey@b{#1}{##1}\unexpanded{{#3}}% + \noexpand\ltxkeys@resa\unexpanded{{#4}}{}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{\ltxkeys@loopcbk{##1}}% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@loopcbk{#2}% + }% +} +\robust@def*\ltxkeys@boolkey@d#1#2#3#4#5{% + \let\gobble@or@empty\@empty + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@boolkey@b{#1}{##1}\unexpanded{{#3}}% + \noexpand\ltxkeys@resa\unexpanded{{#4}{#5}}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{\ltxkeys@loopcbk{##1}}% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@loopcbk{#2}% + }% +} +\robust@def*\ltxkeys@boolkey@e#1#2#3#4#5{% + % We've delayed the calling of \ltxkeys@checkdefkey till + % here because of biboolkeys: + \def\reserved@a##1#2\ltxkeys@nil{% + \def\ltxkeys@macpref{##1}% + }% + \reserved@a#3\ltxkeys@nil + \ltxkeys@checkdefkey + \csnnewif{#3}% + \ifboolFT{ltxkeys@keyst}{}{\ltxkeys@definedefault{#2}{#4}}% + \cptexpandarg{\def#1##1}{% + \csn@def{#3}{####1}% + \noexpandcsn{cpt@pl\ifltxkeys@pl true\else false\fi}% + \unexpanded{\cpt@sttrue\ltxkeys@cc@b,(\ltxkeys@resa)% + {##1}{true,false}#5}% + }% +} +% \ltxkeys@biboolkeys[pref]{fam}[mp]{key1,key2}[dft]{key1-fn}{key2-fn} +% \ltxkeys@biboolkeys+[pref]{fam}[mp]{key1,key2}[dft]{key1-fn}{key2-fn} +% {<fallback>} +% <fallback> will be called if input isn't valid (ie, not in the +% set {true | false}. +\robust@def*\ltxkeys@biboolkeys{% + \ltxkeys@swtrue + \ltxkeys@testpl{\ltxkeys@testopt@e\ltxkeys@biboolkeys@a{}}% +} +\robust@def*\ltxkeys@newbiboolkeys{\ltxkeys@chdeftrue\ltxkeys@biboolkeys} +% #1: <mp> +% #2: keys +% #3: default value +\robust@def*\ltxkeys@biboolkeys@a#1#2[#3]{% + \ifboolTF{ltxkeys@pl}\ltxkeys@biboolkeys@c\ltxkeys@biboolkeys@b + {#1}{#2}{#3}% +} +% #1: <mp> +% #2: keys +% #3: default value +% #4: callback for primary boolean key +% #5: callback for secondary boolean key +\robust@def*\ltxkeys@biboolkeys@b#1#2#3#4#5{% + \ltxkeys@biboolkeys@d{#1}{#2}{#3}% + \ltxkeys@tempa{#4}% + \ltxkeys@tempb{#5}% +} +% #1: <mp> +% #2: keys +% #3: default value +% #4: callback for primary boolean key +% #5: callback for secondary boolean key +% #6: callback if user-supplied value isn't valid +\robust@def*\ltxkeys@biboolkeys@c#1#2#3#4#5#6{% + \ltxkeys@biboolkeys@d{#1}{#2}{#3}% + \ltxkeys@tempa{#4}{#6}% + \ltxkeys@tempb{#5}{#6}% +} +% #1: <mp> +% #2: keys +% #3: default value +\robust@def*\ltxkeys@biboolkeys@d#1#2#3{% + \ltxkeys@ifeltcountTF[,](=)\tw@{#2}{}{% + \ltxkeys@error{Biboolean keys '#2' not equal to 2}\ltxkeys@ehd + }% + \ltxkeys@commanormalize{#2}\ltxkeys@keys + \def\ltxkeys@tempa##1,##2\ltxkeys@nil##3##4{% + \ltxkeys@findpointers{##1}% + \ltxkeys@debug{==}{Boolean key '\ltxkeys@tkey' is being defined}% + \let\ltxkeys@tkeya\ltxkeys@tkey + \ltxkeys@findpointers{##2}% + \ltxkeys@debug{==}{Boolean key '\ltxkeys@tkey' is being defined}% + \cptexpandarg{\cpt@newv@riables{tog}\ltxkeys@hdr} + {\ltxkeys@tkeya,\ltxkeys@tkey}[false]% + \cptexpandsecond\ltxkeys@biboolkeys@e + {{\ltxkeys@tkeya}{\ltxkeys@tkey}}{#1}{#3}{##3}{##4}% + }% + \cptexpandsecond\ltxkeys@tempa + {\ltxkeys@keys\ltxkeys@nil{\ltxkeys@ttpref}{\ltxkeys@tfam}}% + \undefcs\ltxkeys@tkeya +} +% #1: primary key +% #2: secondary key +% #3: <mp> +% #4: default value +% #5: key prefix +% #6: key family +\robust@def\ltxkeys@biboolkeys@e#1#2#3#4#5#6{% + \ifltxkeys@pl + % For primary key: + \long\def\ltxkeys@tempa##1##2{% + % ##1->callback if input is valid, ##2->callback otherwise + \aftercsname\ltxkeys@boolkey@e{\ltxkeys@hdr#1}{#1}{#3#1}{#4}{{% + \ltxkeys@setbool\ltxkeys@resa\usename{#3#1\ltxkeys@resa}% + ##1\relax + \ltxkeys@biboolkeys@f{#1}{#2}{#3#1}{#5}{#6}% + }{##2}}% + }% + % For secondary key: + \long\def\ltxkeys@tempb##1##2{% + % ##1->callback if input is valid, ##2->callback otherwise + \aftercsname\ltxkeys@boolkey@e{\ltxkeys@hdr#2}{#2}{#3#2}{#4}{{% + \ltxkeys@setbool\ltxkeys@resa\usename{#3#2\ltxkeys@resa}% + ##1\relax + \ltxkeys@biboolkeys@f{#2}{#1}{#3#2}{#5}{#6}% + }{##2}}% + }% + \else + % For primary key: + \long\def\ltxkeys@tempa##1{% + % ##1->callback if input is valid + \aftercsname\ltxkeys@boolkey@e{\ltxkeys@hdr#1}{#1}{#3#1}{#4}{% + \ltxkeys@setbool\ltxkeys@resa\usename{#3#1\ltxkeys@resa}% + ##1\relax + \ltxkeys@biboolkeys@f{#1}{#2}{#3#1}{#5}{#6}% + }% + }% + % For secondary key: + \long\def\ltxkeys@tempb##1{% + % ##1->callback if input is valid + \aftercsname\ltxkeys@boolkey@e{\ltxkeys@hdr#2}{#2}{#3#2}{#4}{% + \ltxkeys@setbool\ltxkeys@resa\usename{#3#2\ltxkeys@resa}% + ##1\relax + \ltxkeys@biboolkeys@f{#2}{#1}{#3#2}{#5}{#6}% + }% + }% + \fi +} +\robust@def\ltxkeys@biboolkeys@f#1#2#3#4#5{% + % If #1 is not being called by its twin (#2): + \iftogTF{\ltxkeys@hdr#1}{}{% + % Set flag to show that #2 is being set within its twin (#1): + \settogtrue{\ltxkeys@hdr#2}% + \cptexpandarg{\ltxkeys@setkeys[#4]{#5}}{#2=\thebool@reverse{#3}}% + \settogfalse{\ltxkeys@hdr#2}% + }% +} +%%++ +% \ltxkeys@stylekey[<pref>]{<fam>}[<mp>]{<key>}[<dft>](<deps>){<fn>}. +% The dependants <deps> have the syntax: +% {<keytype>/<keyname>/<dft>/<callback>; another set of dependant; etc}. +% +% <keytype> can be 'ord' (ordinary key), 'cmd' (command key), 'bool' +% (boolean key), or 'choice' (choice key). +% +% If the *-form is used, all undefined dependants will be defined and set +% on the fly as the parent is being set. If the *-form isn't used and +% undefined dependants occur, then an error message will be flagged +% at the time the parent is being set. + +% It is possible to refer to the parent key's name and current value +% (with \parentkey and \parentval) and parent key's callback +% (with full macro name) within <dft> and <callback> of <deps>. +% +% '#1' in the callback of dependant key refers to the current value of +% the dependant key. + +\robust@def*\ltxkeys@stylekey{% + \ltxkeys@swfalse + % The test for star here is for the 2 types of style key. + % The test for defining a default for the key is at + % \ltxkeys@testopt@f, via \ltxkeys@testopt@e. + \ltxkeys@testst{% + \cpt@cnta\ifltxkeys@st1\else0\fi\relax + \ltxkeys@testopt@e\ltxkeys@stylekey@a{style}% + }% +} +\newletcs\ltxkeys@stylekeys\ltxkeys@stylekey +\robust@def*\ltxkeys@newstylekey{\ltxkeys@chdeftrue\ltxkeys@stylekey} +\newletcs\ltxkeys@newstylekeys\ltxkeys@newstylekey +\robust@def*\ltxkeys@stylekey@a#1#2[#3]{% + \def\ltxkeys@macpref{#1}% + \cpt@testpnopt{\ltxkeys@stylekey@b{#1}{#2}{#3}}{}% +} +\robust@def*\ltxkeys@stylekey@b#1#2#3(#4)#5{% + \let\ifltxkeys@keyst\ifltxkeys@st + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@stylekey@c{#1}{##1}\unexpanded{{#3}{#4}{#5}}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{\ltxkeys@loopcbk{##1}}% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@stylekey@c{#1}{#2}{#3}{#4}{#5}% + }% +} +\robust@def*\ltxkeys@stylekey@c#1#2#3#4#5{% + \ltxkeys@debug{==}{Style key '\ltxkeys@tkey' is being defined}% + \ltxkeys@findpointers{#2}% + \ltxkeys@checkdefkey + \ltxkeys@saveinitialkeyvals{}\ltxkeys@tkey{#3}% + \ifltxkeys@keyst + \s@expandarg\ltxkeys@definedefault\ltxkeys@tkey{#3}% + \fi + \cptexpandtwoargs\ltxkeys@in + {\detokenize\expandafter{\unexpanded\expandafter + {\csname\ltxkeys@hdr\ltxkeys@tkey @value\endcsname}}} + {\detokenize{#4}}% + \csn@edef{\ltxkeys@hdr\ltxkeys@tkey @dependants}{\unexpanded{#4}}% + \cptpassexpanded{% + \csn@def{\ltxkeys@hdr\ltxkeys@tkey}####1{% + \csn@edef{#1\ltxkeys@tkey}{\noexpand\unexpanded{####1}}% + \edef\noexpand\parentval{\noexpand\unexpanded{####1}}% + \ifin@ + \csn@xdef{\ltxkeys@hdr\ltxkeys@tkey @value}% + {\noexpand\unexpanded{####1}}% + \fi + \unexpanded{#5}\relax + \ltxkeys@setdependants{\number\cpt@cnta}{#1}% + }% + }% +} + +% #1: style type: '1' (*-form) or '0' (plain, non-*-form). +% #2: <macro prefix> +\robust@def*\ltxkeys@setdependants#1#2{% + \letcstocsn\ltxkeys@tempa{\ltxkeys@hdr\ltxkeys@tkey @dependants}% + % If no dependants: + \ltxkeys@ifcsemptyTF\ltxkeys@tempa{}{% + \cpt@sttrue + \expandafter\cpt@csvnormalize + \expandafter[\ltxkeys@keyparser]\ltxkeys@tempa + % If we're in \ltxkeys@declarekeys, don't set dependants + % when setting up defaults: + \ifboolTF{ltxkeys@dec}{}{% + \cptexpandargonce{\ltxkeys@s@tdependants{#1}{#2}}\ltxkeys@tempa + }% + }% +} +\robust@def*\ltxkeys@s@tdependants#1#2#3{% + \begingroup + \toks0{}\toks1{}\toks2{}% + \def\ltxkeys@do##1{% + \ltxkeys@s@td@pendants{##1}% + \ltxkeys@s@td@p@ndants{#1}% + }% + \cptexpandsecond{\ltxkeys@listparse0}{[\ltxkeys@keyparser]}{#3}% + % We're in a group: so \ifblankTF can be temporarily redefined: + \let\ifblankTF\relax + \cptpassexpanded{% + \endgroup + % If we're in dependant keys, use the user-supplied value + % of parent key to initialize the slave key in \ltxkeys@declarekeys: + \noexpand\ltxkeys@deptrue + \ifblankTF{\the\toks0}{}% + {\ltxkeys@setkeys[\expandcsonce\ltxkeys@ttpref]% + {\expandcsonce\ltxkeys@tfam}{\the\toks0}}% + \ifblankTF{\the\toks1}{}% + {\ltxkeys@declarekeys[\ltxkeys@ttpref]% + {\ltxkeys@tfam}[#2]{\the\toks1}}% + \ifblankTF{\the\toks2}{}{% + \ltxkeys@err{Undefined dependant keys: ||\the\toks2||} + {I have come across undefined dependant keys. You can + \MsgBrk use the star (*) form of '\string\ltxkeys@stylekey' + \MsgBrk to define and set dependant keys on the fly. + }% + }% + }% + \ltxkeys@depfalse +} +\robust@def*\ltxkeys@s@td@pendants#1{% + \begingroup + \def\key@name{}\def\key@default{}\def\key@callback{}% + % '#1' may come with nested parameters that will make it + % impossible to include '#1' directly in \temp@err. + % So we put '#1' in a token register: + \@temptokena{#1}% + \def\ltxkeys@splita##1/##2/{% + \ifblankTF{##1##2}{% + % No keys to read (remove forward slashes): + \ltxkeys@err{Something is wrong with dependant keys}\ltxkeys@ehd + \expandafter\gobble@to@sentinel\expandafter + \ltxkeys@nil\ltxkeys@keyparser + }{% + \ltxkeys@trimspaces{##1}\key@type + % To avoid back-linking, a style key can't have another + % style key as a dependant: + \expandafter\ltxkeys@striplaststar + \key@type\@empty*\@empty\ltxkeys@nil\key@type + \xifstrcmpFT\key@type{sty}{}{% + \ltxkeys@err{A dependant key can't have dependants: + ||\the\@temptokena||}\ltxkeys@ehd + }% + \xifinsetTF\key@type{,ord,cmd,bool,choice,}{}{% + \ltxkeys@err{Invalid key type '\key@type' in dependant key(s) + ||\the\@temptokena||}\ltxkeys@ehd + }% + \ifblankTF{##2}{% + \ltxkeys@err{Empty key name in dependant key(s) + ||\the\@temptokena||}\ltxkeys@ehd + }{% + \ltxkeys@findpointers{##2}% + \let\key@name\ltxkeys@tkey + }% + \ltxkeys@ifrejname{% + \ltxkeys@err{Wrong syntax for dependant keys}\ltxkeys@ehd + }% + \ltxkeys@splitb.% + }% + }% + \def\ltxkeys@splitb##1/##2/##3\ltxkeys@nil{% + \edef\key@default{\expandcsonce{\@gobble##1}}% + \ltxkeys@trimspacesincs\key@default + \xifstrcmpTF{\cptoxdetok\key@default}{\detokenize{\parentval}}{% + \edef\key@default{\expandcstwice\key@default}% + }{}% + \edef\key@callback{\unexpanded{##2}}% + \ltxkeys@stripdotcode\key@callback + }% + \ltxkeys@splita#1/^?^/^?^/^?^/\ltxkeys@nil + \let\do\cpt@csexit + \cptpassexpanded{% + \endgroup + \do\key@type\do\key@name\do\key@default\do\key@callback + }% +} +\robust@def*\ltxkeys@s@td@p@ndants#1{% + \ifcsndefTF{\ltxkeys@hdr\key@name}{% + \cptpassexpanded{% + \toks0{\the\toks0\oifblankTF{\the\toks0}{}{,}% + \expandcsonce\key@name=\expandcsonce\key@default}% + }% + }{% + \cptpassexpanded{% + % Test if the parent was defined with the + % *-form of \ltxkeys@stylekey, ie, if #1=1 or 0: + \ifnum\numexpr#1=\@ne + \toks1{% + \the\toks1\oifblankTF{\the\toks1}{}{\ltxkeys@keyparser}% + \key@type/\expandcsonce\key@name + \ifx\key@default\ltxkeys@rej\else/\expandcsonce\key@default\fi + \ifx\key@callback\ltxkeys@rej\else/\expandcsonce\key@callback\fi + }% + \else + \toks2{\the\toks2\oifblankTF{\the\toks2}{}{,}% + \expandcsonce\key@name}% + \fi + }% + }% +} + +%%++ +% \ltxkeys@choicekey*+![<pref]{<fam>}[<mp>]{<key>}[<bin>]{<alt>}[<dft>]{<f1>}{<f2>} +% If <mp> is absent, then \ltxkeys@choicekey uses \chc<pref>@<family>@<key> +% to hold user input. +% +% When there are no callbacks in <alt> ist has the syntax +% {choice1, choice2, etc}. +% +% But when <alt> has callbacks, it has the syntax: +% {choice1/.code=callback1; choice2/.code=callback2; etc}. +% +% It is possible to refer to the current value of <key> as '#1' in <alt>. +% +\robust@def*\ltxkeys@choicekey{% + \ltxkeys@swfalse + \ltxkeys@suffixcheck{\ltxkeys@teststpl{\ltxkeys@testcl + {\ltxkeys@testopt@a{\cpt@testopt\ltxkeys@choicekey@a + {chc\ltxkeys@hdr}}}}}% +} +\newletcs\ltxkeys@choicekeys\ltxkeys@choicekey +\robust@def*\ltxkeys@newchoicekey{\ltxkeys@chdeftrue\ltxkeys@choicekey} +\newletcs\ltxkeys@newchoicekeys\ltxkeys@newchoicekey +% #1: <mp> (prefix for user-input holder) name; +% #2: keynames +\robust@def*\ltxkeys@choicekey@a[#1]#2{% + \edef\ltxkeys@macpref{#1}% + \begingroup + \catcode`\=\string=12\catcode`\,=12 + \catcode`\;=12\catcode`\.=12 + \cpt@testopt{\expandafter\endgroup\ltxkeys@choicekey@b{#1}{#2}}{}% +} +% #3: bin +% #4 alt values +\robust@def*\ltxkeys@choicekey@b#1#2[#3]#4{% + \ifblankTF{#4}{% + \ltxkeys@err{Choice key can't have empty nominations}\ltxkeys@ehd + }{}% + % Make \ltxkeys@chclist for the choice key: + \ltxkeys@makechclist{#4}{0}% + \cpt@ifbrack{% + \ltxkeys@sttrue\ltxkeys@bracedefault + {\ltxkeys@choicekey@c{#1}{#2}{#3}{#4}}% + }{% + \ltxkeys@stfalse\ltxkeys@choicekey@c{#1}{#2}{#3}{#4}[]% + }% +} +% #1: mp, #2: keynames, #3: bin, #4: alt, #5: default +\robust@def*\ltxkeys@choicekey@c#1#2#3#4[#5]{% + \ltxkeys@commanormalize{#2}\ltxkeys@tempa + \edef\ltxkeys@tempa{\unexpanded{{#1}}{\expandcsonce\ltxkeys@tempa}}% + \cptexpanded{% + \noexpand\expandafter + \ifltxkeys@pl\ltxkeys@choicekey@f\else\ltxkeys@choicekey@e\fi + }% + \ltxkeys@tempa{#3}{#4}{#5}% +} +% #1: mp, #2: keyname, #3: default +\robust@def*\ltxkeys@choicekey@d#1#2#3{% + \ltxkeys@findpointers{#2}% + \ltxkeys@debug{==}{Choice key '\ltxkeys@tkey' is being defined}% + \ltxkeys@checkdefkey + \ifltxkeys@st\ltxkeys@definedefault\ltxkeys@tkey{#3}\fi + \ltxkeys@saveinitialkeyvals{choice}\ltxkeys@tkey{#3}% + \edef\ltxkeys@resa##1##2##3{% + \ltxkeys@choicekey@g\cptmakecs{\ltxkeys@hdr\ltxkeys@tkey}% + {#1\ltxkeys@tkey}{##1}{##2}{##3}% + }% +} +% #1: mp, #2: keynames, #3: bin, #4: alt, #5: default, #6: cbk +\robust@def*\ltxkeys@choicekey@e#1#2#3#4#5#6{% + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@choicekey@d{#1}{##1}\unexpanded{{#5}}% + \noexpand\ltxkeys@resa\unexpanded{{#3}{#4}{{#6}}}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{% + \ltxkeys@loopcbk{##1}% + }% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@loopcbk{#2}% + }% +} +% #1: mp, #2: keyname, #3: bin, #4: alt, #5: default, #6: cbk1, #7: cbk2 +\robust@def*\ltxkeys@choicekey@f#1#2#3#4#5#6#7{% + \edef\ltxkeys@loopcbk##1{% + \ltxkeys@choicekey@d{#1}{##1}\unexpanded{{#5}}% + \noexpand\ltxkeys@resa\unexpanded{{#3}{#4}{{#6}{#7}}}% + }% + \ifinsetTF,{#2}{% + \def\ltxkeys@do##1{% + \ltxkeys@loopcbk{##1}% + }% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@loopcbk{#2}% + }% +} +% #1: keymacro, #2: mp+keyname, #3: bin, #4: alt, #5: cbk +\robust@def*\ltxkeys@choicekey@g#1#2#3#4#5{% + \ifinsetTF{/.code=}{#4}{% + \def\ltxkeys@tempa{\ltxkeys@executechclist}% + }{% + \ifinsetTF{/}{#4}{% + \def\ltxkeys@tempa{\ltxkeys@executechclist}% + }{% + \def\ltxkeys@tempa{\@gobble}% + }% + }% + \edef#1{% + \csn@edef{#2}{\noexpand\unexpanded{####1}}% + \cptmakecs{cpt@st\ifltxkeys@st true\else false\fi}% + \cptmakecs{cpt@pl\ifltxkeys@pl true\else false\fi}% + \ifltxkeys@cl + \edef\noexpand\reserved@a{####1}% + \else + \edef\noexpand\reserved@a{\noexpand\unexpanded{####1}}% + \fi + \def\noexpand\reserved@b{\unexpanded{\ltxkeys@cc@b,(#3)}}% + \unexpanded{\expandafter\reserved@b\expandafter{\reserved@a}}% + {\expandcsonce\ltxkeys@chclist}\unexpanded{#5}% + \expandcsonce\ltxkeys@tempa{\unexpanded{#4}}% + }% + % Believe it or not, this is one of the tricks that works: + \def\ltxkeys@tempa{\def#1####1}% + \expandafter\ltxkeys@tempa\expandafter{#1}% +} +% Make the list of valid alternate values of a choice key: +% #1: alt-list (containing choice callbacks) +% #2: caller identifier (0 for defining, 1 for setting key) +\robust@def*\ltxkeys@makechclist#1#2{% + \begingroup + \def\ltxkeys@chclist{}% + \def\ltxkeys@tempb##1/.code=##2\ltxkeys@nil{% + \ltxkeys@tempd{##1}{##2}% + }% + \def\ltxkeys@tempc##1/##2/##3\ltxkeys@nil{% + \ltxkeys@tempd{##1}{##2}% + }% + \def\ltxkeys@tempd##1##2{% + \ltxkeys@remdottrimspaces{##1}\ltxkeys@tempa + \ifcase#2\relax + % We're defining a choice key: + \cptaddtolist*[,]\ltxkeys@chclist\ltxkeys@tempa + \or + % We're setting a choice key: + \cptexpandarg\lowercase{% + \def\noexpand\ltxkeys@tempa{\expandcsonce\ltxkeys@tempa}% + \def\noexpand\ltxkeys@tval{\expandcsonce\ltxkeys@tval}% + }% + % The comparison must be catcode agonistic: + \oifstrcmpTF\ltxkeys@tempa\ltxkeys@tval{% + \edef\ltxkeys@chclist{\unexpanded{##2}}% + \loopbreak + }{}% + \else + \ltxkeys@err{Invalid number '#2' while + in \string\ltxkeys@makechclist}\ltxkeys@ehd + \fi + }% + \def\ltxkeys@do##1{% + \ifinsetTF{/.code=}{##1}{% + \ltxkeys@tempb.##1\ltxkeys@nil + }{% + \ltxkeys@tempc.##1//\ltxkeys@nil + }% + }% + \expandafter\ifinsetTF\expandafter{\ltxkeys@keyparser}{#1}{% + \cptexpandsecond{\ltxkeys@listparse1}{[\ltxkeys@keyparser]}{#1}% + }{% + \ifinsetTF{,}{#1}{% + \ltxkeys@listparse1[,]{#1}% + }{% + \ltxkeys@listparse1[,]{#1,}% + }% + }% + \postgroupdef\ltxkeys@chclist\endgroup +} +% Execute the callback for alternate values of a choice key: +% #1: alt-list (containing choice callbacks) +\robust@def*\ltxkeys@executechclist#1{% + \begingroup + \ltxkeys@makechclist{#1}{1}% + \expandafter\endgroup\ltxkeys@chclist +} +% #1: key name +% #2: default value +\robust@def*\ltxkeys@definedefault#1#2{% + \xifstrcmpTF{\detokenize{#2}}{\detokenize{\parentval}}{% + \s@expandarg\ltxkeys@trimspaces{#2}\ltxkeys@tempa + }{% + \ltxkeys@trimspaces{#2}\ltxkeys@tempa + }% + \csn@edef{\ltxkeys@hdr#1@default}{% + \noexpandcsn{\ltxkeys@hdr#1}{\expandcsonce\ltxkeys@tempa}% + }% +} +\robust@def*\ltxkeys@getkeyname#1=#2\ltxkeys@nil#3{% + \ltxkeys@findpointers{#1}% + \let#3\ltxkeys@tkey +} +\robust@def*\ltxkeys@getkeynames#1{% + \begingroup + \def\ltxkeys@keynames{}% + \def\ltxkeys@do##1{% + \ltxkeys@getkeyname##1=\ltxkeys@nil\ltxkeys@tempa + \edef\ltxkeys@keynames{% + \csliststack,\ltxkeys@keynames\expandcsonce\ltxkeys@tempa + }% + }% + \ifblankTF{#1}{}{\ltxkeys@listparse3{#1}}% + \postgroupdef\ltxkeys@keynames\endgroup +} +\robust@def*\ltxkeys@getkeyvalue#1=#2\ltxkeys@nil#3{% + \ifinsetTF{=\ltxkeys@nil}{#2\ltxkeys@nil}{% + \ltxkeys@novaluefalse + \begingroup + \def\ltxkeys@tempa##1=##2\ltxkeys@nil{\endgroup +% \s@expandarg\ltxkeys@trimspaces{\@gobble##1}#3% + \ltxkeys@remdottrimspaces{##1}#3% + \let\CurrentVal#3% + }% + \ltxkeys@tempa.#2\ltxkeys@nil + }{% + \ltxkeys@novaluetrue\def#3{}% + }% +} +\robust@def*\ltxkeys@splitkeyval#1\ltxkeys@nil#2#3{% + \ltxkeys@getkeyname#1=\ltxkeys@nil#2% + \ltxkeys@getkeyvalue#1=\ltxkeys@nil#3% +} +% Keys that must (or not) appear in \usepackage and \RequirePackage: +% \ltxkeys@optionkeys[<prf>]{<fam>}{<keys>} +\robust@def*\ltxkeys@optionkeys{% + \ltxkeys@notinpkgclserr\ltxkeys@optionkeys + \cpt@testst\ltxkeys@opti@nkeys +} +\robust@def*\ltxkeys@opti@nkeys{% + \ifboolTF{cpt@st}{% + \ltxkeys@testopt@g{opti@nk@ys}{non}% + }{% + \ltxkeys@testopt@g{opti@nk@ys}{}% + }% +} +\robust@def*\ltxkeys@nonoptionkeys#1{% + \ltxkeys@notinpkgclserr\ltxkeys@nonoptionkeys + \ifstrcmpTF{#1}{*}{% + \ltxkeys@warn{No star form of \string\ltxkeys@nonoptionkeys: + \MsgBrk star (*) ignored}% + \ltxkeys@testopt@g{opti@nk@ys}{non}% + }{% + \ifsingletokenTF{#1}{% + \ltxkeys@testopt@g{opti@nk@ys}{non}#1% + }{% + \ltxkeys@testopt@g{opti@nk@ys}{non}{#1}% + }% + }% +} +\robust@def*\ltxkeys@opti@nk@ys#1#2{% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \ifcsndefTF{\ltxkeys@hdr#1optionkeys}{% + \xifinsetTF{,\detokenize{##1},} + {,\cptsxdetok{\usename{\ltxkeys@hdr#1optionkeys}},}{}{% + \csn@edef{\ltxkeys@hdr#1optionkeys}{% + \expandcsnonce{\ltxkeys@hdr#1optionkeys},% + \unexpanded{##1}% + }% + }% + }{% + \csn@def{\ltxkeys@hdr#1optionkeys}{##1}% + }% + }{% + \ltxkeys@err{Key '##1' is undefined in family '\ltxkeys@tfam'} + {Only defined keys can be made '#1option' keys.}% + }% + }% + \ltxkeys@listparse1{#2}% +} +% Make defined keys option-keys from their <pref> and <fam>. +% The starred (*) variant makes non-option keys. +\robust@def*\ltxkeys@makeoptionkeys{% + \cpt@teststopt\ltxkeys@m@keoptionkeys{KV}% +} +\robust@def*\ltxkeys@m@keoptionkeys[#1]#2{% + \let\ifltxkeys@keyst\ifcpt@st + \ifcsndefTF{#1@#2@initialkeyvals}{% + \letcstocsn\ltxkeys@tempa{#1@#2@initialkeyvals}% + }{% + \ltxkeys@err{No initial key-values for family '#2'}\ltxkeys@ehd + }% + \s@expandarg\ltxkeys@getkeynames\ltxkeys@tempa + \ltxkeys@ifcsemptyTF\ltxkeys@keynames{}{% + \cptexpandargonce + {\usename{ltxkeys@\ifltxkeys@keyst non\fi optionkeys}[#1]{#2}} + \ltxkeys@keynames + }% +} +\robust@def*\ltxkeys@makenonoptionkeys{% + \cpt@sttrue\cpt@testopt\ltxkeys@m@keoptionkeys{KV}% +} +\robust@def*\ltxkeys@handledkeys{% + \ltxkeys@testopt@g{h@ndledkeys}{handled}% +} +\newletcs\ltxkeys@addhandledkeys\ltxkeys@handledkeys +\robust@def*\ltxkeys@removehandledkeys{% + \ltxkeys@testopt@g{rem@vehandledkeys}{handled}% +} +\robust@def*\ltxkeys@undefhandledkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{undefh@ndledkeys}{handled}}% +} +\robust@def*\ltxkeys@emptifyhandledkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{emptifyh@ndledkeys}{handled}}% +} +\robust@def*\ltxkeys@savevaluekeys{% + % \<KV>@<fam>@savevalue@keys is used by pointed keys. + \ltxkeys@testopt@g{h@ndledkeys}{savevalue}% +} +\newletcs\ltxkeys@addsavevaluekeys\ltxkeys@savevaluekeys +\robust@def*\ltxkeys@removesavevaluekeys{% + \ltxkeys@testopt@g{rem@vehandledkeys}{savevalue}% +} +\robust@def*\ltxkeys@undefsavevaluekeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{undefh@ndledkeys}{savevalue}}% +} +\robust@def*\ltxkeys@emptifysavevaluekeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{emptifyh@ndledkeys}{savevalue}}% +} +\robust@def*\ltxkeys@h@ndledkeys#1#2{% + \letcstocsn\ltxkeys@rsvda{\ltxkeys@hdr#1keys}% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \def\ltxkeys@tempb{##1}% + \ifdefTF\ltxkeys@rsvda{% + \oifinset@sp@TF,\ltxkeys@tempb\ltxkeys@rsvda{}{% + \edef\ltxkeys@rsvda{% + \csliststack,\ltxkeys@rsvda\unexpanded{##1}% + }% + }% + }{% + \let\ltxkeys@rsvda\ltxkeys@tempb + }% + }{% + \ltxkeys@err{Key '##1' is undefined in family + '\ltxkeys@tfam'} + {Only defined keys can be made #1-keys.}% + }% + }% + \ltxkeys@listparse1{#2}% + \letcsntocs{\ltxkeys@hdr#1keys}\ltxkeys@rsvda +} +\robust@def*\ltxkeys@rem@vehandledkeys#1#2{% + \letcstocsn\ltxkeys@rsvda{\ltxkeys@hdr#1keys}% + \ifdefTF\ltxkeys@rsvda{% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \def\ltxkeys@tempb{##1}% + \oifinset@sp@TF,\ltxkeys@tempb\ltxkeys@rsvda{% + \let\cpt@fromrem\cptswtrue\cpt@sttrue + \cpt@removeoneelement[,]\ltxkeys@rsvda{##1}% + }{% + \ltxkeys@warn{Key '##1' with prefix '\ltxkeys@ttpref' + in family\MsgBrk '\ltxkeys@tfam' is not a #1 key: + \MsgBrk It couldn't be deleted from #1-keys list.}% + }% + }{% + \ltxkeys@err{Key '##1' with prefix '\ltxkeys@ttpref' in + family\MsgBrk '\ltxkeys@tfam' is not defined.} + {I couldn't delete #1-keys.}% + }% + }% + \ltxkeys@listparse1{#2}% + }{% + \ltxkeys@err{No #1 keys for family '\ltxkeys@tfam'}% + {No #1 keys exist for prefix '\ltxkeys@ttpref' and + \MsgBrk family '\ltxkeys@tfam'.}% + }% + \letcsntocs{\ltxkeys@hdr#1keys}\ltxkeys@rsvda +} +\robust@def*\ltxkeys@undefh@ndledkeys#1{% + \ifcsndefTF{\ltxkeys@hdr#1keys}{% + \usename{\ifltxkeys@cl g\fi undefcsn}{\ltxkeys@hdr#1keys}% + }{% + \ltxkeys@err{No #1 keys for prefix '\ltxkeys@ttpref' + \MsgBrk and family '\ltxkeys@tfam'} + {I couldn't undefine #1-keys.}% + }% +} +\robust@def*\ltxkeys@emptifyh@ndledkeys#1{% + \ifcsndefTF{\ltxkeys@hdr#1keys}{% + \usename{\ifltxkeys@cl g\fi emptifycsn}{\ltxkeys@hdr#1keys}% + }{% + \ltxkeys@err{No #1 keys for prefix '\ltxkeys@ttpref' + \MsgBrk and family '\ltxkeys@tfam'} + {I couldn't emptify #1-keys.}% + }% +} +\robust@def*\ltxkeys@iftkeyinlist#1{% + \ifcsndefTF{\ltxkeys@hdr#1}{% + \letcstocsn\ltxkeys@tempa{\ltxkeys@hdr#1}% + \oifinset@sp@TF,\ltxkeys@tkey\ltxkeys@tempa + }{% + \@secondoftwo + }% +} +\robust@def*\ltxkeys@testsavevaluekey{% + \ltxkeys@debug{==}{Testing if '\ltxkeys@tkey' is a savevalue key}% + \ltxkeys@iftkeyinlist{savevaluekeys}{% + \ltxkeys@svtrue + }{% + \ltxkeys@svfalse + \ltxkeys@debug{==}{'\ltxkeys@tkey' is not a savevalue key}% + }% +} +% Test for option or non-option keys: +\robust@def*\ltxkeys@testoptionkey#1{% + \begingroup + \def\ltxkeys@tempc{\ifstrcmpTF{#1}{non}{not }{}}% + \def\ltxkeys@tempd{\ifstrcmpTF{#1}{non}{}{not }}% + \ltxkeys@debug{==}{Testing if '\ltxkeys@tkey' is + \ltxkeys@tempc option key}% + \ltxkeys@iftkeyinlist{#1optionkeys}{% + \ltxkeys@err + {The following key should \ltxkeys@tempc + appear in \noexpand\usepackage or \string\RequirePackage: + ||\ltxkeys@ttpref, \ltxkeys@tfam, \ltxkeys@tkey||}% + {\ltxkeys@tempc option key error.}% + }{% + \ltxkeys@debug{==}{Key '\ltxkeys@tkey' is + \ltxkeys@tempd option key}% + }% + \endgroup +} +\robust@def*\ltxkeys@testneedvaluekey{% + \ltxkeys@debug{==}{Testing if '\ltxkeys@tkey' is a needvalue key}% + \ltxkeys@iftkeyinlist{needvaluekeys}{% + \ltxkeys@err{You're required to supply a value for + \MsgBrk key '\ltxkeys@tkey' in family '\ltxkeys@tfam'} + {Please supply a value for key '\ltxkeys@tkey' of families + \MsgBrk'\ltxkeys@fams' and rerun. The author of this key + \MsgBrk meant it to require a user value.}% + }{% + \ltxkeys@debug{==}{'\ltxkeys@tkey' is not a + needvalue key}% + }% +} +\robust@def*\ltxkeys@setbool#1{% + \xifstrcmpTF{#1}{on}{% + \def#1{true}% + }{% + \xifstrcmpTF{#1}{off}{% + \def#1{false}% + }{% + \edef#1{#1}% + }% + }% +} + +% Gather keys and their values for use in (declaring +% or defining keys). \key@vals must have been initialized +% by the caller. +% +% #1: default value +% #2: Key macro (for testing if it contains '\ltxkeys@setaliaskey'). +% If the key macro contains '\ltxkeys@setaliaskey', then the key is a +% twin/alias key: +\robust@def*\ltxkeys@accumkeyvals#1#2{% + \ifblankTF{#1}{% + \ltxkeys@twkfalse + }{% + \ltxkeys@ifinlistTF(1){\ltxkeys@setaliaskey,\setaliaskey}{#2}% + {\ltxkeys@twktrue}{\ltxkeys@twkfalse}% + }% + \begingroup + \edef\elt{\ifblankTF{#1}{}{\unexpanded{#1}}}% + \edef\key@vals{% + \csliststack,\key@vals\expandcsonce\key@name=% + \ifltxkeys@dep + % We're dealing with a dependant key; use the user-supplied value: + \expandcsonce\elt + \else + \ifstrcmpTF{#1}{true}{false}{\expandcsonce\elt}% + \fi + }% + % Set slave key with master when 'ltxkeys@ssk' is true, whether + % or not the key macro contains '\ltxkeys@setaliaskey': + \ifltxkeys@ssk + \gletcs\key@vals\key@vals + \else + % If the key macro contains '\ltxkeys@setaliaskey', don't include + % it in the list: + \ifltxkeys@twk\else + \gletcs\key@vals\key@vals + \fi + \fi + \endgroup +} +% Define boolean and command keys compactly & robustly: +% 1. \ltxkeys@definekeys[pref]{<fam>}[macropf]{<keyname>=<dft> +% /<callback>; ...}. +% Key default value and macro can be absent, +% but boolean keys must have values (<true> | <false>), +% to be distinguishable from cmd keys. +% 2. Use \ltxkeys@checkchoice or \CheckUserInput to introduce +% choice keys as command keys. +% 3. Ordinary and choice keys can't be introduced directly by +% this command (use \ltxkeys@declarekeys). +% 4. The *-form can be used to define new keys (in the sense +% of \newcommand). +\robust@def*\ltxkeys@definekeys{% + \begingroup + \endlinechar\m@one + \cpt@teststopt\ltxkeys@definekeys@a{KV}% +} +\robust@def*\ltxkeys@definekeys@a[#1]#2{% + \gletcs\ifltxkeys@keyst\ifcpt@st + \cpt@testopt{\expandafter\endgroup\ltxkeys@definekeys@b{#1}{#2}}{}% +} +\robust@def*\ltxkeys@definekeys@b#1#2[#3]#4{% + \ltxkeys@makepf{#1}% + \ltxkeys@makehdr{#2}% + \ltxkeys@dectrue + \begingroup + \ltxkeys@trimspacesset{% + {#1}\key@pref,{#2}\key@fam,{#3}\macro@pref + }% + \toks@{}% + \def\key@vals{}% + % We want \ltxkeys@definekeys to have a slightly different + % syntax to \ltxkeys@declarekeys. So we use '=' here. But + % the equality sign can always be replaced with '/' and + % this won't cause any problems: + \def\ltxkeys@splita##1={\ltxkeys@splitc##1/.}% + \def\ltxkeys@splitb##1/{\ltxkeys@splitc##1/.}% + \def\ltxkeys@splitc##1/##2/##3/##4\ltxkeys@nil{% + \ifblankTF{##1}{% + \ltxkeys@err{Empty key name while in + \string\ltxkeys@definekeys}\ltxkeys@ehd + }{% + \ltxkeys@findpointers{##1}% + \let\key@name\ltxkeys@tkey + \ifltxkeys@keyst + \ifcsndefFT{\ltxkeys@iffirstnull\key@pref @% + \ltxkeys@iffirstnull\key@fam @\key@name + }{}{% + \ltxkeys@err{Key '\key@name' already defined in family + \MsgBrk '\iflacus#2\dolacus???\else#2\fi' with prefix + '\iflacus#1\dolacus???\else#1\fi'}\ltxkeys@ehd + }% + \fi + \oifblankTF{\@gobble##2}{% + \def\key@default{}% + }{% + \ltxkeys@remdottrimspaces{##2}\key@default + }% + \edef\key@callback{\unexpanded{##3}}% + \ltxkeys@stripdotcode\key@callback + \cptexpandsecond\ltxkeys@accumkeyvals{% + {\ifx\key@default\ltxkeys@rej\else\expandcsonce\key@default\fi}% + {\ifx\key@callback\ltxkeys@rej\else\expandcsonce\key@callback\fi}% + }% + \def\defwith{\ltxkeys@boolkey}% + \oifstrcmpTF\key@default{true}{}{% + \oifstrcmpTF\key@default{false}{}{% + \def\defwith{\ltxkeys@cmdkey}% + }% + }% + \cptexpanded{% + \toks@{\the\toks@ + \cptmakecs{ltxkeys@twk\ifltxkeys@twk true\else false\fi}% + \defwith[\key@pref]{\key@fam}% + \ifx\macro@pref\@empty\else[\macro@pref]\fi + {\expandcsonce\key@name}% + \ifx\key@default\ltxkeys@rej\else[\expandcsonce\key@default]\fi + \ifx\key@callback\ltxkeys@rej{}\else{\expandcsonce\key@callback}\fi + }% + }% + }% + }% + \def\ltxkeys@do##1{% + \ltxkeys@removedotcode{##1}\ltxkeys@tempa + \expandafter\ltxkeys@in\expandafter*\expandafter + =\expandafter{\ltxkeys@tempa}{% + \expandafter\ltxkeys@splita\ltxkeys@tempa/^?^/^?^/\ltxkeys@nil + }{% + \expandafter\ltxkeys@splitb\ltxkeys@tempa/^?^/^?^/\ltxkeys@nil + }% + }% + \cptexpandsecond{\ltxkeys@listparse1}{[\ltxkeys@keyparser]}{#4}% + % Define and initialize the keys here directly: + \cptexpandsecond\endgroup{% + \the\toks@ + \noexpand\ltxkeys@twkfalse + \ltxkeys@ifcsemptyTF\key@vals{}{% + \noexpand\ltxkeys@setkeys[\key@pref]% + {\key@fam}{\expandcsonce\key@vals}% + }% + }% + \ltxkeys@decfalse +} +\new@def*\ltxkeys@badkeytypes{} +% Robustly define keys of all types by one command: +% 1. \ltxkeys@declarekeys[pref]{<fam>}[macropf]{<keytype>/<keyname> +% /<dft>/<callback><parser> ...}. +% Key default and macro can be absent. +% 2. keytype = <ord> | <cmd> | <sty> | <sty*> | <bool> | <choice>. +% 3. Choice keys must have their names associated with +% their admissible values in the format <keyname.chclist>. +% 4. * -> We're defining new keys (in the sense of \newcommand). +% +% Example: +% \ltxkeys@declarekeys*[KV]{<fam>}[mp@]{% +% cmd/keya/mm/\def\x##1{##1*#1*##1}; +% bool/keyb; +% sty/keyc/xxx/\def\y##1{##1yyy#1}; +% sty*/keyd/mm/\def\y##1{##1#1}/cmd>keye>#1>\def\z####1{####1+##1+####1} +% } +% Notice the >...> for the dependant key attributes. +% +\robust@def*\ltxkeys@declarekeys{% + \begingroup + \endlinechar\m@one + \cpt@testst{\cpt@testpnopt\ltxkeys@declarekeys@a{}}% +} +\robust@def*\ltxkeys@declarekeys@a(#1){% + \cpt@testopt{\ltxkeys@declarekeys@b{#1}}{KV}% +} +\robust@def*\ltxkeys@declarekeys@b#1[#2]#3{% + \gletcs\ifltxkeys@keyst\ifcpt@st + \cpt@testopt{\expandafter\endgroup + \ltxkeys@declarekeys@c{#1}{#2}{#3}}{}% +} +\robust@def*\ltxkeys@declarekeys@c#1#2#3[#4]#5{% + \ltxkeys@makepf{#2}% + \ltxkeys@makehdr{#3}% + \ltxkeys@dectrue + \begingroup + \ltxkeys@trimspacesset{{#2}\key@pref,{#3}\key@fam,{#4}\macro@pref}% + \def\key@vals{}\toks@{}% + \def\ltxkeys@splita##1/##2/{% + \ifescapedTF{##1}{% + \ltxkeys@err{Key type can't be a macro: '\detokenize{##1}'}% + \ltxkeys@ehd + }{}% + \ltxkeys@trimspacesset{{##1}\key@type,{##2}\key@name}% + \xifstrcmpTF\key@type{choice}{% + \expandafter\ltxkeys@splitchoice\expandafter{\key@name}% + }{}% + \xifinsetTF{=}{\cptoxdetok\key@type}{% + \ltxkeys@err{The syntax of \noexpand\ltxkeys@definekeys may + \MsgBrk have been used for \string\ltxkeys@declarekeys. + \MsgBrk This may have come from \noexpand\ltxkeyscmd or + \MsgBrk \string\ltxkeysenv}\ltxkeys@ehd + }{}% + \ifx\key@type\@empty + \ltxkeys@err{Empty key type in \string\ltxkeys@declarekeys} + \ltxkeys@ehd + \fi + \ifx\key@name\@empty + \ltxkeys@err{Empty key name in \string\ltxkeys@declarekeys}% + \ltxkeys@ehd + \fi + \ltxkeys@ifrejname{% + \ltxkeys@err{Wrong use syntax for \string\ltxkeys@declarekeys}% + \ltxkeys@ehd + }% + \ifltxkeys@inkeycmd + \xifstrcmpFT\key@type{ord}{}{\def\key@type{cmd}}% + \fi + \expandafter\ltxkeys@findpointers\expandafter{\key@name}% + \let\key@name\ltxkeys@tkey + \ifx\key@type\key@name + \ltxkeys@err{Key type '\key@type' and key name '\key@name' + are identical}{Maybe you gave key type both in parenthesis + and in key list.}% + \fi + \ifltxkeys@keyst + \ifcsndefFT{\ltxkeys@hdr\key@name}{}{% + \ltxkeys@err{Key '\key@name' already defined in family + \MsgBrk '\iflacus#3\dolacus???\else#3\fi' with prefix + '\iflacus#2\dolacus???\else#2\fi'}\ltxkeys@ehd + }% + \fi + \ltxkeys@splitb.% + }% + \def\ltxkeys@splitb##1/##2/##3/##4\ltxkeys@nil{% + \edef\key@default{\expandcsonce{\@gobble##1}}% + \ltxkeys@ifcsemptyTF\key@default{% + \xifstrcmpTF\key@type{bool}{\def\key@default{true}}{}% + }{% + \ltxkeys@trimspacesincs\key@default + }% + \xifstrcmpTF\key@type{bool}{% + \ifx\key@default\ltxkeys@rej + \def\key@default{true}% + \ltxkeys@debug{!!}{Boolean key '\key@name' + has no default; 'true' used}% + \else + \ifcase0% + \ifx\key@default\ltxkeys@truetoks\else + \ifx\key@default\ltxkeys@falsetoks\else1\fi\fi\relax + \else + \ltxkeys@err{Invalid default value for boolean key + '\key@name'}\ltxkeys@ehd + \fi + \fi + }{}% + \edef\key@callback{\unexpanded{##2}}% + \ltxkeys@stripdotcode\key@callback + \expandafter\ltxkeys@striplaststar\key@type\@empty*\@empty + \ltxkeys@nil\key@type@aux + \xifinsetTF{,\key@type@aux,}{,sty,}{% + \ltxkeys@trimspaces{##3}\key@dependants + \ltxkeys@ifxTF\key@dependants\ltxkeys@rej{% + \def\key@dependants{}% + }{% + \expandafter\ltxkeys@declarekeys@e\expandafter{\key@dependants}% + }% + }{% + \xifinsetTF{,\key@type@aux,}{,bool,choice,}{% + \ltxkeys@trimspaces{##3}\key@bicallback + \ltxkeys@ifxTF\key@bicallback\ltxkeys@rej{% + \let\key@bicallback\ltxkeys@keyvalerr + }{}% + }{}% + }% + \cptexpandsecond\ltxkeys@accumkeyvals{% + {\ifx\key@default\ltxkeys@rej\else\expandcsonce\key@default\fi}% + {\ifx\key@callback\ltxkeys@rej\else\expandcsonce\key@callback\fi}% + }% + \def\key@callback@aux{% + \ifx\key@callback\ltxkeys@rej{}\else{\expandcsonce\key@callback}\fi + }% + \def\key@default@aux{% + \ifx\key@default\ltxkeys@rej\else[\expandcsonce\key@default]\fi + }% + \s@expandarg\ltxkeys@declarekeys@d\key@type + \def\reserved@a{ord}% + \edef\ltxkeys@tempa{% + [\key@pref]{\key@fam}% + \ifx\key@type\reserved@a\else\ifx\macro@pref\@empty\else + [\macro@pref]\fi\fi{\expandcsonce\key@name}% + }% + \cptpassexpanded{% + \toks@{\the\toks@ + \cptmakecs{ltxkeys@twk\ifltxkeys@twk true\else false\fi}% + \ifcase\currmatch\relax + \ltxkeys@cmdkey\ltxkeys@tempa\key@default@aux\key@callback@aux + \or + \ltxkeys@boolkey+\ltxkeys@tempa\key@default@aux + \key@callback@aux{\expandcsonce\key@bicallback}% + \or + \ltxkeys@ordkey\ltxkeys@tempa\key@default@aux\key@callback@aux + \or + \ltxkeys@choicekey*+\ltxkeys@tempa + [\unexpanded{\userinput\order}]{\expandcsonce\ltxkeys@alt}% + \key@default@aux\key@callback@aux{\expandcsonce\key@bicallback}% + \or + \ltxkeys@stylekey\ltxkeys@tempa\key@default@aux + (\expandcsonce\key@dependants)\key@callback@aux + \or + \ltxkeys@stylekey*\ltxkeys@tempa\key@default@aux + (\expandcsonce\key@dependants)\key@callback@aux + \else + \cptgaddtolist\noexpand\ltxkeys@badkeytypes{\key@type}% + \fi + }% + }% + }% + \ifdefTF\ltxkeys@keyparser{% + \ltxkeys@stripallouterbracesincs\ltxkeys@keyparser + }{% + \def\ltxkeys@keyparser{;}% + }% + \ifblankTF{#1}{% + % No 'onekeytype': + \edef\ltxkeys@tempa{\unexpanded{#5}}% + }{% + \def\ltxkeys@tempa{}% + \def\ltxkeys@do##1{% + \edef\ltxkeys@tempa{% + \expandafter\csliststack\ltxkeys@keyparser + \ltxkeys@tempa#1/\unexpanded{##1}% + }% + }% + \cptexpandsecond{\ltxkeys@listparse0}{[\ltxkeys@keyparser]}{#5}% + }% + \def\ltxkeys@do##1{% + \ifblankTF{##1}{}{% + \ltxkeys@splita##1/^?^/^?^/^?^/^?^/\ltxkeys@nil + }% + }% + \cptexpandsecond{\ltxkeys@listparse0} + {[\ltxkeys@keyparser]{\expandcsonce\ltxkeys@tempa}}% + \cptexpandsecond\endgroup{% + \the\toks@ + \noexpand\ltxkeys@twkfalse + \edef\noexpand\key@vals{\ox@unexpanded\key@vals}% + }% + \ifx\ltxkeys@badkeytypes\@empty\else + \cpt@err{Invalid key types '\ltxkeys@badkeytypes'}\ltxkeys@ehd + \fi + % Initialize keys: + \ltxkeys@ifcsemptyTF\key@vals{}{% + \cptexpandargonce{\ltxkeys@setkeys[#2]{#3}}\key@vals + }% + \ltxkeys@decfalse +} +\robust@def*\ltxkeys@declarekeys@d#1{% + \ltxkeys@findmatch + {#1}{cmd:0,bool:1,ord:2,choice:3,sty:4,syt*:5}{\def\currmatch{-1}}% +} +% \ltxkeys@declarekeys@e{<dependant key specs>} +\robust@def*\ltxkeys@declarekeys@e#1{% + \ifblankTF{#1}{\def\key@dependants{}\cptgobbletorelax}{}% + \begingroup + \def\ltxkeys@splita##1>##2>{% + \def\key@type{##1}% + \edef\key@name{\unexpanded{##2}}% + \ltxkeys@splitb.% + }% + \def\ltxkeys@splitb##1>##2>##3\ltxkeys@nil{% + \edef\key@default{\expandcsonce{\@gobble##1}}% + \edef\key@callback{\unexpanded{##2}}% + \ltxkeys@stripdotcode\key@callback + \ltxkeys@ifrejname{% + \ltxkeys@err{Wrong syntax for dependants keys in + \MsgBrk\string\ltxkeys@declarekeys}\ltxkeys@ehd + }% + \edef\key@dependants{% + \expandafter\csliststack\ltxkeys@keyparser\key@dependants + \key@type/\expandcsonce\key@name + \ifx\key@default\ltxkeys@rej\else/\expandcsonce\key@default\fi + \ifx\key@callback\ltxkeys@rej\else/\expandcsonce\key@callback\fi + }% + }% + \def\key@dependants{}% + \def\ltxkeys@do##1{% + \ltxkeys@splita##1>^?^>^?^>^?^>\ltxkeys@nil + }% + \ltxkeys@listparse1[,]{#1}% + \postgroupdef\key@dependants\endgroup + \cpt@relax +} +\robust@def*\ltxkeys@savexfamilykeys{% + \begingroup + \endlinechar\m@one + \cpt@testst{\cpt@testltopt\ltxkeys@savexf@milykeys{}}% +} +\robust@def*\ltxkeys@savexf@milykeys<#1>{% + \cpt@testpnopt{\ltxkeys@savexf@milyk@ys{#1}}{}% +} +\robust@def*\ltxkeys@savexf@milyk@ys#1(#2)#3{% + \ifblankTF{#1}{% + \ltxkeys@err{Empty set-identifier for \string\xfamilykeys: + ||\detokenize{#3}||}\ltxkeys@ehd + }{}% + \ltxkeys@trimspaces{#1}\ltxkeys@tempb + \ifcsndefTF{xfamilykeys@id@\ltxkeys@tempb}{% + \ltxkeys@err{xfamilykeys identifier '\ltxkeys@tempb' + already in use}\ltxkeys@ehd + }{}% + \cpt@stchoose{cpt@st}{#3}\ltxkeys@tempa\ltxkeys@savexfamilykeys + \ifblankTF{#2}{}{% + \def\ltxkeys@do##1{% + \edef\ltxkeys@tempa{% + \expandafter\csliststack\ltxkeys@keyparser + \ltxkeys@tempa#2/\unexpanded{##1}% + }% + }% + \cptexpandsecond{\def\ltxkeys@tempa{}\ltxkeys@listparse1}% + {[\ltxkeys@keyparser]{\expandcsonce\ltxkeys@tempa}}% + }% + \cptexpandsecond{\endgroup\csn@edef} + {{xfamilykeys@id@\ltxkeys@tempb}{\ox@unexpanded\ltxkeys@tempa}}% +} + +\robust@def*\ltxkeys@definexfamilykeys{% + \begingroup + \cpt@testst{\cpt@testltopt\ltxkeys@d@finexfamilykeys{}}% +} +\robust@def*\ltxkeys@d@finexfamilykeys<#1>{% + \edef\defwith{\ltxkeys@declarekeys\ifcpt@st*\fi}% + \ifblankTF{#1}{% + \ltxkeys@err{Invalid empty xfamilykeys identifier + \MsgBrk in \string\ltxkeys@definexfamilykeys}\ltxkeys@ehd + }{}% + \ltxkeys@trimspaces{#1}\ltxkeys@tempa + \ifcsndefTF{xfamilykeys@id@\ltxkeys@tempa}{% + \expandafter\cpt@testopt\expandafter{\expandafter + \ltxkeys@d@fin@xfamilykeys\expandafter{\ltxkeys@tempa}}{KV}% + }{% + \ltxkeys@err{Unknown xfamilykeys identifier '\ltxkeys@tempa' + \MsgBrk in \string\ltxkeys@definexfamilykeys}\ltxkeys@ehd + }% +} +\robust@def*\ltxkeys@d@fin@xfamilykeys#1[#2]#3{% + \cpt@testopt{\ltxkeys@d@fin@xf@milykeys{#1}{#2}{#3}}{}% +} +\robust@def*\ltxkeys@d@fin@xf@milykeys#1#2#3[#4]#5{% + \def\ltxkeys@na{#5}% + \def\ltxkeys@splita##1/##2/{% + \ltxkeys@trimspacesset{{##1}\key@type,{##2}\key@name@aux}% + \xifstrcmpTF\key@type{choice}{% + \expandafter\ltxkeys@splitchoice\expandafter{\key@name@aux}% + }{% + \let\key@name\key@name@aux + }% + \ltxkeys@splitb.% + }% + \def\ltxkeys@splitb##1/##2/##3/##4\ltxkeys@nil{% + \edef\key@default{\expandcsonce{\@gobble##1}}% + \edef\key@callback{\unexpanded{##2}}% + \edef\key@dependants{\unexpanded{##3}}% + \oifinset@sp@TF,\key@name\ltxkeys@na{}{% + \let\do\expandcsonce + \edef\ltxkeys@tempa{% + \expandafter\csliststack\ltxkeys@keyparser + \ltxkeys@tempa\key@type/\do\key@name@aux + \ifx\key@default\ltxkeys@rej\else/\do\key@default\fi + \ifx\key@callback\ltxkeys@rej\else/\do\key@callback\fi + \ifx\key@dependants\ltxkeys@rej\else/\do\key@dependants\fi + }% + }% + }% + \def\ltxkeys@tempa{}% + \def\ltxkeys@do##1{% + \ltxkeys@splita##1/^?^/^?^/^?^/^?^/\ltxkeys@nil + }% + \cptexpandsecond{\ltxkeys@listparse1} + {[\ltxkeys@keyparser]{\expandcsnonce{xfamilykeys@id@#1}}}% + \cptexpandsecond\endgroup + {\defwith[#2]{#3}[#4]{\expandcsonce\ltxkeys@tempa}}% +} + +\robust@def*\ltxkeys@presetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{ppsetkeys}{pre}}% +} +\newletcs\ltxkeys@addpresetkeys\ltxkeys@presetkeys +\robust@def*\ltxkeys@removepresetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{removeppsetkeys}{pre}}% +} +\robust@def*\ltxkeys@undefpresetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{undefppsetkeys}{pre}}% +} +\robust@def*\ltxkeys@postsetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{ppsetkeys}{post}}% +} +\newletcs\ltxkeys@addpostsetkeys\ltxkeys@postsetkeys +\robust@def*\ltxkeys@removepostsetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{removeppsetkeys}{post}}% +} +\robust@def*\ltxkeys@undefpostsetkeys{% + \ltxkeys@testcl{\ltxkeys@testopt@g{undefppsetkeys}{post}}% +} +\robust@def*\ltxkeys@ppsetkeys#1#2{% + \def\ltxkeys@rsvda{}% + \def\ltxkeys@rsvdb{}% + \def\ltxkeys@do##1{% + \ltxkeys@splitkeyval##1\ltxkeys@nil\ltxkeys@tkey\ltxkeys@tval + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \ltxkeys@err{Key '\ltxkeys@currtriple' is undefined.}% + \ltxkeys@ehd + }{% + \ifcsndefTF{\ltxkeys@hdr#1setkeys@alreadysaved}{}{% + \csn@def{\ltxkeys@hdr#1setkeys@alreadysaved}{}% + }% + % You can't enter the same key twice in either + % preset or post-set lists in the same family and prefix: + \xifinsetTF{,\cptoxdetok\ltxkeys@tkey,}% + {,\cptsxdetok{\usename{\ltxkeys@hdr#1setkeys@alreadysaved},}}{% + \ltxkeys@err{Double entry for key '\ltxkeys@currtriple' in\MsgBrk + #1set key list}\ltxkeys@ehd + }{% + \edef\ltxkeys@rsvda{\csliststack,\ltxkeys@rsvda + \ltxkeys@tkey\ltxkeys@ifcsemptyTF\ltxkeys@tval{}% + {=\expandcsonce\ltxkeys@tval}}% + \edef\ltxkeys@rsvdb{\csliststack,\ltxkeys@rsvdb + \expandcsonce\ltxkeys@tkey}% + }% + }% + }% + \ltxkeys@listparse3{#2}% + % '...@alreadysaved' saves key names irrespective + % of value, for testing if a preset key is being saved twice: + \ltxkeys@ifcsemptyTF\ltxkeys@rsvda{}{% + \ifcsndefTF{\ltxkeys@hdr#1setkeys}{% + \cptpassexpanded{% + \cptfiltermergekv\noexpandcsn{\ltxkeys@hdr#1setkeys}% + {\expandcsonce\ltxkeys@rsvda}\noexpand\nofilter + \cptfiltermergecsv\noexpandcsn{\ltxkeys@hdr#1setkeys@alreadysaved}% + {\ltxkeys@rsvdb}\noexpand\nofilter + }% + }{% + \csn@edef{\ltxkeys@hdr#1setkeys}{\expandcsonce\ltxkeys@rsvda}% + \csn@edef{\ltxkeys@hdr#1setkeys@alreadysaved}% + {\expandcsonce\ltxkeys@rsvdb}% + }% + \ifltxkeys@cl + \globalizecsn{\ltxkeys@hdr#1setkeys}% + \globalizecsn{\ltxkeys@hdr#1setkeys@alreadysaved}% + \fi + }% +} +\robust@def*\ltxkeys@removeppsetkeys#1#2{% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{% + \ltxkeys@err{No #1set keys defined for prefix '\ltxkeys@ttpref' + and family '\ltxkeys@tfam'}\ltxkeys@ehd + }{% + \def\ltxkeys@rsvda{}\def\ltxkeys@rsvdb{}% + \def\ltxkeys@do##1{% + \ltxkeys@splitkeyval##1=\ltxkeys@nil\ltxkeys@tkey\ltxkeys@tval + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \ltxkeys@err{Key '\ltxkeys@currtriple' is undefined}% + \ltxkeys@ehd + }{% + \xifinsetTF{,\cptoxdetok\ltxkeys@tkey=\cptoxdetok\ltxkeys@tval,}% + {,\cptsxdetok{\usename{\ltxkeys@hdr#1setkeys}},}{% + \edef\ltxkeys@rsvda{\csliststack,\ltxkeys@rsvda + \ltxkeys@tkey\ltxkeys@ifcsemptyTF\ltxkeys@tval{}% + {=\expandcsonce\ltxkeys@tval}}% + \edef\ltxkeys@rsvdb{\csliststack,\ltxkeys@rsvdb + \expandcsonce\ltxkeys@tkey}% + }{% + \ltxkeys@err{Key '\ltxkeys@currtriple' not a #1set key}% + \ltxkeys@ehd + }% + }% + }% + \ltxkeys@listparse3{#2}% + \ltxkeys@ifcsemptyTF\ltxkeys@rsvda{}{% + \cptpassexpanded{% + \cptfilterremovekv\noexpandcsn{\ltxkeys@hdr#1setkeys}% + {\expandcsonce\ltxkeys@rsvda}\noexpand\nofilter + \cptfilterremovecsv\noexpandcsn{\ltxkeys@hdr#1setkeys@alreadysaved}% + {\ltxkeys@rsvdb}\noexpand\nofilter + }% + \ifltxkeys@cl + \globalizecsn{\ltxkeys@hdr#1setkeys}% + \globalizecsn{\ltxkeys@hdr#1setkeys@alreadysaved}% + \fi + }% + }% +} +\robust@def*\ltxkeys@undefppsetkeys#1{% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{% + \ltxkeys@err{No #1set keys defined for prefix '\ltxkeys@ttpref' + and family '\ltxkeys@tfam'}\ltxkeys@ehd + }{% + \usename{\ifltxkeys@cl g\fi undefcsn}{\ltxkeys@hdr#1setkeys}% + \usename{\ifltxkeys@cl g\fi undefcsn}% + {\ltxkeys@hdr#1setkeys@alreadysaved}% + }% +} +% Set a main key after setting its twin/alias. This is NOT +% related to dependant or style keys: +\robust@def*\ltxkeys@setaliaskey#1{% + \ltxkeys@commanormalize{#1}\ltxkeys@tempa + \xifinsetTF{,}{\cptoxdetok\ltxkeys@tempa}{% + \ltxkeys@err{\noexpand\ltxkeys@setaliaskey doesn't + accept key list}\ltxkeys@ehd + }{% + \cptexpandarg\cpt@testopt{\ltxkeys@s@taliaskey\ltxkeys@tempa}{}% + }% +} +\newletcs\setaliaskey\ltxkeys@setaliaskey +\robust@def*\ltxkeys@s@taliaskey#1[#2]{% + \begingroup + \let\x\ltxkeys@tkey + \edef\y{\expandcstwice{\csname\ltxkeys@hdr#1\endcsname{}}}% + \cptexpandsecond{\endgroup\ltxkeys@ifinlistTF(1)}{% + {\ltxkeys@setaliaskey{\x},\setaliaskey{\x}}% + {\expandcsonce\y}% + }{% + \ltxkeys@err{\noexpand\ltxkeys@setaliaskey + or \noexpand\setaliaskey nested}\ltxkeys@ehd + }{}% + \cptexpandsecond\ltxkeys@setkeys{% + [\ltxkeys@ttpref]{\ltxkeys@tfam}{% + #1=\ifblankTF{#2}{\expandcsonce\ltxkeys@tval}{\unexpanded{#2}}% + }% + }% +} +\robust@def*\ltxkeys@splitchoice#1{% + \begingroup + \def\ltxkeys@tempa##1.##2##3\ltxkeys@nil{\endgroup + \ltxkeys@trimspaces{##1}\key@name + \ifstrcmpTF{##2}{.}{% + \ltxkeys@err{Invalid alternate value list for key '#1'} + \ltxkeys@ehd + }{% + \ifmacroTF{##2}{% + \edef\ltxkeys@alt{\expandcsonce{##2}}% + }{% + \edef\ltxkeys@alt{\unexpanded{##2}}% + }% + \ltxkeys@trimspacesincs\ltxkeys@alt + }% + }% + \ltxkeys@tempa#1..\ltxkeys@nil +} +% #1: key prefix +% #2: key family +\robust@def*\ltxkeys@setinitialkeyvals#1#2{% + \ltxkeys@initrue + \ifcsndefFT{#1@#2@initialkeyvals}{}{% + \ifcsnnullTF{#1@#2@initialkeyvals}{}{% + \cptpassexpanded{% + \noexpand\ltxkeys@setkeys[#1]{#2}% + {\expandcsnonce{#1@#2@initialkeyvals}}% + }% + }% + }% + \ltxkeys@inifalse +} + +% \ltxkeys@initializekeys[<prefixes>]{<fams>}[<na>] +% 1. Preset all keys defined in families <fams>; +% ignore keys listed in <na>. <na> comes from key-val +% pairs that the user wants to use as current values +% of keys. Their keys are to be ignored when setting +% up defaults. +% 2. The key-val list to be preset comes from the macros +% \<pref>@<fam>@initialkeyvals: +\robust@def*\ltxkeys@initializekeys{% + \cpt@testopt\ltxkeys@in@tializekeys{KV}% +} +\robust@def*\ltxkeys@in@tializekeys[#1]#2{% + \cpt@testopt{\ltxkeys@in@ti@lizekeys{#1}{#2}}{}% +} +\robust@def*\ltxkeys@in@ti@lizekeys#1#2[#3]{% + \ltxkeys@initrue + \begingroup + \def\ltxkeys@resa{}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \letcstocsn\ltxkeys@tempc{\ltxkeys@hdr initialkeyvals}% + \ifdefTF\ltxkeys@tempc{% + \ltxkeys@remdispox\ltxkeys@tempc + \cptexpandargonce{\cptfiltermergecsv[,]\ltxkeys@resa} + \ltxkeys@tempc\nofilter + }{}% + }% + \ltxkeys@listparse1{#2}% + }% + \ltxkeys@listparse1{#1}% + \ltxkeys@getkeynames{#3}% + \cptexpandsecond{\endgroup\ltxkeys@setkeys*+[#1]{#2}}% + {[\ltxkeys@keynames]{\expandcsonce\ltxkeys@resa}}% + \ltxkeys@inifalse +} +% Remove disabled and pox keys: +\robust@def*\ltxkeys@remdispox#1{% + \begingroup + \letcstocsn\ltxkeys@tempd{\ltxkeys@hdr disabledkeys}% + \ifdefTF\ltxkeys@tempd{}{\def\ltxkeys@tempd{}}% + \letcstocsn\ltxkeys@tempe{\ltxkeys@hdr poxkeys}% + \ifdefTF\ltxkeys@tempe{}{\def\ltxkeys@tempe{}}% + \ltxkeys@ifcsemptyTF\ltxkeys@tempd{% + \ltxkeys@ifcsemptyTF\ltxkeys@tempe\cptgobbletorelax\relax + }{}% + \edef\ltxkeys@tempd + {\expandcsonce\ltxkeys@tempd,\expandcsonce\ltxkeys@tempe}% + \def\ltxkeys@do##1{% + \ltxkeys@getkeyname##1=\ltxkeys@nil\ltxkeys@tkey + \xifinsetTF{,\ltxkeys@tkey,}{,\expandcsonce\ltxkeys@tempd,}{}{% + \edef#1{\csliststack,#1\unexpanded{##1}}% + }% + }% + \cptexpandargonce{\def#1{}\ltxkeys@listparse3}{#1}% + \cpt@relax + \postgroupdef#1\endgroup +} +% \ltxkeys@launchkeys*+[<prefix>]{<fams>}{<curr>} +% 1. First preset all family keys before setting keys in <curr>. +% 2. <curr> are the key-vals to be set in the current run; they +% will be ignored when initializing the keys of families <fams>: +\robust@def*\ltxkeys@launchkeys{% + \ltxkeys@teststpl{\cpt@testopt\ltxkeys@l@unchkeys{KV}}% +} +\robust@def*\ltxkeys@l@unchkeys[#1]#2#3{% + \edef\ltxkeys@cmdpf{\ifltxkeys@st*\fi\ifltxkeys@pl+\fi}% + \ltxkeys@commanormalizeset{{#1}\ltxkeys@prefs,{#2}\ltxkeys@fams}% + \xifinsetTF{,}\ltxkeys@fams{% + \ifltxkeys@pl\else + \ltxkeys@err{Multiple key families: you need + prefix + \MsgBrk for command \string\ltxkeys@launchkeys}\ltxkeys@ehd + \fi + }{}% + \cptexpandsecond\ltxkeys@in@ti@lizekeys + {{\ltxkeys@prefs}{\ltxkeys@fams}}[#3]% + \ifblankTF{#3}\cptgobbletorelax\relax + \begingroup + \def\ltxkeys@resa{}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \edef\ltxkeys@tempc{\unexpanded{#3}}% + \ltxkeys@remdispox\ltxkeys@tempc + \cptexpandargonce{\cptfiltermergecsv[,]\ltxkeys@resa} + \ltxkeys@tempc\nofilter + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs + \cptexpandargonce{\endgroup\expandafter\undefcs\expandafter + \ltxkeys@cmdpf\expandafter\ltxkeys@setkeys + \ltxkeys@cmdpf[#1]{#2}}\ltxkeys@resa + \cpt@relax +} +\robust@def*\ltxkeys@nonlaunchkeys{% + \cpt@teststopt{\ltxkeys@nonl@unchkeys}{KV}% +} +\newletcs\ltxkeys@noninitializekeys\ltxkeys@nonlaunchkeys +\robust@def*\ltxkeys@nonl@unchkeys[#1]#2#3{% + \ifboolTF{cpt@st}{% + \AtBeginDocument{\ltxkeys@nonl@un@hkeys{#1}{#2}{#3}}% + }{% + \ltxkeys@nonl@un@hkeys{#1}{#2}{#3}% + }% +} +\robust@def*\ltxkeys@nonl@un@hkeys#1#2#3{% + \ltxkeys@commanormalizeset + {{#1}\ltxkeys@prefs,{#2}\ltxkeys@fams,{#3}\ltxkeys@keys}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \ltxkeys@nonl@un@hk@ys + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs +} +\robust@def*\ltxkeys@nonl@un@hk@ys{% + \ifcsndefTF{\ltxkeys@hdr poxkeys}{}{% + \csn@def{\ltxkeys@hdr poxkeys}{}% + }% + \letcstocsn\ltxkeys@tempc{\ltxkeys@hdr poxkeys}% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \xifinsetTF{,##1,}{,\expandcsonce\ltxkeys@tempc,}{}{% + \edef\ltxkeys@tempc{% + \csliststack,\ltxkeys@tempc\unexpanded{##1}% + }% + }% + }{}% + }% + \ltxkeys@listparse*0\ltxkeys@keys + \letcsntocs{\ltxkeys@hdr poxkeys}\ltxkeys@tempc +} +\robust@def*\ltxkeys@setkeys{% + \ltxkeys@rmfalse + \ltxkeys@teststpl{\ltxkeys@testopt@c\ltxkeys@setkeys@a}% +} +% Don't call \ltxkeysusekeys \ltxkeyssetkeys, since +% \ltxkeyssetkeys is used in mkii. +\newletcs\ltxkeysusekeys\ltxkeys@setkeys +\newletcs\ltxkeys@setkey\ltxkeys@setkeys +\robust@def*\ltxkeys@setrmkeys{% + \ltxkeys@rmtrue + \ltxkeys@teststpl{\ltxkeys@testopt@c\ltxkeys@setrmkeys@a}% +} +\robust@def*\ltxkeys@setrmkeys@a[#1]{% + \ltxkeys@debug{==}{Setting 'remaining' keys now}% + \cptexpandarg{\ltxkeys@setkeys@a[#1]} + {\expandcsnonce{\ltxkeys@hdr rmkeys}}% +} +\robust@def*\ltxkeys@setkeys@a[#1]#2{% + \begingroup + \def\x{\ltxkeys@nil}% + \xifinsetTF{\x\detokenize{#2}\x} + {\x.\x,\x;\x:\x+\x-\x=\x*\x^\x_\x/\x|\x[\x(\x)\x]\x}{% + \ltxkeys@err{Invalid key list '#2': Something is wrong} + \ltxkeys@ehd + }{}% + \endgroup + \ifcsndefTF{\ltxkeys@hdr executedkeys}{}{% + \csn@def{\ltxkeys@hdr executedkeys}{}% + }% + \ifnum\ltxkeys@keydepth=\z@pt + \csn@def{\ltxkeys@hdr rmkeys}{}% + \def\ltxkeys@undefinedkeys{}% + \fi + \ltxkeys@getkeynames{#2}% + \let\ltxkeys@naa\ltxkeys@keynames + \ifblankTF{#1}{}{% + \edef\ltxkeys@naa{\csliststack,\ltxkeys@naa\unexpanded{#1}}% + }% + \ifboolTF{ltxkeys@tracingkeys}{% + \ltxkeys@getbasechars*[30]\ltxkeys@keynames\ltxkeys@tempa + \edef\ltxkeys@tempb{\ifnum\ltxkeys@charcount>30\string\ETC\fi}% + \wlog{\@spaces(on level \the\ltxkeys@keydepth)}% + \ltxkeys@debug{==}{Setting keys: '\ltxkeys@tempa\ltxkeys@tempb'}% + }{}% + \ltxkeys@usepresetkeys{pre}% + \ltxkeys@setkeys@b{#1}{#2}% + \ltxkeys@usepresetkeys{post}% + \ifnumcmpTF\ltxkeys@keydepth=\z@pt{% + \ltxkeys@debug{==}{Setting keys, returned to level 0}% + \ltxkeys@ifcsemptyTF\ltxkeys@undefinedkeys{% + \ltxkeys@debug{==}{No undefined keys in this run}% + }{% + \ltxkeys@debug{==}{There're undefined keys; logging them}% + \ltxkeys@logunknownkeys + }% + }{}% + \ifltxkeys@exop + \ltxkeys@exopfalse + \ltxkeys@debug{==}{Ended executing options}% + \fi + \ltxkeys@pxopfalse +} +\robust@def*\ltxkeys@usepresetkeys#1{% + \ltxkeys@presettrue + \begingroup + \toks@{}% + \ltxkeys@debug{==}{Looking for #1-set keys}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \ifcsndefFT{\ltxkeys@hdr#1setkeys}{}{% + \cptexpanded{\toks@{\the\toks@\relax\ltxkeys@setkeys@b + {\expandcsonce\ltxkeys@naa} + {\expandcsnonce{\ltxkeys@hdr#1setkeys}}}}% + }% + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs + \oifblankTF{\the\toks@}{% + \endgroup + \ltxkeys@debug{==}{No #1-set keys found}% + }{% + \ltxkeys@debug{==}{P\@gobble#1-set keys found. Setting them now}% + \expandafter\endgroup\the\toks@ + \ltxkeys@debug{++}{Finished setting #1-set keys}% + }% + \ltxkeys@presetfalse +} +\robust@def*\ltxkeys@setkeys@b#1#2{% + \ifblankTF{#1}{% + \def\ltxkeys@nakeys{}% + }{% + \ltxkeys@commanormalize{#1}\ltxkeys@nakeys + }% + \def\ltxkeys@do##1{% + \edef\CurrentKeyval{\unexpanded{##1}}% + \ltxkeys@getkeyvalue##1=\ltxkeys@nil\ltxkeys@tval + \ltxkeys@setkeys@c##1=\ltxkeys@nil + }% + \ltxkeys@listparse3{#2}% +} +\robust@def*\ltxkeys@setkeys@c#1=#2\ltxkeys@nil{% + \ifinsetTF{\needvalue}{#1}{% + \ltxkeys@err{\noexpand\needvalue pointer not allowed + \MsgBrk when setting keys}\ltxkeys@ehd + }{}% + \ltxkeys@findp@inters\savevalue{#1}\ltxkeys@tkey{% + \ltxkeys@svtrue + }{% + \ltxkeys@svfalse + }% + \let\CurrentKey\ltxkeys@tkey + \ltxkeys@ifcsemptyTF\ltxkeys@tkey{% + \ifltxkeys@novalue\else + \ltxkeys@err{No key specified for value + '\expandcsonce\ltxkeys@tval' + \MsgBrk in families '\ltxkeys@fams'}\ltxkeys@ehd + \fi + }{% + \oifinset@sp@TF,\ltxkeys@tkey\ltxkeys@nakeys{}{% + \ltxkeys@setkeys@d + }% + }% +} +\robust@def*\ltxkeys@setkeys@d{% + \ltxkeys@kffalse + \ifboolTF{ltxkeys@preset}{% + \ltxkeys@setkeys@e + }{% + \ifboolTF{ltxkeys@pl}{% + \def\ltxkeys@do##1{% + \def\CurrentPref{##1}% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \def\ltxkeys@tfam{####1}% + \let\CurrentFam\ltxkeys@tfam + \ltxkeys@makehdr\ltxkeys@tfam + \ltxkeys@setkeys@e + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs + }{% + \def\ltxkeys@do##1{% + \def\CurrentPref{##1}% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \def\ltxkeys@tfam{####1}% + \let\CurrentFam\ltxkeys@tfam + \ltxkeys@makehdr\ltxkeys@tfam + \ltxkeys@setkeys@e + \ifltxkeys@kf\loopbreak\fi + }% + \ltxkeys@listparse*0\ltxkeys@fams + \ifltxkeys@kf\loopbreak\fi + }% + \ltxkeys@listparse*0\ltxkeys@prefs + }% + }% + \ifboolTF{ltxkeys@kf}{% + \ifdefboolTF{ltxkeys@pxop}{% + \ltxkeys@ifxTF\ltxkeys@testname\ltxkeys@documentclass{% + \cpt@removecurroption\CurrentKeyval + \ltxkeys@debug{==}{Key \ltxkeys@currtriple, removed from + \string\@unusedoptionlist}% + }{}% + }{}% + }{% + \ifdefboolTF{ltxkeys@pxop}{% + \ifcsndefTF{\ltxkeys@hdr default@ds@opt}{% + \begingroup + \let\xp\expandcsonce + \cptexpandsecond{% + \endgroup\usename{\ltxkeys@hdr default@ds@opt}% + }{% + {\xp\ltxkeys@ttpref}{\xp\ltxkeys@tfam}% + {\xp\ltxkeys@tkey}{\xp\ltxkeys@tval}% + }% + }{% + \ltxkeys@ifxTF\@currext\@clsextension + \relax\ltxkeys@unknownoptionerror + }% + }{% + \ifboolTF{ltxkeys@st}{% + \ifltxkeys@tracingkeys + \ltxkeys@getinnovalue + \ltxkeys@debug{==}{Undefined key \ltxkeys@currtriple, + \InnocentVal, saved in \cptmakecs{\ltxkeys@hdr rmkeys}}% + \fi + \cptexpandargonce{\aftercsname{\cptfiltermergekv[,]}% + {\ltxkeys@hdr rmkeys}}\CurrentKeyval\nofilter + }{% + \ifcsndefTF{\ltxkeys@hdr default@ds@key}{% + \begingroup + \let\xp\expandcsonce + \cptexpandsecond{% + \endgroup\usename{\ltxkeys@hdr default@ds@key}% + }{% + {\xp\ltxkeys@ttpref}{\xp\ltxkeys@tfam}% + {\xp\ltxkeys@tkey}{\xp\ltxkeys@tval}% + }% + }{% + \ltxkeys@debug{==}{Key \ltxkeys@currtriple, saved as undefined}% + \ltxkeys@getinnovalue + \cptexpandarg{\cptfiltermergecsv[;]\ltxkeys@undefinedkeys}{% + \ltxkeys@ttpref,\ltxkeys@tfam,\ltxkeys@tkey,\InnocentVal + }\nofilter + }% + }% + }% + }% +} +\robust@def*\ltxkeys@setkeys@e{% + \ifboolTF{ltxkeys@tracingkeys}{% + \ltxkeys@getinnovaluenopad + \ltxkeys@debug{==}{Setting\@space\ifltxkeys@preset + preset\@space\fi key: \ltxkeys@currtriple,\InnocentVal}% + }{}% + \ifcsndefFT{\ltxkeys@hdr\ltxkeys@tkey}{% + \relax + \ltxkeys@debug{!!}{% + \ifltxkeys@preset Preset key\else Key\fi\@space + is not defined: \ltxkeys@currtriple,\InnocentVal + }% + }{% + \ltxkeys@kftrue + \ifltxkeys@tracingkeys + \ltxkeys@debug{++}{\ifltxkeys@preset Preset key\else Key\fi + \@space'\ltxkeys@tkey' is defined}% + \ifltxkeys@dec\else\ifltxkeys@ini\else + \edef\reserved@e{\ltxkeys@currtriple,\InnocentVal}% + \@onelevel@sanitize\reserved@e + \letcstocsn\reserved@f{\ltxkeys@hdr executedkeys}% + \oifinset@sp@TF*\reserved@e\reserved@f{% + \ltxkeys@debug{!!}{Key '\ltxkeys@currtriple' multiply + set with same value}% + }{% + \csn@edef{\ltxkeys@hdr executedkeys}{% + \csliststack*\reserved@f\reserved@e + }% + }% + \fi\fi + \fi + \ifboolTF{ltxkeys@pxop}{% + \ltxkeys@testoptionkey{non}% + }{% + \ifboolTF{ltxkeys@exop}{}{\ltxkeys@testoptionkey{}}% + }% + \ifboolTF{ltxkeys@sv}{}{% + \ifcsndefTF{\ltxkeys@hdr savevaluekeys}{\ltxkeys@testsavevaluekey}{}% + }% + \ifboolTF{ltxkeys@sv}{% + \ltxkeys@addtosavedvalue\ltxkeys@tkey\ltxkeys@tval + }{}% + \ifboolTF{ltxkeys@novalue}{% + \ifcsndefTF{\ltxkeys@hdr needvaluekeys}{\ltxkeys@testneedvaluekey}{}% + \ifcsndefTF{\ltxkeys@hdr\ltxkeys@tkey @default}{% + \ltxkeys@debug{==}{\ifltxkeys@preset Preset key\else Key\fi\@space + '\ltxkeys@tkey', no user-value, default found}% + \cptsevenxp\ltxkeys@usedefault + \usename{\ltxkeys@hdr\ltxkeys@tkey @default}\ltxkeys@nil + }{% + \ltxkeys@err{No value specified for key '\ltxkeys@tkey'} + \ltxkeys@ehd + }% + }{% + \s@expandarg\ltxkeys@replacepointers\ltxkeys@tval + \ltxkeys@debug{==}{% + \ifltxkeys@preset Preset key\else Key\fi\@space + '\ltxkeys@tkey', macro being executed now% + }% + \cpt@pushstate\ltxkeys@setkeys\ltxkeys@state\ltxkeys@keydepth + \csname\ltxkeys@hdr\ltxkeys@tkey\expandafter + \endcsname\expandafter{\ltxkeys@tval}\relax + \cpt@popstate\ltxkeys@setkeys\ltxkeys@keydepth + \ltxkeys@debug{++}{% + \ifltxkeys@preset Preset key\else Key\fi\@space + '\ltxkeys@tkey', macro executed% + }% + }% + }% +} +\robust@def*\ltxkeys@usedefault#1#2\ltxkeys@nil{% + \ltxkeys@debug{==}{Key '\ltxkeys@tkey', extracting default value}% + \def\reserved@a##1##2\ltxkeys@nil{% + \edef\reserved@a{\cptgobblescape{##1}}% + \edef\reserved@b{% + \detokenize\expandafter\expandafter\expandafter + {\expandafter\ltxkeys@hdr\ltxkeys@tkey}% + }% + \ltxkeys@ifxTF\reserved@a\reserved@b{% + \ltxkeys@debug{==}{Key '\ltxkeys@tkey' has standard macro}% + \begintoksgroup + \csn@def{\ltxkeys@hdr\ltxkeys@tkey}####1{% + \toks@{\edef\ltxkeys@tval{\unexpanded{####1}}}% + }% + \usename{\ltxkeys@hdr\ltxkeys@tkey @default}% + \endtoksgroup + \s@expandarg\ltxkeys@replacepointers\ltxkeys@tval + }{% + \ltxkeys@debug{!!}{Key '\ltxkeys@tkey' has nonstandard macro}% + }% + }% + \xaftercsname\reserved@a{\ltxkeys@hdr\ltxkeys@tkey @default}\ltxkeys@nil + \ifboolTF{ltxkeys@tracingkeys}{% + \ltxkeys@getinnovaluenopad + \ltxkeys@debug{==}{% + \ifltxkeys@preset Preset key\else Key\fi\@space + '\ltxkeys@tkey', macro being executed now% + }% + }{}% + \cpt@pushstate\ltxkeys@setkeys\ltxkeys@state\ltxkeys@keydepth + \ifmacroTF{#1}{% + \expandafter#1\expandafter{\ltxkeys@tval}\relax + }{% + \ltxkeys@err{Faulty key macro '\detokenize{#1}'}\ltxkeys@ehd + }% + \cpt@popstate\ltxkeys@setkeys\ltxkeys@keydepth + \ltxkeys@debug{++}{% + \ifltxkeys@preset Preset key\else Key\fi\@space + '\ltxkeys@tkey', macro executed% + }% +} +\robust@def*\ltxkeys@getsavedvalue#1{% + \def\reserved@a##1#1##2##3\ltxkeys@nil{% + \edef\ltxkeys@tempc{\unexpanded{##2}}% + \ltxkeys@ifxTF\ltxkeys@tempc\ltxkeys@nnil\@secondoftwo\@firstoftwo + }% + \cptsevenxp\reserved@a\usename{\ltxkeys@hdr @savedvaluelist}% + #1{\ltxkeys@nil}\ltxkeys@nil +} +\robust@def*\ltxkeys@replacepointers#1{% + \ltxkeys@debug{==}{Key '\ltxkeys@tkey', replacing pointers}% + \def\ltxkeys@resa{}% + \ltxkeys@swafalse + \ifbracedTF{#1}{% + \ltxkeys@r@placepointers{#1}\usevalue\ltxkeys@nil + }{% + \ltxkeys@r@placepointers#1\usevalue\ltxkeys@nil + }% + \let\ltxkeys@resa\relax +} +\robust@def*\ltxkeys@r@placepointers#1\usevalue#2{% + \def\reserved@a{#2}% + \ltxkeys@ifxTF\reserved@a\ltxkeys@nnil{% + \edef\ltxkeys@tval{\unexpanded{#1}}% + \ifltxkeys@swa + \ifltxkeys@tracingkeys + \ltxkeys@getinnovaluenopad + \ltxkeys@debug{++}{Key '\ltxkeys@tkey', value + inherited from '\ltxkeys@tempb'}% + \fi + \else + \ltxkeys@debug{==}{Key '\ltxkeys@tkey', no pointers found}% + \fi + }{% + \ltxkeys@getsavedvalue{#2}{% + \ltxkeys@swatrue + \def\ltxkeys@tempb{#2}% + \oifinset@sp@TF,\ltxkeys@tempb\ltxkeys@resa{% + \ltxkeys@error{Dangerous back linking of pointers} + {Key pointer replacement terminated due + \MsgBrk to possible back linking.}% + }{% + \edef\ltxkeys@resa{\csliststack,\ltxkeys@resa#2}% + \s@expandarg\ifbracedTF\ltxkeys@tempc{% + \s@expandarg\ltxkeys@r@placepointers\ltxkeys@tempc + }{% + \expandafter\ltxkeys@r@placepointers\ltxkeys@tempc + }% + }% + }{% + \ltxkeys@err{No value recorded for key '#2'}\ltxkeys@ehd + \ltxkeys@r@placepointers + }% + }% +} +\robust@def*\ltxkeys@storevalue{% + \ltxkeys@testpl{\ltxkeys@testopt@a\ltxkeys@st@revalue}% +} +\robust@def*\ltxkeys@st@revalue#1#2{% + \ifinsetFT{,}{#1}{}{% + \ltxkeys@err{Illegal multiple keys for + \string\ltxkeys@storevalue}\ltxkeys@ehd + }% + \ifescapedTF{#2}{}{\cpt@notescapederr{#2}}% + \ltxkeys@getsavedvalue{#1}{% + \ifltxkeys@pl + \expandafter\@firstofone + \else + \ltxkeys@err{% + No value recorded for key '#1' of + \MsgBrk family '\ltxkeys@tfam' and prefix '\ltxkeys@ttpref' + }{% + You have asked me to store the value of key '#1' + \MsgBrk (of family '\ltxkeys@tfam' and prefix '\ltxkeys@ttpref') + in the macro '\detokenize{#2}', + \MsgBrk but I can't find a value for key '#1'. Perhaps + \MsgBrk you haven't yet executed key '#1' or you didn't + \MsgBrk ask me to save its value. + }% + \fi + }{% + \let#2=\reserved@a + }% +} +\robust@def*\ltxkeys@getinnovalue{\ltxkeys@swatrue\ltxkeys@g@tinnovalue} +\robust@def*\ltxkeys@getinnovaluenopad{\ltxkeys@swafalse\ltxkeys@g@tinnovalue} +\robust@def*\ltxkeys@g@tinnovalue{% + \begingroup + \ltxkeys@ifcsemptyTF\ltxkeys@tval{% + \def\InnocentVal{???}% + }{% + \@tempcnta\z@pt + \def\InnocentVal{}% + \def\ltxkeys@tempa{\\}% + \def\do##1{% + \def\reserved@a{##1}% + \ltxkeys@ifxTF\reserved@a\ltxkeys@nnil{}{% + \advance\@tempcnta\@ne + \ifnum\@tempcnta<20\relax + \edef\InnocentVal{% + \InnocentVal + \ifx\reserved@a\ltxkeys@tempa + \ifltxkeys@swa\@space\fi + \else + ##1% + \fi + }% + \else + \def\do####1\ltxkeys@nil{}% + \fi + \do + }% + }% + \expandafter\do\detokenize\expandafter + {\ltxkeys@tval}\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ltxkeys@nil + }% + \postgroupdef\InnocentVal\endgroup +} +\robust@def*\ltxkeys@keyvalerr{% + \ltxkeys@getinnovaluenopad + \ltxkeys@err{Erroneous value '\InnocentVal' for key or option + \MsgBrk'\ltxkeys@tkey'}{Invalid key value encountered.}% +} +\robust@def*\ltxkeys@unknownkeyhandler{% + \def\ltxkeys@default@ds{default@ds@key}% + \cpt@testopt\ltxkeys@unkn@wnkeyhandler{KV}% +} +\robust@def*\ltxkeys@unkn@wnkeyhandler[#1]#2#3{% + \begintoksgroup + \toks1{##1##2##3##4{\ltxkeys@getinnovaluenopad#3}}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \cptexpanded{% + \toks@{\the\toks@ + \csn@def{\ltxkeys@hdr\ltxkeys@default@ds}\the\toks1% + }% + }% + }% + \ltxkeys@listparse1{#2}% + }% + \ltxkeys@listparse1{#1}% + \endtoksgroup +} +\robust@def*\ltxkeys@logunknownkeys{% + \ltxkeys@l@gunknownkeys + \ltxkeys@err{The above keys are undefined and couldn't be set} + {There are undefined keys; see above.}% +} +\robust@def*\ltxkeys@l@gunknownkeys{% + \ltxkeys@debug{==}{Now logging undefined keys}% + \begingroup + \cpt@cnta\z@pt + \edef\ltxkeys@skipa{}% + \cptwhilenum\cpt@cnta<20\do{% + \edef\ltxkeys@skipa{\ltxkeys@skipa\@space}% + \advance\cpt@cnta\@ne + }% + \typeout{\ltxkeys@skipa*** Unknown keys ***}% + \def\ltxkeys@tempb{\\}% + \def\align@do##1##2##3##4##5##6##7##8##9\@@{% + \def\ltxkeys@tempc{##9}% + \def\siso@do####1{% + \def\reserved@a{####1}% + \ifx\reserved@a\ltxkeys@tempb + \edef\ltxkeys@skipb{\@space\ltxkeys@skipb}% + \fi + }% + \siso@@loop{##1##2##3##4##5##6##7##8}% + }% + \edef\ltxkeys@tempa{% + *Prefix,*Family,*Name,*Value;\expandcsonce\ltxkeys@undefinedkeys + }% + \def\ltxkeys@splita##1,##2,##3,##4\ltxkeys@nil{% + \def\ltxkeys@msg{}% + \def\ltxkeys@do####1{% + \let\ltxkeys@skipb\@empty + \align@do####1\\\\\\\\\\\\\\\\\\\@@ + \expandafter\align@do\ltxkeys@tempc\\\\\\\\\\\\\\\\\\\@@ + \edef\ltxkeys@msg{\expandcsonce\ltxkeys@msg####1\ltxkeys@skipb}% + }% + \ltxkeys@listparse1{##1,##2,##3,##4}% + \typeout{\ltxkeys@msg}% + }% + \def\ltxkeys@do##1{% + \ltxkeys@splita##1\ltxkeys@nil + }% + \ltxkeys@listparse*0[;]\ltxkeys@tempa + \typeout{\ltxkeys@skipa*******************}% + \endgroup +} +\robust@def*\ltxkeys@disablekeys{% + \cpt@teststopt{\ltxkeys@dis@blekeys}{KV}% +} +\robust@def*\ltxkeys@dis@blekeys[#1]#2#3{% + \ltxkeys@debug{==}{Now disabling keys}% + \ifboolTF{cpt@st}{% + \AtBeginDocument{% + \ltxkeys@dis@bl@keys{#1}{#2}{#3}% + }% + }{% + \ltxkeys@dis@bl@keys{#1}{#2}{#3}% + }% +} +\robust@def*\ltxkeys@dis@bl@keys#1#2#3{% + \ltxkeys@commanormalizeset + {{#1}\ltxkeys@prefs,{#2}\ltxkeys@fams,{#3}\ltxkeys@keys}% + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \ltxkeys@dis@bl@k@ys + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs +} +\robust@def*\ltxkeys@dis@bl@k@ys{% + \begingroup + \toks@{}% + \ifcsndefTF{\ltxkeys@hdr disabledkeys}{}{% + \@namedef{\ltxkeys@hdr disabledkeys}{}% + }% + \letcstocsn\ltxkeys@dkeys{\ltxkeys@hdr disabledkeys}% + \edef\ltxkeys@tempb##1{% + \ltxkeys@err + {Key '##1' of family '\ltxkeys@tfam' has been disabled}% + {Key '##1' has been disabled.\MsgBrk + You can't set or reset it at this late stage.\MsgBrk + Perhaps you should have set it earlier in\MsgBrk + '\string\documentclass' or '\string\usepackage'.}% + }% + \def\ltxkeys@do##1{% + \ifcsndefTF{\ltxkeys@hdr##1}{% + \xifinsetTF{,##1,}{,\expandcsonce\ltxkeys@dkeys,}{}{% + \cptpassexpanded{% + \toks@{\the\toks@ + \ltxkeys@ordkey[\ltxkeys@ttpref]{\ltxkeys@tfam}{##1}% + \ifcsndefTF{\ltxkeys@hdr##1@default}{[]}{}% + {\expandcsonce{\ltxkeys@tempb{##1}}}% + }% + }% + \edef\ltxkeys@dkeys{% + \csliststack,\ltxkeys@dkeys\unexpanded{##1}% + }% + }% + }{% + \ltxkeys@debug{!!}{Key '##1' is undefined in + family '\ltxkeys@tfam'}% + }% + }% + \ltxkeys@listparse*0\ltxkeys@keys + \cptpassexpanded{\endgroup + \csn@def{\ltxkeys@hdr disabledkeys}{\ltxkeys@dkeys}% + \noexpand\ltxkeys@disabletrue + \the\toks@ + \noexpand\ltxkeys@disablefalse + }% +} +\robust@def*\ltxkeys@nostarform#1#2{% + \if\detokenize{#1*.}% + \ltxkeys@err{No star (*) form of command \string#2}\ltxkeys@ehd + \fi +} +\robust@def*\ltxkeys@declareoption{% + \let\@fileswith@pti@ns\@badrequireerror + \cpt@ifstar{% + \ltxkeys@unknownoptionhandler + }{% + \let\ltxkeys@tempa\ltxkeys@ordkey + \ltxkeys@d@cl@reoption + }% +} +\robust@def\ltxkeys@unknownoptionhandler{% + \cpt@testopt\ltxkeys@unkn@wnoptionhandler{KV}% +} +\robust@def*\ltxkeys@unkn@wnoptionhandler[#1]{% + \cpt@testfam{\ltxkeys@unkn@wnopti@nhandler{#1}}% +} +\robust@def*\ltxkeys@unkn@wnopti@nhandler#1<#2>#3{% + \def\ltxkeys@default@ds{default@ds@opt}% + \ltxkeys@unkn@wnkeyhandler[#1]{#2}{#3}% +} +\robust@def*\ltxkeys@declareordoption#1{% + \let\@fileswith@pti@ns\@badrequireerror + \ltxkeys@d@clareoption{#1}{ord}% +} +\newletcs\ltxkeys@declareordoptions\ltxkeys@declareordoption +\newletcs\ltxkeys@declareoptions\ltxkeys@declareordoption +\robust@def*\ltxkeys@declarecmdoption#1{% + \let\@fileswith@pti@ns\@badrequireerror + \ltxkeys@d@clareoption{#1}{cmd}% +} +\newletcs\ltxkeys@declarecmdoptions\ltxkeys@declarecmdoption +\robust@def*\ltxkeys@declarebooloption#1{% + \let\@fileswith@pti@ns\@badrequireerror + \ltxkeys@d@clareoption{#1}{bool}% +} +\newletcs\ltxkeys@declarebooloptions\ltxkeys@declarebooloption +\robust@def*\ltxkeys@declarechoiceoption#1{% + \let\@fileswith@pti@ns\@badrequireerror + \ltxkeys@d@clareoption{#1}{choice}% +} +\newletcs\ltxkeys@declarechoiceoptions\ltxkeys@declarechoiceoption +\robust@def*\ltxkeys@d@clareoption#1#2{% + \aftercsname{\ltxkeys@nostarform{#1}}{ltxkeys@declare#2option}% + \edef\ltxkeys@tempa{\noexpandcsn{ltxkeys@#2key}}% + \let\@fileswith@pti@ns\@badrequireerror + \ifsingletokenTF{#1}{% + \ltxkeys@d@cl@reoption#1% + }{% + \ltxkeys@d@cl@reoption{#1}% + }% +} +\robust@def*\ltxkeys@d@cl@reoption{% + \cpt@testopt\ltxkeys@d@cl@r@option{KV}% +} +\robust@def*\ltxkeys@d@cl@r@option[#1]{% + \cpt@testfam{\ltxkeys@d@cl@r@opti@n{#1}}% +} +\robust@def*\ltxkeys@d@cl@r@opti@n#1<#2>{\ltxkeys@tempa[#1]{#2}} + +\robust@def*\ltxkeys@declaremultitypeoptions{% + \cpt@testst\ltxkeys@d@claremultitypeoptions +} +\newletcs\declaremultitypeoptions\ltxkeys@declaremultitypeoptions +\robust@def*\ltxkeys@d@claremultitypeoptions{% + \cpt@testpnopt\ltxkeys@d@cl@remultitypeoptions{}% +} +\robust@def*\ltxkeys@d@cl@remultitypeoptions(#1){% + \cpt@testopt{\ltxkeys@d@cl@rem@ltitypeoptions{#1}}{KV}% +} +\robust@def*\ltxkeys@d@cl@rem@ltitypeoptions#1[#2]{% + \cpt@testfam{\ltxkeys@d@cl@rem@ltitypeopti@ns{#1}{#2}}% +} +\robust@def*\ltxkeys@d@cl@rem@ltitypeopti@ns#1#2<#3>{% + \cptexpanded{% + \ltxkeys@declarekeys\ifcpt@st*\fi + \iflacus#1\dolacus\else(#1)\fi[#2]{#3}% + }% +} +\robust@def*\ltxkeys@executeoptions#1{% + \ltxkeys@nostarform{#1}\ltxkeys@executeoptions + \ltxkeys@debug{==}{Executing options}% + \ltxkeys@exoptrue\ltxkeys@stfalse\ltxkeys@pltrue + \ltxkeys@rmfalse + \ifsingletokenTF{#1}{% + \ltxkeys@testopt@@b\ltxkeys@setkeys@a#1% + }{% + \ltxkeys@testopt@@b\ltxkeys@setkeys@a{#1}% + }% +} +\robust@def*\ltxkeys@beforeprocessoptions{% + \ifcsndefTF{\@currname @\@currext @ltxkeys@beginprocessopt}{% + \ltxkeys@warn{Command \noexpand\ltxkeys@beforeprocessoptions + is wrongly located}% + \@gobble + }{% + \grightaddtocsn{\@currname @\@currext + @ltxkeys@beforeprocessopt@hook}% + }% +} +\robust@def*\ltxkeys@afterprocessoptions{% + \ifcsndefTF{\@currname @\@currext @ltxkeys@endprocessopt}{% + \@firstofone + }{% + \grightaddtocsn{\@currname @\@currext + @ltxkeys@afterprocessopt@hook}% + }% +} +\robust@def*\ltxkeys@useandrelaxcsn#1{% + \ifcsndefFT{#1}{}{% + \letcstocsn\reserved@a{#1}% + \letcsntocs{#1}\relax + \reserved@a + }% +} + +\def\ltxkeys@processedoptions{} +\robust@def*\ltxkeys@processoptions{% + \ifcsndefTF{\@currname @\@currext @ltxkeys@beginprocessopt}{% + \ltxkeys@err{\noexpand\ltxkeys@processoptions issued twice + in same \@cls@pkg '\@currname'}\ltxkeys@ehd + }{% + \csn@def{\@currname @\@currext @ltxkeys@beginprocessopt}{}% + }% + \ltxkeys@useandrelaxcsn + {\@currname @\@currext @ltxkeys@beforeprocessopt@hook}% + \ltxkeys@debug{==}{Processing options}% + \ltxkeys@pltrue\ltxkeys@rmfalse + \ltxkeys@testopt@@a\ltxkeys@pr@cessoptions +} +\robust@def*\ltxkeys@pr@cessoptions[#1]{% + \ltxkeys@pxoptrue + \def\ltxkeys@poxlist{}% + \let\@fileswith@pti@ns\@badrequireerror + \edef\ltxkeys@testname{\@currname.\@currext}% + \ltxkeys@ifxTF\ltxkeys@testname\ltxkeys@documentclass{% + \let\@unusedoptionlist\ltxkeys@classoptionslist + }{% + \ifdefboolFT{ltxkeys@st}{}{% + \def\ltxkeys@do##1{% + \edef\CurrentKeyval{\unexpanded{##1}}% + \ltxkeys@getkeyname##1=\ltxkeys@nil\ltxkeys@tkey + \begingroup + \let\xp\expandcsonce + \edef\x{[\xp\ltxkeys@prefs]{\xp\ltxkeys@fams}{\xp\ltxkeys@tkey}}% + \expandafter\endgroup\expandafter\ltxkeys@ifkeydefFT\x{}{% + \ltxkeys@ifcsemptyTF\@unusedoptionlist{% + \cptgaddtolist\ltxkeys@processedoptions{##1}% + }{% + \cpt@removecurroption{##1}% + \ltxkeys@debug{==}{Key \ltxkeys@currtriple, removed from + \string\@unusedoptionlist}% + }% + \cptaddtolist\ltxkeys@poxlist{##1}% + }% + }% + \ltxkeys@ifcsemptyTF\ltxkeys@classoptionslist{} + {\ltxkeys@listparse*0\ltxkeys@classoptionslist}% + }% + }% + \edef\ltxkeys@tempa{\cpt@optionlist{\@currname.\@currext}}% + \edef\ltxkeys@poxlist + {\csliststack,\ltxkeys@tempa\expandcsonce\ltxkeys@poxlist}% + \ltxkeys@ifcsemptyTF\ltxkeys@poxlist{}{% + \cptexpandargonce{\ltxkeys@setkeys@a[#1]}\ltxkeys@poxlist + }% + \s@expandarg\ltxkeys@getkeynames\ltxkeys@poxlist + \def\ltxkeys@do##1{% + \ltxkeys@makepf{##1}% + \def\ltxkeys@do####1{% + \ltxkeys@makehdr{####1}% + \def\ltxkeys@do########1{% + \ifcsndefTF{\ltxkeys@hdr########1}{% + \csn@xdef{\ltxkeys@hdr poxkeys}{% + \csnliststack,{\ltxkeys@hdr poxkeys}% + \unexpanded{########1}% + }% + }% + }% + \ltxkeys@listparse*0\ltxkeys@keynames + \ifcsndefFT{\ltxkeys@hdr optionkeys}{}{% + \letcstocsn\ltxkeys@tempb{\ltxkeys@hdr poxkeys}% + \ifdefTF\ltxkeys@tempb{}{\def\ltxkeys@tempb{}}% + \def\ltxkeys@do########1{% + \xifinsetTF{,########1,}{,\expandcsonce\ltxkeys@tempb,}{}{% + \edef\ltxkeys@tempb{% + \csliststack,\ltxkeys@tempb\unexpanded{########1}% + }% + }% + }% + \aftercsname{\ltxkeys@listparse*0}{\ltxkeys@hdr optionkeys}% + \gletcsntocs{\ltxkeys@hdr poxkeys}\ltxkeys@tempb + }% + }% + \ltxkeys@listparse*0\ltxkeys@fams + }% + \ltxkeys@listparse*0\ltxkeys@prefs + \undefcs\ltxkeys@poxlist + \csn@def{\ltxkeys@hdr rmkeys}{}% + \ltxkeys@pxopfalse + \let\@fileswith@pti@ns\@@fileswith@pti@ns + \AtEndOfPackage{\let\@unprocessedoptions\relax}% + \ltxkeys@debug{==}{Ended processing options}% + \ltxkeys@debug{==}{Now doing <afterprocessoptions>}% + \ltxkeys@useandrelaxcsn + {\@currname @\@currext @ltxkeys@afterprocessopt@hook}% + \csn@def{\@currname @\@currext @ltxkeys@endprocessopt}{}% +} +\robust@def*\ltxkeys@ifkeydefTF{\begingroup\ltxkeys@ifkeydef0} +\robust@def*\ltxkeys@ifkeydefFT{\begingroup\ltxkeys@ifkeydef1} +\robust@def*\ltxkeys@ifkeydef#1{\cpt@testopt{\ltxkeys@ifk@ydef#1}{KV}} +\robust@def*\ltxkeys@ifk@ydef#1[#2]#3#4{% + \ltxkeys@commanormalizeset{{#2}\ltxkeys@prefs,{#3}\ltxkeys@fams}% + \ltxkeys@trimspaces{#4}\ltxkeys@tkey + \cpt@choicefdfalse + \def\ltxkeys@do##1{% + \ifboolTF{cpt@choicefd}{% + \loopbreak + }{% + \ltxkeys@makepf{##1}% + \ltxkeys@ifk@yd@f + }% + }% + \ltxkeys@listparse*0\ltxkeys@prefs + \ltxkeys@ifchcfd#1\endgroup +} +\robust@def*\ltxkeys@ifk@yd@f{% + \def\ltxkeys@do##1{% + \ltxkeys@makehdr{##1}% + \ifcsndefTF{\ltxkeys@hdr\ltxkeys@tkey}{% + \cpt@choicefdtrue\loopbreak + }{}% + }% + \ltxkeys@listparse*0\ltxkeys@fams +} +\robust@def*\ltxkeysglobal{\ltxkeys@globaltrue} +\robust@def*\ltxkeysprotected{\ltxkeys@protectedtrue} +\newletcs\ltxkeysrobust\ltxkeysprotected +\robust@def*\ltxkeys@global@protected{% + \ifltxkeys@global + \ltxkeys@globalfalse + \let\ltxkeys@tempa\global + \else + \let\ltxkeys@tempa\@empty + \fi + \ifltxkeys@protected + \ltxkeys@protectedfalse\protected + \fi + \ltxkeys@tempa +} +\robust@def*\ltxkeyscmd{% + \let\ltxkeys@inenv\cptswfalse + \cpt@starorlong\ltxkeys@keycommand +} +\robust@def*\ltxkeys@keycommand#1{% + \cpt@testopt{\ltxkeys@keycommand@a#1}0% +} +\robust@def*\ltxkeys@keycommand@a#1[#2]{% + \ltxkeys@inkeycmdtrue + \cpt@ifbrack + {\ltxkeys@keycommand@e#1{#2}}{\ltxkeys@keycommand@b#1{#2}}% +} +\robust@def*\ltxkeys@keycommand@b#1#2{% + \cpt@testltopt{\ltxkeys@keycommand@c{#1}{#2}}{}% +} +\robust@def*\ltxkeys@keycommand@c#1#2<#3>{% + \cpt@testpnopt{\ltxkeys@keycommand@d{#1}{#2}{#3}}{}% +} +\robust@def\ltxkeys@keycommand@d#1#2#3(#4)#5{% + \ifcsdefinable#1\relax + \edef\reserved@a{\cptgobblescape#1}% + \cptexpandsecond{\ltxkeys@declarekeys*[CMDKEY]} + {{ltxkeys@\reserved@a}[\reserved@a @]}{#4}% + \def\reserved@a{\ltxkeys@keycommand@h#1\@ne{#2}{#3}}% + \expandafter\reserved@a\expandafter{% + \expandafter\long\expandafter\edef\expandafter + \ltxkeys@cmdbody\expandafter{\expandafter + {\ltxkeys@inenv}{\unexpanded{#5}}}% + \cptexpandarg\cpt@testpnopt{\ltxkeys@keycommand@j + {\cptgobblescape#1}}{}% + }% +} +\robust@def*\ltxkeys@keycommand@e#1#2[#3]{% + \cpt@testltopt{\ltxkeys@keycommand@f{#1}{#2}{#3}}{}% +} +\robust@def*\ltxkeys@keycommand@f#1#2#3<#4>{% + \cpt@testpnopt{\ltxkeys@keycommand@g{#1}{#2}{#3}{#4}}{}% +} +\robust@def\ltxkeys@keycommand@g#1#2#3#4(#5)#6{% + \ifcsdefinable#1\relax + \edef\reserved@a{\cptgobblescape#1}% + \cptexpandsecond{\ltxkeys@declarekeys*[CMDKEY]} + {{ltxkeys@\reserved@a}[\reserved@a @]}{#5}% + \ifltxkeys@global\global\fi + \ifltxkeys@protected\protected\fi + \expandafter\def\expandafter#1\expandafter{% + \expandafter\@protected@testopt\expandafter#1% + \csname\string#1\endcsname{#3}% + }% + \def\reserved@a{% + \aftercsname\ltxkeys@keycommand@h{\string#1}\tw@{#2}{#4}% + }% + \expandafter\reserved@a\expandafter{% + \expandafter\long\expandafter\edef\expandafter + \ltxkeys@cmdbody\expandafter{\expandafter + {\ltxkeys@inenv}{\unexpanded{#6}}}% + \cptexpandarg\cpt@testpnopt{\ltxkeys@keycommand@j + {\cptgobblescape#1}}{}% + }% +} +\robust@def*\ltxkeys@keycommand@h#1#2#3#4{% + \ifnum#2=\tw@ + \def\ltxkeys@tempb##11{[####1]}% + \else + \let\ltxkeys@tempb\@gobble + \fi + \expandafter\ltxkeys@keycommand@i\expandafter{\number#3}#1{#4}% +} +\robust@def\ltxkeys@keycommand@i#1#2#3{% + \begingroup + \iflacus#3\dolacus + \let\elt\@gobble + \else + \def\elt##1{\expandcsnonce{d##1}}% + \@tempcnta\z@pt + \loop + \advance\@tempcnta\@ne + \csn@def{d\number\@tempcnta}{}% + \ifnum\@tempcnta<9\relax + \repeat + \@tempcnta\z@pt + \def\@do##1##2{% + \edef\ltxkeys@tempa{\cpttrimspace{##1}}% + \ifstrcmpTF{##1}\keycommand@nil{}{% + \advance\@tempcnta\@ne + \ifnum\@tempcnta>#1\relax + \ltxkeys@err{Number of delimiters exceeds + number of parameters}\ltxkeys@ehd + \fi + \xifinsetTF{,\expandcsonce\ltxkeys@tempa,}% + {,1,2,3,4,5,6,7,8,9,}{}{% + \ltxkeys@err{Invalid delimiter syntax: + \MsgBrk no digit [1-9] found before + delimiter}\ltxkeys@ehd + }% + \csn@edef{d\ltxkeys@tempa}{\cpttrimspace{##2}}% + \@do + }% + }% + \@do#3\keycommand@nil\keycommand@nil + \fi + \iflacus#3\dolacus\else + \ifx\ltxkeys@tempb\@gobble\else + \expandafter\ifx\csname d1\endcsname\@empty\else + \ltxkeys@err{First argument of command \string#2 is + \MsgBrk already delimited by '[]'}\ltxkeys@ehd + \fi + \fi + \fi + \edef\ltxkeys@tempc{% + 0####1\ifx\ltxkeys@tempb\@gobble\elt1\fi + ####2\elt2####3\elt3####4\elt4####5\elt5####6\elt6% + ####7\elt7####8\elt8####9\elt9% + }% + \def\ltxkeys@tempa##1#1##2##{% + \def\ltxkeys@tempc{% + \ltxkeys@inkeycmdfalse + \ltxkeys@global@protected\l@ngrel@x + }% + \cptexpandsecond{\expandafter\endgroup\ltxkeys@tempc + \expandafter\def\expandafter#2\ltxkeys@tempb##1#1}{\elt{#1}}% + }% + \expandafter\ltxkeys@tempa\ltxkeys@tempc###1% +} +\robust@def*\ltxkeys@keycommand@j#1(#2){% + \ltxkeys@setkeys[CMDKEY]{ltxkeys@#1}{#2}% + \cptpushfunctions\ltxkeyscmd{% + \\\val\\\ifval\\\ifvalTF\\\keyval\\\ifkeyval\\\ifkeyvalTF + }\ltxkeyscmd@depth + \def\val##1{\usename{#1@\cpttrimspace{##1}}}% + \def\ifval##1\then{\usename{if#1@\cpttrimspace{##1}}}% + \def\ifvalTF##1{% + \ifval##1\then\expandafter\cptiofii\else\expandafter\cptiiofii\fi + }% + \def\keyval##1{% + \ifcsndefTF{#1@\cpttrimspace{##1}}{% + \usename{#1@\cpttrimspace{##1}}% + }{% + \ltxkeys@err{Key '\cpttrimspace{##1}' not defined by + command '\@backslashchar#1'}\ltxkeys@ehd + }% + }% + \def\ifkeyval##1\then{% + \ifcsndefTF{if#1@\cpttrimspace{##1}}{% + \usename{if#1@\cpttrimspace{##1}}% + }{% + \ltxkeys@err{Key '\cpttrimspace{##1}' not defined by + command '\@backslashchar#1'}\ltxkeys@ehd + }% + }% + \def\ifkeyvalTF##1{% + \ifkeyval##1\then\expandafter\cptiofii\else\expandafter\cptiiofii\fi + }% + \long\def\reserved@a##1##2\ltxkeys@nil{% + % \ifswitch won't work here: + \ifcondTF\if##1\fi{% + ##2% + }{% + ##2% + \cptpopfunctions\ltxkeyscmd\ltxkeyscmd@depth + }% + }% + \expandafter\reserved@a\ltxkeys@cmdbody\ltxkeys@nil +} +\robust@def*\reltxkeyscmd{% + \let\ltxkeys@inenv\cptswfalse + \cpt@starorlong\ltxkeys@rekeycommand +} +\robust@def*\ltxkeys@rekeycommand#1{% + \ifdefTF{#1}{}{% + \ltxkeys@warn{Command '\string#1' was previously undefined + \MsgBrk but now defined by \string\ltsrenewcommand}% + }% + \let\ifcsdefinable\rc@ifcsdefinable + \ltxkeys@keycommand#1% +} +\robust@def*\ltxkeysenv{% + \let\ltxkeys@inenv\cptswtrue + \cpt@starorlong\ltxkeys@keyenvironment +} +\robust@def*\ltxkeys@keyenvironment#1{\cpt@testopt{\ltxkeys@newenv@a#1}0} +\robust@def*\ltxkeys@newenv@a#1[#2]{% + \begingroup + \toks@{}% + \ifnum#2=\z@pt\else + \@tempcnta\z@pt + \loop + \advance\@tempcnta\@ne + \cptexpanded{% + \toks@{\the\toks@\csn@def{keyenvarg@\romannumeral\@tempcnta}% + {########\the\@tempcnta}}% + }% + \ifnum\@tempcnta<#2\relax + \repeat + \fi + \cpt@ifbrack{\ltxkeys@newenv@b#1[#2]}{\ltxkeys@newenv@c{#1}[#2]}% +} +\robust@def*\ltxkeys@newenv@b#1[#2][#3]{% + \cpt@testltopt{\ltxkeys@newenv@d{#1}{[#2][{#3}]}}{}% +} +\robust@def*\ltxkeys@newenv@c#1[#2]{% + \cpt@testltopt{\ltxkeys@newenv@d{#1}{[#2]}}{}% +} +\robust@def*\ltxkeys@newenv@d#1#2<#3>{% + \cpt@testpnopt{\ltxkeys@newenv@e{#1}{#2}{#3}}{}% +} +\robust@def\ltxkeys@newenv@e#1#2#3(#4)#5#6{% + \ifcsndefTF{#1}{}{\letcsntocsn{#1}{end#1}}% + \def\@do##1{\edef\@do{\unexpanded{##1}}}% + \ifblankTF{#3}{% + \ifblankTF{#4}{% + \@do{#2}% + }{% + \@do{#2(#4)}% + }% + }{% + \ifblankTF{#4}{% + \@do{#2<#3>}% + }{% + \@do{#2<#3>(#4)}% + }% + }% + \xdef\ltxkeys@newenv@f{% + \ifltxkeys@global\global\fi + \ifltxkeys@protected\protected\fi + }% + \cptexpandsecond{% + \endgroup\ltxkeys@keycommand + }{% + \noexpandcsn{#1}\expandcsonce\@do{% + \the\toks@\unexpanded{#5}% + }% + }% + \ltxkeys@newenv@f + \l@ngrel@x\csn@def{end#1}{% + \def\envarg####1{\usename{keyenvarg@\romannumeral####1}}% + #6\relax + \cptpopfunctions\ltxkeyscmd\ltxkeyscmd@depth + \ltxkeys@everyeoehook + }% +} +\robust@def*\reltxkeysenv{% + \let\ltxkeys@inenv\cptswtrue + \cpt@starorlong\ltxkeys@rekeyenvironment +} +\robust@def*\ltxkeys@rekeyenvironment#1{% + \ifdefTF{#1}{}{% + \ltxkeys@warn{Environment '\string#1' was previously undefined + \MsgBrk but now defined by \string\reltxkeysenv}% + }% + \letcsntocs{#1}\relax + \letcsntocs{end#1}\relax + \ltxkeys@keyenvironment{#1}% +} +\robust@def\ltxkeys@ifpattern#1#2{% + \begingroup + \edef\ltxkeys@tempa##1{\def##1####1\detokenize{#1}####2&}% + \ltxkeys@tempa\ltxkeys@tempa{% + \aftercsname\endgroup{@\ifblankTF{##2}{second}{first}oftwo}% + }% + \edef\ltxkeys@tempb##1{##1\detokenize{#1}&}% + \ltxkeys@tempb{\expandafter\ltxkeys@tempa\meaning#2}% +} + +\new@def*\ltxkeys@everyeoehook{} +\robust@def*\ltxkeys@everyeoe#1{% + \ifblankTF{#1}{% + \gdef\ltxkeys@everyeoehook{}% + }{% + \xdef\ltxkeys@everyeoehook{% + \unexpanded{#1}\expandcsonce\ltxkeys@everyeoehook + }% + }% + \ltxkeys@ifpattern\@ignoretrue\ltxkeys@everyeoehook{% + \ltxkeys@ifpattern\ignorespacesafterend\ltxkeys@everyeoehook{% + \ltxkeys@err{Bad '\string\ltxkeys@everyeoe'} + {You can't have both '\string\@ignoretrue' and + '\string\ignorespacesafterend' in + \MsgBrk '\string\ltxkeys@everyeoe'.}% + }{% + \ltxkeys@checkbadeoe\@ignoretrue + }% + }{% + \ltxkeys@ifpattern\ignorespacesafterend\ltxkeys@everyeoehook{% + \ltxkeys@checkbadeoe\ignorespacesafterend + }{}% + }% +} +\new@def*\ltxkeys@checkbadeoe#1{% + \begingroup + \edef\ltxkeys@tempa##1{\def##1####1\detokenize{#1}####2&}% + \ltxkeys@tempa\ltxkeys@tempa{% + \ifblankTF{##2}{}{% + \xifinsetTF{\detokenize{#1}}{##2}{% + \ltxkeys@err{'\detokenize{#1}' repeated in + '\string\ltxkeys@everyeoe'.} + {Multiple '\detokenize{#1}' not allowed in + '\string\ltxkeys@everyeoe'.}% + }{% + \ltxkeys@err{Bad last token in '\string\ltxkeys@everyeoe'} + {'\detokenize{#1}' not the last token in + '\string\ltxkeys@everyeoe'.}% + }% + }% + }% + \expandafter\ltxkeys@tempa\meaning\ltxkeys@everyeoehook&% + \endgroup +} +\ltxkeys@everyeoe\ignorespacesafterend + +\robust@def*\setvarvalues{\cpt@testopt\ltxkeys@setvarvalues{var@subfam}} +\robust@def*\ltxkeys@setvarvalues[#1]#2{\pathkeys{pathkeys@var@fam/#1/set:#2}} +\new@def*\getvarvalue{\cpt@newxtestopt\ltxkeys@getvarvalue{var@subfam}} +\new@def*\ltxkeys@getvarvalue[#1]#2{\pathkeysval{pathkeys@var@fam/#1/#2}} +\robust@def*\ltxkeys@declarevariables{% + \cpt@testopt\ltxkeys@d@clarevariables{var@subfam}% +} +\robust@def*\ltxkeys@d@clarevariables[#1]#2{% + \begingroup + \def\elt##1{\oifstrcmpTF{^?^}{##1}{}{/\expandcsonce##1}}% + \cptdocommalist{#2}{% + \ltxkeys@d@cl@revariables##1=^?^=^?^=\ltxkeys@nil + }% + \cptexpanded{\endgroup + \pathkeys{pathkeys@var@fam/#1/define*:\expandcsonce\key@list}% + }% +} +\robust@def*\ltxkeys@d@cl@revariables#1={% + \def\reserved@a##1={% + \def\reserved@a####1=####2\ltxkeys@nil{% + \ltxkeys@trimspaces{#1}\reserved@a + \ltxkeys@remdottrimspaces{##1}\reserved@b + \ltxkeys@remdottrimspaces{####1}\reserved@c + \cptexpanded{% + \cptgaddtolist[;]\noexpand\key@list{% + \cptexpandbracenext{\cptifcasse\ifstrcmpTF}\reserved@a + {true}{bool}{false}{bool}% + \elseif + cmd% + \endif + /\expandcsonce\reserved@a\elt\reserved@b\elt\reserved@c + }% + }% + }% + \reserved@a.% + }% + \reserved@a.% +} +\robust@def*\ltxkeys@emergencystop{% + \immediate\write\sixt@@n{OK, I'm exiting now.}% + \interactionmode\z@pt + \ifnumcmpTF\currentgrouptype>\z@pt{% + \endgroup\aftergroup\@@end + }{% + \aftergroup\@@end + }% +} +\robust@def*\ltxkeys@unknownoptionerror{% + \ltxkeys@err{Unknown option '\CurrentKey' for + \@cls@pkg\space '\@currname'} + {Unknown option '\CurrentKey' for \@cls@pkg\space '\@currname'. + \MsgBrk The option '\CurrentKey' was not declared in \@cls@pkg + \MsgBrk'\@currname'. Perhaps you misspelled its name. + }% +} +\cptonlypreamble{% + \ltxkeys@declareoption,\ltxkeys@declareoptions, + \ltxkeys@declareordoption,\ltxkeys@declareordoptions, + \ltxkeys@declarecmdoption,\ltxkeys@declarecmdoptions, + \ltxkeys@declarebooloption,\ltxkeys@declarebooloptions, + \ltxkeys@declarechoiceoption,\ltxkeys@declarechoiceoptions, + \ltxkeys@processoptions,\ltxkeys@executeoptions, + \ltxkeys@unknownoptionhandler,\ltxkeys@declaremultitypeoptions, + \declaremultitypeoptions +} +\ltxkeys@declareoption*[KV]<ltxkeys>{% + \ltxkeys@warn{Unknown option '\CurrentKey' with + value '\InnocentVal' ignored.}% +} +\ltxkeys@declarecmdoption[KV]<ltxkeys>[ltxkeys@]{keyparser}[{;}]{% + \ltxkeys@stripallouterbracesincs\ltxkeys@keyparser +} +\ltxkeys@declarecmdoption[KV]<ltxkeys>[ltxkeys@]{% + \needvalue{keydepthlimit}% +}{% + \ifblankTF{#1}{% + \ltxkeys@err{Invalid empty value for 'keydepthlimit'} + \ltxkeys@ehd + }{% + \xdef\cpt@optionstacklimit{\number0#1}% + }% +} +\ltxkeys@declarecmdoption[KV]<ltxkeys>[ltxkeys@]{% + \needvalue{keystacklimit}% +}{% + \ltxkeys@setaliaskey{keydepthlimit}% +} +\ltxkeys@declarebooloptions[KV]<ltxkeys>[ltxkeys@]{% + tracingkeys,reservenopath +}[true]{} +\ltxkeys@declarebooloption[KV]<ltxkeys>[ltxkeys@]{allowemptypath}[true]{% + \ifltxkeys@allowemptypath\ltxkeys@useemptytrue\fi +} +\ltxkeys@executeoptions[KV]<ltxkeys>{keyparser,keydepthlimit=4}\relax + +\ltxkeys@processoptions*[KV]<ltxkeys>\relax + +\cpt@optioncleanup\ltxkeys@processedoptions + +\robust@def*\setltxkeysoptions#1{% + \ifblankTF{#1}{}{\ltxkeys@setkeys[KV]{ltxkeys}{#1}}% +} + +\endinput + +%% End of file ltxkeys.sty %% |