diff options
author | Karl Berry <karl@freefriends.org> | 2011-09-29 23:44:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2011-09-29 23:44:46 +0000 |
commit | 11df19d00fedac57b77345afb713e878d0482088 (patch) | |
tree | 753e98c2ee11986a36a4a00b45464e9362d4f504 | |
parent | 7320c39b3943cac8ea4e08425e2c51f6238075bb (diff) |
ltxtools (27sep11)
git-svn-id: svn://tug.org/texlive/trunk@24148 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/ltxtools/README | 32 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/ltxtools/ltxtools.sty | 5141 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/ltxtools.tlpsrc | 0 |
5 files changed, 5175 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/ltxtools/README b/Master/texmf-dist/doc/latex/ltxtools/README new file mode 100644 index 00000000000..59e42388eab --- /dev/null +++ b/Master/texmf-dist/doc/latex/ltxtools/README @@ -0,0 +1,32 @@ +This is the README file for the ltxtools package. + +VERSION + +Version 0.0.1, September 2011 + +SUMMARY + +The ltxtools package provides several LaTeX API tools. + + +LICENSE + +Copyright (c) 2011 Ahmed Musa. + +This software is author-maintained. Permission is granted to copy, +distribute and/or modify this software under the terms of the +LaTeX Project Public License, version 1.3 or higher. 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 any particular purpose. + + +AUTHOR + +Ahmed Musa (amusa22@gmail.com) + + +RELEASE NOTES + +The user guide is not yet complete, but some of my packages +require the tools in ltxtools.
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/ltxtools/ltxtools.sty b/Master/texmf-dist/tex/latex/ltxtools/ltxtools.sty new file mode 100644 index 00000000000..f3ece20a3ea --- /dev/null +++ b/Master/texmf-dist/tex/latex/ltxtools/ltxtools.sty @@ -0,0 +1,5141 @@ +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% +% % +% This is file 'ltxtools.sty', version 0.0.1, September 2011. % +% % +% 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 Ahmed Musa (amusa22@gmail.com). % +% % +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% + +\@ifpackageloaded{catoptions}{}{\RequirePackage{catoptions}[2011/07/07]} +\UseNormalCatcodes +\StyleFilePurpose{A collection of (La)TeX utilities} +\StyleFileRCSInfo +$Id: ltxtools.sty,v 0.0.1 2011/09/20 09:00:00 Ahmed Musa Exp $ +\ProvidesPackage{ltxtools}[\StyleFileInfo] +\NeedsTeXFormat{LaTeX2e}[2005/12/01] +\SetStyleFileMessages[LTS@]{info}{warn}{err} +\catcode`\&=\thr@@ +\robust@def*\LTS@verbosewarn#1{\ifLTS@verbose\LTS@warn{#1}\fi} +\robust@def*\LTS@verboseinfo#1{\ifLTS@verbose\LTS@info{#1}\fi} +\newvariables{if}[LTS@]{st,pl,cl,rt,pm,lt,verbose}[false] +\def\@empty{} +\new@def\LTS@car#1#2\car@nil{#1} +\new@def\LTS@cartwo#1#2#3\car@nil{#1#2} +\new@def\LTS@cartworev#1#2#3\car@nil{#2#1} +\new@def\LTS@cdr#1#2\cdr@nil{#2} +\new@def\LTS@cdrtwo#1#2#3\cdr@nil{#3} +\new@def\LTS@carcube#1#2#3#4\car@nil{#1#2#3} +\newletcs\LTS@nil\relax +\new@def*\LTS@nnil{\LTS@nil} +\long\def\@firstofone#1{#1} +\long\def\@firstoftwo#1#2{#1} +\long\def\@secondoftwo#1#2{#2} +\long\def\@firstofthree#1#2#3{#1} +\long\def\@secondofthree#1#2#3{#2} +\long\def\@thirdofthree#1#2#3{#3} +\long\def\@gobbleone#1{} +\long\def\@gobbletwo#1#2{} +\long\def\@gobblethree#1#2#3{} +\long\def\@gobblefour#1#2#3#4{} +\letcsntocs{LTS@0of1}\@gobbleone +\letcsntocs{LTS@1of1}\@firstofone +\letcsntocs{LTS@1of2}\@firstoftwo +\letcsntocs{LTS@2of2}\@secondoftwo +\def\strip@prefix#1>{} +\new@def*\realmeaning#1{\expandafter\strip@prefix\meaning#1} +\robust@def*\sanitizecs#1{\edef#1{\realmeaning#1}} +\new@edef*\LTS@hashchar{\string#} + +\robust@def*\preservebracedefQ#1#2{% + \def\preserve@prefix{#1}% + \def\preserve@delimiter{#2}% +} +\preservebracedefQ\relax\@nil +\robust@def*\preservebracedef#1{% + \cpt@presbr@setup\reserved@a#1.% +} +\robust@def*\PreserveBraceDef#1#2{% + \cpt@presbr@setup + \long\edef\preserve@after{\unexpanded{#1}}% + \afterassignment\preserve@after + \reserved@a#2.% +} +\robust@def*\cpt@presbr@setup{% + \cptexpandsecondonce{\def\reserved@a##1##2}% + \preserve@delimiter{% + \preserve@prefix\edef##1{% + \unexpanded\expandafter{\cpt@removetodot##2}% + }% + }% +} + +\robust@def*\getdefaultoptarg#1{% + \begingroup + \edef\LTS@tempa##1{% + \def##1####1\cptoxdetok{\@backslashchar#1}####2&% + }% + \LTS@tempa\LTS@tempa{% + \ifblankTF{##2}{% + \endgroup\def\@optarg{}% + }{% + \xifinsetTF{\cptoxdetok{\@backslashchar#1}}{##2}{% + \edef\LTS@tempa####1{% + \def####1########1\cptoxdetok{\@backslashchar#1}&% + }% + \LTS@tempa\LTS@tempa{\endgroup + \def\@optarg{####1}% + \cptscantokens\@optarg + }% + \LTS@tempa##2&% + }{% + \endgroup\def\@optarg{}% + }% + }% + }% + \edef\LTS@tempb##1{##1\cptoxdetok{\@backslashchar#1}&}% + \LTS@tempb{\expandafter\LTS@tempa\meaning#1}% +} +% \ifx ... \LTS@texdie{I am exiting now}\stop\fi +\robust@def\LTS@texdie#1#2\fi{\fi\immediate\write16{#1}\batchmode#2} +\robust@def*\LTS@emergencystop{% + \immediate\write\sixt@@n{OK, I'm exiting now.}% + \interactionmode\z@pt\stop +} +\robust@def*\ltsensurecomma{\cpt@ifnextchar,{}{\LTS@err{Don’t forget comma}}} +\robust@def*\LTS@nohyphens{\hyphenpenalty\@M\exhyphenpenalty\@M} +\robust@def*\ltsfulllet#1#2{% + \def\reserved@e##1##2{% + \LTS@stfalse\LTS@cltrue\LTS@ifonetoken{##1}{}{##2}% + }% + \reserved@e{#1}{% + \LTS@err{Multiple or blank arguments '\detokenize{#1}'}\@ehc + }% + \reserved@e{#2}{% + \LTS@err{Multiple or blank arguments '\detokenize{#2}'}\@ehc + \@gobble + }% + \let#1=#2% + \ifdefFT#2{}{% + \ifcsndefTF{\string#2}{% + \letcsntocsn{\string#1}{\string#2}% + }{% + \ifcsndefFT{\cptgobblescape#2\@space}{}{% + \letcsntocsn{\cptgobblescape#1\@space} + {\cptgobblescape#2\@space}% + \ifcsndefFT{\string#2\@space}{}{% + \letcsntocsn{\string#1\@space}{\string#2\@space}% + }% + }% + }% + }% +} +\robust@def*\newletcsset{% + \cpt@ifstar + {\let\LTS@let\ltsfulllet\LTS@newletcsset}% + {\let\LTS@let\let\LTS@newletcsset}% +} +\robust@def*\LTS@newletcsset#1{% + \def\reserved@f##1##2\LTS@nil{% + \ifblankFT{##2}{}{% + \LTS@err{The partner of command '\string##1' is void}{% + \noexpand\newletcsset error. + }% + }% + \ifdefTF{##1}{% + \cpt@isdeferr{##1}% + }{% + \LTS@let##1=##2% + }% + }% + \def\csv@do##1{% + \ifblankTF{##1}{}{% + \reserved@f##1\LTS@nil + }% + }% + \csv@@parse[,]{#1}% +} +\robust@def\LTS@checkoptprefix#1#2#3#4{% + \def\LTS@checkopt@a{% + \ifstrcmpTF{#4}{+}{% + \ifstrcmpTF{#2#3}{*!}{% + #1#2#4#3% + }{% + \ifstrcmpTF{#2#3}{!*}{#1#3#4#2}{#1#2#3#4}% + }% + }{% + \LTS@checkopt@b + }% + }% + \def\LTS@checkopt@b{% + \ifstrcmpTF{#4}{!}{% + \ifstrcmpTF{#2#3}{*+}{% + #1#2#3#4% + }{% + \ifstrcmpTF{#2#3}{+*}{#1#3#2#4}{#1#2#3#4}% + }% + }{% + \LTS@checkopt@c + }% + }% + \def\LTS@checkopt@c{% + \ifstrcmpTF{#3}{*}{% + \ifstrcmpTF{#2}{+}{% + \ifsingletokenTF{#4}{#1#3#2#4}{#1#3#2{#4}}% + }{% + \ifstrcmpTF{#2}{!}{% + \ifsingletokenTF{#4}{#1#3#2#4}{#1#3#2{#4}}% + }{% + \ifsingletokenTF{#4}{#1#2#3#4}{#1#2#3{#4}}% + }% + }% + }{% + \LTS@checkopt@d + }% + }% + \def\LTS@checkopt@d{% + \ifstrcmpTF{#3}{+}{% + \ifstrcmpTF{#2}{*}{% + \ifsingletokenTF{#4}{#1#2#3#4}{#1#2#3{#4}}% + }{% + \ifstrcmpTF{#2}{!}{% + \ifsingletokenTF{#4}{#1#3#2#4}{#1#3#2{#4}}% + }{% + \ifsingletokenTF{#4}{#1#2#3#4}{#1#2#3{#4}}% + }% + }% + }{% + \LTS@checkopt@e + }% + }% + \def\LTS@checkopt@e{% + \ifsingletokenTF{#4}{% + \long\def\@gtempa{#4}% + }{% + \long\def\@gtempa{{#4}}% + }% + \LTS@checkopt@f + }% + \def\LTS@checkopt@f{% + \ifsingletokenTF{#3}{% + \ifsingletokenTF{#2}{% + \LTS@checkopt@g{#1#2#3}% + }{% + \LTS@checkopt@g{#1{#2}#3}% + }% + }{% + \ifsingletokenTF{#2}{% + \LTS@checkopt@g{#1#2{#3}}% + }{% + \LTS@checkopt@g{#1{#2}{#3}}% + }% + }% + }% + \def\LTS@checkopt@g##1{% + \begingroup + \long\edef\x{\endgroup\unexpanded{##1}}% + \expandafter\x\@gtempa + }% + \ifstrcmpTF{#4}{*}{% + \ifstrcmpTF{#2#3}{+!}{% + #1#4#2#3% + }{% + \ifstrcmpTF{#2#3}{!+}{% + #1#4#3#2% + }{% + \ifsingletokenTF{#2}{% + \ifsingletokenTF{#3}{#1#2#3#4}{#1#2{#3}#4}% + }{% + \ifsingletokenTF{#3}{#1{#2}#3#4}{#1{#2}{#3}#4}% + }% + }% + }% + }{% + \LTS@checkopt@a + }% +} +\robust@def*\LTS@suffixerr#1#2#3{% + \if\detokenize{#1#2}\relax + \LTS@err{Invalid suffix '#1' to command '\string#3'}\@ehc + \fi +} +\robust@def*\LTS@blankargerr#1#2{% + \LTS@err{Invalid blank/empty argument to command + '\string#1'}\@ehc +} +% #1: parser, #2: csv list +\robust@def*\getlastcsv#1#2{% + \cpt@ch@cklistparser{#1}% + \def\rest{}% + \def\LTS@getlastcsv##1#1##2#1{% + \ifx##2\noboundary + \edef\last{\unexpanded{##1}}% + \expandafter\cpt@removetonnil + \else + \edef\rest{\csliststack#1\rest\unexpanded{##1}}% + \expandafter\LTS@getlastcsv + \fi + ##2#1% + }% + \LTS@getlastcsv#2#1\noboundary#1\noboundary#1\cpt@nnil +} +\robust@def*\getlasttsv#1{% + \def\rest{}% + \LTS@getlasttsv#1\noboundary\noboundary\cpt@nnil +} +\robust@def*\LTS@getlasttsv#1#2{% + \ifx#2\noboundary + \edef\last{\unexpanded{#1}}% + \expandafter\cpt@removetonnil + \else + \edef\rest{\expandcsonce\rest\unexpanded{#1}}% + \expandafter\LTS@getlasttsv + \fi + #2% +} +\robust@def*\ifstringcase{\LTS@testst\LTS@ifstringcase} +\robust@def\LTS@ifstringcase#1#2:{% + \ifblankTF{#2}{% + \LTS@blankargerr\ifstringcase{second}% + }{% + \LTS@testopt{\LTS@ifstringcase@a{#1}#2}{}% + }% +} +\robust@def\LTS@ifstringcase@a#1#2[#3]{% + \ifLTS@st + \let\LTS@ifstringcase@b\ifstrcmpTF + \else + \let\LTS@ifstringcase@b\ifstreqTF + \fi + \def\LTS@ifstringcase@c##1##2##3\LTS@nil{% + \LTS@ifstringcase@b{#1}{##1}{##2}{% + \ifnullTF{##3}{#3}{% + \LTS@ifstringcase@c##3\LTS@nil + }% + }% + }% + \LTS@ifstringcase@c#2\LTS@nil +} +\robust@def\ifstringcases#1#2:{% + \ifblankTF{#2}{% + \LTS@blankargerr\ifstringcases{second}% + }{% + \LTS@testopt{\LTS@ifstringcases{#1}#2}{}% + }% +} +\long\def\LTS@ifstringcases#1#2[#3]{% + \begingroup + \toks@{}% + \long\def\LTS@tempa##1##2{% + \ifstrcmpTF{##1}{\LTS@nil}{% + \oifblankFT{\the\toks@}{}{\toks@{#3}}% + }{% + \ifstrcmpTF{#1}{##1}{% + \toks@\expandafter{\the\toks@##2}% + \LTS@tempa + }{% + \LTS@tempa + }% + }% + }% + \LTS@tempa#2\LTS@nil\LTS@nil + \expandafter\endgroup\the\toks@\relax +} +\robust@def\ifmembercases#1#2:{% + \ifblankTF{#2}{% + \LTS@blankargerr\ifmembercases{second}% + }{% + \LTS@testopt{\LTS@ifmembercases{#1}#2}{}% + }% +} +\robust@def\LTS@ifmembercases#1#2[#3]{% + \begingroup + \toks@{}% + \long\def\LTS@tempa##1##2{% + \ifstrcmpTF{##1}{\LTS@nil}{% + \oifblankFT{\the\toks@}{}{\toks@{#3}}% + }{% + \ifinsetTF{,#1,}{,##1,}{% + \toks@\expandafter{\the\toks@##2}% + \LTS@tempa + }{% + \LTS@tempa + }% + }% + }% + \LTS@tempa#2\LTS@nil\LTS@nil + \expandafter\endgroup\the\toks@\relax +} +\robust@def\ifnumcase{% + \let\LTS@ifnumcase@b\LTS@ifnumcase + \LTS@ifnumcase@a +} +\robust@def\LTS@ifnumcase@a#1#2:{% + \LTS@suffixerr{*}{#1}\ifnumcase + \ifblankTF{#2}{% + \LTS@blankargerr\ifnumcase{second}% + }{% + \LTS@testopt{\LTS@ifnumcase@b{#1}#2}{}% + }% +} +\robust@def\LTS@ifnumcase#1#2[#3]{% + \def\LTS@ifnumcase@c##1##2##3\LTS@nil{% + \ifnumcmpTF#1=##1{% + ##2% + }{% + \ifnullTF{##3}{% + #3% + }{% + \LTS@ifnumcase@c##3\LTS@nil + }% + }% + }% + \LTS@ifnumcase@c#2\LTS@nil +} +\robust@def\ifnumcases{% + \let\LTS@ifnumcase@b\LTS@ifnumcases + \LTS@ifnumcase@a +} +\robust@def\LTS@ifnumcases#1#2[#3]{% + \begingroup + \toks@{}% + \long\def\LTS@tempa##1##2{% + \ifstrcmpTF{##1}{\LTS@nil}{% + \oifblankFT{\the\toks@}{}{\toks@{#3}}% + }{% + \ifnumcmpTF#1=##1{% + \toks@\expandafter{\the\toks@##2}% + \LTS@tempa + }{% + \LTS@tempa + }% + }% + }% + \LTS@tempa#2\LTS@nil\LTS@nil + \expandafter\endgroup\the\toks@\relax +} + +%% David Kastrup: +\newcommand*\ltsreplicate[1]{% + \csname LTS@repl\expandafter\LTS@replicate + \romannumeral\number\number#1 000q\endcsname +} +\long\def\LTS@replicate#1#2\endcsname#3{#1\endcsname{#3}#2} +\long\def\LTS@replm#1#2{#1\csname LTS@repl#2\endcsname{#1}} +\let\LTS@replq\@gobble +%%-- + +\new@def*\useifnotempty#1{% + \ifdefinedTF#1{% + \ifcsnullTF{#1}{}{#1}% + }{% + \cpt@notdeferr{#1}% + }% +} +\robust@def*\makecsn#1#2{% + \ifblankTF{#1}{}{% + \edef#2{\cpttrimspaces{#1}}% + \edef#2{\expandafter\cptgobblescape#2}% + }% +} +\makecsn{\\}\@backslashchar +\robust@def*\get@csname{\LTS@testst\LTS@getcsname} +\new@def*\LTS@getcsname#1#2{% + \begingroup + \ifcsnullTF#1{% + \edef#2{\ifLTS@st{}\fi}% + }{% + \escapechar\m@one + \ifLTS@st + \edef#2{{\expandafter\string#1}}% + \else + \edef#2{\expandafter\string#1}% + \fi + }% + \postgroupdef#2\endgroup +} +\robust@def*\ltsemptify{% + \LTS@checkoptprefix{\LTS@teststcl\LTS@emptify}% +} +\def\LTS@emptify#1{% + \is@long@or@relax\is@global@or@relax + \glob@lrel@x\l@ngrel@x\def#1{}% +} +\robust@def*\ltsemptifycsset{% + \LTS@checkoptprefix{\LTS@testplcl\LTS@emptifycsset}% +} +\robust@def*\ltsemptifycsset@{% + \LTS@plfalse\LTS@clfalse\LTS@emptifycsset +} +\new@def*\LTS@emptifycsset#1{% + \is@global@or@relax + \def\csv@do##1{% + \ifLTS@pl + \glob@lrel@x\emptifycsn{##1}% + \else + \LTS@ensurescape{##1}% + \glob@lrel@x\def##1{}% + \fi + }% + \csv@@parse[,]{#1}% +} +\new@def\swapbracetwo#1#2{{#2}{#1}} +\new@def\swapbracefirst#1#2{#2{#1}} +\new@def\swapbracesecond#1#2{{#2}#1} +\new@def\swapfirstthird#1#2#3{#3{#2}{#1}} +\new@edef*\LTS@istrue{\string\iftrue} +\new@edef*\LTS@isfalse{\string\iffalse} + +% \ltsinputfiles[x]{a,b}[tex]{if file exists}: +\robust@def*\ltsinputfiles{\cpt@testopt\LTS@Inp@tFiles{}} +\def\LTS@Inp@tFiles[#1]#2{\cpt@testopt{\LTS@Inp@tF@les[#1]#2}{tex}} +\def\LTS@Inp@tF@les[#1]#2[#3]#4{% + \begingroup + \toks@{}% + \def\csv@do##1{% + \toks@\expandafter{\the\toks@\InputIfFileExists{#1##1.#3}% + {#4}{\@missingfileerror{#1##1}{#3}}}% + }% + \edef\LTS@tempa{\cptzapspaces{#2}}% + \csv@@loop*[,]\LTS@tempa + \expandafter\endgroup\the\toks@ +} +\robust@def\safefullexpand#1{% + \begingroup + \LTS@safeactivesedef\reserved@a{\endgroup#1}\reserved@a +} +\robust@def\safeexpandarg#1#2{% + \begingroup + \LTS@safeactivesedef\reserved@a{\endgroup\unexpanded{#1}{#2}}% + \reserved@a +} +\robust@def\safeexpandsecond#1#2{% + \begingroup + \LTS@safeactivesedef\reserved@a{\endgroup\unexpanded{#1}#2}% + \reserved@a +} +\robust@def\ltsexpandargs#1#2#3#4\LTS@nil{% + \cptpassexpanded{% + \ifcase#1\relax + \unexpanded{#2}{#3}% + \or + \unexpanded{#2#3}{#4}% + \or + \unexpanded{#2}{#3}{#4}% + \or + \unexpanded{#2}{#3}\unexpanded{#4}% + \else + \LTS@err{Unknown expansion type '\string#1' for + \string\ltsexpandargs}{I expected your first argument + '\string#1' to \string\ltsexpandargs\MsgBrk to be + in the interval [0,3].}% + \fi + }% +} +\robust@def*\safeexpandtwoargs#1#2#3{% + \begingroup + \LTS@safeactivesedef\reserved@a{\endgroup\noexpand#1{#2}{#3}}% + \reserved@a +} +\robust@def*\expanddetoktwoargs#1#2#3{% + \cptexpandtwoargs#1{\cptoxdetok{#2}}{\cptoxdetok{#3}}% +} + +%% Ulrich Diez: +\new@def*\stepexpandarg#1{% + 0\csname @space\expandafter\LTS@stepexpandarg + \romannumeral\number\number#1000D\endcsname +} +\new@def*\LTS@stepexpandarg#1{% + \if#1m\expandafter\expandafter + \csname endcsname\expandafter\LTS@stepexpandarg\fi +} +%%-- + +\robust@def*\StepExpandArg{\LTS@testopt\LTS@StepExpandArg{}} +\robust@def*\LTS@StepExpandArg[#1]#{% + \begingroup + \edef\LTS@tempa{\endgroup\unexpanded{#1}}% + \expandafter\LTS@tempa\romannumeral\stepexpandarg +} +\robust@def*\nameidef#1#2#3{% + \expandafter\def\csname#1\expandafter + \endcsname\expandafter{\romannumeral\stepexpandarg{#2}#3}% +} +\robust@def*\namejdef#1#{\romannumeral\LTS@namejdef{#1}} +\new@def*\LTS@namejdef#1#2#3#{\LTS@n@mejdef{#1}{#2}{#3}} +\newcommand\LTS@n@mejdef[5]{% + \expandafter\cptswap\expandafter{% + \csname#2\expandafter\cptswap\expandafter{\expandafter{% + \romannumeral\stepexpandarg{#4}#5% + }}{\endcsname #3}% + }{0 #1}% +} +\new@def*\ltsexpandtimes#1{% + \expandafter\LTS@expandtimes\expandafter + {\romannumeral\number#1000}% +} +\new@def*\LTS@expandtimes#1#2{% + \ifnullTF{#1}{% + \unexpanded{#2}% + }{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% + \unexpanded\expandafter{#2}% + }{% + \expandafter\swapbracefirst\expandafter{#2}% + {\expandafter\LTS@expandtimes\expandafter{\@gobble#1}}% + }% + }% +} + +% Reserve condition. Eg, turn \iffoundTF to \iffoundFT, +% \iffoundFT to \iffoundTF, \iffoundT to \iffoundF, etc. +% If there is no 'TF' (or 'T' or 'F') at end of csname, +% then use \unless: +\new@def*\revcond#1{% + \LTS@revcond@b{#1}\LTS@cartworev{TF}{% + \LTS@revcond@c{#1}\LTS@cdrtwo{FT}% + }{% + \LTS@revcond@b{#1}\LTS@cartworev{FT}{% + \LTS@revcond@c{#1}\LTS@cdrtwo{TF}% + }{% + \LTS@revcond@b{#1}\LTS@car{T}{% + \LTS@revcond@c{#1}\LTS@cdr{F}% + }{% + \LTS@revcond@b{#1}\LTS@car{F}{% + \LTS@revcond@c{#1}\LTS@cdr{T}% + }{% + \unless#1% + }% + }% + }% + }% +} +\def\LTS@revcond@a#1{% + \expandafter\expandafter\expandafter\directreverse + \expandafter\expandafter\expandafter + {\cptremovescape{#1}}% +} +\new@def*\LTS@revcond@b#1#2#3{% + \expandafter\ifstrcmpTF\expandafter{\romannumeral0\expandafter#2% + \romannumeral0\LTS@revcond@a{#1}\car@nil}{#3}% +} +\new@def*\LTS@revcond@c#1#2#3{% + \usename{\expandafter\expandafter\expandafter\directreverse + \expandafter\expandafter\expandafter{\expandafter#2\romannumeral0% + \LTS@revcond@a{#1}\cdr@nil}#3}% +} +\robust@def*\ifonetokenTF{% + \LTS@checkoptprefix{\LTS@teststcl\LTS@ifonetoken}% +} +\robust@def*\LTS@ifonetoken#1{% + \begingroup + \ifbracedTF{#1}{% + \aftergroup\@secondoftwo + }{% + \def\reserved@a##1\LTS@nil{% + \def\reserved@a{% + \aftercsname\aftergroup{LTS@\expandafter\ifnullTF + \expandafter{\@gobble##1}12of2}% + }% + \ifLTS@cl + % Strictly one token: + \ifblankTF{##1}{\aftergroup\@secondoftwo}{\reserved@a}% + \else + % Nil or one token: + \ifblankTF{##1}{\aftergroup\@firstoftwo}{\reserved@a}% + \fi + }% + \ifLTS@st\expandafter\expandafter\fi\reserved@a#1\LTS@nil + }% + \endgroup +} +\robust@def*\ifonetokenFT#1{\ifonetokenTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\ifonetoken#1\do#2{% + \LTS@stfalse\LTS@cltrue + \LTS@ifonetoken{#1}{#2}{% + \LTS@err{More than one token in '\detokenize{#1}'}\@ehc + }% +} +\new@def*\ifboxvoidTF#1{% + \usename{@\ifvoid#1\@empty first\else second\fi ftwo}% +} +\new@def*\ifboxvoidFT#1{\usename{LTS@\ifboxvoidTF{#1}21of2}} +\new@def\LTS@csnifx@a#1\or#2\fi\@@nil{\fi#1} +\new@def\LTS@csnifx@b#1\fi\@@nil{\fi#1} +\new@def\LTS@csnifx@c#1#2#3#4{% + \ifcase\numexpr#1\relax + \LTS@csnifx@a + \ifcsnameTF{#3}% + {\usename{ifx#2\cptthreexp}\usename{#3}{#4}}% + {\usename{ifx#2}{#4}\LTS@undefined}% + \or + \LTS@csnifx@b + \ifcsnameTF{#4}% + {\usename{ifx#2\cptthreexp}\usename{#4}{#3}}% + {\usename{ifx#2}{#3}\LTS@undefined}% + \fi\@@nil +} +%% Eg, \csifxcsnTF\x{y}{T}{F}, \csnifxcsTF{y}\x{T}{F} +\newcommand*\csnifxcsTF[2]{\LTS@csnifx@c0{TF}{#1}{#2}} +\newcommand*\csnifxcsFT[2]{\LTS@csnifx@c0{FT}{#1}{#2}} +\newcommand*\csifxcsnTF[2]{\LTS@csnifx@c1{TF}{#1}{#2}} +\newcommand*\csifxcsnFT[2]{\LTS@csnifx@c1{FT}{#1}{#2}} +\newcommand*\csnifxcsnTF[2]{\aftercsname\csifxcsnTF{#1}{#2}} +\newcommand*\csnifxcsnFT[2]{\aftercsname\csifxcsnFT{#1}{#2}} + +\new@def*\ifdefinedTF#1{% + \usename{LTS@\ifdefined#1\@empty1\else2\fi of2}% +} +\new@def*\ifdefinedFT#1{\usename{LTS@\ifdefinedTF{#1}21of2}} + +\let\then\iffalse +\new@def*\ifnnum#1\then{% + \ifdim\LTS@ptlt\LTS@ptgt\LTS@pteq#1pt\cpt@removetonnil<=>\cpt@nnil +} +\new@def*\LTS@ptlt#1<{#1pt<} +\new@def*\LTS@ptgt#1>{#1pt>} +\new@def*\LTS@pteq#1={#1pt=} +\new@def*\realnumcmp{TT\fi\ifnum\realnums} +\new@def*\realnums#1\then{% + \dimexpr\LTS@dptlt\LTS@dptgt\LTS@dpteq#1pt% + \cpt@removetonnil<=>\cpt@nnil\@space +} +\new@def*\LTS@dptlt#1<{#1pt<\dimexpr} +\new@def*\LTS@dptgt#1>{#1pt>\dimexpr} +\new@def*\LTS@dpteq#1={#1pt=\dimexpr} +\begingroup +\catcode`\Y=12 +\catcode`\Z=12 +\lccode`\Y=`\p +\lccode`\Z=`\t +\lowercase{% + \defpass\x{\endgroup + \new@def*\LTS@ifinteger@a##1.##2YZ{% + \expandafter\ifx\expandafter\\\romannumeral0% + \ifnum##2>\z@pt\else\expandafter\@gobble\fi + \LTS@ifinteger@b\@space\\\cpt@removetonnil\cpt@nnil + }% + }% +} +\new@def\LTS@ifinteger@b#1\cpt@nnil{\noexpand\cpt@nnil} +\new@def\LTS@ifinteger#1\then{% + \expandafter\LTS@ifinteger@a + \the\dimexpr\LTS@mminus\LTS@pplus#1\p@ + \cpt@removetonnil+-\cpt@nnil\relax +} +\def\LTS@mminus#1-{#1\p@-} +\def\LTS@pplus#1+{#1\p@+} +\new@def\ifintegerTF#1#{% + \usename{LTS@\LTS@ifinteger#1\then1\else2\fi of2}% +} +\new@def\LTS@IfInteger#1\then{% + \begingroup + \toks@{}% + \LTS@integerparse{#1}{-}% + \toks@\expandafter{\expandafter}% + \expandafter\LTS@integerparse\expandafter{\the\toks@}{+}% + \defpass\LTS@tempa{% + \xifinsetFT{\p@\p@\LTS@nil}{\the\toks@\LTS@nil}{}{% + \def\LTS@tempb####1\p@\LTS@nil{% + \toks@{####1}% + \LTS@tempa + }% + \expandafter\LTS@tempb\the\toks@\LTS@nil + }% + }% + \edef\LTS@tempa{\the\dimexpr\the\toks@}% + \expandafter\endgroup\expandafter\LTS@ifinteger + \expandafter\rem@pt\LTS@tempa\then +} +\new@def\LTS@integerparse#1#2{% + \def\LTS@tempa##1#2##2\LTS@nil{% + \ifblankTF{##2}{% + \toks@\expandafter{\the\toks@##1\p@}% + }{% + \ifstrcmpTF{#2}{##2}{% + \toks@\expandafter{\the\toks@##1\p@}% + }{% + \toks@\expandafter{\the\toks@##1\p@#2}% + \LTS@tempa##2#2\LTS@nil + }% + }% + }% + \LTS@tempa#1\LTS@nil +} +\new@def\IfIntegerTF#1#{% + \LTS@ifinteger#1\then + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi +} +\robust@def*\ifonedefTF{% + \begingroup\def\case@nr{0}\LTS@testpl\LTS@ifonedef +} +\robust@def*\ifonedefFT{% + \begingroup\def\case@nr{1}\LTS@testpl\LTS@ifonedef +} +\robust@def*\LTS@ifonedef#1{% + \cpt@choicefdfalse + \def\csv@do##1{% + \usename{if\ifLTS@pl csn\fi defFT}{##1}{}{% + \cpt@choicefdtrue\loopbreak + }% + }% + \csv@@parse[,]{#1}% + \LTS@onecase +} +\robust@def*\ifonetrueTF{% + \begingroup + \def\case@nr{0}% + \LTS@testst{\LTS@testopt\LTS@ifonetrue{}}% +} +\robust@def*\ifonetrueFT{% + \begingroup + \def\case@nr{1}% + \LTS@testst{\LTS@testopt\LTS@ifonetrue{}}% +} +\def\LTS@ifonetrue[#1]#2{% + \cpt@choicefdfalse + \edef\reserved@a{\ifLTS@st*\fi}% + \def\csv@do##1{% + \uselivecsn{if#1##1}% + \cpt@choicefdtrue\loopbreak + \fi + }% + \expandafter\csv@@parse\reserved@a[#1]{#2}% + \LTS@onecase +} +\robust@def*\LTS@onecase{% + \edef\next##1##2##3{% + \ifcase\case@nr + ##11##22##32\or##12##21##32\or##11##20##31\or + ##10##21##31% + \fi + }% + \aftercsname\endgroup{LTS@\next\ifcpt@choicefd\else{\fi of}}% +} +\new@def*\ifcsndefeqTF#1#2{% + \ifcsndefFT{#1}\@secondoftwo + {\ifcsndefFT{#2}\@secondoftwo + {\aftercsname\ifxTF{#1\aftercsname}{#2}}}% +} +\new@def*\ifcsndefeqFT#1#2{\usename{LTS@\ifcsndefeqTF{#1}{#2}21of2}} +\robust@def*\LTS@notdefinable{% + \PackageError{ltxtools}% + {Command '\@backslashchar\LTS@rsvda' or + '\@backslashchar\@qend\LTS@rsvda' already defined}% + {Command '\@backslashchar\LTS@rsvda' already defined, + or name '\@backslashchar\@qend\LTS@rsvda' illegal.}% +} +\robust@def*\LTS@saveprimitive#1#2{% + \begingroup + \cpt@swafalse + \edef\LTS@tempa{\string#1}% + \edef\LTS@tempb{\meaning#1}% + \ifx\LTS@tempa\LTS@tempb + \cpt@swatrue + \else + \edef\LTS@tempb{\meaning#2}% + \ifx\LTS@tempa\LTS@tempb\else\LTS@s@veprimitive#1#2\fi + \fi + \expandafter\endgroup\ifcpt@swa\let#2#1\fi +} +\robust@def*\LTS@s@veprimitive#1#2{% + \def\LTS@tempb##1#1##2##3\edef{\edef\LTS@tempb{##2}\edef}% + \LTS@tempb + \nullfont{select font nullfont}% + \topmark{\string\topmark:}% + \firstmark{\string\firstmark:}% + \botmark{\string\botmark:}% + \splitfirstmark{\string\splitfirstmark:}% + \splitbotmark{\string\splitbotmark:}% + #1{\string#1}% + \edef\LTS@tempa{\expandafter\strip@prefix\meaning\LTS@tempb}% + \edef\LTS@tempb{\meaning#1}% + \ifx\LTS@tempa\LTS@tempb + \cpt@swatrue + \else + \@latex@error{Command \noexpand#1 no longer a primitive}\@ehc + \fi +} +\robust@def*\LTS@badargerr#1#2{% + \LTS@err{Bad '\string#2' argument for command '\string#1'}{% + Bad '\string#2' argument for command '\string#1'.\MsgBrk + You need to look again at user instruction\MsgBrk + for command '\string#1'. + }% +} +\newletcs\ifpackageloadedTF\@ifpackageloaded +\newletcs\ifclassloadedTF\@ifclassloaded +\new@def*\ifpackageloadedFT#1{\ifpackageloadedTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifclassloadedFT#1{\ifclassloadedTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\LTS@ifclasscurr{\LTS@ifpkg@cls@curr\@clsextension} +\new@def*\LTS@ifpackagecurr{\LTS@ifpkg@cls@curr\@pkgextension} +\new@def*\LTS@ifpkg@cls@curr#1#2#3{% + \usename{LTS@\ifnum\cptsevenxp\@parse@version + \usename{ver@#2.#1}//00\@nil<\expandafter + \@parse@version#3//00\@nil2\else1\fi of2}% +} +\new@def*\ifclasscurrentTF{\LTS@ifloadedcurr{class}} +\new@def*\ifpackagecurrentTF{\LTS@ifloadedcurr{package}} +\let\ifpkgcurrTF\ifpackagecurrentTF +\new@def*\LTS@ifloadedcurr#1#2#3{% + \usename{if#1loadedTF}{#2}{% + \usename{LTS@if#1curr}{#2}{#3}{% + \@firstoftwo + }{% + \LTS@err{Loaded version of #2 package is not current}% + {You need a higher version of #2 package:\MsgBrk + The version of #2 package available on your TeX\MsgBrk + installation is lower than you require.}% + \@secondoftwo + }% + }{% + \@secondoftwo + }% +} +\new@def*\ifpackagecurrentFT#1{\ifpackagecurrentTF{#1}\@secondoftwo\@firstoftwo} +\new@def*\ifclasscurrentFT#1{\ifclasscurrentTF{#1}\@secondoftwo\@firstoftwo} +% #1: package name +% #2: package date (mandatory) +\new@def*\NeedPackage#1#2{% + \ifx\documentclass\@twoclasseserror + \def\reserved@a{\usepackage}% + \else + \def\reserved@a{\RequirePackage}% + \fi + \cptexpanded{\LTS@testopt{\LTS@needpackage{#1}{#2}% + \expandcsonce\reserved@a}}{}% +} +\newletcs\needpackage=\NeedPackage +% #3: \usepackage or \RequirePackage; +% #4: options, if any +\robust@def*\LTS@needpackage#1#2#3[#4]{% + % If the package has been loaded and is current, don't + % reload: + \ifpackagecurrentTF{#1}{#2}{}{#3[#4]{#1}[#2]}% +} +\newcommand*\removeouterbraces[1]{% + \romannumeral\ifstrcmpTF{#1}{all}{% + \LTS@r@movebraces + }{% + \expandafter\LTS@removeouterbraces + \expandafter{\romannumeral#1000}% + }% +} +\newcommand\LTS@removeouterbraces[2]{% + \ifnullTF{#1}{0 #2}{% + \expandafter\ifnullTF\expandafter{\@gobble#2}{% + \ifbracedTF{#2}{% + \expandafter\swapbracefirst + \expandafter{\@iden#2}% + {\expandafter\LTS@removeouterbraces\expandafter{\@gobble#1}}% + }{0 #2}% + }{0 #2}% + }% +} +\newcommand\LTS@r@movebraces[1]{% + \expandafter\ifnullTF\expandafter{\@gobble#1}{% + \ifbracedTF{#1}{% + \expandafter\LTS@r@movebraces\expandafter{\@iden#1}% + }{0 #1}% + }{0 #1}% +} +\robust@def*\LTS@ensuremacro#1{% + \ifmacroTF{#1}{}{\cpt@notcserr{#1}}% +} +\robust@def*\LTS@ensurescape#1{% + \ifescapedTF{#1}{}{\cpt@notescapederr{#1}}% +} +\robust@def*\LTS@ensurenoscape#1{% + \ifescapedTF{#1}{\cpt@isescapederr{#1}}{}% +} +\robust@def*\LTS@ensurescape@csset#1#2{% + \docommalist{#2}{% + \usename{LTS@ensure\ifnullTF{#1}{}{no}scape}{##1}% + }% +} +\robust@def\LTS@ifnextchar#1#2#3{% + \LTS@ifn@@tchar\bgroup + {\LTS@ifn@@tchar{#1}{#2}{#3}}% + {\LTS@ifn@xtchar{#1}{#2}{#3}}% +} +\new@def\LTS@ifn@xtchar#1#2#3#4{% + \csname LTS@\if\detokenize{#1#4}1\else2\fi of2\endcsname + {#2}{#3}#4% +} +\newcsndef{LTS@ifnextch} {\futurelet\next\LTS@ifn@@tch@r} +\new@def\LTS@ifn@@tchar#1#2#3{% + \begingroup + \let\reserved@a=#1\toks@{#2}\toks1{#3}% + \futurelet\next\LTS@ifn@@tch@r +} +\new@def*\LTS@ifn@@tch@r{% + \ifx\next\@sptoken + \let\LTS@next\LTS@ifnextch + \else + \ifx\next\reserved@a + \edef\LTS@next{\endgroup\the\toks@}% + \else + \edef\LTS@next{\endgroup\the\toks1}% + \fi + \fi + \LTS@next +} +\robust@def*\NoGobbleSpaceIfnextchar#1#2#3{% + \begingroup + \let\reserved@a=#1\toks@{#2}\toks1{#3}% + \futurelet\next\LTS@nogobblespaceifnext +} +\new@def*\LTS@nogobblespaceifnext{% + \cptpassexpanded{\endgroup + \ifxTF\next\reserved@a{\the\toks@}{\the\toks1}% + }% +} +\robust@def*\LTS@ifchar#1#2#3{% + \LTS@ifnextchar + #1{\begingroup\defpass\x#1{\endgroup#2}}{#3}% +} +\robust@def*\LTS@ifstar{\LTS@ifchar*} +\robust@def*\LTS@ifplus{\LTS@ifchar+} +\robust@def*\LTS@ifclam{\LTS@ifchar!} +\robust@def*\LTS@ifdot{\LTS@ifchar.} +\robust@def*\LTS@ifright{\LTS@ifchar>} +\robust@def*\LTS@ifleft{\LTS@ifchar<} +\robust@def*\LTS@ifprime{\LTS@ifchar'} +\robust@def*\ifnextisbrack#1#2{\LTS@ifnextchar[{#1}{#2}} +\robust@def*\ifnextisparen#1#2{\LTS@ifnextchar({#1}{#2}} +\robust@def*\ifnextisleftang#1#2{\LTS@ifnextchar<{#1}{#2}} +\robust@def*\LTS@testst#1{\LTS@ifstar{\LTS@sttrue#1}{\LTS@stfalse#1}} +\robust@def*\LTS@testpl#1{\LTS@ifplus{\LTS@pltrue#1}{\LTS@plfalse#1}} +\robust@def*\LTS@testcl#1{\LTS@ifclam{\LTS@cltrue#1}{\LTS@clfalse#1}} +\robust@def*\LTS@testpm#1{\LTS@ifprime{\LTS@pmtrue#1}{\LTS@pmfalse#1}} +\robust@def*\LTS@testrt#1{\LTS@ifright{\LTS@rttrue#1}{\LTS@rtfalse#1}} +\robust@def*\LTS@testlt#1{\LTS@ifleft{\LTS@lttrue#1}{\LTS@ltfalse#1}} +\robust@def*\LTS@teststpl#1{\LTS@testst{\LTS@testpl{#1}}} +\robust@def*\LTS@teststplcl#1{\LTS@testst{\LTS@testpl{\LTS@testcl{#1}}}} +\robust@def*\LTS@teststplpm#1{\LTS@testst{\LTS@testpl{\LTS@testpm{#1}}}} +\robust@def*\LTS@teststcl#1{\LTS@testst{\LTS@testcl{#1}}} +\robust@def*\LTS@teststpm#1{\LTS@testst{\LTS@testpm{#1}}} +\robust@def*\LTS@testplcl#1{\LTS@testpl{\LTS@testcl{#1}}} +\robust@def*\LTS@testopt#1#2{\ifnextisbrack{#1}{#1[{#2}]}} +\robust@def*\LTS@testltopt#1#2{\ifnextisleftang{#1}{#1<{#2}>}} +\robust@def*\LTS@testpnopt#1#2{\ifnextisparen{#1}{#1({#2})}} +\new@def*\LTS@Test@pt#1{\usename{LTS@\ifnullTF{#1}12of2}} +\new@def*\LTS@IfBrack#1#2#3{\LTS@IfBr@ck#1&[&{#2}{#3{#1}}} +\new@def*\LTS@IfBr@ck#1[#2#{\LTS@Test@pt{#1#2}} +\new@def*\LTS@TestOpt#1#2#3{\LTS@IfBr@ck#1&[&{#2#1}{#2[{#3}]{#1}}} +\new@def*\LTS@IfStar#1#2#3{\LTS@IfSt@r#1&*&{#2}{#3{#1}}} +\new@def*\LTS@IfSt@r#1*#2#{\LTS@Test@pt{#1#2}} +\new@def*\LTS@IfPlus#1#2#3{\LTS@IfPl@s#1&+&{#2}{#3{#1}}} +\new@def*\LTS@IfPl@s#1+#2#{\LTS@Test@pt{#1#2}} +% Look ahead for many characters: +\robust@def\ltsifnextchars#1#2#3{% + \begingroup + \long\def\special@car{\futurelet\next\special@car@a}% + \long\def\special@car@a##1##2\car@nil{% + \ifx\next\temp@bgroup\toks@{{##1}}\else\toks@{##1}\fi + }% + \let\temp@bgroup\bgroup + \let\bgroup\LTS@undefined + \def\LTS@tempa{#1}\def\LTS@tempb{#2}% + \def\LTS@tempc{#3}\def\LTS@tempd{}% + \LTS@ifnextchars@a +} +\def\LTS@ifnextchars@a{\futurelet\next\LTS@ifnextchars@b} +\def\LTS@ifnextchars@b{% + \ifxTF\next\@sptoken{% + \afterassignment\LTS@ifnextchars@a\let\next= % + }{% + \LTS@ifnextchars@c + }% +} +\def\LTS@ifnextchars@c#1{% + \ifx\next\temp@bgroup\toks1{{#1}}\else\toks1{#1}\fi + \expandafter\special@car\LTS@tempa\car@nil + \xifstrcmpTF{\the\toks@}{\the\toks1}{% + \edef\LTS@tempd{\expandcsonce\LTS@tempd\the\toks@}% + \toks@\cptthreexp{\expandafter\cpt@cdr\LTS@tempa\cdr@nil}% + \edef\LTS@tempa{\the\toks@}% + \ifcsnullTF\LTS@tempa{% + \cptthreexp\endgroup\expandafter\LTS@tempb\LTS@tempd + }{% + \LTS@ifnextchars@a + }% + }{% + \edef\LTS@tempd{\expandcsonce\LTS@tempd\the\toks1}% + \cptthreexp\endgroup\expandafter\LTS@tempc\LTS@tempd + }% +} +\robust@def*\ltscommanormalize#1#2{% + \let\LTS@inkv\cptswfalse + \edef#2{\comma@kv@normalize{#1}}% +} +\robust@def*\ltskvnormalize#1#2{% + \let\LTS@inkv\cptswtrue + \edef#2{\comma@kv@normalize{#1}}% +} +\begingroup +\catcode`\!=13 +\uccode`\~=`\,% +\uccode`\!=`\=% +\uppercase{\endgroup + \def\comma@kv@normalize#1{% + \unexpanded\expandafter{\romannumeral-`\q + \LTS@activecomma,#1,~\LTS@nil}% + }% + \def\LTS@activecomma#1~#2\LTS@nil{% + \ifblankTF{#2}{% + \ifcondTF\if\LTS@inkv\fi{% + \LTS@activeequal#1!\LTS@nil + }{% + \LTS@spacecomma#1 ,\LTS@nil + }% + }{% + \LTS@activecomma#1,#2\LTS@nil + }% + }% +} +\defpass\LTS@tempa#1{% + \begingroup + \uccode`\~=`\=% + \uppercase{\endgroup + \def\LTS@activeequal##1~##2\LTS@nil{% + \ifblankTF{##2}{% + \LTS@spacecomma##1#1,\LTS@nil + }{% + \LTS@activeequal##1=##2\LTS@nil + }% + }% + }% + \def\LTS@spacecomma##1#1,##2\LTS@nil{% + \ifblankTF{##2}{% + \LTS@commaspace##1,#1\LTS@nil + }{% + \LTS@spacecomma##1,##2\LTS@nil + }% + }% + \def\LTS@commaspace##1,#1##2\LTS@nil{% + \ifblankTF{##2}{% + \ifcondTF\if\LTS@inkv\fi{% + \LTS@spaceequal##1#1=\LTS@nil + }{% + \LTS@doublecomma##1,,\LTS@nil + }% + }{% + \LTS@commaspace##1,##2\LTS@nil + }% + }% + \def\LTS@spaceequal##1#1=##2\LTS@nil{% + \ifblankTF{##2}{% + \LTS@equalspace##1=#1\LTS@nil + }{% + \LTS@spaceequal##1=##2\LTS@nil + }% + }% + \def\LTS@equalspace##1=#1##2\LTS@nil{% + \ifblankTF{##2}{% + \LTS@doublecomma##1,,\LTS@nil + }{% + \LTS@equalspace##1=##2\LTS@nil + }% + }% +}{ } +\def\LTS@doublecomma#1,,#2\LTS@nil{% + \ifblankTF{#2}{% + \ifcondTF\if\LTS@inkv\fi{% + \LTS@doubleequal#1==\LTS@nil + }{% + \LTS@remleadcomma#1\LTS@nil + }% + }{% + \LTS@doublecomma#1,#2\LTS@nil + }% +} +\def\LTS@doubleequal#1==#2\LTS@nil{% + \ifblankTF{#2}{% + \LTS@remleadcomma#1\LTS@nil + }{% + \LTS@doubleequal#1=#2\LTS@nil + }% +} +\def\LTS@commaequalerr#1,=#2\LTS@nil{% + \ifblankTF{#2}{}{% + \LTS@err{There is ',=' in your key-value list}\@ehc + }% +} +\new@def*\LTS@remleadcomma,#1\LTS@nil{\noexpand#1} + +% !! Enter in manual. Preserves braces. Takes arbitrary parser. +% General list parser. Use '#1' in <callback> for current +% item on level 1, ##1 on level 2, etc: +% \ltsdocsvlist[<parser>]<list>{<callback>} +% \ltsdocsvlist*[<parser>]<listcmd>{<callback>} +\robust@def*\ltsdocsvlist{\cpt@teststopt\lts@docsvlist,} +\robust@def*\lts@docsvlist[#1]#2#3{% + \pushfunctions\ltsdocsvlist + {\cpt@csvdo,\cpt@csvact,\ifloopbreak}\cpt@csvdepth + \cpt@stchoose{cpt@st}{#2}\cpt@csvarg\ltsdocsvlist + \def\cpt@csvact##1{#3}% + \def\cpt@csvdo##1#1{% + \ifcsvbreakTF{##1}\loopbreak\relax + \ifboolTF{loopbreak}{% + \gobble@to@sentinel\cpt@csvnil#1% + }{% + \edef\cpt@csvarg{\unexpanded\expandafter{\@gobble##1}}% + \ifxTF\cpt@csvarg\cpt@csvnil{}{% + \expandafter\cpt@csvact\expandafter{\cpt@csvarg}\relax + \cpt@csvdo.% + }% + }% + }% + \loopbreakfalse + \cpt@sttrue\cpt@csvnormalize[#1]\cpt@csvarg + \expandafter\cpt@csvdo\expandafter.\cpt@csvarg#1\cpt@csvnil#1% + \popfunctions\ltsdocsvlist\cpt@csvdepth +} + +% !! Enter in manual: +\robust@def*\commacsvloop{% + \let\LTS@nmlz\cptswfalse + \let\LTS@inkv\cptswfalse + \cpt@testst\LTS@commaparse +} +\robust@def*\commacsvparse{% + \let\LTS@nmlz\cptswtrue + \let\LTS@inkv\cptswfalse + \cpt@testst\LTS@commaparse +} +\robust@def*\commakvloop{% + \let\LTS@nmlz\cptswfalse + \let\LTS@inkv\cptswtrue + \cpt@testst\LTS@commaparse +} +\robust@def*\commakvparse{% + \let\LTS@nmlz\cptswtrue + \let\LTS@inkv\cptswtrue + \cpt@testst\LTS@commaparse +} +\robust@def*\LTS@commaparse#1{% + \cpt@stchoose{cpt@st}{#1}\LTS@tempa\LTS@commaparse + \pushfunctions\LTS@commaparse + {\ifloopbreak,\sav@comma@do}\cpt@csvdepth + \ifdefTF\comma@do{% + \let\sav@comma@do\comma@do + }{% + \cpt@notdeferr\comma@do + }% + \ifdefswitchTF{LTS@nmlz}{% + \edef\LTS@tempa{\s@expandarg\comma@kv@normalize\LTS@tempa}% + \ifdefswitchTF{LTS@inkv}{% + \expandafter\LTS@commaequalerr\LTS@tempa,=\LTS@nil + }{}% + }{}% + \loopbreakfalse + \let\currsentinel\cpt@commanil + \expandafter\LTS@c@mmaparse\LTS@tempa,\cpt@commanil,% + \popfunctions\LTS@commaparse\cpt@csvdepth + \undefcs\comma@do +} +\robust@def*\LTS@c@mmaparse#1,{% + \ifsentinelTF{#1}{}{% + \ifcsvbreakTF{#1}\loopbreak\relax + \ifboolTF{loopbreak}{% + \gobble@to@sentinel\cpt@commanil,% + }{% + \sav@comma@do{#1}\relax\LTS@c@mmaparse + }% + }% +} +\newvariables{if}{lastfox}[false] +\newcommand*\LTS@foxnil{\LTS@foxnil} + +% \foxloop[<parser>]{<list>}{<callback>} +% \foxloop*[<parser>]{<listcmd>}{<callback>} +% You can use \currfox<level>, \nextfox<level>, and +% \currfoxnr<level> within <callback> to access the current +% element of <list>, the next element of <list>, and +% the serial number of the current item, respectively, at +% various levels of nesting. <level> is given in roman numerals, +% eg, \currfoxi, \currfoxii. +% You can inset \csvbreak as an element of <list> to break +% out of the loop. Similarly, you can use \loopbreak within +% <callback> to break out of the loop. +% You can insert \csvpause as an element of <list> to pause the loop. +\robust@def*\foxloop{% + \LTS@testst{\LTS@testopt\LTS@fox@@a{,}}% +} +\robust@def*\LTS@fox@@a[#1]{% + \cpt@checklistparser{#1}\relax + \usename{LTS@fox@\ifLTS@st b\else a\fi}[#1]% +} +\robust@def*\LTS@fox@a[#1]#2{% + \declarefoxlistparser{#1}% + \LTS@fox@@b{#2}% +} +\robust@def*\LTS@fox@b[#1]#2{% + \declarefoxlistparser{#1}% + \expandafter\LTS@fox@@b\expandafter{#2}% +} +\robust@def*\declarefoxlistparser#1{% + % ##1 -> list; ##2 -> callback: + \long\def\LTS@fox@@b##1##2{% + \pushfunctions\foxloop{% + \getnextfox,\LTS@foxrema,\foxparser,\LTS@fox@@d,% + \currfox,\nextfox,\currfoxnr,\iflastfox,\ifloopbreak + }\cpt@csvdepth + \pushnumber\foxdepth + \def\foxparser{#1}% + \long\def\LTS@foxrema####1\LTS@foxnil#1{% + \long\edef\foxremainder{\unexpanded{####1}}% + \ifcsemptyTF\foxremainder\relax + {\cpt@trimparsers[#1]\foxremainder}% + }% + \chardef\currfoxnr\z@ + \def\getnextfox####1#1####2\getnextfox{% + \edef\nextfox{\expandcsonce{\cpt@removetodot####1}}% + \ifxTF\nextfox\LTS@foxnil{% + \lastfoxtrue + \let\nextfox\@empty + \letcsntocs{nextfox\romannumeral\cpt@csvdepth}\@empty + }{% + \lastfoxfalse + \letcsntocs{nextfox\romannumeral\cpt@csvdepth}\nextfox + }% + }% + \def\LTS@fox@@c####1####2{% + \getnextfox.####1\getnextfox + ####2\relax + % Rather than evaluate \iflastfox here for every item, + % let \ifx\currfox\LTS@foxnil terminate the loop. + \ifboolTF{loopbreak}{}{% + \LTS@fox@@d.####1\LTS@fox@@d{####2}% + }% + }% + \long\def\LTS@fox@@d####1#1####2\LTS@fox@@d####3{% + \edef\currfox{\expandcsonce{\cpt@removetodot####1}}% + \letcsntocs{currfox\romannumeral\cpt@csvdepth}\currfox + \edef\currfoxnr{\the\numexpr\currfoxnr+1}% + \letcsntocs{currfoxnr\romannumeral\cpt@csvdepth}\currfoxnr + \ifxTF\currfox\LTS@foxnil{}{% + \ifxTF\currfox\cpt@csvbreak{% + \LTS@foxrema####2% + }{% + \ifxTF\currfox\cpt@csvpause{% + \message{^^J! List pause: + ^^JType x or X to quit, or <RETURN> to proceed^^J}% + {\endlinechar-1\global\read-1 to\@gtempa}% + \lowercase\expandafter{\expandafter\def\expandafter + \@gtempa\expandafter{\@gtempa}}% + \xifstrcmpTF\@gtempa{x}{% + \LTS@foxrema####2% + }{% + \LTS@fox@@c{####2}{####3}% + }% + }{% + \LTS@fox@@c{####2}{####3}% + }% + }% + }% + }% + \loopbreakfalse\lastfoxfalse + \cpt@stfalse\cpt@csvnormalize[#1]{##1}% + \expandafter\LTS@fox@@d\expandafter + .\normalized@list#1\LTS@foxnil#1\LTS@fox@@d{##2}% + \popfunctions\foxloop\cpt@csvdepth + \popnumber\foxdepth + }% +} +\new@def*\ltsprotectedtokens#{% etoolbox + \ifx\protect\@typeset@protect + \LTS@protectedtoken\@firstofone\fi + \ifx\protect\@unexpandable@protect + \LTS@protectedtoken\LTS@unexpandable\fi + \ifx\protect\noexpand + \LTS@protectedtoken\unexpanded\fi + \ifx\protect\string + \LTS@protectedtoken\detokenize\fi + \@firstofone +} +\new@def*\LTS@protectedtoken#1#2\@firstofone{\fi#1} +\new@def\LTS@unexpandable#1{\unexpanded{\ltsprotectedtokens{#1}}} +\new@def\LTS@neverexpand#1{% + \unexpanded{\unexpanded{\unexpanded{\unexpanded{% + \unexpanded{\unexpanded{\unexpanded{\unexpanded{#1}}}}}}}}% +} +\new@def*\LTS@csnalloc#1{\usename{new#1\aftercsname}} +\providerobust@def*\csnnewif{\LTS@csnalloc{if}} +\robust@def*\csnnewtoks{\LTS@csnalloc{toks}} +\robust@def*\csnnewcount{\LTS@csnalloc{count}} +\robust@def*\csnnewdimen{\LTS@csnalloc{dimen}} +\robust@def*\csnnewskip{\LTS@csnalloc{skip}} +\robust@def*\csnnewmuskip{\LTS@csnalloc{muskip}} +\robust@def*\csnnewbox{\LTS@csnalloc{box}} +\robust@def*\csnnewwrite{\LTS@csnalloc{write}} +\robust@def*\csnnewread{\LTS@csnalloc{read}} +\robust@def*\LTS@createtwincmds#1{% + \begingroup\escapechar92\relax\expandafter\endgroup + \if\expandafter\LTS@car\string#1x\car@nil\@backslashchar\else + \LTS@err{Non-escaped command name '\detokenize{#1}'}\@ehc + \fi + \ifcsdefinable#1\relax + \ifcsndefinable{No\cptremovescape{#1}}\relax +} +\robust@def*\CreateTwinBooleanCommands#1#2{% + \LTS@createtwincmds{#1}% + \ifcsndefinable{if\cptremovescape{#2}}{% + \csnnewif{\cptremovescape{#2}}% + }% + \def#1{\gletcsntocs{if\cptremovescape{#2}}\iftrue}% + \csn@def{No\cptremovescape{#1}}{% + \gletcsntocs{if\cptremovescape{#2}}\iffalse + }% + \usename{No\cptremovescape{#1}}% +} +\robust@def*\CreateTwinSwitchCommands#1#2{% + \LTS@createtwincmds{#1}% + \def#1{\global\let#2\cptswtrue}% + \csn@def{No\cptremovescape{#1}}{\global\let#2\cptswfalse}% + \usename{No\cptremovescape{#1}}% +} +% Eg, \CreateTwinNumberCommands\StrictCheck\strict +\robust@def*\CreateTwinNumberCommands#1#2{% + \LTS@createtwincmds{#1}% + \def#1{\global\chardef#2\@ne}% + \csn@def{No\cptremovescape{#1}}{\global\chardef#2\z@pt}% + \usename{No\cptremovescape{#1}}% +} +\CreateTwinSwitchCommands\ExpandPrimitives\LTS@expprim +\CreateTwinSwitchCommands\WrapQuotes\LTS@wq +\CreateTwinSwitchCommands\ConvertInputToLowercase\LTS@lwc +\CreateTwinSwitchCommands\StrictHashCheck\stricthashcheck +\robust@def*\LTS@detok@zap#1{% + \LTS@ensuremacro{#1}% + \edef#1{\s@expandarg\cptzapspaces{\detokenize\expandafter{#1}}}% +} +\new@def*\is@global@or@relax{% + \ifLTS@cl\let\glob@lrel@x\global\else\let\glob@lrel@x\relax\fi +} +\let\glob@lrel@x\relax +\new@def*\is@long@or@relax{% + \ifLTS@st\let\l@ngrel@x\relax\else\let\l@ngrel@x\long\fi +} +\begingroup +\endlinechar\m@one +\def\siso@do#1{\catcode`#1\string=\active} +\siso@@loop{!"$&'()*+,-./:;<=>?[]^_|~} +\new@gdef\LTS@safeactivesedef#1#2{% + \begingroup + \def\siso@do##1{% + \ifnum\catcode`##1\string=\active\edef##1{\string##1}\fi + }% + \siso@@loop{!"$&'()*+,-./:;<=>?[]^_|~}% + \cptexpandsecond\endgroup + {\edef\noexpand#1{\noexpand\unexpanded{#2}}}% +} +\endgroup + +\robust@def*\reversetokens{\LTS@testst\LTS@reverse} +\new@def*\LTS@reverse#1#2{% + \begingroup + \def\LTS@tempa##1\reverse@nil{% + \def\LTS@tempa####1####2{% + \expandafter\ifxTF\cpt@car####2\car@nil + \endreverse{####1}{\LTS@tempa{####2####1}}% + }% + \toks@\expandafter{\romannumeral0\LTS@tempa{}##1\@space\endreverse}% + }% + \ifLTS@st\expandafter\expandafter\fi + \LTS@tempa#2\reverse@nil + \cptexpandsecond\endgroup + {\edef\noexpand#1{\noexpand\unexpanded{\the\toks@}}}% +} +\newletcs\endreverse\end +\new@def\directreverse#1{\LTS@directreverse{}#1\endreverse} +\new@def\LTS@directreverse#1#2{% + \expandafter\ifxTF\cpt@car#2\car@nil\endreverse{% + \if@test\expandafter\@iden\else\expandafter\unexpanded\fi{#1}% + }{% + \LTS@directreverse{#2#1}% + }% +} +\new@def\robustreverse#1{\LTS@robustreverse{}.#1\endreverse} +\new@def\LTS@robustreverse#1#2\endreverse{% + \LTS@r@bustreverse{#1}% + {\expandafter\ifleftbracedTF\expandafter{\cpt@removetodot#2}}#2\endreverse +} +\new@def\LTS@r@bustreverse#1#2.#3{% + \expandafter\ifxTF\cpt@car#3\car@nil\endreverse{% + \if@test\expandafter\@iden\else\expandafter\unexpanded\fi{#1}% + }{% + #2{\LTS@robustreverse{{#3}#1}}{\LTS@robustreverse{#3#1}}.% + }% +} + +% Create a delimiter for command Rabfe (meaning 'Remove all but +% first undelimited element'): +\robust@def*\DeclareRabfeDelimiter{\LTS@testst\LTS@DeclareRabfeDelimiter} +\robust@def*\LTS@DeclareRabfeDelimiter#1{% + \ifLTS@st + \long\def\ltsgetfirstelement##1##2#1{{##1}}% + \else + \long\def\ltsgetfirstelement##1##2#1{##1}% + \fi +} +\DeclareRabfeDelimiter{\LTS@nil} + +% Eg, #1 with two delimiters: +% \LTS@DeclareRabfeDelimiter\LTS@nil +% \edef\x{% +% \removeallbutfirstelement{xyz\LTS@nil\LTS@nil}} +% +\new@def\removeallbutfirstelement#1{% Ulrich Diez + \romannumeral-`\q + \expandafter\expandafter\expandafter\ifnullTF + \expandafter\expandafter\expandafter{% + \expandafter\@gobble\ltsgetfirstelement#1}{% + \expandafter\@firstofone\expandafter{% + \ltsgetfirstelement#1}% + }{% + \expandafter\expandafter\expandafter\@gobblefour + \expandafter\removeallbutfirstelement + \expandafter{\ltsgetfirstelement#1}% + }% +} + +\robust@def*\remleadparser{\LTS@testopt\LTS@remleadparser{,}} +\new@def\LTS@remleadparser[#1]#2{% + \LTS@ensuremacro{#2}% + \begingroup + \def\reserved@a#1{\futurelet\next\reserved@d}% + \@namedef{reserved@b} {\reserved@a#1}% + \def\reserved@d{% + \ifx\next\@sptoken + \expandafter\reserved@b + \else + \ifx#1\next + \cptthreexp\reserved@a + \else + \cptthreexp\reserved@c + \fi + \fi + }% + \def\reserved@c##1\LTS@nil{\endgroup\edef#2{\unexpanded{##1}}}% + \expandafter\reserved@a\expandafter#1#2\LTS@nil +} +\robust@def*\remtrailparser{\LTS@testopt\LTS@remtrailparser{,}} +\robust@def*\LTS@remtrailparser[#1]#2{% + \begingroup + \LTS@ensuremacro{#2}% + \let\trimpr@nil\relax + \defpass\LTS@rsvda{% + \despacecontent#2% + \xifinsetFT{#1\trimpr@nil}{\expandcsonce#2\trimpr@nil}{}{% + \def\LTS@rsvdb####1#1\trimpr@nil{% + \edef#2{\unexpanded{####1}}% + \LTS@rsvda + }% + \expandafter\LTS@rsvdb#2\trimpr@nil + }% + }% + \postgroupdef#2\endgroup +} +\robust@def*\ltsremoveparser{\LTS@testopt\LTS@remparser{,}} +\robust@def*\LTS@remparser[#1]#2{% + \LTS@remleadparser[#1]#2% + \LTS@remtrailparser[#1]#2% +} + +\robust@def*\SelectiveSanitize{\LTS@testopt\s@lectivesanitize\@M} +\robust@def*\s@lectivesanitize[#1]#2#3{% + \LTS@ensuremacro{#3}% + \begingroup + \cpt@cnta#1\advance\cpt@cnta\@ne + \let\temp@bgroup\bgroup + \let\bgroup\@undefined + \cptexpandsecond + {\s@l@ctivesanitize#3}{{\detokenize{#2}}{\expandcsonce#3}}% + \postgroupdef#3\endgroup +} +\robust@def*\s@l@ctivesanitize#1#2#3{% + \def\LTS@i{\futurelet\next\LTS@ii}% + \def\LTS@ii{% + \expandafter\LTS@iii\meaning\next\LTS@nil + \ifx\next\end + \let\cmd\@gobbleone + \else + \ifx\next\@sptoken + \edef#1{\expandcsonce#1\@space}% + \lowercase{\def\cmd} {\LTS@i}% + \else + \let\cmd\LTS@iv + \fi + \fi + \cmd + }% + \def\LTS@iii##1##2\LTS@nil{% + \if##1\@backslashchar\let\next\relax\fi + }% + \def\LTS@iv##1{% + \toks@\expandafter{#1}\toks1{##1}% + \ifx\next\temp@bgroup + \advance\cpt@cnta\m@one + \ifnum\cpt@cnta>\z@pt + \begingroup + \cptexpandsecond\s@l@ctivesanitize + {\noexpandcsn{\string#1}{#2}{\the\toks1}}% + \edefpass#1{\endgroup\toks1{\expandcsnonce{\string#1}}}% + \fi + \edef#1{\the\toks@{\the\toks1}}% + \advance\cpt@cnta\@ne + \else + \edef#1{\expandafter\string\the\toks1}% + \expandafter\cpt@in\expandafter{#1}{#2}% + \edef#1{\the\toks@\ifcpt@in#1\else\the\toks1\fi}% + \fi + \LTS@i + }% + \def#1{}\LTS@i#3\end +} +\robust@def*\LTS@checksanitya#1#2{\LTS@checksanity{,}{#1}#2} +\robust@def*\LTS@checksanityb#1#2{\LTS@checksanity{,.=}{#1}#2} +\robust@def*\LTS@checksanityc#1#2{\LTS@checksanity{,;}{#1}#2} +\robust@def*\LTS@checksanityd#1#2{\LTS@checksanity{,;:|-=}{#1}#2} +\robust@def*\LTS@checksanity#1#2#3{% + \cpt@checkfalse + \def\tsv@do##1{% + \ifboolTF{cpt@check}{}{% + \LTS@ch@cksanity{##1}{#2}% + }% + }% + \tsv@@parse{#1}% + \ifboolTF{cpt@check}{% + \edef#3{\unexpanded{#2}}% + \SelectiveSanitize[1]{#1}#3% + }{}% +} +\robust@def*\LTS@ch@cksanity#1#2{% + \ifbelongFT{#1}{#2}{}{% + \defpass\reserved@a##1#1##2\LTS@nil{% + \ifblankTF{##2}{\cpt@checktrue\loopbreak}{}% + }% + #2#1\LTS@nil + }% +} +\robust@def*\LTS@ensureothersanity#1#2{% + \begingroup + \edef#2{\unexpanded{#1}}% + \LTS@scantoksb#2% + \postgroupdef#2\endgroup +} + +% #1 : optional parser +% #2 : a control sequence or name (+ -> name) of original list +% #3 : new list to merge with #2 (* -> #3 is a macro) +% #4 : filter (use \nofilter when there isn't a filter) +\robust@def*\ltsfiltermergecsv{% + \begingroup + \let\LTS@parse\csv@@parse + \LTS@checkoptprefix + {\LTS@teststplcl{\LTS@testopt\LTS@filtermergelists{,}}}% +} +\robust@def*\ltsfiltermergekv{% + \begingroup + \let\LTS@parse\kv@@parse + \LTS@checkoptprefix + {\LTS@teststplcl{\LTS@testopt\LTS@filtermergelists,}}% +} +\robust@def*\LTS@filtermergelists[#1]#2#3#4{% + \edef\temp@do + {\noexpandcsn{\ifxTF\LTS@parse\csv@@parse{csv}{kv}@do}}% + \def\LTS@tempa{}% + \ifLTS@pl + \ifcsndefTF{#2}{\letcstocsn\LTS@tempa{#2}}{}% + \else + \ifdefTF{#2}{\let\LTS@tempa#2}{}% + \fi + \cpt@stchoose{LTS@st}{#3}\LTS@tempb\LTS@filtermergelists + \cptdeclarefilter{#4}% + \cpt@useemptyfalse + \def\LTS@tempf##1{\csliststack#1\LTS@tempa\unexpanded{##1}}% + \expandafter\def\temp@do##1{% + \edef\LTS@tempb{\unexpanded{##1}}% + % csv/kv loops don't use cpt@swa. So it is safe + % to use it here: + \cpt@swatrue + \cpt@usefilter\LTS@tempb\LTS@tempc + \let\LTS@tempd\LTS@tempa + \def\LTS@tempa{}% + \expandafter\def\temp@do####1{% + \edef\LTS@tempd{\unexpanded{####1}}% + \cpt@usefilter\LTS@tempd\LTS@tempe + \ifx\LTS@tempc\LTS@tempe + \cpt@swafalse + \edef\LTS@tempa{\LTS@tempf{##1}}% + \else + \edef\LTS@tempa{\LTS@tempf{####1}}% + \fi + }% + \ifcsnullTF\LTS@tempd{}{\LTS@parse*[#1]\LTS@tempd}% + \ifdefboolFT{cpt@swa}{}{\edef\LTS@tempa{\LTS@tempf{##1}}}% + }% + \ifcsnullTF\LTS@tempb{}{\LTS@parse*[#1]\LTS@tempb}% + \cptpassexpanded{% + \ifLTS@cl\global\fi + \let\ifLTS@pl\cptmakecs{#2}\else\noexpand#2\fi + \noexpand\LTS@tempa + }% + % If cl is true, then global assignment has already been done: + \ifboolTF{LTS@cl}\endgroup{% + \ifboolTF{LTS@pl}{% + \expandafter\postgroupdef\csname#2\endcsname\endgroup + }{% + \postgroupdef#2\endgroup + }% + }% +} +\robust@def*\filter@merge@csv#1{% + \begingroup + \let\LTS@parse\csv@@parse + \LTS@sttrue + \LTS@ifstringcase{#1}% + {fff}{\LTS@stfalse\LTS@plfalse\LTS@clfalse}% + {tff}{\LTS@sttrue\LTS@plfalse\LTS@clfalse}% + {ttf}{\LTS@sttrue\LTS@pltrue\LTS@clfalse}% + {ttt}{\LTS@sttrue\LTS@pltrue\LTS@cltrue}% + {ftt}{\LTS@stfalse\LTS@pltrue\LTS@cltrue}% + {fft}{\LTS@stfalse\LTS@plfalse\LTS@cltrue}% + {tft}{\LTS@sttrue\LTS@plfalse\LTS@cltrue}:% + [\LTS@err{No match for \string\filter@merge@csv}\@ehc]% + \LTS@filtermergelists +} + +% #1: parser +% #2: new single element, in a macro or otherwise; +% #3: old list (in a macro); +% #4: filter (a macro); +% We want to filter #2 before entering the result in #3: +\robust@def*\singleelementfiltermerge{% + \LTS@testcl{\LTS@testopt\LTS@sefm,}% +} +\robust@def*\LTS@sefm[#1]#2#3#4{% + \cptdeclarefilter{#4}% + \cpt@usefilter{#2}\reserved@a + \edef\reserved@a{\simpleexpandarg\cpttrimspace\reserved@a}% + \ifdefTF#3{}{\def#3{}}% + \xifinsetTF{#1\cptoxdetok\reserved@a#1}{#1\cptoxdetok#3#1}{}{% + \ifLTS@cl\global\fi + \edef#3{\csliststack#1#3\expandcsonce\reserved@a}% + }% +} +% #1 : control sequence of old (non-separated) list +% #2 : new update (a non-separated list) +% #3 : filter (use \nofilter when there isn't a filter) +\robust@def*\ltsfiltermergetsv{\LTS@testcl\LTS@filtermergetokens} +\robust@def*\LTS@filtermergetokens#1#2#3{% + \begingroup + \let\ifLTS@mergecl\ifLTS@cl + \cptdeclarefilter{#3}% + \ifdefTF{#1}{}{\emptify#1}% + \def\LTS@tempa{#2}% + \LTS@tfor@b\LTS@tempa\LTS@tempa{% + \cpt@swatrue + \cpt@usefilter\LTS@tempa\LTS@tempb + \let\LTS@tempc#1\emptify#1% + \LTS@tfor@b\LTS@tempc\LTS@tempc{% + \cpt@usefilter\LTS@tempc\LTS@tempd + \ifx\LTS@tempb\LTS@tempd + \cpt@swafalse + \edef#1{\expandcsonce#1\expandcsonce\LTS@tempa}% + \else + \edef#1{\expandcsonce#1\expandcsonce\LTS@tempc}% + \fi + }% + \ifcpt@swa\edef#1{\expandcsonce#1\expandcsonce\LTS@tempa}\fi + }% + \ifLTS@mergecl + \globalize#1\endgroup + \else + \cptpassacross#1\endgroup + \fi +} +% #1 : optional list parser; +% #2 : control sequence (or, if +, cs name) of csv list; +% #3 : non-contiguous sublist to remove +% ('*' implies that this is a control sequence); +% #4 : filter (use \nofilter when there isn't a filter); +\robust@def*\filterremovecsv{% + \begingroup + \let\LTS@parse\csv@@parse + \LTS@checkoptprefix + {\LTS@teststplcl{\LTS@testopt\LTS@filterremoveelements{,}}}% +} +\robust@def*\filterremovekv{% + \begingroup + \let\LTS@parse\kv@@parse + \LTS@checkoptprefix + {\LTS@teststplcl{\LTS@testopt\LTS@filterremoveelements{,}}}% +} +\robust@def*\LTS@filterremoveelements[#1]#2#3#4{% + \cpt@checklistparser{#1}\relax + \begingroup + \edef\temp@do + {\noexpandcsn{\ifxTF\LTS@parse\csv@@parse{csv}{kv}@do}}% + \letcstocsn\LTS@normalize + {cpt@\ifxTF\LTS@parse\csv@@parse{csv}{kv}normalize}% + \ifLTS@pl + \ifcsndefTF{#2}{}{\emptifycsn{#2}}% + \letcstocsn\LTS@tempa{#2}% + \else + \ifdefTF{#2}{}{\def#2{}}% + \let\LTS@tempa#2% + \fi + \cpt@stchoose{LTS@st}{#3}\LTS@tempb\LTS@filterremoveelements + \ifcsnullTF\LTS@tempb{} + {\cpt@sttrue\LTS@normalize[#1]\LTS@tempb}% + \cptdeclarefilter{#4}% + \def\LTS@tempd{}% + \expandafter\def\temp@do##1{% + \edef\LTS@tempa{\unexpanded{##1}}% + \cpt@usefilter\LTS@tempa\LTS@tempc + \oifinset@sp@TF#1\LTS@tempc\LTS@tempb{}{% + \edef\LTS@tempd{\csliststack#1\LTS@tempd\unexpanded{##1}}% + }% + }% + \ifcsnullTF\LTS@tempa{}{\LTS@parse*[#1]\LTS@tempa}% + \cptpassexpanded{% + \ifLTS@cl\global\fi + \let\ifLTS@pl\cptmakecs{#2}\else\noexpand#2\fi + \noexpand\LTS@tempd + }% + \ifboolTF{LTS@cl}\endgroup{\postgroupdef#2\endgroup}% +} + +% \purgeelements is faster than \filterremoveelements but it +% first detokenizes the tokens. It thus isn't as versatile. +% Also inherent leading and trailing spaces may cause +% problems in the removal of elements. It is handy in +% cleaning \@unusedoptionlist. +% #1: optional parser; +% #2: noncontiguous sublist; +% #3: container of original list +\robust@def*\purgeelements{% + \LTS@testst{% + \let\ifLTS@purgest\ifLTS@st + \begingroup + \@makeother{\#}% + \LTS@testopt{\expandafter\endgroup\LTS@p@rgeelements}{,}% + }% +} +% The parameter character '#' must be innocent when +% calling \purgeelements: +\robust@def*\LTS@purgeelements{% + \LTS@err{Use \noexpand\purgeelements instead}\@ehc +} +\robust@def*\LTS@p@rgeelements[#1]#2#3{% + \cpt@checklistparser{#1}\relax + \begingroup + \def\csv@do##1{% + \ifblankTF{##1}{}{% + \def\LTS@tempb####1#1##1#1####2\LTS@nil{####1#1####2\purge@nil}% + \def\LTS@tempc####1#1\purge@nil####2\purge@nil{% + \ifx#1####1\@empty\else####1\fi + }% + \def\LTS@tempa{% + \cptthreexp\LTS@tempc\expandafter\LTS@tempb\expandafter + #1\detokenize\expandafter{#3}#1\purge@nil#1##1#1\LTS@nil + }% + \expandafter\edef\expandafter#3\expandafter{\LTS@tempa}% + }% + }% + \ifblankTF{#2}{}{\cptexpandarg{\csv@@loop[#1]}{\detokenize{#2}}}% + \postgroupdef#3\endgroup + \LTS@remparser[#1]#3% + \ifboolTF{LTS@purgest}{}{\LTS@scantoks@hash#3}% + \undefcs\ifLTS@purgest +} +% #1 : container of original (non-separated) tokens +% #2 : non-separated members to delete (* -> a macro) +% #2 : filter +\robust@def*\filterdeletetokens{\LTS@teststcl\LTS@deletetokens} +\robust@def*\LTS@deletetokens#1#2#3{% + \let\ifLTS@fdelcl\ifLTS@cl + \begingroup + \cptdeclarefilter{#3}% + \def\siso@do##1{% + \edef\LTS@tempa{\unexpanded{##1}}% + \cpt@usefilter\LTS@tempa\LTS@tempc + \edef\LTS@tempa{\expandcsonce\LTS@tempc}% + \cptexpandsecond{% + \def\LTS@tempb####1}{\expandcsonce\LTS@tempa}####2####3\LTS@nil{% + \edef\LTS@tempb{\unexpanded{####2}}% + \ifxTF\LTS@nnil\LTS@tempb{}{% + \cptexpandsecond{\def\LTS@tempb########1}{% + \expandcsonce\LTS@tempa}########2\LTS@nil{% + \edef#1{\unexpanded{########1########2}}% + }% + \expandafter\LTS@tempb#1\LTS@nil + }% + }% + \cptexpandsecond\LTS@tempb + {\expandcsonce#1\expandcsonce\LTS@tempa}{\LTS@nil}\LTS@nil + }% + \ifboolTF{LTS@st}{% + \expandafter\siso@@loop\expandafter{#2}% + }{% + \siso@@loop{#2}% + }% + \postgroupdef#1\endgroup + \ifLTS@fdelcl\globalize#1\fi + \undefcs\ifLTS@fdelcl +} +% #1 : container of original (non-separated) tokens +% #2 : non-separated members to delete +\robust@def*\simpledeletetokens#1#2{% + \def\siso@do##1{% + \def\LTS@tempa####1##1####2####3\LTS@nil{% + \edef\LTS@tempa{\unexpanded{####2}}% + \ifx\LTS@nnil\LTS@tempa\else + \def\LTS@tempa########1##1########2\LTS@nil{% + \edef#1{\unexpanded{########1########2}}% + }% + \expandafter\LTS@tempa#1\LTS@nil + \fi + }% + \expandafter\LTS@tempa#1##1{\LTS@nil}\LTS@nil + }% + \expandafter\siso@@loop\expandafter{#2}% +} +\robust@def*\DeclareVerbatimDelimiter#1{% + \ifsingletokenFT{#1}{% + \LTS@err{Verbatim delimiter isn't a single token}\@ehc + }{% + \def\LTS@v@rbatimstore##1#1##2#1{% + \endgroup + \LTS@v@rb@timstore{##2}% + }% + }% +} +\robust@def*\LTS@v@rb@timst@re{% + \begingroup + \@sanitize\obeyspaces + \LTS@v@rbatimstore +} +\robust@def*\verbatimstore#1{% + \long\def\LTS@v@rb@timstore##1{\def#1{##1}}% + \LTS@v@rb@timst@re +} +\robust@def*\ltsretokenize{\LTS@testst\LTS@retokenize} +\robust@def\LTS@retokenize#1#2{% + \begingroup + \edef\LTS@tempa{\unexpanded{#2}}% + \ifLTS@st + \def\LTS@ret@kenize##1\LTS@nil{\protected@edef#1{##1}}% + \else + \def\LTS@ret@kenize##1\LTS@nil{\edef#1{\unexpanded{##1}}}% + \fi + \cpteveryscan + \everyeof{\LTS@nil}% + \expandafter\LTS@ret@kenize\scantokens\expandafter{\LTS@tempa}% + \relax\postgroupdef#1\endgroup +} +\robust@def*\LTS@scantoksa#1{% + \begingroup + \edef#1{\long\def\string#1{\detokenize\expandafter{#1}}}% + \cpteveryscan + \scantokens\expandafter{#1}\relax + \postgroupdef#1\endgroup +} +\robust@def*\LTS@scantoks@hash#1{% + \begingroup + \edef#1{\long\def\string#1{\detokenize\expandafter{#1}}}% + \catcode`\#=6\relax\cpteveryscan + \scantokens\expandafter{#1}\relax + \postgroupdef#1\endgroup +} +\robust@def*\LTS@scantoksb#1{% + \begingroup + \def\siso@do##1{\catcode`##1\string=12\relax}% + \siso@@loop{=,;|-+?><}% + \LTS@scantoksa#1% + \postgroupdef#1\endgroup +} +\robust@def*\LTS@scantoksc{\LTS@testplcl\LTS@sc@ntoksc} +\robust@def\LTS@sc@ntoksc#1{% + \def\comma@do##1{% + \ifboolTF{LTS@pl}{% + \expandafter\LTS@ensuremacro\csname ##1\endcsname + \letcstocsn\reserved@e{##1}% + }{% + \LTS@ensuremacro{##1}% + \let\reserved@e##1% + }% + \LTS@scantoksa\reserved@e + \cptpassexpanded{% + \ifLTS@cl\global\fi\let\ifLTS@pl + \cptmakecs{##1}\else\unexpanded{##1}\fi + \noexpand\reserved@e + }% + }% + \commacsvparse{#1}% +} +\robust@def*\LTS@scantoksd#1#2{% + \cptexpandsecond{#1\cpteveryscan\scantokens}{% + {#2}% + \everyeof{\the\everyeof}% + \noexpand\endlinechar\the\endlinechar\relax + \catcode`\noexpand\@=\the\catcode`\@\relax + \catcode`\noexpand\ =\the\catcode`\ \relax + \catcode`\noexpand\\=\the\catcode`\\\relax + \catcode`\noexpand\{=\the\catcode`\{\relax + \catcode`\noexpand\}=\the\catcode`\}\relax + }% +} +\providecommand*\newbool{\ltsnewbool} +\providecommand*\setbool{\ltssetbool} +\providecommand*\booltrue{\ltsbooltrue} +\providecommand*\boolfalse{\ltsboolfalse} +\providecommand*\setbooltrue{\ltssetbooltrue} +\providecommand*\setboolfalse{\ltssetboolfalse} +\robust@def*\ltsnewbool#1{\cpt@swatrue\LTS@testopt{\LTS@newbool{#1}}{false}} +\robust@def*\defbool#1{\cpt@swafalse\LTS@testopt{\LTS@newbool{#1}}{false}} +\new@def*\LTS@newbool#1[#2]{% + \ifinsetFT{,}{#1}{}{% + \begingroup + \edef\LTS@tempa{\ifcpt@swa'\string\ltsnewbool' + \else'\string\ltsdefbool'\fi}% + \edef\LTS@tempb{\ifcpt@swa'\string\NewBooleans' + \else'\string\DefBooleans'\fi}% + \LTS@err{Command \LTS@tempa\@space doesn't accept list}% + {Please submit only one boolean to \LTS@tempa\MsgBrk + at a time. You may consider using\LTS@tempb\MsgBrk + if you really want to define a set of booleans.}% + \endgroup + }% + \LTS@ensurenoscape{#1}% + \LTS@badboolname{#1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{if#1}\relax + \LTS@getboolstate\ltsnewbool{#2}% + }{% + \ifcsndefFT{if#1}{}{% + \LTS@verbosewarn{Boolean '\@backslashchar if#1' redefined}% + }% + \LTS@getboolstate\ltsdefbool{#2}% + }% + \csnnewif{#1}% + \usename{#1\LTS@boolval}% +} +\robust@def*\NewBooleans{\cpt@swatrue\LTS@testopt\LTS@NewBooleans{}} +\robust@def*\DefBooleans{\cpt@swafalse\LTS@testopt\LTS@NewBooleans{}} +\robust@def*\LTS@NewBooleans[#1]#2{% + \LTS@testopt{\LTS@B@oleans{#1}{#2}}{false}% +} +\new@def*\LTS@B@oleans#1#2[#3]{% + \cptexpandsecond\LTS@getboolstate + {\ifboolTF{cpt@swa}\NewBooleans\DefBooleans}{#3}% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \LTS@badboolname{#1##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{if#1##1}\relax + }{% + \ifcsndefFT{if#1##1}{}{% + \LTS@verbosewarn{Boolean '\@backslashchar if#1##1' + redefined}% + }% + }% + \csnnewif{#1##1}% + \usename{#1##1\LTS@boolval}% + }% + \commacsvparse{#2}% +} +\robust@def*\ltssetbool#1#2{% + \ifcsndefFT{if#1}{% + \LTS@noboolerr{#1}% + }{% + \LTS@getboolstate\ltssetbool{#2}% + \csname#1\LTS@boolval\endcsname + }% +} +\robust@def*\ltssetbooltrue#1{% + \ifcsndefFT{if#1}{\LTS@noboolerr{#1}}{\usename{#1true}}% +} +\newletcs\ltsbooltrue\ltssetbooltrue +\robust@def*\ltssetboolfalse#1{% + \ifcsndefFT{if#1}{\LTS@noboolerr{#1}}{\usename{#1false}}% +} +\newletcs\ltsboolfalse\ltssetboolfalse +\robust@def*\LTS@noboolerr#1{% + \LTS@err{Boolean/switch '\string#1' is undefined}% + {You need to first define the boolean/switch '\string#1'.}% +} +\robust@def*\LTS@boolnameerr#1{% + \LTS@err{'\string\if#1' not valid as a boolean/switch}% + {Invalid boolean/switch name '\string#1'.}% +} +\new@def*\LTS@boolvalerr#1#2{% + \LTS@err{Invalid boolean/switch value '#2' in \string#1}% + {Valid boolean/switch values are \LTS@validboolvalues.}% +} +\new@def*\LTS@validboolvalues{true,false} +\robust@def*\AddValidBooleanValues#1{% + \ltsfiltermergecsv![,]\LTS@validboolvalues{#1}\nofilter +} +\robust@def*\RemoveValidBooleanValues#1{% + \filterremovecsv!\LTS@validboolvalues{#1}\nofilter +} +\robust@def*\LTS@getboolstate#1#2{% + \lowercase{% + \xifinsetTF{,#2,}{,\LTS@validboolvalues,}{% + \edef\LTS@boolval{#2}% + }% + }{% + \LTS@boolvalerr{#1}{#2}% + }% +} +\robust@def*\LTS@badboolname#1{% + \begingroup + \xifstrcmpTF{\expandafter\LTS@cartwo\string#1xx\car@nil}{if}{% + \LTS@boolnameerr{if}% + }{% + \edef\LTS@tempa{\s@expandarg\cpttrimspaces{\cptrm-`\q#1}}% + \oifstrcmpTF\LTS@tempa{x}{\LTS@boolnameerr{x}}{% + \oifstrcmpTF\LTS@tempa{on}{\LTS@boolnameerr{on}}{% + \oifstrcmpTF\LTS@tempa{off}{\LTS@boolnameerr{off}}{% + \oifstrcmpTF\LTS@tempa{tog}{\LTS@boolnameerr{tog}}{% + \oifstrcmpTF\LTS@tempa{bool}{\LTS@boolnameerr{bool}}{% + \oifstrcmpTF\LTS@tempa{switch}{\LTS@boolnameerr{switch}}{}% + }% + }% + }% + }% + }% + }% + \endgroup +} +\providecommand*\newswitch[1]{\cpt@swatrue\LTS@testopt{\LTS@newswitch#1}{false}} +\robust@def*\defswitch#1{\cpt@swafalse\LTS@testopt{\LTS@newswitch#1}{false}} +\robust@def*\LTS@newswitch#1[#2]{% + \ifinsetFT{,}{#1}{}{% + \begingroup + \edef\LTS@tempa{\ifcpt@swa'\string\newswitch' + \else'\string\defswitch'\fi}% + \edef\LTS@tempb{\ifcpt@swa'\string\NewSwitches' + \else'\string\DefSwitches'\fi}% + \LTS@err{Command \LTS@tempa\@space doesn't accept list}% + {Please submit only one switch to \LTS@tempa\MsgBrk + at a time. You may consider using\LTS@tempb\MsgBrk + if you really want to define a set of switches.}% + \endgroup + }% + \LTS@ensurenoscape{#1}% + \LTS@badboolname{#1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1}\relax + \LTS@getboolstate\newswitch{#2}% + }{% + \ifcsndefFT{#1}{}{% + \LTS@verbosewarn{Switch '\@backslashchar#1' redefined}% + }% + \LTS@getboolstate\defswitch{#2}% + }% + \letcsntocsn{#1}{cpt\LTS@boolval}% +} +\robust@def*\NewSwitches{\cpt@swatrue\LTS@testopt\LTS@NewSwitches{}} +\robust@def*\DefSwitches{\cpt@swafalse\LTS@testopt\LTS@NewSwitches{}} +\robust@def*\LTS@NewSwitches[#1]#2{% + \LTS@testopt{\LTS@Sw@tches{#1}{#2}}{false}% +} +\new@def*\LTS@Sw@tches#1#2[#3]{% + \cptexpandsecond\LTS@getboolstate + {\ifboolTF{cpt@swa}\NewSwitches\DefSwitches}{#3}% + \docommalist{#2}{% + \LTS@ensurenoscape{##1}% + \LTS@badboolname{#1##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{if#1##1}\relax + }{% + \ifcsndefFT{if#1##1}{}{% + \LTS@verbosewarn{Switch '\@backslashchar if#1##1' + redefined}% + }% + }% + \letcsntocsn{#1##1}{cpt\LTS@boolval}% + }% +} +\robust@def*\NewTogs{\cpt@swatrue\LTS@testopt\LTS@NewTogs{}} +\robust@def*\DefTogs{\cpt@swafalse\LTS@testopt\LTS@NewTogs{}} +\new@def*\LTS@NewTogs[#1]#2{\LTS@testopt{\LTS@NewT@gs[#1]{#2}}{false}} +\new@def*\LTS@NewT@gs[#1]#2[#3]{% + \cptexpandsecond\LTS@getboolstate + {\ifcpt@swa\NewTogs\else\DefTogs\fi}{#3}% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \cptpassexpanded{\ifcpt@swa\newtog\else\deftog\fi}{#1##1}% + \usename{settog\LTS@boolval}{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewToks{\cpt@swatrue\LTS@testopt\LTS@NewToks{}} +\robust@def*\DefToks{\cpt@swafalse\LTS@testopt\LTS@NewToks{}} +\new@def*\LTS@NewToks[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Token register '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewtoks{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewCounts{\cpt@swatrue\LTS@testopt\LTS@NewCounts{}} +\robust@def*\DefCounts{\cpt@swafalse\LTS@testopt\LTS@NewCounts{}} +\new@def*\LTS@NewCounts[#1]#2{\LTS@testopt{\LTS@N@wCounts[#1]#2}{}} +\new@def*\LTS@N@wCounts[#1]#2[#3]{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1#3}\relax + }{% + \ifcsndefFT{#1##1#3}{}{% + \LTS@verbosewarn{Counter register '\@backslashchar + #1##1#3' redefined}% + }% + }% + \csnnewcount{#1##1#3}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewCounters{\cpt@swatrue\LTS@testopt\LTS@NewCounters{}} +\robust@def*\DefCounters{\cpt@swafalse\LTS@testopt\LTS@NewCounters{}} +\new@def*\LTS@NewCounters[#1]#2{\LTS@testopt{\LTS@N@wCounters[#1]#2}{}} +\new@def*\LTS@N@wCounters[#1]#2[#3]{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1#3}\relax + }{% + \ifcsndefFT{#1##1#3}{}{% + \LTS@verbosewarn{Counter register '\@backslashchar + #1##1#3' redefined}% + }% + }% + \@definecounter{#1##1#3}% + }% + \commacsvparse{#2}% +} +\newletcs\NewNumbers\NewCounters +\robust@def*\NewDimens{\cpt@swatrue\LTS@testopt\LTS@NewDimens{}} +\robust@def*\DefDimens{\cpt@swafalse\LTS@testopt\LTS@NewDimens{}} +\new@def*\LTS@NewDimens[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Dimension register '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewdimen{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewBoxes{\cpt@swatrue\LTS@testopt\LTS@NewBoxes{}} +\robust@def*\DefBoxes{\cpt@swafalse\LTS@testopt\LTS@NewBoxes{}} +\new@def*\LTS@NewBoxes[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Box register '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewbox{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewSkips{\cpt@swatrue\LTS@testopt\LTS@NewSkips{}} +\robust@def*\DefSkips{\cpt@swafalse\LTS@testopt\LTS@NewSkips{}} +\new@def*\LTS@NewSkips[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Skip register '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewskip{#1##1}% + }% + \commacsvparse{#2}% +} +\newletcs\NewLengths\NewSkips +\newletcs\DefLengths\DefSkips +\robust@def*\NewMuSkips{\cpt@swatrue\LTS@testopt\LTS@NewMuSkips{}} +\robust@def*\DefMuSkips{\cpt@swafalse\LTS@testopt\LTS@NewMuSkips{}} +\new@def*\LTS@NewMuSkips[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{\noexpand\muskip register '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewmuskip{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewWrites{\cpt@swatrue\LTS@testopt\LTS@NewWrites{}} +\robust@def*\DefWrites{\cpt@swafalse\LTS@testopt\LTS@NewWrites{}} +\new@def*\LTS@NewWrites[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Write stream '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewwrite{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\NewReads{\cpt@swatrue\LTS@testopt\LTS@NewReads{}} +\robust@def*\DefReads{\cpt@swafalse\LTS@testopt\LTS@NewReads{}} +\new@def*\LTS@NewReads[#1]#2{% + \def\comma@do##1{% + \LTS@ensurenoscape{##1}% + \ifboolTF{cpt@swa}{% + \ifcsndefinable{#1##1}\relax + }{% + \ifcsndefFT{#1##1}{}{% + \LTS@verbosewarn{Read stream '\@backslashchar + #1##1' redefined}% + }% + }% + \csnnewread{#1##1}% + }% + \commacsvparse{#2}% +} +\robust@def*\checknewcommands{% + \LTS@checkoptprefix{\LTS@teststpl\LTS@checknewcmds}% +} +\new@def*\LTS@checknewcmds#1{% + \begingroup + \edef\LTS@tempa{\ifLTS@st*\fi}% + \def\csv@do##1{% + \usename{ifcs\ifLTS@pl n\fi definable}{##1}\relax + }% + \expandafter\csv@@parse\LTS@tempa[,]{#1}% + \endgroup +} +\new@def*\LTS@post@prefixerr#1{% + \LTS@err{Bad prefixes for command '\string#1'}% + {You have wrongly prefixed command '\string#1'\MsgBrk + with both star sign and exclamation mark.\MsgBrk + You have to choose one of them. The star expands\MsgBrk + the arguments once, while the exclamation mark\MsgBrk + expands the arguments fully.}% +} +\robust@def*\postgroup{\LTS@teststcl\LTS@postgroup} +\new@def\LTS@postgroup#1{% + \ifLTS@st + \ifLTS@cl + \LTS@post@prefixerr\postgroup + \else + \edef\LTS@tempa{\unexpanded{#1}}% + \expandallonce\LTS@tempa + \fi + \else + \ifLTS@cl + \if\detokenize{#1*}% + \LTS@post@prefixerr\postgroup + \fi + \let\next\@firstofone + \else + \let\next\unexpanded + \fi + \fi + \advance\@tempcnta\@ne + \csn@xdef{LTS@aft@rgroup@\romannumeral\@tempcnta}{% + \gundefcsn{LTS@aft@rgroup@\romannumeral\@tempcnta}% + \ifboolTF{LTS@st}{\@firstofone\LTS@tempa\@gobble}\next{#1}% + }% + \aftercsname\aftergroup{LTS@aft@rgroup@\romannumeral\@tempcnta}% +} +\robust@def*\postassignment{\LTS@teststcl\LTS@postassignment} +\robust@def\LTS@postassignment#1{% + \begingroup + \ifboolTF{LTS@st}{% + \ifboolTF{LTS@cl}{% + \LTS@post@prefixerr\postassignment + }{% + \edef\LTS@tempa{\unexpanded{#1}}% + \expandallonce\LTS@tempa + }% + }{% + \ifboolTF{LTS@cl}{% + \if\detokenize{#1*}% + \LTS@post@prefixerr\postassignment + \fi + \let\next\@firstofone + }{% + \let\next\unexpanded + }% + }% + \advance\@tempcnta\@ne + \aftercsname\xdef{LTS@p@stassignment@\romannumeral\@tempcnta}{% + \gundefcsn{LTS@p@stassignment@\romannumeral\@tempcnta}% + \ifboolTF{LTS@st}{\@firstofone\LTS@tempa\@gobble}\next{#1}% + }% + \aftercsname{\endgroup\afterassignment} + {LTS@p@stassignment@\romannumeral\@tempcnta}% +} +\robust@def*\minorpostassignment{\LTS@testst\LTS@minorpostassignment} +\robust@def\LTS@minorpostassignment#1{% + \begingroup + \advance\@tempcnta\@ne + \csn@xdef{LTS@p@stassignment@\romannumeral\@tempcnta}{% + \gundefcsn{LTS@p@stassignment@\romannumeral\@tempcnta}% + \ifLTS@st\expandafter\@iden\else\expandafter\unexpanded\fi{#1}% + }% + \aftercsname{\endgroup\afterassignment} + {LTS@p@stassignment@\romannumeral\@tempcnta}% +} +\robust@def*\LTS@undef{\LTS@testcl\LTS@und@f} +\new@def*\LTS@und@f#1{% + \is@global@or@relax + \docommalist{#1}{% + \ifsingletoken@sp@TF{##1}{% + \LTS@ensurescape{##1}% + \glob@lrel@x\undefcs##1% + }{% + \cpt@notonetokenerr{##1}% + }% + }% +} +\robust@def*\ltsundefcslist{% + \LTS@checkoptprefix{\LTS@teststplcl{\cpt@testopt\LTS@undefcslist{,}}}% +} +\new@def*\LTS@undefcslist[#1]#2{% + \is@global@or@relax + \edef\reserved@a{\ifLTS@st*\fi}% + \def\csv@do##1{% + \ifLTS@pl + \glob@lrel@x\undefcsn{##1}% + \else + \glob@lrel@x\undefcs##1% + \fi + }% + \expandafter\csv@@parse\reserved@a[#1]{#2}% +} +\robust@def*\declarepackagecmd{\LTS@testopt\LTS@declarepkgcmd{}} +\new@def\LTS@declarepkgcmd[#1]#2{% + \LTS@ensurescape{#2}% + \ifdefTF#2{% + \letcsntocs{Saved\cptremovescape#2}#2% + \cptpassexpanded{% + \AtTagEndPackage{% + \let\noexpand#2\noexpandcsn{Saved\cptremovescape#2}% + \gundefcs\noexpandcsn{Saved\cptremovescape#2}% + }% + }% + }{% + \AtTagEndPackage{\gundefcs#2}% + }% + #1\def#2% +} +\robust@def*\declaredocumentcmd{\LTS@testopt\LTS@declaredoccmd{}} +\new@def\LTS@declaredoccmd[#1]#2{% + \LTS@ensurescape{#2}% + \ifcsdefinable#2\relax + \ifinstylefileTF{% + \cptpassexpanded{% + \LTS@AtBeginDocument{% + \let\noexpand#2\noexpandcsn{Saved\cptremovescape#2}% + \gundefcs\noexpandcsn{Saved\cptremovescape#2}% + }% + }% + \postassignment{% + \letcsntocs{Saved\cptremovescape#2}#2% + \gundefcs#2% + }% + }{}% + #1\def#2% +} +\robust@def*\LTS@providedef{\LTS@teststcl{\LTS@pr@videdef\relax}} +\robust@def*\LTS@providerobustdef{\LTS@teststcl{\LTS@pr@videdef\protected}} +\new@def\LTS@pr@videdef#1#2{% + \is@long@or@relax\is@global@or@relax + \LTS@ensurescape{#2}% + \ifdefTF#2{% + \LTS@verboseinfo{Command '\string#2' already defined: + \MsgBrk Not redefined}% + \minorpostassignment{\gundefcs\pr@v@de}% + }{% + \minorpostassignment{% + \gletcs#2\pr@v@de + \gletcsntocs{LTS@test@\cptremovescape#2}#2% + \gundefcs\pr@v@de + }% + }% + \glob@lrel@x\l@ngrel@x#1\def\pr@v@de +} +\new@def\testprovidedcommand#1{% + \LTS@ensurescape{#1}% + \begingroup + \ifmacroFT#1{% + \aftergroup\@secondoftwo + }{% + \aftercsname\aftergroup{LTS@\cptthreexp + \ifxTF\usename{LTS@test@\cptremovescape#1}#112of2}% + }% + \endgroup +} +\robust@def*\LTS@reviewcommandhandler#1{% + \LTS@verboseinfo{% + Previously 'provided' definition of '\string#1'\MsgBrk + is retained. Your new definition was ignored\MsgBrk + }% +} +\robust@def*\reviewcommand{\LTS@testopt\LTS@revcommand{}} +\new@def\LTS@revcommand[#1]#2#3{% + \testprovidedcommand#2{% + \LTS@reviewcommandhandler{#2}% + }{% + #1\def#2{#3}% + }% +} +% #1: list of comma-separated command pairs: +\robust@def*\newprovidedcommands#1{% + \def\reserved@e##1##2\LTS@nil{% + \ifdefTF{##2}{% + \LTS@providerobustdef*##1{##2}% + }{% + \cpt@notdeferr{##2}% + }% + }% + \def\csv@do##1{\reserved@e##1\LTS@nil}% + \csv@@parse[,]{#1}% +} +\new@def*\ifrelaxTF#1{% + \ifdefinedTF{#1}% + {\usename{LTS@\expandafter\ifxTF\cpt@car#1\car@nil + \relax12of2}}\@secondoftwo +} +\new@def*\ifcsnrelaxTF#1{% + \ifcsnameFT{#1}\@secondoftwo + {\usename{LTS@\aftercsname\expandafter\ifxTF\cpt@car#1\car@nil + \relax12of2}}% +} +\def\ifcsnrelaxFT#1{\usename{LTS@\ifcsnrelaxTF{#1}21of2}} +\new@def*\ifdefaxTFN#1{% + \ifdefinedTF{#1}% + {\usename{LTS@\expandafter\ifxTF\cpt@car#1\car@nil + \relax21of3}}\@thirdofthree +} +\new@def*\ifcsndefaxTFN#1{% + \ifcsnameTF{#1}% + {\usename{LTS@\expandafter\ifxTF\csname#1\endcsname + \relax21of3}}\@thirdofthree +} +\robust@def*\ifargifTF#1{% + \usename{LTS@\ifnum\pdfstrcmp + {\expandafter\LTS@carcube\string#1xxx\car@nil}% + {\string\if}=\z@pt1\else2\fi of2}% +} +\robust@def*\LTS@detokenize{\LTS@testst\LTS@det@kenize} +\robust@def*\LTS@det@kenize#1#2{% + \edef#2{\detokenize{#1}}% + \ifLTS@st + \simpleexpandarg\ifargifTF#2{% + \LTS@err{'\@backslashchar if' not valid}\@ehc + }{% + \LTS@scantoksa#2% + \edef#2{\cpttxdetok#2}% + }% + \fi +} +\new@def*\LTS@detokdespace{\LTS@testpl\LTS@det@kdespace} +\new@def\LTS@det@kdespace#1{% + \ifboolTF{LTS@pl}{% + \edef\LTS@resa{\detokenize{#1}}% + \despacecontent\LTS@resa + }{% + \ifdefTF{#1}{}{% + \LTS@err{Command '\string#1' is undefined}{Command + '\string\LTS@detokdespace' doesn't accept undefined + \MsgBrk commands when submitted without the '+' prefix.}% + }% + \ifargifTF{#1}{% + \LTS@err{Invalid argument '\string#1' for command\MsgBrk + '\string\LTS@detokdespace'}{Command '\string\LTS@detokdespace' + doesn't accept '\@backslashchar if'\MsgBrk when submitted + without the '+' prefix.}% + }{% + \edef#1{\cptoxdetok{#1}}% + \despacecontent#1% + }% + }% +} +\robust@def*\ifltxprotectTF#1{% + \begingroup + \ifmacroFT#1{% + \aftergroup\@secondoftwo + }{% + \edef\LTS@tempa##1{\def##1####1\string\protect####2&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}21of2}}% + \edef\LTS@tempb##1{##1\realmeaning#1\string\protect&}% + \LTS@tempb\LTS@tempa + }% + \endgroup +} +\robust@def*\ifltxprotectFT#1{% + \ifltxprotectTF{#1}\@secondoftwo\@firstoftwo +} +\robust@def*\ifcsnltxprotectTF{\aftercsname\ifltxprotectTF} +\robust@def*\ifetexprotectedTF#1{% + \begingroup + \edef\LTS@tempa##1{\def##1####1\string\protected####2&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}21of2}}% + \edef\LTS@tempb##1{##1\meaning#1\string\protected&}% + \LTS@tempb\LTS@tempa + \endgroup +} +\robust@def*\ifetexprotectedFT#1{% + \ifetexprotectedTF{#1}\@secondoftwo\@firstoftwo +} +\robust@def*\ifcsnprotectedTF{\aftercsname\ifetexprotectedTF} +\robust@def*\apptocs{% + \LTS@checkoptprefix{\LTS@teststplcl{\LTS@hooktomac{>}}}% +} +\robust@def*\preptocs{% + \LTS@checkoptprefix{\LTS@teststplcl{\LTS@hooktomac{<}}}% +} +\robust@def\LTS@hooktomac#1#2#3{% + \ifLTS@st\let\@expandb\expandcsonce\else\let\@expandb\unexpanded\fi + \cpt@getmacroprefix{#2}% + \ifLTS@pl + \let\@ifdef\ifcsndefFT\let\@expanda\expandcsnonce + \def\LTS@i##1{\def\@def####1{\aftercsname##1{####1}}}% + \else + \let\@ifdef\ifdefFT\let\@expanda\expandcsonce + \def\LTS@i##1{\def\@def####1{##1####1}}% + \fi + \ifLTS@cl\LTS@i\xdef\else\LTS@i\edef\fi + \@ifdef{#2}{% + \macroprefix\@def{#2}{\@expandb{#3}}% + }{% + \ifx#1>% + \macroprefix\@def{#2}{\@expanda{#2}\@expandb{#3}}% + \else + \macroprefix\@def{#2}{\@expandb{#3}\@expanda{#2}}% + \fi + }% + \LTS@undef!{\@ifdef,\@def,\@expanda,\@expandb,\LTS@i}% +} +\robust@def*\LTS@uaddtolist{\chardef\LTS@addnr\z@pt\LTS@addt@list} +\robust@def*\LTS@addtolist{\chardef\LTS@addnr\@ne\LTS@addt@list} +\robust@def*\LTS@xaddtolist{\chardef\LTS@addnr\tw@\LTS@addt@list} +\robust@def*\LTS@addt@list#1{% + \ifx#1*% + \LTS@err{Star (*) isn't valid as suffix to + \noexpand\LTS@addtolist or \string\LTS@listadd}% + \fi + \LTS@testplcl{\LTS@testlt{\LTS@testopt\LTS@addt@l@st{,}}}% + #1% +} +\new@def*\LTS@addt@l@st[#1]{% + \edef\parser{\detokenize{#1}}% + \ifLTS@cl\let\@def\xdef\else\let\@def\edef\fi + \ifLTS@pl\expandafter\aftercsname\fi\LTS@addt@l@@t +} +\robust@def\LTS@addt@l@@t#1#2{% + \ifcase\LTS@addnr + \let\@expand\unexpanded + \or + \let\@expand\expandcsonce + \else + \let\@expand\@iden + \fi + \begingroup + \toks@{\endgroup + \ifdefFT{#1}{% + \@def#1{\@expand{#2}}% + }{% + \ifcsnullTF#1{% + \@def#1{\@expand{#2}}% + }{% + \ifboolTF{LTS@lt}{% + \@def#1{\@expand{#2}\parser\expandcsonce{#1}}% + }{% + \@def#1{\expandcsonce{#1}\parser\@expand{#2}}% + }% + }% + }% + }% + \usename{% + \ifnum\LTS@addnr=\z@pt\else\ifnum\LTS@addnr=\@ne o\else x\fi\fi + ifblankTF% + }{#2}{\ifcpt@useempty\the\toks@\else\endgroup\fi}{\the\toks@}% + \undefcs\@expand\undefcs\@def + \chardef\LTS@addnr\@ne +} +\robust@def*\LTS@listadd#1{% + \LTS@plfalse\LTS@clfalse\LTS@ltfalse\chardef\LTS@addnr\z@pt + \LTS@addt@l@st[#1]% +} +\robust@def*\LTS@olistadd#1{% + \LTS@plfalse\LTS@clfalse\LTS@ltfalse\chardef\LTS@addnr\@ne + \LTS@addt@l@st[#1]% +} +\robust@def*\LTS@xlistadd#1{% + \LTS@plfalse\LTS@clfalse\LTS@ltfalse\chardef\LTS@addnr\tw@ + \LTS@addt@l@st[#1]% +} +\robust@def*\addtolistexpanded{% + \LTS@testcl{\LTS@testopt\LTS@addtolistexpanded{,}}% +} +\robust@def*\LTS@addtolistexpanded[#1]#2#3{% + \begingroup + \toks@{\endgroup + \ifdefTF#2{% + \usename{protected@\ifLTS@cl x\else e\fi def}% + #2{#2\ifcsnullTF{#2}{}{#1}#3}% + }{% + \usename{protected@\ifLTS@cl x\else e\fi def}#2{#3}% + }% + }% + \oifblankTF{#3}{\ifcpt@useempty\the\toks@\else\endgroup\fi} + {\the\toks@}% +} +\renew@def*\@check@eq#1#2{% + \expandafter\ifxTF\cpt@car#1\car@nil{#2}{}{% + \LTS@verbosewarn{% + Previous definition of '\string#1'\MsgBrk + doesn't match your new definition.\MsgBrk + I haven't redefined '\string#1'}% + }% +} +\ifpkgcurrTF{atveryend}{2010/03/24}{}{% + \RequirePackage{atveryend}[2010/03/24]} +\robust@def*\LTS@notprerr{% + \LTS@err{You have issued a preamble command here}% + {Move shown command to document preamble.}% +} +\robust@def*\LTS@notenderr{% + \LTS@err{You've called an \noexpand\enddocument + command\MsgBrk at the wrong place}{% + Move command to before \string\enddocument. + }% +} +\robust@def*\LTS@AtBeginDocument{\AtBeginDocument} +\robust@def*\LTS@BeforeBeginDocument{% + \grightaddtocs\LTS@beforedocstart +} +\new@def*\LTS@beforedocstart{} +\leftaddtocs\document{% + \endgroup + \let\LTS@BeforeBeginDocument\@firstofone + \LTS@beforedocstart + \let\LTS@BeforeBeginDocument\LTS@notprerr + \gundefcs\LTS@beforedocstart + \begingroup +} +\robust@def*\LTS@AfterBeginDocument{% + \grightaddtocs\LTS@afterdocstart +} +\new@def*\LTS@afterdocstart{} +\robust@def*\LTS@AfterAfterBeginDocument{% + \grightaddtocs\LTS@afterafterdocstart +} +\new@def*\LTS@afterafterdocstart{} +\rightaddtocs\document{% + \let\LTS@AfterBeginDocument\@firstofone + \LTS@afterdocstart + \let\LTS@AfterBeginDocument\LTS@notprerr + \gundefcs\LTS@afterdocstart + \let\LTS@AfterAfterBeginDocument\@firstofone + \LTS@afterafterdocstart + \let\LTS@AfterAfterBeginDocument\LTS@notprerr + \gundefcs\LTS@afterafterdocstart + \ignorespaces +} +\LTS@BeforeBeginDocument{\let\LTS@AtBeginDocument\@firstofone} +\robust@def*\LTS@AtEndDocument{\AtEndDocument} +\robust@def*\LTS@BeforeLastPage{\grightaddtocs\LTS@beforelastpage} +\new@def*\LTS@beforelastpage{} +\LTS@AtEndDocument{% + \let\LTS@bef@relastpage\AtVeryEnd@BeforeClearDocumentHook + \def\AtVeryEnd@BeforeClearDocumentHook{% + \let\LTS@BeforeLastPage\@firstofone + \LTS@beforelastpage\LTS@bef@relastpage + \let\LTS@BeforeLastPage\LTS@notenderr + \LTS@undef!{\LTS@beforelastpage,\LTS@bef@relastpage}% + }% +} +\robust@def*\LTS@AfterLastPage{\grightaddtocs\LTS@afterlastpage} +\new@def*\LTS@afterlastpage{} +\LTS@AtEndDocument{% + \let\LTS@afterl@stpage\AtVeryEnd@AfterLastShipoutHook + \def\AtVeryEnd@AfterLastShipoutHook{% + \let\LTS@AfterLastPage\@firstofone + \LTS@afterlastpage\LTS@afterl@stpage + \let\LTS@AfterLastPage\LTS@notenderr + \LTS@undef!{\LTS@afterlastpage,\LTS@afterl@stpage}% + }% +} +\robust@def*\LTS@AfterEndDocument{\grightaddtocs\LTS@afterenddoc} +\new@def*\LTS@afterenddoc{} +\AtEndOfPackage{\newletcs\AtTagEndOfDocument\LTS@AfterEndDocument} +\LTS@AtEndDocument{% + \let\LTS@aft@renddoc\AtVeryEnd@AtVeryEndDocumentHook + \def\AtVeryEnd@AtVeryEndDocumentHook{% + \let\LTS@AfterEndDocument\@firstofone + \LTS@afterenddoc\LTS@aft@renddoc + \let\LTS@AfterEndDocument\LTS@notenderr + \LTS@undef!{\LTS@afterenddoc,\LTS@aft@renddoc}% + }% +} +\robust@def*\LTS@AtEndPackage{\AtEndOfPackage} +\robust@def*\LTS@BeforeEndPackage{% + \gleftaddtocsn{\@currname.\@currext-h@@k}% +} +\robust@def*\LTS@AfterEndPackage{% + \grightaddtocsn{\@currname.\@currext-LTS@hook}% +} +\let\LTS@AtEndClass\LTS@AtEndPackage +\let\LTS@BeforeEndClass\LTS@BeforeEndPackage +\let\LTS@AfterEndClass\LTS@AfterEndPackage +\leftaddtocs\@popfilename{% + \usename{\@currname.\@currext-LTS@hook}% + \gundefcsn{\@currname.\@currext-LTS@hook}% +} +\robust@def\AtTagEndPackage#1{\AtEndOfPackage{\LTS@AfterEndPackage{#1}}} +\newletcs\LTS@AtTagEndPackage\AtTagEndPackage +\robust@def\afterpackageloaded#1{% + \LTS@after@cls@pkg@loaded{#1}\@pkgextension +} +\robust@def\afterclassloaded#1{% + \LTS@after@cls@pkg@loaded{#1}\@clsextension +} +\robust@def\LTS@after@cls@pkg@loaded#1#2#3{% + \edef\LTS@tempa{\expandafter\ifxTF\cpt@car#2\car@nil + \@pkgextension{sty}{cls}}% + \cptexpanded{% + \LTS@AfterAfterBeginDocument{% + \noexpand\ifcsndefTF{ver@#1.\LTS@tempa}{}{% + \LTS@warn{Package '#1' was never loaded}% + }% + }% + }% + \ifcsndefTF{ver@#1.\LTS@tempa}{% + #3\relax + }{% + \grightaddtocsn{#1.\LTS@tempa-LTS@hook}{#3}% + }% +} +\robust@def*\LTS@preamblecmdhook{} +\robust@def*\preamblecommands{\LTS@testpl\LTS@preamblecmds} +\new@def*\LTS@preamblecmds#1{% + \begingroup + \def\@cmd{\preamblecommands}% + \let\@ifnopattern\ifnopattern + \LTS@pkgpreamplecmd{#1}\LTS@preamblecmdhook{% + \cptpassexpanded{% + \grightaddtocs\LTS@preamblecmdhook + {\LTS@dopreamble\@expand\LTS@tempa}% + }% + }% + \endgroup +} +\robust@def*\AddPreambleCommands#1{% + \def\csv@do##1{% + \ltsfiltermergetsv!\LTS@preamblecmdhook + {\LTS@dopreamble{##1}}\nofilter + }% + \csv@@parse[,]{#1}% +} +\robust@def*\RemovePreambleCommands#1{% + \def\csv@do##1{% + \filterdeletetokens!\LTS@preamblecmdhook + {\LTS@dopreamble{##1}}\nofilter + }% + \csv@@parse[,]{#1}% +} +\robust@def*\packagecommands{\LTS@testpl\LTS@packagecmds} +\robust@def*\LTS@packagecmds#1{% + \begingroup + \toks@{}% + \def\@cmd{\packagecommands}% + \def\@ifnopattern##1\in##2{\ifnopattern##2\in{##1}}% + \LTS@pkgpreamplecmd{#1}\LTS@packagecmderr{% + \@after\ifparamacroTF\LTS@tempa{% + \def\@prepto{\preptoparamcs}% + }{% + \def\@prepto{\leftaddtocs}% + }% + \cptexpandarg{\toks@}{\the\toks@\@prepto\@expand\LTS@tempa + {\LTS@packagecmderr{\@expand\LTS@tempa}}\relax\relax}% + }% + \expandafter\endgroup\the\toks@ +} +\robust@def*\LTS@pkgpreamplecmd#1#2#3{% + \ifLTS@pl + \def\@scape{\simpleexpandarg\LTS@ensurenoscape}% + \let\@after\aftercsname + \let\@expand\noexpandcsn + \else + \def\@scape{\simpleexpandarg\LTS@ensurescape}% + \let\@after\expandafter + \let\@expand\expandcsonce + \fi + \def\csv@do##1{% + \def\LTS@tempa{##1}% + \@after\ifonetoken\LTS@tempa\do{% + \@scape\LTS@tempa + \@after\ifdefTF\LTS@tempa{% + \@after\@ifnopattern\LTS@tempa\in{#2}{#3}{}% + }{% + \LTS@warn{Command '\@after\string\LTS@tempa' undefined: + \MsgBrk ignored by \expandcsonce\@cmd}% + }% + }% + }% + \csv@@parse{#1}% +} +\robust@def*\LTS@dopreamble#1{% + \gdef#1{\LTS@err{'\string#1' is a preamble command}% + {Move command '\string#1' to document preamble.}}% +} +\LTS@AfterBeginDocument{% + \LTS@preamblecmdhook + \gletcs\LTS@dopreamble\@gobbleone +} +\robust@def*\LTS@packagecmderr#1{% + \ifinstylefileTF{}{% + \LTS@err{Command '\detokenize{#1}' issued outside style file}% + {The command '\detokenize{#1}' is available only + in style files.}% + }% +} +\robust@def*\parsemacro{\LTS@testst\LTS@parsemacro} +\robust@def*\LTS@parsemacro#1#2#3{% + \let\ifLTS@noxpst\ifLTS@st + \begingroup + \def\LTS@tempd##1{% + \emptify\LTS@resa + \edef\LTS@tempb{\cptoxdetok{#3}##1&}% + \edef\LTS@tempc####1{\def####1########1##1########2&}% + \LTS@tempc\LTS@tempc{% + \ifblankTF{####2}{% + \edef\LTS@resa{\expandcsonce\LTS@resa####1}% + }{% + \edef\LTS@resa{\expandcsonce\LTS@resa####1\detokenize{#2}##1}% + \LTS@tempc####2&% + }% + }% + \expandafter\LTS@tempc\LTS@tempb + \edef#3{\expandcsonce\LTS@resa}% + }% + \edef\LTS@tempa{\cptoxdetok{#1}}% + \def\tsv@do##1{\LTS@tempd{##1}}% + \tsv@@parse*\LTS@tempa + \postgroupdef#3\endgroup + % \LTS@scantoksa assumes that #3 has no parameters; + % use \LTS@scantoksd otherwise: + \ifLTS@noxpst\LTS@scantoksa#3\fi + \undefcs\ifLTS@noxpst +} +\robust@def*\noexpandparse#1{\parsemacro*\@backslashchar\noexpand#1} +\robust@def*\NoexpandParse#1{% + \let\ifLTS@noxpst\ifLTS@st + \begingroup + \emptify\LTS@resa + \def\LTS@tempd##1{\edef\LTS@resa{\expandcsonce\LTS@resa + \noexpand\noexpand\unexpanded{##1}}}% + \def\tsv@do##1{% + \ifmacroTF{##1}{% + \LTS@tempd{##1}% + }{% + \edef\LTS@tempb{\detokenize{##1}}% + \edef\LTS@tempc{\expandafter\LTS@car\LTS@tempb x\car@nil}% + \ifxTF\LTS@tempc\@backslashchar{% + \LTS@tempd{##1}% + }{% + \edef\LTS@resa{\expandcsonce\LTS@resa\unexpanded{##1}}% + }% + }% + }% + \tsv@@parse*{#1}% + \edef#1{\expandcsonce\LTS@resa}% + \postgroupdef#1\endgroup + \ifLTS@noxpst\LTS@scantoksa#1\fi + \undefcs\ifLTS@noxpst +} + +% #1: list; +% #2: a defined/undefined command: +\robust@def*\despacecommalist#1#2{% + \LTS@stfalse\LTS@despacecsvlist[,]{#1}% + \let#2=\despaced@list +} +\robust@def*\despacecsvlist{% + \LTS@testst{\LTS@testopt\LTS@despacecsvlist{,}}% +} +\robust@def*\LTS@despacecsvlist[#1]#2{% + \cpt@stchoose{LTS@st}{#2}\despaced@list\LTS@despacecsvlist + \ifcsnullTF\despaced@list{}{% + \xifinsetTF{\detokenize{#1}}{\cptoxdetok\despaced@list}{% + \cpt@sttrue\cpt@csvnormalize[#1]\despaced@list + }{% + \edef\despaced@list + {\simpleexpandarg\cpttrimspaces\despaced@list}% + }% + }% + \ifboolTF{LTS@st}{\let#2=\despaced@list}{}% +} +\robust@def*\despacexcsvlist{% + \LTS@teststpm{% + \ifnextisbrack\LTS@despacexcsvlist{\LTS@despacexcsvlist[,]}% + }% +} +\robust@def*\LTS@despacexcsvlist[#1]{% + \ifnextisbrack + {\LTS@d@spacexcsvlist#1}{\LTS@d@spacexcsvlist#1[#1]}% +} + +% #1: outer parser +% #2: inner parser +% #3: <list> or <listcmd> +% * -> #3 is a macro +% ' -> each element of #3 is again a macro of list +\robust@def*\LTS@d@spacexcsvlist#1[#2]#3{% + \let\ifxdespm\ifLTS@pm + \cpt@stchoose{LTS@st}{#3}\reserved@e\LTS@d@spacexcsvlist + \def\despaced@list{}% + \ifcsnullTF\reserved@e{}{% + \def\csv@do##1{% + \ifboolTF{xdespm}{% + \cpt@sttrue\cpt@csvnormalize[#2]{##1}% + \LTS@listadd#1\despaced@list{##1}% + }{% + \edef\reserved@e{\cpttrimspaces{##1}}% + \LTS@olistadd{#1}\despaced@list\reserved@e + }% + }% + \csv@@parse*[#1]\reserved@e + }% + \ifboolTF{LTS@st}{\let#3=\despaced@list}{}% + \undefcs\ifxdespm +} +\robust@def*\despacetsvlist#1#2{% + \LTS@ensuremacro{#2}% + \def#2{}% + \def\tsv@do##1{\rightaddtocs#2{##1}}% + \tsv@@parse{#1}% +} +\robust@def*\despacextsvlist#1#2{% + \LTS@ensuremacro{#2}% + \def#2{}% + \def\tsv@do##1{% + \despacetsvlist{##1}\reserved@e + \cptexpandargonce{\rightaddtocs#2}\reserved@e + }% + \tsv@@parse{#1}% +} +\robust@def*\newletmanytocs#1#2{% + \def\csv@do##1{% + \newletcs##1#2% + }% + \csv@@parse[,]{#1}% +} +\robust@def*\ltsnewletcs{\LTS@testst\LTS@newletcs} +\new@def*\LTS@newletcs#1{% + \cpt@ifeql{\LTS@n@wletcs{#1}}{\LTS@n@wletcs{#1}}% +} +\new@def*\LTS@n@wletcs#1#2{% + \ifdefTF#1{% + \ifLTS@st + \ifdefTF#2{% + \let#1=#2% + \LTS@verboseinfo{Command '\string#1' redefined}% + }{% + \LTS@err{Command '\string#2' undefined}% + {I can't let '\string#1' to undefined '\string#2'.}% + }% + \else + \LTS@err{Command '\string#1' already defined}% + {I can't assign defined '\string#1' to '\string#2'.}% + \fi + }{% + \ifdefTF#2{\let#1=#2}{% + \LTS@err{Command '\string#2' undefined}% + {I can't let '\string#1' to undefined '\string#2'.}% + }% + }% +} +\new@def*\LTS@newletcsnerr#1#2{% + \begingroup + \def\LTS@tempa{\ifcpt@swa\string#2\else\noexpandcsn{#2}\fi}% + \LTS@err{% + Command '\LTS@tempa' is already defined + }{% + Command '\LTS@tempa' is defined: You may use the starred + \MsgBrk version of \noexpand#1 for this type of assignment. + }% + \endgroup +} +\new@def*\newletcstocs{% + \LTS@err{% + Command '\string\newletcstocs' is undefined + }{% + Command '\string\newletcstocs' is undefined. You can use + \string\newletcs,\MsgBrk but this can't assign control + sequence names.\MsgBrk Perhaps you meant to use + \string\newletcsntocs, or\MsgBrk\noexpand\newletcstocsn + or \string\newletcsntocsn. + }% +} +\robust@def*\newletcsntocs{\LTS@teststcl\LTS@newletcsntocs} +\new@def*\LTS@newletcsntocs#1#2{% + \is@global@or@relax + \ifLTS@st + \glob@lrel@x\letcsntocs{#1}#2% + \else + \ifcsndefFT{#1}% + {\glob@lrel@x\letcsntocs{#1}#2}% + {\cpt@swafalse\LTS@newletcsnerr\newletcsntocs{#1}}% + \fi +} +\robust@def*\newletcstocsn{\LTS@teststcl\LTS@newletcstocsn} +\new@def*\LTS@newletcstocsn#1#2{% + \LTS@ensurescape{#1}% + \is@global@or@relax + \def\reserved@e{\begingroup\expandafter\endgroup\expandafter + \glob@lrel@x\expandafter\let\expandafter#1\csname#2\endcsname}% + \ifLTS@st + \reserved@e + \else + \ifdefFT{#1}\reserved@e{% + \cpt@swatrue\LTS@newletcsnerr\newletcstocsn{#1}% + }% + \fi +} +\robust@def*\newletcsntocsn{\LTS@teststcl\LTS@newletcsntocsn} +\new@def*\LTS@newletcsntocsn#1#2{% + \is@global@or@relax + \def\reserved@e{\begingroup\expandafter\endgroup\expandafter + \glob@lrel@x\expandafter\let\csname#1\aftercsname\endcsname{#2}}% + \ifLTS@st + \reserved@e + \else + \ifcsndefFT{#1}\reserved@e{% + \cpt@swafalse\LTS@newletcsnerr\newletcsntocsn{#1}% + }% + \fi +} +\robust@def*\provideletcsntocs{\LTS@testcl\LTS@provideletcsntocs} +\new@def*\LTS@provideletcsntocs#1#2{% + \is@global@or@relax + \ifcsndefTF{#1}{}{\glob@lrel@x\letcsntocs{#1}#2}% +} +\robust@def*\provideletcstocsn{\LTS@testcl\LTS@provideletcstocsn} +\new@def*\LTS@provideletcstocsn#1#2{% + \is@global@or@relax + \ifdefTF#1{}{% + \begingroup\expandafter\endgroup\expandafter\glob@lrel@x + \expandafter\let\expandafter#1\csname#2\endcsname + }% +} +\robust@def*\provideletcsntocsn{\LTS@testcl\LTS@provideletcsntocsn} +\def\LTS@provideletcsntocsn#1#2{% + \is@global@or@relax + \ifcsndefTF{#1}{}{% + \begingroup\expandafter\endgroup\expandafter\glob@lrel@x + \expandafter\let\csname#1\aftercsname\endcsname{#2}% + }% +} +\new@def*\provideletcstocs{% + \LTS@err{'\string\provideletcstocs' is undefined}% + {Command '\string\provideletcstocs' is undefined. + Perhaps you meant \MsgBrk to use \string\provideletcsntocs, + or \noexpand\provideletcstocsn or \string\provideletcsntocsn.}% +} +\robust@def*\numberexpr{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numexpr{num}}}% +} +\robust@def*\dimensionexpr{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numexpr{dim}}}% +} +\robust@def*\rubberexpr{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numexpr{glue}}}% +} +\robust@def*\mrubberexpr{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numexpr{mu}}}% +} +\new@def*\LTS@numexpr#1#2{% + \if\detokenize{#2*}% + \LTS@err{Invalid suffix to '\string\dimensionexpr' or + '\string\numberexpr'}{Star (*) not valid as suffix to + '\string\dimensionexpr' and '\string\numberexpr'.}% + \fi + \is@global@or@relax + \ifboolTF{LTS@pl}{% + \cptexpandsecond{\LTS@n@mexpr{#1}}{\noexpandcsn{#2}}% + }{% + \LTS@n@mexpr{#1}{#2}% + }% +} +\new@def*\LTS@n@mexpr#1#2#3{% + \LTS@ensurescape@notempty{#2}{#3}% + \ifdefTF{#2}{% + \glob@lrel@x#2=\usename{#1expr}#3\relax + }{% + \begingroup + \LTS@getorderincsvlist[,](\nr){#1}{num,dim,glue,mu}% + \edef\LTS@tempa{\ifcase\nr\relax + count\or dimen\or skip\or muskip\fi}% + \usename{new\LTS@tempa}#2\relax + \endgroup + \glob@lrel@x#2=\usename{#1expr}#3\relax + }% +} +\robust@def*\numberdef{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numdef{num}}}% +} +\robust@def*\dimensiondef{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numdef{dim}}}% +} +\robust@def*\rubberdef{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numdef{glue}}}% +} +\robust@def*\mrubberdef{% + \LTS@checkoptprefix{\LTS@testplcl{\LTS@numdef{mu}}}% +} +\new@def*\LTS@numdef#1#2{% + \if\detokenize{*#2}% + \LTS@err{Invalid suffix to '\string\dimensiondef' or + '\string\numberdef'}{Star (*) not valid as suffix to + '\string\dimensiondef' and '\string\numberdef'.}% + \fi + \is@global@or@relax + \ifboolTF{LTS@pl}{% + \cptexpandsecond{\LTS@num@def{#1}}{\noexpandcsn{#2}}% + }{% + \LTS@num@def{#1}{#2}% + }% +} +\new@def*\LTS@num@def#1#2#3{% + \LTS@ensurescape@notempty{#2}{#3}% + \glob@lrel@x\edef#2{\the\usename{#1expr}#3\relax}% +} +\robust@def*\LTS@ensurescape@notempty#1#2{% + \LTS@ensurescape{#1}% + \ifblankFT{#2}{}{% + \LTS@err{Argument '\string#2' is empty}% + {Empty argument '\string#2' is invalid.\MsgBrk + I expected a nonempty argument here.}% + }% +} + +% #1: parser +% #2: string to find +% #3: list +% * -> both #2 and #3 are macros +% Call it with [] if there is no parser: +\robust@def*\ifexistinTF{\LTS@testst{\LTS@testopt\LTS@ifexistinTF,}} +\robust@def*\LTS@ifexistinTF[#1]#2\in#3{% + \begingroup + \edef\reserved@e{\ifboolTF{LTS@st}\cptoxdetok\detokenize{#2}}% + \despacecontent\reserved@e + \edef\reserved@f{\ifboolTF{LTS@st}\cptoxdetok\detokenize{#3}}% + \cpt@sttrue\cpt@csvnormalize[#1]\reserved@f + \edef\x{\detokenize{#1}}% + \cptexpandtwoargs{\endgroup\ifinsetTF} + {\x\reserved@e\x}{\x\reserved@f\x}% +} +\robust@def\ifpresentTF#1\in#2#{\ifinsetTF{#1}{#2}} +% This is more expensive but offers a variation on \ifexistinTF: +\robust@def*\ifpresentinTF{\LTS@testst{\LTS@testopt\LTS@ifpresentinTF,}} +\robust@def*\LTS@ifpresentinTF[#1]#2\in#3{% + \begingroup + \edef\reserved@e{\ifboolTF{LTS@st}\cptoxdetok\detokenize{#2}}% + \despacecontent\reserved@e + \edef\reserved@f{\ifboolTF{LTS@st}\cptoxdetok\detokenize{#3}}% + \cpt@choicefdfalse + \def\csv@do##1{% + \def\reserved@a{##1}% + \ifx\reserved@a\reserved@e\cpt@choicefdtrue\loopbreak\fi + }% + \csv@@parse*[;]\reserved@f + \ifboolTF{cpt@choicefd} + {\endgroup\@firstoftwo}{\endgroup\@secondoftwo}% +} + +% You can use \ifleadspaceTF or \iftrailspaceTF to test +% tokens beginning or ending with space. \ifendwithTF isn't +% suitable for this task: +\robust@def*\ifendwithTF#1#2{% + \ifblankTF{#2}\@secondoftwo{% + \begingroup + \edef\LTS@tempa{\s@expandarg\cpttrimspace{\detokenize{#1}}}% + \edef\LTS@tempb{\s@expandarg\cpttrimspace{\detokenize{#2}}}% + \let\endwith\relax + \cptexpandtwoargs\cpt@in{\LTS@tempb\endwith}{\LTS@tempa\endwith}% + \aftercsname\endgroup{@\ifcpt@in first\else second\fi oftwo}% + }% +} +\robust@def*\ifbeginwithTF#1#2{% + \ifblankTF{#2}\@secondoftwo{% + \begingroup + \edef\LTS@tempa{\s@expandarg\cpttrimspace{\detokenize{#1}}}% + \edef\LTS@tempb{\s@expandarg\cpttrimspace{\detokenize{#2}}}% + \let\begwith\relax + \cptexpandtwoargs\cpt@in{\begwith\LTS@tempb}{\begwith\LTS@tempa}% + \aftercsname\endgroup{@\ifcpt@in first\else second\fi oftwo}% + }% +} +\robust@def*\in@detok#1#2{% + \cptexpandtwoargs\cpt@in{\detokenize{#1}}{\detokenize{#2}}% +} +\newletcs\ifmemberTF\ifinsetTF +\newletcs\ifmemberFT\ifinsetFT +\robust@def*\ifbelongTF#1#2{% + \cptexpandtwoargs\ifinsetTF{\detokenize{#1}}{\detokenize{#2}}% +} +\robust@def*\ifbelongFT#1#2{\ifbelongTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def*\oifbelongTF#1#2{\cptexpandtwoargsonce\ifbelongTF{#1}{#2}} +\robust@def*\oifbelongFT#1#2{\cptexpandtwoargsonce\ifbelongFT{#1}{#2}} +\robust@def*\xifbelongTF#1#2{\cptexpandtwoargs\ifbelongTF{#1}{#2}} +\robust@def*\xifbelongFT#1#2{\cptexpandtwoargs\ifbelongFT{#1}{#2}} +\new@def*\ifdraftTF{\usename{LTS@\ifboolTF{LTS@draft}12of2}} +\new@def*\ifdraftFT{\usename{LTS@\ifdraftTF21of2}} +\new@def*\iffinalTF{\usename{LTS@\ifboolTF{LTS@final}12of2}} +\new@def*\iffinalFT{\usename{LTS@\iffinalTF21of2}} + +\new@def*\ValidCommandPrefixes{\relax\long\global\protected} +\robust@def*\newfunction{\begingroup\let\cmd0\LTS@newfunction@a} +\robust@def*\LTS@newfunction@a{% + \toks@{}% + \def\LTS@tempa##1{% + \def\cmd{##1}% + \LTS@ifnextchar.\LTS@newfunction@b{\LTS@newfunction@b..}% + }% + \ifcondTF\if\cmd0\fi{% + \LTS@starorlong\LTS@tempa + }{% + \LTS@tempa + }% +} +\robust@def*\LTS@newfunction@b.#1.{% + \def\checkprefix{% + \let\LTS@rsvda\prefix + \simpledeletetokens\LTS@rsvda\ValidCommandPrefixes + \ifcsemptyTF\LTS@rsvda{}{% + \LTS@err{Illegal prefixes '\expandcsonce\LTS@rsvda' + for command '\expandcsonce\cmd'}\@ehc + }% + }% + \ifsingletokenTF{#1}{% + \def\prefix{#1}\def\sentinel{}% + }{% + \def\prefix##1,##2##3\LTS@nil{% + \def\prefix{##1}\def\reserved{##2}% + \ifx\reserved\LTS@nnil + \def\sentinel{}% + \else + \if\detokenize{##2,}% + \def\sentinel{}% + \else + \def\sentinel{##2}% + \fi + \fi + }% + \prefix#1,{\LTS@nil}\LTS@nil + \checkprefix + }% + \expandafter\LTS@testopt\expandafter + {\expandafter\LTS@newfunction@c\cmd}0% +} +\robust@def*\LTS@newfunction@c#1[#2]{% + \ifnextisbrack{\LTS@newfunction@e#1[#2]}{\LTS@newfunction@d#1[#2]}% +} +\robust@def\LTS@newfunction@d#1[#2]#3{% + \ifcsdefinable#1{\LTS@newfunction@f#1\@ne{#2}{#3}}% +} +\robust@def\LTS@newfunction@e#1[#2][#3]#4{% + \ifcsdefinable#1{% + \cptexpandargonce{\cpt@in\protected}\prefix + \edef\LTS@tempa{% + \ifcpt@in\LTS@testopt\else\unexpanded{\@protected@testopt#1}\fi + \noexpandcsn{\string#1}\unexpanded{{#3}}% + }% + \cptexpandarg\toks@{% + \l@ngrel@x\prefix\def\noexpand#1{\expandcsonce\LTS@tempa}% + }% + \aftercsname\LTS@newfunction@f{\string#1}\tw@{#2}{#4}% + }% +} +\robust@def\LTS@newfunction@f#1#2#3{% + \ifx#2\tw@ + \gdef\@gtempa##11{[####1]}% + \else + \gletcs\@gtempa\@gobble + \fi + \expandafter\LTS@newfunction@g\expandafter{\number#3}#1% +} +\robust@def\LTS@newfunction@g#1#2{% + \defpass\reserved@a##1#1##2##{% + \edef\reserved@a{% + \endgroup\the\toks@\l@ngrel@x\prefix + \unexpanded{\expandafter\def\expandafter#2\@gtempa}% + }% + \s@expandarg\cptswap\sentinel{\reserved@a##1#1}% + }% + 0##1##2##3##4##5##6##7##8##9###1% +} +\robust@def*\renewfunction{% + \begingroup + \let\cmd1\LTS@starorlong\LTS@renewfunction +} +\def\LTS@renewfunction#1{% + \ifdefTF#1{% + \LTS@verboseinfo{Command '\string#1' redefined}% + }{% + \LTS@warn{Command '\string#1' was previously undefined, + \MsgBrk but now defined with \string\renewfunction}% + }% + \let\ifcsdefinable\rc@ifcsdefinable + \LTS@newfunction@a#1% +} +%% One-step expandable \l@ngrel@x: +\robust@def*\LTS@starorlong#1{% + \LTS@ifstar + {\def\l@ngrel@x{\relax}#1}{\def\l@ngrel@x{\long}#1}% +} +\robust@def*\LTS@starornone#1{% + \LTS@ifstar + {\let\l@ngrel@x\relax\def\st@rn@ne{*}#1}% + {\let\l@ngrel@x\long\def\st@rn@ne{}#1}% +} +\robust@def*\needcommand{\LTS@starornone\LTS@needcommand} +\new@def*\LTS@needcommand#1{% + \LTS@ensurescape{#1}% + \ifdefTF{#1}% + {\expandafter\CheckCommand\st@rn@ne}% + {\expandafter\newcommand\st@rn@ne}% + {#1}% +} +\robust@def*\ifinlistTF{% + \LTS@testst{\LTS@testopt\LTS@ifinlista{,}}% +} +\robust@def\LTS@ifinlista[#1]#2#3{% + \begingroup + \def\reserved@e##1#1#2#1##2\LTS@nil{\endgroup + \ifblankTF{##2}\@secondoftwo\@firstoftwo + }% + \ifboolTF{LTS@st}{% + \LTS@ensurescape{#3}% + \expandafter\reserved@e\expandafter + }{% + \reserved@e + }% + #1#3#1#2#1\LTS@nil +} +\new@def\oifinlistTF#1#2{% + \ifx#1,% + \LTS@err{Invalid first argument to \string\oifinlistTF}\@ehc + \fi + \cptexpandsecondargonce\ifinlistTF{#1}{#2}% +} +\new@def\xifinlistTF#1#2{% + \if\detokenize{#1,}% + \LTS@err{Invalid first argument '#1' to + \string\xifinlistTF}\@ehc + \fi + \cptexpandsecondarg\ifinlistTF{#1}{#2}% +} +\robust@def*\LTS@checkch{\LTS@teststpl\LTS@checkchoice} +\robust@def\ifinlistbTF#1#2#3#4{% + \if\LTS@lwc\LTS@sttrue\else\LTS@stfalse\fi + \LTS@pltrue + \LTS@checkchoice[\val\nr]{#1}{#2}{#3}{#4}% +} +\robust@def\ifinlistbFT#1#2#3#4{\ifinlistbTF{#1}{#2}{#4}{#3}} +\robust@def\oifinlistbTF#1#2#3#4{% + \if\LTS@lwc\LTS@sttrue\else\LTS@stfalse\fi + \LTS@pltrue + \cptexpandsecond{\LTS@checkchoice[\val\nr]}% + {{\expandcsonce{#1}}{\expandcsonce{#2}}}{#3}{#4}% +} +\robust@def\oifinlistbFT#1#2#3#4{\oifinlistbTF{#1}{#2}{#4}{#3}} +\robust@def\xifinlistbTF#1#2#3#4{% + \if\LTS@lwc\LTS@sttrue\else\LTS@stfalse\fi + \LTS@pltrue + \cptexpandsecond + {\LTS@checkchoice[\val\nr]}{{#1}{#2}}{#3}{#4}% +} +\robust@def\xifinlistbFT#1#2#3#4{% + \if\LTS@lwc\LTS@sttrue\else\LTS@stfalse\fi + \LTS@pltrue + \cptexpandsecond + {\LTS@checkchoice[\val\nr]}{{#1}{#2}}{#4}{#3}% +} +\new@def*\LTS@nochoice@handler#1#2{% + \LTS@err{% + Value '\expandcsonce{#1}' is not in list ^^J'\expandcsonce{#2}' + }{% + You have submitted an invalid value '\expandcsonce{#1}'\MsgBrk + for your key or test parameter. Value '\expandcsonce{#1}'\MsgBrk + is not in list:^^J'\expandcsonce{#2}'. + }% +} +\robust@def*\LTS@checkchoice{\LTS@testopt\LTS@ch@ckchoice{}} +\robust@def*\LTS@ch@ckchoice[#1]#2#3{% + \cpt@choicefdfalse + \begingroup + \ifLTS@st\lowercase{\fi + \ifblankTF{#1}{% + \def\LTS@tempa{\endgroup\LTS@ch@@@choice\LTS@nil{#2}{#3}}% + }{% + \def\LTS@tempa{\endgroup\LTS@ch@@kchoice#1\LTS@nil{#2}{#3}}% + }% + \ifLTS@st}\fi\LTS@tempa +} +\robust@def*\LTS@ch@@kchoice#1#2\LTS@nil#3#4{% + \ifblankTF{#2}% + {\LTS@ch@@@choice#1{#3}{#4}}{\LTS@ch@@@@hoice#1#2{#3}{#4}}% +} +\robust@def*\LTS@ch@@@choice#1#2#3{% + \begingroup + \def\LTS@tempc{#1}% + \ifx\LTS@tempc\LTS@nnil + % From \LTS@ch@ckchoice: + \emptify\LTS@tempc + \else + \def\LTS@tempc{\def#1{#2}}% + \fi + \cptexpandtwoargs\cpt@in{,\detokenize{#2},}{,\detokenize{#3},}% + \usename{cpt@choicefd\ifcpt@in true\else false\fi}% + \LTS@ch@@@@@oice\LTS@nochoice@handler{#2}{#3}% +} +\robust@def*\LTS@ch@@@@hoice#1#2#3#4{% + \def#1{#3}\def#2{-1}% + \begingroup + \LTS@scantoksa#1% + \cpt@cnta\z@pt + \def\LTS@tempc{}% + \def\csv@do##1{% + \def\LTS@tempb{##1}% + \LTS@scantoksa\LTS@tempb + \ifx#1\LTS@tempb + \edef\LTS@tempc{% + \def\noexpand#1{\unexpanded{##1}}% + \def\noexpand#2{\the\cpt@cnta}% + }% + \cpt@choicefdtrue\loopbreak + \fi + \advance\cpt@cnta\@ne + }% + \csv@@parse[,]{#4}% + \LTS@ch@@@@@oice\LTS@nochoice@handler{#3}{#4}% +} +\robust@def\LTS@ch@@@@@oice#1#2#3{% + \NoConvertInputToLowercase + \ifboolTF{cpt@choicefd}{% + \ifboolTF{LTS@pl}{% + \rightaddtocs\LTS@tempc\@firstoftwo + }{% + \rightaddtocs\LTS@tempc\@firstofone + }% + }{% + \ifboolTF{LTS@pl}{% + \rightaddtocs\LTS@tempc\@secondoftwo + }{% + \rightaddtocs\LTS@tempc{#1{#2}{#3}\@gobbleone}% + }% + }% + \expandafter\endgroup\LTS@tempc +} +\robust@def*\LTS@notpresent@handler#1#2{% + \LTS@verboseinfo{None of the tokens '\detokenize{#1}' + is found in '\detokenize{#2}'}% +} +\robust@def*\lwccontent#1{% + \ltsifmacroTF{#1}{% + \expandafter\if\expandafter\LTS@lwc\expandafter + \lowercase\expandafter{\expandafter\fi\expandafter\def + \expandafter#1\expandafter{#1}\if\LTS@lwc}\fi + }{% + \cpt@notcserr{#1}% + }% +} + +% #1: parser; +% #2: macro to hold order; +% #3: nomination/choice; +% #4: csv list; +% * -> both #3 and #4 are macros: +\robust@def*\getorderincsvlist{% + \LTS@testst{\LTS@testopt\LTS@getorderincsvlist{,}}% +} +\robust@def*\LTS@getorderincsvlist[#1]{% + \LTS@testpnopt{\LTS@g@torderincsvlist#1}\LTS@order +} +\robust@def*\LTS@g@torderincsvlist#1(#2)#3#4{% + \def#2{-1}% + \begingroup + \ifboolTF{LTS@st}{% + \edef\LTS@tempa{\simpleexpandarg\cpttrimspaces{#3}}% + \let\LTS@tempb=#4% + }{% + \edef\LTS@tempa{\cpttrimspaces{#3}} + \edef\LTS@tempb{\unexpanded{#4}}% + }% + \lwccontent\LTS@tempa\lwccontent\LTS@tempb + \edef\LTS@tempa{\cptoxdetok\LTS@tempa}% + \edef\LTS@tempb{\cptoxdetok\LTS@tempb}% + \cpt@cnta\z@pt\def\LTS@tempc{}% + \def\csv@do##1{% + \def\LTS@tempb{##1}% + \ifx\LTS@tempb\LTS@tempa + \edef\LTS@tempc{\def\noexpand#2{\the\cpt@cnta}}% + \loopbreak + \fi + \advance\cpt@cnta\@ne + }% + \csv@@parse*[,]\LTS@tempb + \NoConvertInputToLowercase + \expandafter\endgroup\LTS@tempc +} + +% #1: sublist (to check if one member of #1 is in #2); +% #2: main comma-separated list; +\robust@def*\ifoneincommalistTF#1#2{% + \if\LTS@lwc\LTS@sttrue\else\LTS@stfalse\fi + \LTS@pltrue + \LTS@ch@ckpresence[\val\nr]{#1}{#2}% +} + +% #1: bin (eg, \val\nr); +% #2: sublist (to check if one member of #2 is in #3); +% #3: main comma-separated list; +% For comma-separated list only: +\robust@def*\LTS@checkpr{\LTS@teststpl\LTS@checkpresence} +\robust@def*\LTS@checkpresence{\LTS@testopt\LTS@ch@ckpresence{}} +\new@def*\LTS@ch@ckpresence[#1]#2#3{% + \cpt@choicefdfalse + \begingroup + \ifLTS@st\lowercase{\fi + \ifblankTF{#1}{% + \def\LTS@tempa{\endgroup\LTS@ch@@@presence\LTS@nil{#2}{#3}}% + }{% + \def\LTS@tempa{\endgroup\LTS@ch@@kpresence#1\LTS@nil{#2}{#3}}% + }% + \ifLTS@st}\fi\LTS@tempa +} +\new@def*\LTS@ch@@kpresence#1#2\LTS@nil#3#4{% + \ifblankTF{#2}% + {\LTS@ch@@@presence#1{#3}{#4}}% + {\LTS@ch@@@@resence#1#2{#3}{#4}}% +} +\new@def*\LTS@ch@@@presence#1#2#3{% + \begingroup + \def\LTS@tempc{#1}% + \ifxTF\LTS@nnil\LTS@tempc{% + \def\LTS@tempc{}% + }{% + \def\LTS@tempc{\def#1{#3}}% + }% + \edef\LTS@tempa{\detokenize{#3}}% + \cpt@sttrue\cpt@csvnormalize[,]\LTS@tempa + % Leave \csv@@parse here! + \def\csv@do##1{% + \xifinsetFT{,\detokenize{##1},}{,\LTS@tempa,}{}{% + \edef\LTS@tempc{\def\noexpand#1{\unexpanded{##1}}}% + \cpt@choicefdtrue\loopbreak + }% + }% + \csv@@parse[,]{#2}% + \LTS@ch@@@@@oice\LTS@notpresent@handler{#2}{#3}% +} +\new@def*\LTS@ch@@@@resence#1#2#3#4{% + \def#1{}\def#2{-1}% + \begingroup + \cpt@cnta\z@pt\def\LTS@tempc{}% + \def\csv@do##1{% + \xifinsetFT{,\detokenize{##1},}{,\detokenize{#4},}{}{% + \edef\LTS@tempc{% + \def\noexpand#1{\unexpanded{##1}}% + \def\noexpand#2{\the\cpt@cnta}% + }% + \cpt@choicefdtrue\loopbreak + }% + \advance\cpt@cnta\@ne + }% + \csv@@parse[,]{#3}% + \LTS@ch@@@@@oice\LTS@notpresent@handler{#3}{#4}% +} + +% \ifmanyincsvlistTF[parser](no.){sublist}{mainlist} +% Check if the no. of elements of parser-separated list +% '#3' found in #4 is equal or greater than '#2'. #4 +% is the main list. If the test is true, \itemspresent returns +% all the elements found and \noofitems returns the number +% of elements found: +\ifcsdefinable\itemspresent\relax +\ifcsdefinable\noofitems\relax +\robust@def*\ifmanyincsvlistTF{% + \LTS@testopt\LTS@ifmanyincsvlistTF{,}% +} +\robust@def*\LTS@ifmanyincsvlistTF[#1]{% + \LTS@testpnopt{\LTS@ifm@nyincsvlistTF#1}{1}% +} +\robust@def*\LTS@ifm@nyincsvlistTF#1(#2)#3#4{% + \begingroup + \if\LTS@lwc\lowercase{\fi + \edef\LTS@tempa{\unexpanded{#3}}% + \edef\LTS@tempb{\unexpanded{#4}}% + \if\LTS@lwc}\fi + \cpt@sttrue\cpt@csvnormalize[#1]\LTS@tempb + \def\LTS@tempc{}\cpt@cnta\z@pt + \def\csv@do##1{% + \edef\x{\detokenize{#1}}% + \xifinsetFT{\detokenize{#1##1#1}}{\x\cptoxdetok\LTS@tempb\x}{% + \edef\LTS@tempc{\csliststack,\LTS@tempc\unexpanded{##1}}% + \advance\cpt@cnta\@ne + \ifnum\cpt@cnta>\numexpr#2-1\relax\loopbreak\fi + }% + }% + \csv@@parse*[#1]\LTS@tempa + \ifnum\cpt@cnta>\numexpr#2-1\relax + \gletcs\itemspresent\LTS@tempc + \xdef\noofitems{\the\cpt@cnta}% + \else + \gdef\itemspresent{}\gdef\noofitems{-1}% + \fi + \NoConvertInputToLowercase + \aftercsname\endgroup + {LTS@\ifnumcmpTF\cpt@cnta>\numexpr#2-1{1}2of2}% +} + +% \ifmanyintsvlistTF(no){sublist}{mainlist} +% Check if the no. of elements of tsv list #2 +% found in #3 is equal or greater than '#1'. #3 +% is the main list. If the test is true, \itemspresent returns +% all the elements found and \noofitems returns the number +% of elements found: +\robust@def*\ifmanyintsvlistTF{% + \LTS@testpnopt\LTS@ifmanyintsvlistTF{1}% +} +\robust@def*\LTS@ifmanyintsvlistTF(#1)#2#3{% + \begingroup + \if\LTS@lwc\lowercase{\fi + \edef\LTS@tempa{\unexpanded{#2}}% + \edef\LTS@tempb{\unexpanded{#3}}% + \if\LTS@lwc}\fi + \def\LTS@tempc{}\cpt@cnta\z@pt + \def\tsv@do##1{% + \xifinsetFT{\detokenize{##1}}{\cptoxdetok\LTS@tempb}{}{% + \edef\LTS@tempc{\csliststack,\LTS@tempc\unexpanded{##1}}% + \advance\cpt@cnta\@ne + \ifnum\cpt@cnta>\numexpr#1-1\relax\loopbreak\fi + }% + }% + \tsv@@parse*\LTS@tempa + \ifnum\cpt@cnta>\numexpr#1-1\relax + \gletcs\itemspresent\LTS@tempc + \xdef\noofitems{\the\cpt@cnta}% + \else + \gdef\itemspresent{}\gdef\noofitems{-1}% + \fi + \NoConvertInputToLowercase + \aftercsname\endgroup + {LTS@\ifnumcmpTF\cpt@cnta>\numexpr#1-1{1}2of2}% +} +\robust@def*\LTS@undeftogerr#1{% + \LTS@err{Toggle '#1' undefined}% + {You need to first define toggle '#1' before use.}% +} +\providecommand*\newtog[1]{\cpt@swatrue\LTS@testopt{\LTS@newtog{#1}}{false}} +\robust@def*\deftog#1{\cpt@swafalse\LTS@testopt{\LTS@newtog{#1}}{false}} +\new@def*\LTS@newtog#1[#2]{% + \begingroup + \ifinsetFT{,}{#1}{}{% + \edef\x{\ifcpt@swa'\string\newtog'\else'\string\deftog'\fi}% + \edef\y{\ifcpt@swa'\string\NewTogs'\else'\string\DefTogs'\fi}% + \LTS@err{Command \x doesn't accept list}{% + Please submit only one toggle to \x at a time. + \MsgBrk You can use \y to define a set of togs. + }% + }% + \endgroup + \LTS@ensurenoscape{#1}% + \ifboolTF{cpt@swa}{% + \ifcsndefFT{cpt@tog@#1}{}{% + \LTS@err{Toggle '#1' already defined}% + {Please provide a new toggle or use '\string\deftog'.}% + }% + \LTS@getboolstate\newtog{#2}% + }{% + \ifcsndefFT{cpt@tog@#1}{}{% + \LTS@verbosewarn{Toggle '#1' redefined}% + }% + \LTS@getboolstate\deftog{#2}% + }% + \letcsntocsn{cpt@tog@#1}{@\cptstrcmp + {\LTS@boolval}{true}{first}{second}oftwo}% +} +\providecommand*\providetog[1]{% + \ifcsndefTF{cpt@tog@#1}{% + \LTS@verboseinfo{Toggle '#1' already defined.\MsgBrk + Not redefined}% + }{% + \letcsntocs{cpt@tog@#1}\@secondoftwo + }% +} +\providecommand*\requiretog[1]{% + \aftercsname\needcommand{cpt@tog@#1}[2]{##2}% +} +\newtog{pdf}[false] +\newletcs\ifpdfTF\@secondoftwo +\newletcs\ifpdfFT\@firstoftwo +\ifdefTF\pdfoutput{% + \ifnumcmpTF\pdfoutput<\@ne{}{% + \settogtrue{pdf}% + \let\ifpdfTF\@firstoftwo + \let\ifpdfFT\@secondoftwo + }% +}{} +\new@def*\savecs#1{% + \LTS@ensurescape{#1}% + \ifcsndefTF{saved\cptgobblescape#1}{% + \LTS@err{\noexpand#1 already saved. You've to restore + \MsgBrk it or undefine '\noexpandcsn{saved\cptgobblescape#1}' + before\MsgBrk you can save \noexpand#1 again}\@ehc + }{% + \ifdefTF#1{% + \letcsntocs{saved\cptgobblescape#1}#1% + \ifcsndefFT{\string#1}{}{% + \letcsntocsn{@saved\cptgobblescape#1}{\string#1}% + }% + \ifcsndefFT{\cptgobblescape#1\@space}{}{% + \letcsntocsn{@@saved\cptgobblescape#1}% + {\cptgobblescape#1\@space}% + }% + \ifcsndefFT{\string#1\@space}{}{% + \letcsntocsn{@@@saved\cptgobblescape#1}{\string#1\@space}% + }% + }{% + \LTS@err{Undefined '\string#1' couldn't be saved\on@line}% + {You can't restore undefined commands. So why save\MsgBrk + undefined '\string#1' here?}% + }% + }% +} +\new@def*\restorecs#1{% + \LTS@ensurescape{#1}% + \ifcsndefTF{saved\cptgobblescape#1}{% + \letcstocsn#1{saved\cptgobblescape#1}% + \gundefcsn{saved\cptgobblescape#1}% + \ifcsndefFT{@saved\cptgobblescape#1}{}{% + \letcsntocsn{\string#1}{@saved\cptgobblescape#1}% + \gundefcsn{@saved\cptgobblescape#1}% + }% + \ifcsndefFT{@@saved\cptgobblescape#1}{}{% + \letcsntocsn{\cptgobblescape#1\@space}% + {@@saved\cptgobblescape#1}% + \gundefcsn{@@saved\cptgobblescape#1}% + }% + \ifcsndefFT{@@@saved\cptgobblescape#1}{}{% + \letcsntocsn{\string#1\@space}{@@@saved\cptgobblescape#1}% + \gundefcsn{@@@saved\cptgobblescape#1}% + }% + }{% + \LTS@err{No saved version of '\string#1' is available:\MsgBrk + '\string#1' couldn't be restored\on@line + }{% + Unsaved '\string#1' can't be restored.\MsgBrk + Note that each call to \noexpand\restorecs + undefines the saved command. + }% + }% +} +\providecommand*\input@path{} +\robust@def*\InputFileOnce{% + \savecs\input@path + \LTS@testst{\LTS@testpl{\LTS@testopt\LTS@inputfileonce{.}}}% +} +\new@def*\LTS@inputfileonce[#1]#2{% + \ifblankTF{#1}{}{\grightaddtocs\input@path{{#1/}}}% + \ifboolTF{LTS@st}{% + % Don't check whether the file has already been read: + \LTS@inp@tfileonce{#2}% + }{% + \ifcsndefTF{#2@LTS@read}{% + \ifLTS@verbose + \LTS@info{File '#2' already read:\MsgBrk + File '#2' wasn't read again}% + \fi + }{% + \LTS@inp@tfileonce{#2}% + }% + }% +} +\def\LTS@inp@tfileonce#1{% + \def\reserved@a##1##2{% + \IfFileExists{#1}{##1\@filef@und##2}% + }% + \ifboolTF{LTS@pl}{% + \reserved@a\include + }{% + \reserved@a\@@input + }{% + \letcsntocs{#1@LTS@read}\relax + \restorecs\input@path + }{% + \typein[\@gtempa]{^^J! File '\string#1' does not exist. + ^^JEnter filename or 'x' and <return> to continue.}% + \def\reserved@a{x}% + \ifxTF\@gtempa\reserved@a{% + \restorecs\input@path + }{% + \cptexpandarg{\LTS@inputfileonce[]}\@gtempa + }% + }% +} +\new@def*\xp@counttokens#1{% + \long\def\xp@counttokens##1{% + \the\numexpr\expandafter + \LTS@xpcounttokens##1#1\cpt@nnil\cpt@nnil\relax + }% +} +\xp@counttokens{ } +\new@def\LTS@xpcounttokens#1{% + \expandafter\ifxTF\cpt@car#1\car@nil + \cpt@nnil{0\cpt@removetonnil}{1+\LTS@xpcounttokens}% +} +\robust@def*\countalltokens#1{% + \def\countalltokens##1{% + \let\nr\m@one + \def\@counttokens{\futurelet\@let@token\LTS@countalltokens}% + \expandafter\@counttokens##1#1\cpt@nnil + }% +} +\countalltokens{ } +\robust@def*\LTS@countalltokens{% + \ifxTF\@let@token\cpt@nnil\cpt@removetonnil{% + \edef\nr{\the\numexpr\nr+1}% + \afterassignment\@counttokens + \let\@let@token= % + }% +} +\robust@def*\counttokens{\LTS@testst\LTS@counttokens} +\robust@def\LTS@counttokens#1{% + \begingroup + \def\nr{0}\def\emp{0}\def\spo{0}% + \def\siso@do##1{% + \ifx\@empty##1\@empty + \edef\emp{\the\numexpr\emp+1}% + \edef\nr{\the\numexpr\nr+1}% + \else + \ifx##1\@sptoken + \edef\spo{\the\numexpr\spo+1}% + \edef\nr{\the\numexpr\nr+1}% + \else + \edef\nr{\the\numexpr\nr+1}% + \fi + \fi + }% + \ifboolTF{LTS@st}{% + \expandafter\siso@@loop\expandafter{#1}% + }{% + \siso@@loop{#1}% + }% + \cptpassexpanded{% + \endgroup + \def\noexpand\nonempty{\nr}% + \def\noexpand\nr{{\nr}{\emp}{\spo}}% + }% +} +\newcommand*\ltscountargs[1]{% + \protected\def\ltscountargs##1{% + \begingroup + \@tempcnta\z@pt\@tempcntb\z@pt\cpt@cnta\z@pt + \def\end@countargs{\end@countargs}% + \def\LTS@countargs@a{\futurelet\next\LTS@countargs@c}% + \def\LTS@countargs@b####1{\LTS@countargs@a}% + \expandafter\LTS@countargs@a##1#1\end@countargs + }% +} +\ltscountargs{ } +\def\LTS@countargs@c{% + \ifxTF\next\end@countargs{% + \edef\next{% + \endgroup + \edef\noexpand\argcount{\the\numexpr\the\@tempcnta-1}% + \edef\noexpand\spacecount{\the\numexpr\the\@tempcntb-1}% + \edef\noexpand\nonspacecount{\the\cpt@cnta}% + }% + \expandafter\next\@gobble + }{% + \advance\@tempcnta\@ne + \ifxTF\next\@sptoken{% + \advance\@tempcntb\@ne + \afterassignment\LTS@countargs@a\let\next= % + }{% + \advance\cpt@cnta\@ne + \LTS@countargs@b + }% + }% +} +\robust@def*\macronizetokens{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \LTS@testopt\LTS@macronize{}% +} +\robust@def*\LTS@macronize[#1]#2#3{% + % Check for catcode-10 tokens while keeping '#' as other: + \toks0{#3}% + \scantokens{\toks1{#3}}% + \xifstrcmpTF{\the\toks0}{\the\toks1}{}{% + \LTS@err{I can't macronize unscannable tokens: + ^^J^^J||\detokenize{#3}||}\@ehc + }% + \endgroup + \begingroup + \LTS@twohashcheck{#3}{}{% + \LTS@err{Illegal nested parameters in: + ^^J^^J\detokenize{#3}}\@ehc + }% + \edef\reserved@e{\detokenize{#3}}% + \chardef\nr@b\z@pt + \xifinsetFT\LTS@hashchar\reserved@e{}{% + \def\nr@a{1}% + \cptwhilenum\nr@a<10\do{% + \cptexpandtwoargs\cpt@in{\LTS@hashchar\nr@a}{\reserved@e}% + \ifcpt@in\let\nr@b\nr@a\fi + \pushnumber\nr@a + }% + \ifnum\nr@b>\z@pt + \emptify#2\def\nr@a{1}% + \cptwhilenum\nr@a<\numexpr\nr@b+1\do{% + \edef#2{\expandcsonce#2\LTS@hashchar\nr@a}% + \pushnumber\nr@a + }% + \fi + }% + \edef#2{#1\def\string#2#2{\reserved@e}}% + \LTS@scantoksd\endgroup#2% +} +\robust@def*\ifmeaningTF#1#2{% + \begingroup + \ifdefFT{#1}{% + \endgroup\@secondoftwo + }{% + \edef\LTS@tempa{\realmeaning{#1}}% + \edef\LTS@tempb{\detokenize{#2}}% + \aftercsname\endgroup{LTS@\ifxTF\LTS@tempa\LTS@tempb12of2}% + }% +} +\robust@def*\ifactivecharTF#1{% + \begingroup + \ltsifmacroTF{#1}{% + \edef\LTS@tempa{\string#1}% + \def\LTS@tempb{#1}% + \edef\LTS@tempb{\realmeaning\LTS@tempb}% + \aftercsname\aftergroup{LTS@\ifxTF\LTS@tempa\LTS@tempb12of2}% + }{% + \aftergroup\@secondoftwo + }% + \endgroup +} +\robust@def*\ltsifmacroTF#1{% + \begingroup + \edef\LTS@tempa##1{\def##1####1\detokenize{macro}:####2&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}21of2}% + }% + \edef\LTS@tempb##1{##1\detokenize{macro}:&}% + \LTS@tempb{\expandafter\LTS@tempa\meaning#1}% + \endgroup +} +\robust@def*\ltsifmacroFT#1{\ltsifmacroTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\ifparamacroTF#1{% + \begingroup + \edef\LTS@tempa##1{\def##1####1\detokenize{macro}:####2->####3&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}21of2}% + }% + \edef\LTS@tempb##1{##1\detokenize{macro}:->&}% + \LTS@tempb{\expandafter\LTS@tempa\meaning#1}% + \endgroup +} +\robust@def*\ifparamacroFT#1{\ifparamacroTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\ifcsnparamacroTF{\aftercsname\ifparamacroTF} +\robust@def*\ifprefmacroTF#1{% + \begingroup + \ifmacroFT{#1}{% + \aftergroup\@secondoftwo + }{% + \edef\LTS@tempa##1{\def##1####1\detokenize{macro}:####2&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##1}21of2}% + }% + \edef\LTS@tempb##1{##1\detokenize{macro}:&}% + \LTS@tempb{\expandafter\LTS@tempa\meaning#1}% + }% + \endgroup +} +\robust@def*\ifprefmacroFT#1{\ifprefmacroTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\ifprimitiveTF#1{% + \begingroup + \ltsifmacroTF{#1}{% + \endgroup\@secondoftwo + }{% + \def\LTS@tempa##1##2&{% + \aftercsname\endgroup{LTS@\if##1\@backslashchar1\else2\fi of2}% + }% + \expandafter\LTS@tempa\meaning#1&% + }% +} +\robust@def*\ifprimitiveFT#1{\ifprimitiveTF{#1}\@secondoftwo\@firstoftwo} +\robust@def\ifpatternTF#1#2{% + \begingroup + \edef\LTS@tempa##1{\def##1####1\detokenize{#2}####2&}% + \LTS@tempa\LTS@tempa{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}21of2}% + }% + \edef\LTS@tempb##1{##1\detokenize{#2}&}% + \LTS@tempb{\expandafter\LTS@tempa\meaning#1}% + \endgroup +} +\robust@def*\ifpatternFT#1#2{\ifpatternTF{#1}{#2}\@secondoftwo\@firstoftwo} +\robust@def*\ifnopattern#1\in#2{\ifpatternFT{#2}{#1}} +\robust@def*\ifscannableTF#1{% + % Fails if the content of #1 is already detokenized. + \begingroup + \edef\LTS@rsvda##1{% + \def##1####1\detokenize{macro}:####2->####3&{% + ####1\def\string\LTS@rsvda####2{####3}% + }% + \edef##1{##1\meaning#1&}% + }% + \LTS@rsvda\LTS@rsvda + \makeatletter\everyeof{\noexpand}\endlinechar\m@one + \scantokens\expandafter{\LTS@rsvda}\relax + \aftercsname\endgroup{LTS@\expandafter\ifxTF\cpt@car#1\car@nil + \LTS@rsvda12of2}% +} +\robust@def*\ifscannableFT#1{\ifscannableTF{#1}\@secondoftwo\@firstoftwo} +\robust@def*\delimitmacro#1#2{% + \ifsingletokenTF{#2}{}{% + \LTS@err{Delimiter '\detokenize{#2}' is more than + one token}\@ehc + }% + \ifscannableTF#1{% + \begingroup + \edef\LTS@tempa##1{% + \def##1####1\detokenize{macro:}####2->####3&{% + ####1\def\string#1####2\string#2{####3}% + }% + \edef##1{##1\meaning#1&}% + }% + \LTS@tempa\LTS@tempa + \LTS@scantoksd\endgroup\LTS@tempa + }{% + \LTS@err{Your \noexpand#1 isn't scannable}{% + Sorry, I can't delimit the last parameter of your\MsgBrk + command \noexpand#1: it isn't scannable. + }% + }% +} +\robust@def*\LTS@stepdownhash{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \LTS@st@pdownhash +} +\robust@def*\LTS@st@pdownhash#1#2{% + \xifinsetTF{\detokenize{##}}{\detokenize{#1}}{% + \edef\LTS@rsvda##1{##1\detokenize{#1##}&}% + \edef\LTS@rsvdb##1{\def##1####1\detokenize{##}####2&}% + \LTS@rsvdb\LTS@rsvdb{% + \ifblankTF{##2}{% + \toks@\expandafter{\the\toks@##1}% + }{% + \cptpassexpanded{\toks@{\the\toks@##1\LTS@hashchar}}% + \LTS@rsvdb##2&% + }% + }% + \LTS@rsvda{\toks@{}\LTS@rsvdb}% + \edef#2{\the\toks@}% + }{% + \edef#2{\detokenize{#1}}% + }% + \postgroupdef#2\endgroup +} +\robust@def*\LTS@stepuphash{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \LTS@st@puphash +} +\robust@def*\LTS@st@puphash#1#2{% + \xifinsetTF{\LTS@hashchar}{\detokenize{#1}}{% + \edef\LTS@rsvda##1{##1\detokenize{#1}\LTS@hashchar&}% + \edef\LTS@rsvdb##1{\def##1####1\LTS@hashchar####2&}% + \LTS@rsvdb\LTS@rsvdb{% + \ifblankTF{##2}{% + \toks@\expandafter{\the\toks@##1}% + }{% + \cptpassexpanded{\toks@{\the\toks@##1\LTS@hashchar\LTS@hashchar}}% + \LTS@rsvdb##2&% + }% + }% + \LTS@rsvda{\toks@{}\LTS@rsvdb}% + \edef#2{\the\toks@}% + }{% + \edef#2{\detokenize{#1}}% + }% + \postgroupdef#2\endgroup +} + +\robust@def*\LTS@onehashcheck#1{% + \begingroup + \edef\LTS@rsvda##1{\def##1####1\LTS@hashchar####2&}% + \LTS@rsvda\LTS@rsvda{% + \aftercsname\aftergroup{LTS@\ifblankTF{##2}12of2}}% + \edef\LTS@rsvdb##1{##1\detokenize{#1}\LTS@hashchar&}% + \LTS@rsvdb\LTS@rsvda + \endgroup +} +\robust@def*\LTS@twohashcheck#1{% + \begingroup + \edef\LTS@rsvda##1{\def##1####1\detokenize{##}####2&}% + \LTS@rsvda\LTS@rsvda{% + \aftercsname\endgroup{LTS@\ifblankTF{##2}12of2}% + }% + \edef\LTS@rsvdb##1{##1\detokenize{#1}\detokenize{##}&}% + \LTS@rsvdb\LTS@rsvda +} +\robust@def*\robustifycs{\LTS@testopt\LTS@robustifycs{}} +\robust@def*\LTS@robustifycs[#1]#2{% + \ifdefFT{#2}{% + \cpt@notdeferr{#2}% + }{% + \ltsifmacroTF{#2}{% + \ifetexprotectedTF{#2}{% + \LTS@verboseinfo + {Protected command '\string#2' not re-protected}% + }{% + \ifltxprotectTF{#2}{% + \letcstocsn\LTS@rsvda{\cptgobblescape#2\@space}% + \cpt@swatrue + }{% + \let\LTS@rsvda#2\cpt@swafalse + }% + \ifparamacroTF\LTS@rsvda{% + \ifscannableTF\LTS@rsvda{% + \begingroup + \edef\LTS@rsvdb##1{% + \def##1####1\detokenize{macro}:####2->####3&{% + #1\protected####1\def\string\LTS@rsvda####2{####3}% + }% + \edef##1{##1\meaning\LTS@rsvda&}% + }% + \LTS@rsvdb\LTS@rsvdb + \LTS@scantoksd\endgroup\LTS@rsvdb + \let#2\LTS@rsvda + }{% + \LTS@err{Command '\string#2' can't be made robust}% + {Command '\string#2' isn't retokenizable.}% + \cpt@swafalse + }% + }{% + \protected#1\edef#2{\expandcsonce\LTS@rsvda}% + }% + \ifcpt@swa + \ifcsndefTF{\string#2\@space}{}% + {\undefcsn{\cptgobblescape#2\@space}}% + \fi + }% + }{% + \LTS@err{Command '\string#2' isn't a macro}% + {Command '\string#2' can't be made robust.}% + }% + }% +} +\robust@def*\robustifycsn{\LTS@testopt\LTS@robustifycsn{}} +\robust@def*\LTS@robustifycsn[#1]#2{% + \cptexpandarg{\robustifycs[#1]}{\noexpandcsn{#2}}% +} +\robust@def*\robustifycsset{\LTS@testopt\LTS@robustifycsset{}} +\robust@def*\LTS@robustifycsset[#1]#2{% + \def\csv@do##1{% + \LTS@ensuremacro{##1}% + \robustifycs[#1]{##1}% + }% + \csv@@parse[,]{#2}% +} +\new@def*\LTS@hookfail#1#2{% + \LTS@warn{Hooking to command '\string#1' failed:\MsgBrk#2}% +} +% [<prefix>]{<cmd1>}{<cmd2>}{<success>}{<failure>} +\robust@def*\apptoparamcs{% + \long\def\setarg##1##2{##1##2}% + \begingroup\@makeother{\#}\LTS@hooktoparamcs +} +\robust@def*\preptoparamcs{% + \let\setarg\cptswap + \begingroup\@makeother{\#}\LTS@hooktoparamcs +} +\newcommand\LTS@hooktoparamcs[3][]{% + \endgroup + \ifdefFT{#2}{% + \LTS@hookfail{#2}{Command isn't defined or is relaxed}% + \@secondoftwo + }{% + \ltsifmacroTF{#2}{% + \ifparamacroTF{#2}{% + \ifscannableTF{#2}{% + \LTS@twohashcheck{#3}{% + \ifblankTF{#1}{% + \LTS@h@oktoparamcs{#2}{#3}% + }{% + \LTS@h@oktoparamcs[#1]{#2}{#3}% + }% + \@firstoftwo + }{% + \LTS@hookfail{#2}{Nested commands or parameters}% + \@secondoftwo + }% + }{% + \LTS@hookfail{#2}{Macro can't be retokenized\MsgBrk + safely after patching}% + \@secondoftwo + }% + }{% + \LTS@onehashcheck{#3}{% + \LTS@verboseinfo{Macro '\string#2' patched successfully}% + \ifetexprotectedTF{#2}\protected\relax + #1\edef#2{\setarg{\expandcsonce#2}{\unexpanded{#3}}}% + \LTS@verboseinfo{Macro '\string#2' patched successfully}% + \@firstoftwo + }{% + \LTS@hookfail{#2}{Command is a parameterless macro + \MsgBrk but you're hooking with a parametered macro}% + \@secondoftwo + }% + }% + }{% + \LTS@hookfail{#2}{Command isn't a macro}% + \@secondoftwo + }% + }% +} +\newcommand\LTS@h@oktoparamcs[3][]{% + \begingroup + \edef\LTS@tempa##1{% + \def##1####1\detokenize{macro}:####2->####3&{% + #1####1\def\string#2####2{\setarg{####3}{\detokenize{#3}}}% + }% + \edef##1{##1\meaning#2&}% + }% + \LTS@tempa\LTS@tempa + \LTS@scantoksd\endgroup\LTS@tempa +} +\robust@def*\TracingPatchesOn{\let\LTS@tracepatches\cptswtrue} +\robust@def*\TracingPatchesOff{\let\LTS@tracepatches\cptswfalse} +% If 'patchability' has been established: +\robust@def*\simplecmdpatch{% + \begingroup + \@makeother{\#}% + \endlinechar\m@one + \LTS@testopt\LTS@simplecmdpatch{####1}% +} +\new@def*\LTS@simplecmdpatch[#1]#2#3#4{% + \if\LTS@tracepatches + \typeout{^^J** Debugging patches: command '\string#2'}% + \fi + \endgroup + \begingroup + \edef\LTS@tempa##1##2{% + \def##1####1\detokenize{macro:}####2->####3&{% + #1\def\string#2####2{##2####3&}% + }% + \def##2####1\detokenize{#3}####2&{####1\detokenize{#4}####2}% + \edef##1{##1\meaning#2&}% + }% + \LTS@tempa\LTS@tempa\LTS@tempb + \catcode`\#=6\relax\makeatletter + \LTS@scantoksd\endgroup\LTS@tempa +} + +\robust@def*\patchcs{% + \LTS@ifstar\LTS@patchcs@b\LTS@patchcs@a +} +\robust@def*\LTS@patchcs@a{% + \let\LTS@hashcheckorno\LTS@twohashcheck + \begingroup + \@makeother{\#}\endlinechar\m@one + % If \LTS@testopt uses a different definition of + % \@ifnextchar, the number of hash characters here + % would have to change; it will most likely become 8: + \LTS@testopt\LTS@patchcs{####1}% +} +\robust@def*\LTS@patchcs@b{% + \if\stricthashcheck + \LTS@err{Patching failed: you can't use the star (*) + \MsgBrk variant while strict hash check is in force. + \MsgBrk Relax strict hash check with + '\string\NoStrictHashCheck'}\@ehc + \fi + \let\LTS@hashcheckorno\ifblankFT + \begingroup + \@makeother{\#}\endlinechar\m@one + \LTS@testopt\LTS@patchcs{####1}% +} +\new@def*\LTS@patchcs[#1]#2#3#4{% + \if\LTS@tracepatches + \typeout{^^J** Debugging patches: command '\string#2'}% + \fi + \LTS@hashcheckorno{#4}{% + \LTS@p@tchcs{#1}{#2}{#3}{#4}% + }{% + \endgroup + \LTS@patchdebug{--}{Nested parameters}% + \@secondoftwo + }% +} +\new@def*\LTS@p@tchcs#1#2#3#4{% + \LTS@ifpatchable{#2}{#3}{#4}{% + \LTS@patchdebug{++}{Command is patchable}% + \LTS@patchdebug{==}{Patching has begun}% + \begingroup + \edef\LTS@tempa##1##2{% + \def##1####1\detokenize{macro:}####2->####3&{% + #1\def\string#2####2{##2####3&}% + }% + \def##2####1\detokenize{#3}####2&{####1\detokenize{#4}####2}% + \edef##1{##1\meaning#2&}% + }% + \LTS@tempa\LTS@tempa\LTS@tempb + \LTS@scantoksd\endgroup\LTS@tempa + \LTS@patchdebug{==}{Patching completed successfully}% + \@firstoftwo + }{% + \LTS@patchdebug{--}{Patching couldn't be completed}% + \@secondoftwo + }% +} +\new@def*\LTS@patchdebug#1#2{% + \if\LTS@tracepatches + \typeout{[debug] #1 #2}% + \fi +} +\robust@def*\LTS@ifpatchable#1#2#3{% + \endgroup + \ifdefswitchTF{stricthashcheck}{% + \LTS@patchdebug{==}{'stricthashcheck' set true}% + % If #3 is macronizable, then it is scannable. + % Macronizing doesn't accept nested hash, but + % we're already in strict mode here. + \macronizetokens\LTS@rsvda{#3}% + \LTS@patchdebug{++}{No illegal nested parameters in command}% + }{}% + \ifdefFT{#1}{% + \LTS@patchdebug{--}{Command not defined}% + \@secondoftwo + }{% + \LTS@patchdebug{++}{Command is defined}% + \ltsifmacroTF{#1}{% + \LTS@patchdebug{++}{Command is a macro}% + \ifscannableTF{#1}{% + \LTS@patchdebug{++}{Macro can be retokenized safely + after patching}% + \LTS@hashcheckorno{#2}{% + \LTS@patchdebug{++}{No nested parameters in command + or 'stricthashcheck' is false}% + \ifpatternTF{#1}{#2}{% + \LTS@patchdebug{++}{Requested search pattern found}% + \@firstoftwo + }{% + \LTS@patchdebug{--}{Requested search pattern not found}% + \@secondoftwo + }% + }{% + \LTS@patchdebug{--}{Nested commands or parameters}% + \@secondoftwo + }% + }{% + \LTS@patchdebug{--}{Macro can't be retokenized + safely after patching}% + \@secondoftwo + }% + }{% + \LTS@patchdebug{--}{Command isn't a macro}% + \@secondoftwo + }% + }% +} +\robust@def*\ifpatchableTF{\begingroup\LTS@ifpatchable} +\robust@def*\reverseexpansion#1#2{% + \ifnumcmpFT#2=\@ne{}{% + \LTS@err{Invalid expansion order '\string#2' for + '\string\reverseexpansion'}{Why not just use + '\string\expandafter' here instead\MsgBrk of + '\string\reverseexpansion'?}% + \@gobbleone + }% + \ifcase\numexpr#2-2\relax + \def\LTS@rsvda{2,2}% + \or + \def\LTS@rsvda{3,4,4}% + \or + \def\LTS@rsvda{4,6,8,8}% + \else + \LTS@err{Invalid expansion order \string#2} + {Number '\string#2' of '\string\reverseexpansion' + is too large.}% + \expandafter\@gobble + \fi + \def\csv@do##1{% + \LTS@sttrue + \LTS@expandoneahead#1{##1}% + }% + \csv@@loop*[,]\LTS@rsvda +} +\robust@def*\expandoneahead{\LTS@testst\LTS@expandoneahead} +\robust@def\LTS@expandoneahead#1#2{% + \begingroup + \makecsn{\{}\lb\makecsn{\}}\rb + \toks@{}% + \@tempcnta\m@one + \def\LTS@i{\futurelet\next\LTS@iv}% + \def\LTS@ii{\afterassignment\LTS@i\let\next= }% + \def\LTS@iii##1{% + \ifnum\@tempcnta<#2\relax + \ifx##1\bgroup\relax + \toks@\expandafter{\the\expandafter\toks@\expandafter\expandafter\lb}% + \else + \ifx##1\egroup\relax + \toks@\expandafter{\the\expandafter\toks@\expandafter\expandafter\rb}% + \else + \toks@\expandafter{\the\toks@\expandafter##1}% + \fi + \fi + \else + \ifx##1\bgroup + \toks@\expandafter{\the\expandafter\toks@\lb}% + \else + \ifx##1\egroup + \toks@\expandafter{\the\expandafter\toks@\rb}% + \else + \toks@\expandafter{\the\toks@##1}% + \fi + \fi + \fi + }% + \def\LTS@iv{% + \advance\@tempcnta\@ne + \ifx\next\end + \let\cmd\@gobbleone + \else + \ifx\next\@sptoken + \toks@\expandafter{\the\toks@ \expandafter\@space}% + \let\cmd\LTS@ii + \else + \ifx\next\bgroup + \LTS@iii\bgroup\let\cmd\LTS@ii + \else + \ifx\next\egroup + \LTS@iii\egroup\let\cmd\LTS@ii + \else + \let\cmd\LTS@v + \fi + \fi + \fi + \fi + \cmd + }% + \def\LTS@v##1{\LTS@iii##1\LTS@i}% + \ifdefboolFT{LTS@st}{}\expandafter\LTS@i#1\end + \edef\LTS@resa{\the\toks@}% + \postgroupdef\LTS@resa\endgroup + \LTS@scantoksa\LTS@resa + \ifLTS@st\let#1\LTS@resa\fi +} +\robust@def*\expandallonce{\LTS@testopt\LTS@expandallonce\@M} +\robust@def*\LTS@expandallonce[#1]#2{% + \begingroup + \let\temp@bgroup\bgroup + \let\bgroup\LTS@undefined + \cpt@cnta#1\relax\advance\cpt@cnta\@ne + \LTS@exp@ndallonce#2% + \postgroupdef#2\endgroup + \NoExpandPrimitives +} +\new@def*\LTS@exp@ndallonce#1{% + \def\LTS@i{\futurelet\next\LTS@ii}% + \def\LTS@ii{% + \expandafter\LTS@iii\meaning\next\LTS@nil + \ifx\next\end + \let\cmd\@gobbleone + \else + \ifx\next\@sptoken + \edef#1{\expandcsonce#1\@space}% + \csn@def{cmd} {\LTS@i}% + \else + \let\cmd\LTS@iv + \fi + \fi + \cmd + }% + \def\LTS@iii##1##2\LTS@nil{\if##1\@backslashchar\let\next\relax\fi}% + \def\LTS@iv##1{% + \toks@\expandafter{#1}\toks1{##1}% + \ifx\next\temp@bgroup + \advance\cpt@cnta\m@one + \ifnum\cpt@cnta>\z@pt + \begingroup + \aftercsname\edef{\string#1}{\the\toks1}% + \aftercsname\LTS@exp@ndallonce{\string#1}% + \toks1\cptsevenxp{\usename{\string#1}}% + \edefpass#1{\endgroup\toks1{\the\toks1}}% + \fi + \edef#1{\the\toks@{\the\toks1}}% + \advance\cpt@cnta\@ne + \else + \edef#1{\the\toks1}% + \LTS@exp@nd@llonce#1% + \edef#1{\the\toks@\expandcsonce#1}% + \fi + \LTS@i + }% + \expandafter\emptify\expandafter#1\expandafter\LTS@i#1\end +} +\robust@def*\LTS@exp@nd@llonce#1{% + \begingroup + \oifmacroTF#1{% + \edef#1{\noexpand\expandcsonce\expandcsonce#1} + }{% + \edef\LTS@rsvda{\cptsevenxp\LTS@car\cptoxdetok{#1}x\car@nil}% + \ifxTF\LTS@rsvda\@backslashchar{% + \simpleexpandarg\ifprimitiveTF{#1}{% + \if\LTS@expprim + \edef#1{\expandcsonce#1}% + \else + \edef#1{\noexpand\noexpand\expandcsonce#1}% + \fi + }{% + \edef#1{\noexpand\noexpand\expandcsonce#1}% + }% + }{% + \edef#1{\expandcsonce#1}% + }% + }% + \postgroupdef#1\endgroup +} +\new@def*\CurrentPackageOrClass{\@cls@pkg\@space'\@currname'} +\new@def*\LTS@parsedate#1/#2/#3 v#4\LTS@nil{#1/#2/#3} +\robust@def*\LTS@notloadederr#1{% + \ifcsndefTF{ver@#1.\@pkgextension}{}{% + \LTS@err{Package '#1' wasn't loaded}% + {Document has begun and package '#1' wasn't loaded.\MsgBrk + You wanted package '#1' loaded.}% + }% +} +\new@def*\LTS@notloaded{} +\robust@def*\ensurepackageloaded#1{% + \def\csv@do##1{% + \grightaddtocs\LTS@notloaded{\LTS@doloaded{##1}}% + }% + \csv@@parse[,]{#1}% +} +\LTS@AtBeginDocument{% + \let\LTS@doloaded\LTS@notloadederr + \LTS@notloaded + \gletcs\LTS@doloaded\@gobbleone +} +\robust@def*\QuotationMarks#1{% + \begingroup + \ifinsetTF,{#1}{% + \def\LTS@tempa##1,##2\LTS@nil{% + \ifblankTF{##2}{% + \LTS@err{Unbalanced quotation marks '#1'}\@ehc + }{% + \protected@xdef\LTS@lquote{% + {\ltsprotectedtokens{\normalcolor\normalfont}##1}}% + \protected@xdef\LTS@rquote{% + {\ltsprotectedtokens{\normalcolor\normalfont}##2}}% + }% + }% + \LTS@tempa#1\LTS@nil + }{% + \LTS@err{I can't find comma in quotation marks '#1'}\@ehc + }% + \endgroup +} +\QuotationMarks{`,'} +\new@def*\ApplyToQuotes#1{% + \ifnumcmpTF\LTS@quotednr@b>\z@pt{% + \LTS@err{You haven't called '\string\ApplyNilToQuotes'\MsgBrk + since you last called '\string\ApplyToQuotes'}\@ehc + \@gobbleone + }{% + \gdef\LTS@quotefmt{#1}% + }% + \let\LTS@quotednr@b\@ne +} +\new@def*\ApplyNilToQuotes{% + \gletcs\LTS@quotefmt\@firstofone + \chardef\LTS@quotednr@b\z@pt +} +\ApplyNilToQuotes +\def\quote@while{\cpt@choicefdfalse\quote@loop} +\def\quote@loop#1{% + \ifboolTF{cpt@choicefd}{% + \quote@end + }{% + \ifx#1\quote@repeat\quote@repeat\fi + \ifx#1\quote@next\cpt@choicefdtrue\fi + }% + \quote@loop +} +\def\quote@repeat#1\quote@loop{\fi} +\def\quote@end#1\quote@repeat{} +\chardef\LTS@quotednr@a\z@pt +\chardef\LTS@quotednr@b\z@pt +\robust@def*\quoted{% + \pushnumber\LTS@quotednr@a + \ifnumcmpTF\LTS@quotednr@a>\tw@{% + \cpt@toodeep\quoted\tw@ + }{% + \begingroup + \@makeother{\#}% + \LTS@testst\LTS@quoted + }% +} +\new@def*\LTS@quoted#1{% + \def\LTS@quotearg{{\LTS@quotefmt{#1}}}% + \gletcsntocs{ifLTS@st@\romannumeral\LTS@quotednr@a}\ifLTS@st + \def\LTS@tempa{% + \ifLTS@st@i + \protected@edef\lquote{\LTS@lquote}% + \protected@edef\rquote{\LTS@rquote}% + \else + \protected@edef\lquote{\LTS@lquote\LTS@lquote}% + \protected@edef\rquote{\LTS@rquote\LTS@rquote}% + \fi + }% + \def\LTS@tempb##1##2{% + \ifnum\LTS@quotednr@a>\@ne + \LTS@tempa + \else + \protected@edef\lquote{##1\LTS@lquote}% + \protected@edef\rquote{##2\LTS@rquote}% + \fi + }% + \ifLTS@st + \LTS@tempb\LTS@lquote\LTS@rquote + \else + \LTS@tempb{}{}% + \fi + \def\popnumber{\noexpand\popnumber\noexpand}% + \protected@edef\rquote{\rquote\popnumber\LTS@quotednr@a}% + \futurelet\quote@next\LTS@qu@ted +} +\new@def*\LTS@qu@ted{% + \def\LTS@quotefnt{\footnote\footnotetext\footnotemark\mpfootnotemark}% + \def\LTS@quote@a{% + \if\LTS@wq + \expandafter\quote@while\LTS@quotefnt\quote@repeat + \ifcpt@choicefd + \protected@xdef\LTS@qu@t@d####1####2{% + \lquote\expandcsonce\LTS@quotearg\unskip####1{####2}\rquote + }% + \else + \protected@xdef\LTS@qu@t@d####1{% + \lquote\expandcsonce\LTS@quotearg\unskip####1\rquote}% + \fi + \else + \protected@xdef\LTS@qu@t@d{% + \lquote\expandcsonce\LTS@quotearg\rquote\unskip}% + \fi + }% + \protected@edef\LTS@tempa{,;:.!?\expandcsonce\LTS@quotefnt}% + \expandafter\quote@while\LTS@tempa\quote@repeat + \ifcpt@choicefd + \expandafter\LTS@quote@a + \else + \protected@xdef\LTS@qu@t@d{\lquote\expandcsonce\LTS@quotearg\rquote}% + \fi + \expandafter\endgroup\LTS@qu@t@d +} +\robust@def*\MakeQuoteCommand{\LTS@testst\LTS@MakeQuoteCommand} +\robust@def*\LTS@MakeQuoteCommand#1{% + \begingroup + \lccode`\~=`#1% + \lowercase{\endgroup + \newcsnedef*{\string~@quote}{\the\catcode`~}% + \ifLTS@st + \ifdefFT~{}{\letcsntocs{\string~@@quote}~}% + \let~\quoted + \else + \newletcs~\quoted + \fi + \catcode`#1=\active + }% +} +\robust@def*\DeleteQuoteCommand#1{% + \begingroup + \lccode`\~=`#1% + \lowercase{\endgroup + \ifcsndefTF{\string~@@quote}{% + \letcstocsn~{\string~@@quote}% + }{% + \gletcs~\LTS@undefined + }% + \catcode`#1=\usename{\string~@quote}% + }% +} +\robust@def*\nameabbrev#1#2{% + \begingroup + \LTS@ensurescape{#1}% + \makecsn#1\LTS@tempa + \expandafter\LTS@testopt\expandafter + {\expandafter\LTS@nameabbrev\expandafter{\LTS@tempa}{#2}}{}% +} +\new@def*\LTS@nameabbrev#1#2[#3]{% + \ifblankTF{#3}{% + \LTS@err{Empty abbreviation for name '\noexpandcsn{#1}'}\@ehc + }{% + \newcsnpgdef*{#1long}{#2\sspace}% + \newcsnpgdef*{#1short}{#3\sspace}% + \newcsnpgdef*{#1first}{#2~(#3)\sspace}% + }% + \newcsnpgdef*{#1}{% + \ifnamedefTF{nameabbrev@#1}{% + #3\sspace + }{% + \csn@gdef{nameabbrev@#1}{}% + \usename{#1first}\sspace + }% + }% + \endgroup +} +\newletcs\killifdocstarted\@iden +\LTS@AfterAfterBeginDocument{% + \LTS@scantoksa\sspace@exceptions + \let\killifdocstarted\@gobble +} +\robust@def*\sspace@while{\cpt@choicefdfalse\sspace@loop} +\robust@def*\sspace@loop#1{% + \ifboolTF{cpt@choicefd}{% + \sspace@end + }{% + \ifx#1\sspace@repeat\sspace@repeat\fi + \ifx#1\sspace@next\cpt@choicefdtrue\fi + }% + \sspace@loop +} +\robust@def\sspace@repeat#1\sspace@loop{\fi} +\robust@def\sspace@end#1\sspace@repeat{} +\robust@def*\sspace@exceptions{% + \},.'/?;:!~-)\ \/\bgroup\egroup\sspace\nobreak\penalty + \@sptoken\@space\@xobeysp\footnote\footnotemark +} +\robust@def*\sspace{\begingroup\futurelet\sspace@next\LTS@sspace} +\robust@def*\LTS@sspace{% + \killifdocstarted{\LTS@scantoksa\sspace@exceptions}% + \expandafter\sspace@while\sspace@exceptions\sspace@repeat + \expandafter\endgroup + \ifcpt@choicefd\else\expandafter\@space\fi +} +\robust@def*\AddSspaceExceptions#1{% + \ltsfiltermergetsv!\sspace@exceptions{#1}\nofilter +} +\robust@def*\RemoveSspaceExceptions#1{% + \filterdeletetokens!\sspace@exceptions{#1}\nofilter +} +\long\def\LTS@exprerr#1{% + \ltx@err{Invalid test expression}{#1.}% +} +\robust@def*\ltsifexprTF#1{% + \begingroup + \let\LTS@expr@neg\cptswfalse + \@tempcnta\z@pt + \LTS@expr@beg + \LTS@expr@bgroup#1(\expr@nil + \LTS@expr@end + \LTS@expr@eval@end +} +\def\LTS@expr@beg{% + \begingroup + \let\LTS@expr@neg\cptswfalse + \@tempcnta\z@pt +} +\def\LTS@expr@end{% + \LTS@expr@eval@end\LTS@expr@true\LTS@expr@false +} +\def\LTS@expr@eval@end{% + \aftercsname\endgroup + {@\ifnum\@tempcnta<\z@pt second\else first\fi oftwo}% +} +\def\LTS@expr@true{% + \advance\@tempcnta\if\LTS@expr@neg\m@one\else\z@pt\fi + \let\LTS@expr@neg\cptswfalse +} +\def\LTS@expr@false{% + \advance\@tempcnta\if\LTS@expr@neg\z@pt\else\m@one\fi + \let\LTS@expr@neg\cptswfalse +} +\long\def\LTS@expr@bgroup#1(#2\expr@nil{% + \LTS@expr@egroup#1)\expr@nil + \ifblankTF{#2}{}{% + \LTS@expr@beg + \LTS@expr@bgroup#2\expr@nil + }% +} +\long\def\LTS@expr@egroup#1)#2\expr@nil{% + \LTS@expr@and#1and\expr@nil + \ifblankTF{#2}{}{% + \LTS@expr@end + \LTS@expr@egroup#2\expr@nil + }% +} +\long\def\LTS@expr@and#1and#2\expr@nil{% + \LTS@expr@or#1or\expr@nil + \ifblankTF{#2}{}{% + \ifnum\@tempcnta<\z@pt + \@tempcnta\m@one + \else + \@tempcnta\z@pt + \fi + \LTS@expr@and#2\expr@nil + }% +} +\long\def\LTS@expr@or#1or#2\expr@nil{% + \LTS@expr@not#1not\expr@nil + \ifblankTF{#2}{}{% + \ifnum\@tempcnta<\z@pt + \@tempcnta\z@pt + \else + \@tempcnta\@ne + \fi + \LTS@expr@or#2\expr@nil + }% +} +\long\def\LTS@expr@not#1not#2\expr@nil{% + \LTS@expr@tog#1togg\expr@nil + \ifblankTF{#2}{}{% + \let\LTS@expr@neg\cptswtrue + \LTS@expr@not#2\expr@nil + }% +} +\long\def\LTS@expr@tog#1togg#2\expr@nil{% + \LTS@expr@bool#1bool\expr@nil + \ifblankTF{#2}{}{\LTS@expr@tog@a#2\expr@nil}% +} +\long\def\LTS@expr@tog@a#1#2\expr@nil{% + \ifcsndefTF{cpt@tog@\cpttrimspaces{#1}}{% + \usename{cpt@tog@#1}\LTS@expr@true\LTS@expr@false + }{% + \LTS@exprerr{Toggle '#1' undefined}% + \LTS@expr@false + }% + \LTS@expr@tog#2\expr@nil +} +\long\def\LTS@expr@bool#1bool#2\expr@nil{% + \LTS@expr@test#1test\expr@nil + \ifblankTF{#2}{}{\LTS@expr@bool@a#2\expr@nil}% +} +\long\def\LTS@expr@bool@a#1#2\expr@nil{% + \ifcsndefTF{if\cpttrimspaces{#1}}{% + \csname if#1\endcsname + \LTS@expr@true + \else + \LTS@expr@false + \fi + }{% + \LTS@exprerr{Boolean '#1' undefined}% + \LTS@expr@false + }% + \LTS@expr@bool#2\expr@nil +} +\long\def\LTS@expr@test#1test#2\expr@nil{% + \ifblankTF{#1}{}{% + \LTS@exprerr{The invalid part is: '\detokenize{#1}'}% + }% + \ifblankTF{#2}{}{% + \LTS@expr@test@a#2\expr@nil + }% +} +\long\def\LTS@expr@test@a#1#2\expr@nil{% + \cpttrimspaces{#1}% + \LTS@expr@true\LTS@expr@false + \LTS@expr@test#2\expr@nil +} + +% \newenviron, \renewenviron {<start>}<body>{<end>}. +% Collect environment body in \envbody: +\ltsnewbool{LTS@alwaystrim} +\new@def*\AlwaysTrimEnvironmentEntries{% + \global\LTS@alwaystrimtrue +} +\new@def*\trimenvspaces{% + \ifboolTF{LTS@alwaystrim}\cpttrimspaces\unexpanded +} +\new@def*\everyeoenv#1{\gdef\LTS@everyeoenv{#1}} +\everyeoenv{\@ignoretrue} +\robust@def*\newenviron{\cpt@starorlong\LTS@newenviron} +\robust@def*\LTS@newenviron#1{% + \edef\LTS@tempa{\trimenvspaces{#1}}% + \cptexpandarg\cpt@testopt + {\LTS@n@wenviron{\expandcsonce\LTS@tempa}}0% +} +\robust@def*\LTS@n@wenviron#1[#2]{% + \cpt@ifbrack + {\LTS@n@wenv@ron#1[#2]} + {\LTS@n@wenv@r@n{#1}{[#2]}}% +} +\robust@def*\LTS@n@wenv@ron#1[#2][#3]{\LTS@n@wenv@r@n{#1}{[#2][{#3}]}} +\robust@def*\renewenviron{\cpt@starorlong\LTS@renewenviron} +\robust@def*\LTS@renewenviron#1{% + \edef\LTS@tempa{\trimenvspaces{#1}}% + \ifcsndefTF\LTS@tempa{} + {\@latex@error{Environment #1 is undefined}\@ehc}% + \letcsntocs\LTS@tempa\relax + \letcsntocs{end\LTS@tempa}\relax + \expandafter\LTS@newenviron\expandafter{\LTS@tempa}% +} +\robust@def\LTS@n@wenv@r@n#1#2#3#4{% + \ifcsndefTF{#1}{}{\letcsntocsn{#1}{end#1}}% + \aftercsname\new@command{#1}#2{% + \edef\LTS@beforebody{\trimenvspaces{#3}}% + \LTS@collectbody + }% + \l@ngrel@x\csn@edef{end#1}{% + \begingroup + \defpass\noexpand\x{\endgroup\trimenvspaces{#4}}% + }% +} +\robust@def*\LTS@collectbody{% + \begingroup + \toks@{}% + \everyeof{\end{EOF}\relax}% + \LTS@coll@ctbody +} +\robust@def\LTS@coll@ctbody#1\end#2{% + \toks1{% + \cptexpanded{% + \toks@{\the\toks@\trimenvspaces{#1}% + \noexpand\end{\expandcsonce\LTS@tempa}}% + }% + \LTS@coll@ctbody + }% + \edef\LTS@tempa{\trimenvspaces{#2}}% + \ifxTF\LTS@tempa\@currenvir{% + \edef\LTS@tempb{\LTS@pushbegin#1\begin\end\cpt@relax}% + \ifcsemptyTF\LTS@tempb{% + \cptexpandsecond\endgroup{% + \edef\noexpand\envbody{\noexpand\unexpanded{% + \the\toks@\ifblankTF{#1}{}{\trimenvspaces{#1}}% + }}% + \unexpanded{% + \LTS@beforebody\relax\LTS@everyeoenv + \ifboolTF{LTS@alwaystrim}\@ignoretrue\relax + }% + \noexpand\end{\LTS@tempa}% + }% + }{% + \the\toks1 + }% + }{% + \oifstrcmpTF{\LTS@tempa}{document}{% + \expandafter\endgroup\expandafter + \@checkend\expandafter{\LTS@tempa}% + }{% + \oifstrcmpTF{\LTS@tempa}{EOF}{% + \expandafter\endgroup\expandafter + \@checkend\expandafter{\LTS@tempa}% + }{% + \the\toks1 + }% + }% + }% +} +\new@def\LTS@pushbegin#1\begin#2{% + \expandafter\ifxTF\cpt@car#2x\car@nil\end{% + \@gobble + }{% + \xifstrcmpTF{\detokenize\expandafter{\romannumeral-`\q + \trimenvspaces{#2}}}{\cptoxdetok\LTS@tempa}{% + x\cpt@gobbletorelax + }{% + \LTS@pushbegin + }% + }% +} + +\packagecommands{% + \packagecommands,\AtEndOfPackage, + \LTS@AtEndPackage,\AtEndOfClass,\LTS@AtEndClass, + \LTS@BeforeEndPackage,\LTS@BeforeEndClass,\LTS@AfterEndPackage, + \LTS@AfterEndClass,\ifclasscurrentTF,\ifclasscurrentFT +} +\preamblecommands{% + \preamblecommands,\LTS@BeforeBeginDocument,\ensurepackageloaded, + \needpackage +} +\XDeclareBiBooleanOptions{draft,final}[true](LTS@){}{} +\XDeclareBooleanOption{verbose}[true](LTS@){% + \ifLTS@verbose\cpt@verbosetrue\else\cpt@verbosefalse\fi +} +\XDeclareSwitchOption{tracepatches}[true](LTS@){% + \ifdefswitchTF{LTS@tracepatches}{% + \LTS@info{'tracepatches' set true\on@line}% + }{}% +} +\XDeclareOption*{\LTS@warn{Unknown option '\CurrentOption' ignored}} +\XExecuteOptions{verbose=false,final=true,tracepatches=false} +\XProcessOptions*\relax + +\endinput + +%%% End of file ltxtools.sty %%% diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 6987414a236..36ec65722eb 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -230,7 +230,7 @@ my @TLP_working = qw( lshort-polish lshort-portuguese lshort-russian lshort-slovak lshort-slovenian lshort-spanish lshort-thai lshort-turkish lshort-ukr lshort-vietnamese ltabptch - ltxdockit ltxindex ltxkeys ltxmisc ltxnew + ltxdockit ltxindex ltxkeys ltxmisc ltxnew ltxtools lua-alt-getopt luabibentry luacode luaindex luainputenc lualatex-doc lualatex-math lualibs luamplib luaotfload luapersian luasseq luatexbase luatextra diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index d6044e51035..525887a865d 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -383,6 +383,7 @@ depend ltxdockit depend ltxindex depend ltxkeys depend ltxnew +depend ltxtools depend magaz depend mailing depend mailmerge diff --git a/Master/tlpkg/tlpsrc/ltxtools.tlpsrc b/Master/tlpkg/tlpsrc/ltxtools.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/ltxtools.tlpsrc |