%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % 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 \space to proceed.\MsgBrk If that fails, type X and then \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', . % 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[]{}{}[]{} \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} % {} % 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: % #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: % #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: % #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: % #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: % #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[]{}[]{}[](){}. % The dependants have the syntax: % {///; another set of dependant; etc}. % % 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 and of . % % '#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: \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*+![}[]{}[]{}[]{}{} % If is absent, then \ltxkeys@choicekey uses \chc@@ % to hold user input. % % When there are no callbacks in ist has the syntax % {choice1, choice2, etc}. % % But when has callbacks, it has the syntax: % {choice1/.code=callback1; choice2/.code=callback2; etc}. % % It is possible to refer to the current value of as '#1' in . % \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: (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[]{}{} \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 and . % 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{% % \@@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]{}[macropf]{= % /; ...}. % Key default value and macro can be absent, % but boolean keys must have values ( | ), % 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]{}[macropf]{/ % // ...}. % Key default and macro can be absent. % 2. keytype = | | | | | . % 3. Choice keys must have their names associated with % their admissible values in the format . % 4. * -> We're defining new keys (in the sense of \newcommand). % % Example: % \ltxkeys@declarekeys*[KV]{}[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{} \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[]{}[] % 1. Preset all keys defined in families ; % ignore keys listed in . 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 % \@@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*+[]{}{} % 1. First preset all family keys before setting keys in . % 2. are the key-vals to be set in the current run; they % will be ignored when initializing the keys of families : \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 }% \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@warn{Unknown option '\CurrentKey' with value '\InnocentVal' ignored.}% } \ltxkeys@declarecmdoption[KV][ltxkeys@]{keyparser}[{;}]{% \ltxkeys@stripallouterbracesincs\ltxkeys@keyparser } \ltxkeys@declarecmdoption[KV][ltxkeys@]{% \needvalue{keydepthlimit}% }{% \ifblankTF{#1}{% \ltxkeys@err{Invalid empty value for 'keydepthlimit'} \ltxkeys@ehd }{% \xdef\cpt@optionstacklimit{\number0#1}% }% } \ltxkeys@declarecmdoption[KV][ltxkeys@]{% \needvalue{keystacklimit}% }{% \ltxkeys@setaliaskey{keydepthlimit}% } \ltxkeys@declarebooloptions[KV][ltxkeys@]{% tracingkeys,reservenopath }[true]{} \ltxkeys@declarebooloption[KV][ltxkeys@]{allowemptypath}[true]{% \ifltxkeys@allowemptypath\ltxkeys@useemptytrue\fi } \ltxkeys@executeoptions[KV]{keyparser,keydepthlimit=4}\relax \ltxkeys@processoptions*[KV]\relax \cpt@optioncleanup\ltxkeys@processedoptions \robust@def*\setltxkeysoptions#1{% \ifblankTF{#1}{}{\ltxkeys@setkeys[KV]{ltxkeys}{#1}}% } \endinput %% End of file ltxkeys.sty %%