%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % % % This is file 'skeycommand.sty', version 0.4. % % % % 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 (a.musa@rocketmail.com). % % % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \@ifpackageloaded{catoptions}{% \@ifpackagelater{catoptions}{2011/10/22}{}{% \@latex@error{Loaded version of catoptions package is not current}\@ehc }% }{% \RequirePackage{catoptions}[2011/10/22]% } \UseNormalCatcodes \StyleFilePurpose{Create commands and environments with keys (AM)} \StyleFileRCSInfo $Id: skeycommand.sty,v 0.4 2011/10/20 09:00:00 Ahmed Musa Exp $ \ProvidesPackage{skeycommand}[\StyleFileInfo] \NeedsTeXFormat{LaTeX2e}[1996/12/01] \SetStyleFileMessages[skc@]{info}{warn}{err} \loadifnotloaded{ltxkeys}[2011/10/22] \newvariables{if}[skc@]{inkey}[false] \ltxkeys@biboolkeys[SKC]{skeycommand}[skc@]{verbose,silent}[true]{% \ifskc@verbose\cpt@verbosetrue\fi }{% \ifskc@silent\cpt@verbosefalse\fi } \ltxkeys@declareoption*{\skc@warn{Unknown option '\CurrentOption' ignored}} \ltxkeys@executeoptions[SKC]{verbose=false} \ltxkeys@processoptions*[SKC]\relax \robust@def*\skeycommand#1{% \ifblankTF{#1}{\ltxkeys@setkeys[SKC]{skeycommand}{#1}}% } \robust@def*\skc@testltopt#1#2{\ifnextcharTF<{#1}{#1<{#2}>}} \robust@def*\skc@testpnopt#1#2{\ifnextcharTF({#1}{#1({#2})}} \robust@def*\skc@scantoksa#1{% \begingroup \def\siso@do##1{\catcode`##1\string=12\relax}% \siso@@loop{=,;|-+?><}% \cptscantokens#1% \postgroupdef#1\endgroup } \robust@def*\skc@scantoksb{\cpt@testcl\skc@sc@ntoksb} \robust@def\skc@sc@ntoksb#1{% \def\csv@do##1{% \cptscantokens{##1}% \ifcpt@cl\global\fi\let##1=##1% }% \csv@@parse[,]{#1}% } \robust@def*\skc@definekeys{% \begingroup \endlinechar\m@one \cpt@testopt\skc@d@finekeys{SKC}% } \robust@def*\skc@d@finekeys[#1]#2{% \cpt@testopt{\expandafter\endgroup\skc@d@f@nekeys{#1}{#2}}{}% } \robust@def*\skc@d@f@nekeys#1#2[#3]#4{% \begingroup \ltxkeys@makepf{#1}% \ltxkeys@makehdr{#2}% \trim@@space{#1}\skc@keypref \trim@@space{#2}\skc@keyfam \trim@@space{#3}\skc@macpref \toks@{}% \def\skc@keyvals{}% \def\skc@splita##1={% \begingroup \defpass\skc@rsvda####1\skc@nil{\endgroup \skc@splitb##1/####1/^?/\skc@nil }.% }% \def\skc@splitb##1/##2/##3/##4\skc@nil{% \ifblankTF{##1}{% \ifblankTF{##2##3}{}{\skc@err{Empty key name}\@ehc}% }{% \ltxkeys@findpointers{##1}% \let\skc@keyname\ltxkeys@tkey \ifcsndefTF{\skc@keypref @\skc@keyfam @\skc@keyname}{% \skc@err{Key '\skc@keyname' already defined in family \MsgBrk '#2' with prefix '#1'}\@ehc }{}% \ifstrcmpTF{##2}{^?}{% \def\skc@keydefault{}% }{% \simpleexpandarg\trim@@space{\@gobble##2}\skc@keydefault }% \ifstrcmpTF{##3}{^?}{% \def\skc@keycallback{}% }{% \trim@@space{##3}\skc@keycallback }% \edef\skc@keyvals{% \csliststack,\skc@keyvals\expandcsonce\skc@keyname=% \oifstrcmpTF\skc@keydefault{true}{false}{% \expandcsonce\skc@keydefault }% }% \def\skc@defkey{\ltxkeys@boolkey}% \oifstrcmpTF\skc@keydefault{true}{}{% \oifstrcmpTF\skc@keydefault{false}{}{% \def\skc@defkey{\ltxkeys@cmdkey}% }% }% \cptpassexpanded{% \toks@{\the\toks@ \skc@defkey[\skc@keypref]{\skc@keyfam}[\skc@macpref]% {\skc@keyname}[\expandcsonce\skc@keydefault]% {\expandcsonce\skc@keycallback}% }% }% }% }% \long\def\csv@do##1{% \cpt@checkeq##1\cpt@nil{% \skc@splita##1\skc@nil }{% \skc@splitb##1/^?/^?/\skc@nil }% }% \csv@@parse[,]{#4}% \cptexpandsecond\endgroup{% \the\toks@ \ifcsnullTF\skc@keyvals{}{\noexpand\ltxkeys@setkeys [\skc@keypref]{\skc@keyfam}{\expandcsonce\skc@keyvals}% }% }% } \def\skc@everyeoehook{} \robust@def*\EveryEndOfKeyEnviron#1{% \ifnullTF{#1}{% \gdef\skc@everyeoehook{}% }{% \xdef\skc@everyeoehook{% \unexpanded{#1}\expandcsonce\skc@everyeoehook }% }% \begingroup \edef\skc@tempa{\string\@ignoretrue}% \edef\skc@tempb{\string\ignorespacesafterend}% \edef\skc@tempc{% \expandafter\strip@prefix\meaning\skc@everyeoehook }% \oifinsetTF\skc@tempa\skc@tempc{% \oifinsetTF\skc@tempb\skc@tempc{% \skc@err{Bad '\string\EveryEndOfKeyEnviron'}{% You can't have both '\string\@ignoretrue' and '\string\ignorespacesafterend' in '\string\EveryEndOfKeyEnviron'.}% }{% \skc@checkbadeoe\@ignoretrue }% }{% \oifinsetFT\skc@tempb\skc@tempc{}{% \skc@checkbadeoe\ignorespacesafterend }% }% \endgroup } \new@def*\skc@checkbadeoe#1{% \begingroup \edef\skc@tempa##1{\def##1####1\detokenize{#1}####2\relax}% \skc@tempa\skc@tempa{% \ifblankTF{##2}{% \ifskc@verbose \skc@info{Good last token '\detokenize{#1}' in '\string\EveryEndOfKeyEnviron'}% \fi }{% \xifinsetTF{\detokenize{#1}}{\detokenize{##2}}{% \skc@err{'\detokenize{#1}' repeated in '\string\EveryEndOfKeyEnviron'.}{% Multiple '\detokenize{#1}' not allowed in '\string\EveryEndOfKeyEnviron'.}% }{% \skc@err{Bad last token in '\string\EveryEndOfKeyEnviron'}% {'\detokenize{#1}' not the last token in '\string\EveryEndOfKeyEnviron'.}% }% }% }% \cptexpandsecond\skc@tempa {\expandafter\strip@prefix\meaning\skc@everyeoehook\relax}% \endgroup } \newletcs\skceveryeoe=\EveryEndOfKeyEnviron \EveryEndOfKeyEnviron\ignorespacesafterend \robust@def*\newkeycmd{\cpt@starorlong\skc@keycmd@i} \robust@def*\csnnewkeycmd{\aftercsname\newkeycmd} \new@def*\skc@keycmd@i#1{% \let\long@or@relax\l@ngrel@x \ifescapedTF{#1}{}{% \skc@err{Illegal command name: \MsgBrk command not escaped}\@ehc }% \def\skc@cmdname{#1}% \edef\skc@currfam{\cptgobblescape{#1}}% \edef\skc@macpref{\cptthreexp\@carcube \expandafter\@gobble\string#1xxx\@nil @}% \skc@scantoksb{\skc@currfam,\skc@macpref}% \skc@testltopt\skc@keycmd@ii\skc@macpref } \new@def\skc@keycmd@ii<#1>{% \cptexpandarg\skc@macprefixerr{#1}% \edef\skc@macpref{#1}% \skc@testpnopt\skc@keycmd@iii{}% } \new@def\skc@keycmd@iii(#1){% \ifnullFT{#1}{}\skc@nilkeylisterr \cptexpandsecond\skc@definekeys {[SKC]{\skc@currfam}[\skc@macpref]}{#1}% \cpt@testopt\skc@keycmd@iv{0}% } \new@def\skc@keycmd@iv[#1]{% \skc@paramnoerr{#1}% \cpt@testopt{\skc@keycmd@v#1}{}% } \new@def\skc@keycmd@v#1[#2]#3{% \skc@inkeytrue \skc@keycmd@vi{#1}{#2}{#3}% \ifx\long@or@relax\relax \def\skc@rsvdb{\newtwooptcmd*}% \else \let\skc@rsvdb\newtwooptcmd \fi \skc@rsvda{\expandafter\skc@rsvdb\skc@cmdname}% \skc@inkeyfalse } \robust@def*\skc@keycmd@vi#1#2#3{% \edef\skc@rsvda##1{% ##1[\the\numexpr#1+1]\ifblankTF{#2}{}{[\unexpanded{#2}]}{% \ltxkeys@setkeys[SKC]{\skc@currfam}{####\the\numexpr#1+1}% \unexpanded{#3}% }% }% } \robust@def*\renewkeycmd{\cpt@starorlong\skc@renewkeycmd@i} \robust@def*\csnrenewkeycmd{\aftercsname\renewkeycmd} \new@def*\skc@renewkeycmd@i#1{% \ifdefTF#1{}{% \skc@err{Command '\string#1' undefined}% {Undefined command '\string#1' can't be redefined.\MsgBrk Use '\string\newkeycmd' instead.}% }% \let\ifcsdefinable\rc@ifcsdefinable \skc@keycmd@i#1% } \robust@def*\newkeyenviron{\cpt@starorlong\skc@keyenviron@i} \robust@def*\csnnewkeyenviron{\aftercsname\newkeyenviron} \new@def\skc@keyenviron@i#1{% \let\long@or@relax\l@ngrel@x \ifescapedTF{#1}{% \skc@err{Illegal environment name: \MsgBrk no escape expected}\@ehc }{}% \ifcsndefFT{#1}{}{% \skc@err{You have submitted an existing macro '\string#1' as an\MsgBrk environment name}% {'\string#1' not allowed as environment name.}% }% \edef\skc@currfam{#1}% \edef\skc@macpref{\@carcube#1xxx\@nil @}% \edef\skc@cmdname{\noexpandcsn{#1}}% \skc@testltopt\skc@keyenviron@ii\skc@macpref } \new@def\skc@keyenviron@ii<#1>{% \cptexpandarg\skc@macprefixerr{#1}% \edef\skc@macpref{#1}% \skc@testpnopt\skc@keyenviron@iii{}% } \new@def\skc@keyenviron@iii(#1){% \ifnullFT{#1}{}\skc@nilkeylisterr \cptexpandsecond\skc@definekeys {[SKC]{\skc@currfam}[\skc@macpref]}{#1}% \cpt@testopt\skc@keyenviron@v{0}% } \new@def\skc@keyenviron@v[#1]{% \skc@paramnoerr{#1}% \cpt@testopt{\skc@keyenviron@vi#1}{}% } \new@def\skc@keyenviron@vi#1[#2]#3#4{% \skc@inkeytrue \skc@keycmd@vi{#1}{#2}{#3}% \ifx\long@or@relax\relax \def\skc@rsvdb{\newtwooptcmd*}% \else \let\skc@rsvdb\newtwooptcmd \fi \skc@rsvda{\expandafter\skc@rsvdb\skc@cmdname}% \edef\skc@rsvda##1{% \long@or@relax\def\noexpandcsn{end\skc@currfam}% {##1\expandcsonce\skc@everyeoehook}% }% \skc@rsvda{#4}% \skc@inkeyfalse } \robust@def*\renewkeyenviron{\cpt@starorlong\skc@renewkeyenviron@i} \robust@def*\csnrenewkeyenviron{\aftercsname\renewkeyenviron} \new@def*\skc@renewkeyenviron@i#1{% \ifcsndefTF{#1}{}{% \skc@err{Environment '#1' undefined}% {Undefined environment '#1' can't be redefined.}% }% \undefcsn{#1}\undefcsn{end#1}% \skc@keyenviron@i{#1}% } \robust@def*\newtwooptcmd{\cpt@starorlong\skc@newcommand@i} \new@def*\skc@newcommand@i#1{% \let\long@or@relax\l@ngrel@x \cpt@testopt{\skc@newcommand@ii#1}0% } \new@def*\skc@newcommand@ii#1[#2]{% \cpt@ifbrack{\skc@xargdef#1{#2}}{\skc@argdef#1{#2}}% } \new@def\skc@argdef#1#2#3{\ifcsdefinable#1{\skc@yargdef#1{1}{#2}{#3}}} \new@def\skc@xargdef#1#2[#3]#4{% \ifcsdefinable#1{% \edef\skc@rsvda##1##2##3{% \def##1{##2\noexpandcsn{\string#1}{##3}}% }% \skc@rsvda#1{\@protected@testopt#1}{#3}% \aftercsname\skc@yargdef{\string#1}{2}{#2}{#4}% }% } \new@def\skc@yargdef#1#2#3{% \ifnum#2=2\relax \edef\skc@shear##11{[\detokenize{####1}]}% \else \let\skc@shear\@gobble \fi \cptexpandarg\skc@yargd@f{\the\numexpr#3}#1% } \new@def*\skc@dotparse@a#1{% \begingroup \toks@{}% \def\reserved@f##1.##2\skc@nil{% \oifinsetTF{[}{##1}{% \toks@\expandafter{\the\toks@##1}% }{% \toks@\expandafter{\the\toks@{##1}}% }% \ifnullTF{##2}{}{\reserved@f##2\skc@nil}% }% \reserved@f#1.\skc@nil \edef\reserved@f{\the\toks@}% \postgroupdef\reserved@f\endgroup } \new@def*\skc@dotparse@b#1{% \begingroup \toks@{}% \def\reserved@f##1.##2\skc@nil{% \toks@\expandafter{\the\toks@##1}% \ifnullTF{##2}{}{\reserved@f##2\skc@nil}% }% \reserved@f#1.\skc@nil \edef\reserved@f{\the\toks@}% \postgroupdef\reserved@f\endgroup } \new@def\skc@yargd@f#1#2{% \begingroup \edef\skc@rsvdb{\detokenize{0####1.####2.####3.####4.####5.% ####6.####7.####8.####9.#####1}}% \def\skc@rsvda##1#1##2\skc@nil{% \def\skc@rsvdb{##1}% \def\skc@rsvda####1{% \def\skc@rsvda########1####1########2\skc@nil{% \ifnullTF{########1}{% \edef\skc@tempa{\skc@shear####1########2#1}% \let\skc@tempb\skc@tempa \let\skc@tempc\skc@tempa }{% \edef\skc@rsvda{\skc@shear########1####1}% \simpleexpandarg\skc@dotparse@a\skc@rsvda \let\skc@tempa\reserved@f \simpleexpandarg\skc@dotparse@b\skc@rsvda \let\skc@tempb\reserved@f \edef\skc@rsvda{########2#1}% \simpleexpandarg\skc@dotparse@b\skc@rsvda \edef\skc@tempc{\skc@tempb(\reserved@f)}% }% }% \expandafter\skc@rsvda\skc@rsvdb\skc@nil }% \ifnum#1=\z@pt \cptemptifycsset{\skc@tempa,\skc@tempb,\skc@tempc}% \else \simpleexpandarg\skc@rsvda{\the\numexpr#1-1}% \fi }% \expandafter\skc@rsvda\skc@rsvdb\skc@nil \skc@scantoksb{\skc@tempa,\skc@tempb,\skc@tempc}% \edef\skc@rsvda{\cptgobblescape{#2@skc@}}% \let\reserved@e\relax \let#2\relax \cptpassexpanded{\endgroup \def\reserved@e{% \long@or@relax \def\noexpandcsn\skc@rsvda\expandcsonce\skc@tempc }% \ifnumcmpTF#1<\tw@{% \ifxTF\skc@shear\@gobble{% \ifskc@inkey \long@or@relax\def#2% {\skc@testpnopt\noexpandcsn\skc@rsvda{}}% \long@or@relax\def\noexpandcsn\skc@rsvda(\skc@tempc)% \else \long@or@relax\def#2\skc@tempb {\noexpandcsn\skc@rsvda{\skc@tempa}}% \reserved@e \fi }{% \long@or@relax\def#2\skc@tempb {\noexpandcsn\skc@rsvda\skc@tempa}% \reserved@e }% }{% \long@or@relax\def#2\skc@tempb {\skc@testpnopt{\noexpandcsn\skc@rsvda\skc@tempa}{}}% \reserved@e }% }% } \new@def\skc@reargdef#1[#2]{\skc@yargdef#1{1}{#2}} \robust@def*\renewtwooptcmd{\cpt@starorlong\skc@renewcommand@i} \new@def*\skc@renewcommand@i#1{% \ifdefTF#1{}{% \skc@err{Undefined command '\string#1' can't be redefined}\@ehc }% \let\ifcsdefinable\rc@ifcsdefinable \skc@newcommand@i#1% } \new@def*\newtwooptenviron{\cpt@starorlong\skc@newenvironment@i} \new@def*\skc@newenvironment@i#1{% \let\long@or@relax\l@ngrel@x \cpt@testopt{\skc@newenv@a#1}0% } \new@def*\skc@newenv@a#1[#2]{% \cpt@ifbrack{\skc@newenv@b#1[#2]}{\skc@newenv{#1}{[#2]}}% } \new@def\skc@newenv#1#2#3#4{% \ifcsndefTF{#1}{}{\letcsntocsn{#1}{end#1}}% \aftercsname\skc@newcommand@i{#1}#2{#3}% \long@or@relax\@namedef{end#1}{#4}% } \new@def*\skc@newenv@b#1[#2][#3]{\skc@newenv{#1}{[#2][{#3}]}} \new@def*\renewtwooptenviron{\cpt@starorlong\skc@renewenvironment@i} \new@def*\skc@renewenvironment@i#1{% \ifcsndefTF{#1}{}{% \skc@err{Undefined environment '#1' can't be redefined}\@ehc }% \undefcsn{#1}\undefcsn{end#1}% \skc@newenvironment@i{#1}% } \robust@def*\skc@nilprefixerr{% \skc@err{No macro prefix submitted. The prefix will\MsgBrk be used to hold your values for the declared keys}{% Keycommand requires macro prefix. I guess you\MsgBrk submitted an empty prefix using '<>'. I can use\MsgBrk the default macro prefix (the first three\MsgBrk letters of your key command) if you don't submit\MsgBrk any prefix. In that case leave out '<>' from your\MsgBrk command. }% } \new@def*\skc@ifdigitpresent#1{% \begingroup \cpt@choicefdfalse \def\tsv@do##1{% \ifinsetTF{##1}{0123456789}{% \cpt@choicefdtrue\cptbreakloop }{}% }% \tsv@@parse{#1}% \expandafter\endgroup\ifcpt@choicefd \expandafter\@iden\else\expandafter\@gobble\fi } \new@def*\skc@macprefixlist{} \robust@def*\skc@macprefixerr#1{% \xifblankTF{#1}{% \skc@nilprefixerr }{% \xifinsetTF{,#1,}{,\skc@macprefixlist,}{% \skc@err{Macro prefix '#1' already used, \MsgBrk or name '#1' illegal}\@ehc }{% \edef\skc@macprefixlist{\csliststack,\skc@macprefixlist#1}% \skc@ifdigitpresent{#1}{% \skc@err{'\string#1' is likely a wrong macro prefix}{% I expected letters here, not digits.\MsgBrk OK, digits are actually acceptable as macro\MsgBrk prefix but you need to be wary of them if they\MsgBrk appear in your control sequences. Also, I fear\MsgBrk you may have wrongly entered the number of\MsgBrk arguments of your key command here, instead\MsgBrk of putting it in the right place, ie, in square brackets. }% }% }% }% } \robust@def*\skc@nilkeylisterr{% \skc@err{No key list submitted or wrong command syntax.\MsgBrk Please see the user guide.}{Key-commands require keys. Perhaps you submitted\MsgBrk an empty key list, or your arguments to command\MsgBrk are inconsistent. Please see the user guide.\MsgBrk }% } \new@def*\skc@paramnoerr#1{% \ifnum#1<9\relax\else \skc@err{Number '\string#1' of parameters too large}{% You're limited to 8 parameters here.\MsgBrk If necessary, you can use keys to submit\MsgBrk more variables. In fact, you can use keys to\MsgBrk submit all your variables. }% \fi } \endinput %%% End of file skeycommand.sty %%%