%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% % This is file 'skeyval.sty', version 1.1, 2012/10/15. % % % % 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. % % % % The following files constitute the skeyval bundle and must be % % distributed as a whole: % % % % readme, skeyval.sty, skeyval-core.tex, skeyval-for.tex, % % skeyval-view.sty, skeyval-ltxpatch.sty, skeyval-ltxcmds.tex, % % skeyval-pstkey.sty, skeyval-pstkey.tex, skeyval-testclass.cls, % % and skeyval-testpkg.sty. % % % % Copyright (c) 2010-2012 Ahmed Musa (amusa22@gmail.com). % %++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% \begingroup \catcode035 06 % # \catcode064 11 % @ \catcode123 01 % { \catcode125 02 % } \catcode044 12 % , \def\skv@prova{\endgroup \def\do##1,{% \ifx\do##1\else \catcode##1\string=\the\catcode##1\relax \expandafter\do \fi }% \edef\skv@restorecodes{\do035,064,123,125,061,059,\do,}% } \skv@prova \catcode035 06 % # \catcode064 11 % @ \catcode123 01 % { \catcode125 02 % } \catcode061 12 % = \catcode044 12 % , \def\do#1=#2,{% \ifx\do#1\else \edef\skv@restorecodes{% \skv@restorecodes \catcode#1=\the\catcode#1\relax }% \catcode#1=#2\relax \expandafter\do \fi } \do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,% 059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\do=,% \ProvidesPackage{skeyval}[2012/10/15 v1.1 Robust key-value parser (AM)] \NeedsTeXFormat{LaTeX2e}[2011/06/27] \input skeyval-core \skvrobustdef*\skvAfterEndPackage{% \skvifcsdef{\@currname.\@currext-skv@endpkghook}{}{% \@namedef{\@currname.\@currext-skv@endpkghook}{}% }% \expandafter\g@addto@macro \csname\@currname.\@currext-skv@endpkghook\endcsname } \skvrobustdef*\skvAfterPackage#1{% \skvAfterBeginDocument{% \skvifcsdef{ver@#1.\@pkgextension}{}{% \skv@warn{Package '#1' was never loaded}% }% } \skvifcsdef{ver@#1.\@pkgextension}{% \@firstofone }{% \skvappendtomacro{#1.\@pkgextension-skv@endpkghook}% }% } \xdef\@popfilename{% \unexpanded{% \csname\@currname.\@currext-skv@endpkghook\endcsname \expandafter\let \csname\@currname.\@currext-skv@endpkghook\endcsname\relax }% \unexpanded\expandafter{\@popfilename}% } \skvrobustdef*\skv@getdocumentclass{% \skv@swafalse \ifx\@filelist\@undefined\else \ifx\@filelist\relax\else \ifx\@filelist\@gobble\else\skv@swatrue\fi \fi\fi \ifskv@swa \skvcommaparse*\@filelist\skv@tempa{% \filename@parse\skv@tempa \ifx\filename@ext\@clsextension \skvifcsundef{opt@\filename@area\filename@base.\filename@ext}{}{% \edef\skv@documentclass{% \filename@area\filename@base.\filename@ext }% }% \fi \ifx\skv@documentclass\@undefined\else\skvbreakloop\fi }% \fi } \skv@getdocumentclass % Filter class options to remove those with '=': \skvrobustdef*\skv@filterclassoptions{% \skv@swafalse \ifx\@classoptionslist\@undefined\else \ifx\@classoptionslist\relax\else\skv@swatrue\fi \fi \ifskv@swa \let\skv@filterclassoptions\relax \skvkvnormalize\@classoptionslist \let\skv@origclassoptlist\@classoptionslist \let\skv@classoptionslist\@classoptionslist \let\@classoptionslist\@empty \skvcommaloop*\skv@origclassoptlist\skv@tempa{% \skvxifin{=}{\skvexpandonce\skv@tempa}{}{% \skvaddtolist*\@classoptionslist\skv@tempa }% }% \def\@fileswith@ptions##1[##2]##3{% \edef\skv@tempa{\unexpanded{##3}}% \skvcsvnormalize\skv@tempa % The following packages need access to the original % \@classoptionslist. \skvcommaloop{xkeyval,kvoptions,keyval2e,ltxkeys}\skv@prova{% \skvxifin{,\skv@prova,}{,\skv@tempa,}{% \let\@classoptionslist\skv@origclassoptlist \skvbreakloop }{}% }% \skvifnextchar[{\@fileswith@pti@ns##1[##2]##3}% {\@fileswith@pti@ns##1[##2]##3[]}% }% \fi } \skvifundef\skv@documentclass{% \let\skv@documentclass\@empty \let\skv@classoptionslist\@empty \edef\@popfilename{% \skvexpandonce\@popfilename\skv@filterclassoptions }% }{% \skv@filterclassoptions } \skvrobustdef*\skvBeforeBeginDocument{% \skvgappendtomacro\skv@beforebegindoc } \skvnewdef*\skv@beforebegindoc{} \skvprependtomacro\document{% \endgroup \let\skvBeforeBeginDocument\@firstofone \skv@beforebegindoc \gdef\skvBeforeBeginDocument{\skv@notprerr\skvBeforeBeginDocument}% \global\let\skv@beforebegindoc\relax \begingroup } \skvrobustdef*\skvAfterBeginDocument{% \skvgappendtomacro\skv@afterbegindoc } \skvnewdef*\skv@afterbegindoc{} \skvgappendtomacro\document{% \let\skvAfterBeginDocument\@firstofone \skv@afterbegindoc \gdef\skvAfterBeginDocument{\skv@notprerr\skvAfterBeginDocument}% \global\let\skv@afterbegindoc\relax \ignorespaces } \skvrobustdef*\skv@notprerr#1{% \@latex@error{Command \detokenize{#1} should be used only in preamble}\@ehd } \skvnewdef*\skv@everypagehook{} \skvrobustdef*\skvAtBeginEveryPage{\skvgappendtomacro\skv@everypagehook} \skvAfterBeginDocument{% \let\skv@savedoutputpage\@outputpage \def\@outputpage{% \let\skv@savedbegindvi\@begindvi \def\@begindvi{% \skv@everypagehook \skv@savedbegindvi }% \skv@savedoutputpage \let\@begindvi\skv@savedbegindvi }% } \skvnewdef*\skv@preamblecmdhook{} \skvrobustdef*\skvonlypreamble#1{% \skvcommaparse{#1}\skv@tempa{% \skvxifin{\detokenize\expandafter{\expandafter\do\skv@tempa}}% {\skvoxdetok\skv@preamblecmdhook}{% \skv@warn{Command '\skvexpandonce\skv@tempa' multiply \MessageBreak submitted to \string\skvonlypreamble: ignored}% }{% \xdef\skv@preamblecmdhook{% \skvexpandonce\skv@preamblecmdhook \unexpanded\expandafter{\expandafter\do\skv@tempa}% }% }% }% } \AtEndOfPackage{% \skvAfterBeginDocument{% \def\do#1{% \skvifdef#1{% \gdef#1{\@latexerr{'\string#1' is a preamble command}\@ehd}% }{% \@@warning{Undefined command '\unexpanded{#1}' appeared in \string\skvonlypreamble}% }% }% \skv@preamblecmdhook \let\skv@preamblecmdhook\relax \let\do\relax }% } %%+++++++++++++++++ Utilities for handling options ++++++++++++++++%% % \skvunknownoptionhandler[]<>{} % \skvrobustdef*\skvunknownoptionhandler{% \skv@testopt\skv@unknownoptionhandler{KV}% } \skvrobustdef*\skv@unknownoptionhandler[#1]{% \skvifnextchar<{\skv@unkn@wnoptionhandler{#1}}% {\skv@unkn@wnoptionhandler{#1}<\@currname.\@currext>}% } \skvrobustdef*\skv@unkn@wnoptionhandler#1<#2>{% \skv@unknownkeyhandler[#1]{#2}% } \skvrobustdef*\skv@testopte#1{\skv@testopta{\skv@t@stopte{#1}}} \skvrobustdef*\skv@t@stopte#1{\skv@testopt{\skv@t@st@pte{#1}}{KV}} \skvrobustdef*\skv@t@st@pte#1[#2]{% % Only one prefix is allowed: \skvxifin{,}{\detokenize{#2}}{% \skv@err{Only one prefix is allowed, but you gave '#2'}\@ehd }{% \skv@makeprefix{#2}% \skvifnextchar<{\skv@@t@st@pte{#1}}% {\skv@@t@st@pte{#1}<\@currname.\@currext>}% }% } \skvrobustdef*\skv@@t@st@pte#1<#2>{% \edef\skv@fams{#2}% \skvxifin{,}{\detokenize{#2}}{% \skvcsvnormalize\skv@fams }{% \skvdespacecontent\skv@fams }% \skv@testopt{#1}{}% } \skvrobustdef*\skveveryunknownoption{\skvdeclareoption*} % \skvdeclareoption[]<>{}[]{} % \skvdeclareoption*{} \skvrobustdef*\skvdeclareoption{% \let\@fileswith@pti@ns\@badrequireerror \let\skvdefkey\skvordkey \skvifstar\skv@dox\skv@dox@a } % \skvdeclarevoidoption[]<>{}[]{} \skvrobustdef*\skvdeclarevoidoption{% \let\@fileswith@pti@ns\@badrequireerror \let\skvdefkey\skvvoidkey \skv@dox@a } % \skvdeclarebooloption[]<>[]{}[]{} \skvrobustdef*\skvdeclarebooloption{% \let\@fileswith@pti@ns\@badrequireerror \let\skvdefkey\skvboolkey \skv@dox@a } % \skvdeclarecmdoption[]<>[]{}[]{} \skvrobustdef*\skvdeclarecmdoption{% \let\@fileswith@pti@ns\@badrequireerror \let\skvdefkey\skvcmdkey \skv@dox@a } % Our default action for unknown options is tied to \@currname & \@currext: \skvrobustdef\skv@dox#1{% \skvcsedef{skv@dox@\@currname @\@currext}{% \unexpanded{% \begingroup \ifx\skvcurrentvalue\skv@novaluetoks \def\skvcurrentvalue{no value}% \fi \@onelevel@sanitize\CurrentOption \@onelevel@sanitize\skvcurrentvalue #1% \endgroup }% }% } \skvrobustdef*\skv@dox@a{\skv@testopt\skv@dox@b{KV}} \skvrobustdef*\skv@dox@b[#1]{% \skvifnextchar<% {\skv@dox@c{#1}}% {\skv@dox@c{#1}<\@currname.\@currext>}% } \skvrobustdef*\skv@dox@c#1<#2>{\skvdefkey[#1]{#2}} % \skvexecuteoptions+[][]{} % This has no star (*) variant; any star suffix is quietly ignored. \skvrobustdef*\skvexecuteoptions{% \skv@testopte{\skv@stfalse\skv@setkeys@a}% } % \skvprocessoptions*+[]{}[] % % 1. If not using LaTeX, then no processing of options. % 2. The plus (+) variant of \skvprocessoptions will process the options % in all the listed families. But the star form of \skvprocessoptions % doesn't seem to make sense here, since - unlike in LaTeX2e - a star % suffix here would mean 'save unknown keys'. It is meaningless to seek % to save unknown keys when processing options. Any star (*) suffix on % \skvprocessoptions is, therefore, quietly ignored. % 3. Class options are always processed first, but class options ocurring % also local/package options are dropped from the list of options % to be processed. \skvrobustdef*\skvprocessoptions{\skv@testopte\skv@pox} \skvrobustdef*\skv@pox[#1]{% \skv@inpoxtrue \let\@fileswith@pti@ns\@badrequireerror \begingroup \let\skv@classoptsfound\@empty \let\skv@exitpoxkeys\@empty \edef\skv@testclass{\@currname.\@currext}% \skvifx\skv@testclass\skv@documentclass{% \let\@unusedoptionlist\skv@classoptionslist }{% \skv@swafalse \ifx\skv@classoptionslist\@empty\else \ifskv@st\skv@swatrue\fi \fi \skvifnotbool{skv@swa}{}{% \skvcommaloop*\skv@classoptionslist\CurrentOption{% \expandafter\expandafter\expandafter \skv@g@tkeyname\CurrentOption=\skv@nil\skvcurrentkey \skvexpanded{% % Test if key is defined in one of the families. The search will % stop as soon as the key is found in any of the families. \skvifkeyundef[\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}% }{}{% \edef\skv@classoptsfound{% \skvexpandonce\skv@classoptsfound \ifx\skv@classoptsfound\@empty\else,\fi \skvexpandonce\CurrentOption }% \expandafter\skv@useoption\expandafter{\CurrentOption}% }% }% \ifx\skv@classoptsfound\@empty\else\skvafterfi \skvexpbracenext\skv@getkeynames\skv@classoptsfound\skv@tempd \skvexpbracenext\skv@getpoxkeys\skv@tempd \fi }% }% \skvletcs\skv@pkgorclsopts{opt@\@currname.\@currext}% \skvifx\skv@pkgorclsopts\@empty{}{% \skvifx\skv@pkgorclsopts\relax{}{% \skvexpbracenext\skv@getkeynames\skv@pkgorclsopts\skv@tempd \skvexpbracenext\skv@getpoxkeys\skv@tempd }% }% % Package options have higher priority than class options. Hence % filter class options \skv@classoptsfound that are also present % as package options \skv@pkgorclsopts: \ifcase0\ifx\skv@classoptsfound\@empty0\else \ifx\skv@pkgorclsopts\@empty0\else \ifx\skv@pkgorclsopts\relax0\else1\fi\fi\fi\relax \else\skvafterfi \skvifx\skv@testclass\skv@documentclass{}{% \skvcommaloop*\skv@classoptsfound\CurrentOption{% \expandafter\expandafter\expandafter \skv@g@tkeyname\CurrentOption=\skv@nil\skv@tempa \skvxifin{,\skvoxdetok\skv@tempa,}{,\skvoxdetok\skv@tempd,}{}{% \edef\skv@pkgorclsopts{% \skvexpandonce\skv@pkgorclsopts,\skvexpandonce\CurrentOption }% }% }% }% \fi \skvexpanded{\endgroup \skv@exitpoxkeys % There may be preset keys even when \skv@pkgorclsopts is empty: \skvsetkeys\ifskv@pl+\fi[\skvcurrentprefix]{\skv@fams}[#1]% {\skvexpandonce\skv@pkgorclsopts}% }% \skvcslet{skv@dox@\@currname @\@currext}\relax \skvinitializermkeys*\skvcurrentprefix\skv@fams \skv@inpoxfalse \let\@fileswith@pti@ns\@@fileswith@pti@ns \AtEndOfPackage{\let\@unprocessedoptions\relax}% \csname skv@\@currname @\@currext @afterprocess@hook\endcsname \skvcslet{skv@\@currname @\@currext @afterprocess@hook}\relax } % \skvrestrictedprocessoptions*+[]{}[] % 1. This will not process class options, but only options % issued to the package. \skvrobustdef*\skvrestrictedprocessoptions{\skv@testopte\skv@restrictedpox} \skvrobustdef*\skv@restrictedpox[#1]{% \skv@inpoxtrue \let\@fileswith@pti@ns\@badrequireerror \begingroup \let\skv@exitpoxkeys\@empty \let\skv@pkgorclsopts\@empty \skvletcs\skv@pkgorclsopts{opt@\@currname.\@currext}% \ifcase0\ifx\skv@pkgorclsopts\@empty0\else \ifx\skv@pkgorclsopts\relax0\else1\fi\fi\relax \else\skvafterfi \skvexpbracenext\skv@getkeynames\skv@pkgorclsopts\skv@tempd \skvexpbracenext\skv@getpoxkeys\skv@tempd \fi \skvexpanded{\endgroup \skv@exitpoxkeys \skvsetkeys\ifskv@pl+\fi[\skvcurrentprefix]{\skv@fams}[#1]% {\skvexpandonce\skv@pkgorclsopts}% }% \skvcslet{skv@dox@\@currname @\@currext}\relax \skvinitializermkeys*\skvcurrentprefix\skv@fams \skv@inpoxfalse \let\@fileswith@pti@ns\@@fileswith@pti@ns \AtEndOfPackage{\let\@unprocessedoptions\relax}% \csname skv@\@currname @\@currext @afterprocess@hook\endcsname \skvcslet{skv@\@currname @\@currext @afterprocess@hook}\relax } % Get pox keys (ie, keys processed as options) from package or % class options: \skvrobustdef*\skv@getpoxkeys#1{% \skvcommaloop{#1}\skvcurrentkey{% \skvexpanded{% \skvifkeynotinfamilies [\skvcurrentprefix]{\skv@fams}{\skvcurrentkey}% }{}{% % \skv@header is formed in the search for the key: \skvletcs\skv@prova{\skv@header.@poxkeys}% \skvifdef\skv@prova{% \skvxifin{,\skvoxdetok\skvcurrentkey,}{,\skvoxdetok\skv@prova,}{}{% \skvcsedef{\skv@header.@poxkeys}{\skv@prova,\skvcurrentkey}% }% }{% \skvcsedef{\skv@header.@poxkeys}{\skvcurrentkey}% }% \skvxifin{\skvoxdetok\skv@header}{\skvoxdetok\skv@exitpoxkeys}{}{% \edef\skv@exitpoxkeys{% \skvexpandonce\skv@exitpoxkeys \noexpand\skvcsexit{\skv@header.@poxkeys}% }% }% }% }% } % +++++++++ Utilities for handling options via \directkeys +++++++++% \skvrobustdef*\dirkeys@declareoptions@a{% \let\@fileswith@pti@ns\@badrequireerror \skv@dox } \skvrobustdef*\dirkeys@declareoptions@b#1{% \let\@fileswith@pti@ns\@badrequireerror \skv@inopttrue \begingroup \edef\skv@tempb{\unexpanded{#1}}% \def\skv@tempa{}% \def\do##1##2{% \edef\skv@tempa{% \skvexpandonce\skv@tempa \skvdefinekeys\ifskv@handlerswa*\fi[##1]{##2}% [\dirkeys@holderprefixtoks]{\skvexpandonce\skv@tempb}% }% }% \dirkeys@getcurrentroots\do \expandafter\endgroup\skv@tempa \skv@inoptfalse } \skvrobustdef*\dirkeys@executeoptions#1{% \skv@inopttrue \begingroup \edef\skv@tempb{\unexpanded{#1}}% \def\skv@tempa{}% \def\do##1##2{% \edef\skv@tempa{% \skvexpandonce\skv@tempa \skvsetkeys\ifskv@handlerswa+\fi [##1]{##2}[\skvcsuse{##1/##2/.@ignoredkeys}]% {\skvexpandonce\skv@tempb}% }% }% \dirkeys@getcurrentroots\do \expandafter\endgroup\skv@tempa \skv@inoptfalse } \skvrobustdef*\dirkeys@executeoptions@b#1{% \skv@inopttrue \begingroup \def\skv@tempa{}\def\skv@tempb{}\def\skv@tempc{}% \def\do##1##2{% \skvxifin{,##1,}{,\skv@tempa,}{}{% \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}% }% \skvxifin{,##2,}{,\skv@tempb,}{}{% \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}% }% \edef\skv@tempc{% \skv@tempc\ifx\skv@tempc\@empty\else,\fi \skvcsuse{##1/##2/.@ignoredkeys}% }% }% \dirkeys@getcurrentroots\do \@tempcnta\skvz@ \let\skv@tempd\skv@tempa \skvcommaloop*\skv@tempa\skv@prova{% \advance\@tempcnta\@ne \ifnum\@tempcnta>\@ne \skv@err{You can't submit more than one prefix here}\@ehd \skvbreakloop \fi }% \skvexpanded{\endgroup \skvsetkeys\ifskv@handlerswa+\fi[\skv@tempd]{\skv@tempb}[\skv@tempc]% }{#1}% \skv@inoptfalse } \skvrobustdef*\dirkeys@processoptions{% \skv@inopttrue \begingroup \def\skv@tempa{}% \def\do##1##2{% \edef\skv@tempa{% \skvexpandonce\skv@tempa \skvprocessoptions\ifskv@handlerswa*\fi\ifskv@handlerswb+\fi [##1]<##2>[\skvcsuse{##1/##2/.@ignoredkeys}]% }% }% \dirkeys@getcurrentroots\do \expandafter\endgroup\skv@tempa \skv@inoptfalse } \skvrobustdef*\dirkeys@processoptions@b{% \skv@inopttrue \begingroup \def\skv@tempa{}\def\skv@tempb{}\def\skv@tempc{}% \def\do##1##2{% \skvxifin{,##1,}{,\skv@tempa,}{}{% \edef\skv@tempa{\skv@tempa\ifx\skv@tempa\@empty\else,\fi##1}% }% \skvxifin{,##2,}{,\skv@tempb,}{}{% \edef\skv@tempb{\skv@tempb\ifx\skv@tempb\@empty\else,\fi##2}% }% \edef\skv@tempc{% \skv@tempc\ifx\skv@tempc\@empty\else,\fi \skvcsuse{##1/##2/.@ignoredkeys}% }% }% \dirkeys@getcurrentroots\do \@tempcnta\skvz@ \let\skv@tempd\skv@tempa \skvcommaloop*\skv@tempa\skv@prova{% \advance\@tempcnta\@ne \ifnum\@tempcnta>\@ne \skv@err{You can't submit more than one prefix here}\@ehd \skvbreakloop \fi }% \skvexpanded{\endgroup \skvprocessoptions\ifskv@handlerswa+\fi [\skv@tempd]<\skv@tempb>[\skv@tempc]% }% \skv@inoptfalse } % ++++++++ Keys for the handler <.mega process options> +++++++++ % \directkeys*{% .prefix=SKV, .family=megapox, .holder prefix=dirkeys@pox@, .initialize keys after define=true, .new keys={ .ord/.ignore options// \def\dirkeys@pox@igkeys{#1} \skvstripouterbraces{2}\dirkeys@pox@igkeys , .ord/.options prefix/KV/ \skvxifin{,}{\detokenize{#1}}{ \skv@err{Only one prefix is allowed in processing options}\@ehd }{ \def\dirkeys@pox@pref{#1} \skvstripouterbraces{2}\dirkeys@pox@pref } , .ord/.options families/\@currname.\@currext/ \edef\dirkeys@pox@fams{#1} \skvstripouterbraces{2}\dirkeys@pox@fams , .ord/.copy class options/true/ \edef\dirkeys@pox@copyclass{\skvifstrcmp{#1}{true}{00}{01}} , }, .styles={ .prefix/.options prefix=#1, .options family/.options families=#1, .family/.options families=#1, .families/.options families=#1, .include class options/.copy class options=#1, }, } %\skvshowcs{SKV/megapox/.options family.@cbk} %\skvshowcs{SKV/megapox/.pref.@cbk} \skvrobustdef*\dirkeys@megaprocessoptions#1{% \skvpushfunctions\dirkeys@megaprocessoptions{% \do\dirkeys@pox@pref\do\dirkeys@pox@fams \do\dirkeys@pox@igkeys\do\dirkeys@pox@copyclass }\skv@gendepth \skv@inopttrue \skvsetkeys[SKV]{megapox}{#1}% \skvexpanded{% \skvprocessoptions\if\dirkeys@pox@copyclass*\fi+% [\dirkeys@pox@pref]<\dirkeys@pox@fams>[\dirkeys@pox@igkeys]% }% \skv@inoptfalse \skvpopfunctions\dirkeys@megaprocessoptions\skv@gendepth } % +++++++++++++ Handlers for processing options ++++++++++++++ % \directkeys*{% .new handlers={ .action for unknown options=\dirkeys@declareoptions@a{#1}, .declare options={ \skv@handlerswafalse\dirkeys@declareoptions@b{#1} }, .new options={ \skv@handlerswatrue\dirkeys@declareoptions@b{#1} }, % Handler <.execute options> has no star variant, since we don't % want to ignore unknown options from within package or class. .execute options={ \skv@handlerswafalse\dirkeys@executeoptions{#1} }, .execute options+={ \skv@handlerswatrue\dirkeys@executeoptions@b{#1} }, % 1. All <.process options> handlers will filter out ignored paths % and keys. % 2. <.process options*> will copy class options. % 3. <.process options+> will set options in all the active families % in which the options exist. % 4. <.process options*+> will copy class options and set options in % all the active families in which the options are found. .process options={ \skv@handlerswafalse\skv@handlerswbfalse\dirkeys@processoptions }, .process options*={ \skv@handlerswatrue\skv@handlerswbfalse\dirkeys@processoptions }, .process options+={ \skv@handlerswafalse\skv@handlerswbtrue\dirkeys@processoptions@b }, .process options*+={ \skv@handlerswatrue\skv@handlerswbtrue\dirkeys@processoptions@b }, % The handler <.mega process options> will: % 1. Search all families in its key . % 2. Not perform filtering of ignored paths and keys; in fact, will not % use active paths and keys. % 3. The handler '.mega process options' has the keys , % , , and . % These keys have aliases. % See an example later in this file. .mega process options={ \dirkeys@megaprocessoptions{#1} }, .mega process options*={ \dirkeys@megaprocessoptions{#1,copy class options} }, }, .handler let={ .action for unknown option=.action for unknown options, .every unknown option=.action for unknown options, .define options=.declare options, .processoptions=.process options, .processoptions*=.process options*, .copy class options and process options in all active families= .process options*+, .copy class options and process options in all families= .process options*+, .copy class options and process options=.process options*, .executeoptions=.execute options, }, } %\skvshowcs{dirkeys@handler@.every unknown option} % Loading a package while in options section is illegal. The command % \skvafterprocessoptions can be used to defer the loading of packages % till after the options section: \skvrobustdef*\skvafterprocessoptions{% \expandafter\skvgappendtomacro \csname skv@\@currname @\@currext @afterprocess@hook\endcsname } \skvnewlet\skvAfterProcessOptions\skvafterprocessoptions \skvnewlet\skvifpackageloaded\@ifpackageloaded \def\skv@visiteduseoptions{01} \skvrobustdef*\skv@useoption#1{% \if\skv@visiteduseoptions\else\skvafterfi \skvcsvnormalize\@unusedoptionlist \def\skv@visiteduseoptions{00}% \fi \begingroup \def\do##1=##2=##3\useoption@nil{% \edef\CurrentOption{\skvtrimspace{##1}}% \def\skv@tempa{}% \def\do####1=####2=####3\useoption@nil{% \edef\reserved@a{\skvtrimspace{####1}}% }% \skvcommaloop*\@unusedoptionlist\skv@prova{% \expandafter\do\skv@prova==\useoption@nil \ifx\reserved@a\CurrentOption\else \edef\skv@tempa{% \skv@tempa\ifx\skv@tempa\@empty\else,\fi\skv@prova }% \fi }% \let\@unusedoptionlist\skv@tempa }% \@onelevel@sanitize\@unusedoptionlist \expandafter\do\detokenize{#1}==\useoption@nil \skvaftergroupdef\@unusedoptionlist\endgroup } \skvonlypreamble{% \skvdeclareoption,\skvexecuteoptions,\skvprocessoptions,\skv@useoption } %+++++++++++++++++ This package's options section ++++++++++++++++++% \skvrobustdef*\setupskeyval{\skvsetkeys[SKV]{skeyval}} \skv@inoptionsectrue %\skvshowcs{dirkeys@handler@.every unknown option} \directkeys*{% .prefix=SKV, .family=skeyval, .holder prefix=skv@, .every unknown option={ \@onelevel@sanitize\CurrentOption \PackageWarning{skeyval}{Unknown option '\CurrentOption'}% }, .new options={ .bool/tracingkeys/true, .ords/{keyparser,key parser}/{,}/ \def\skv@keyparser{#1}% \skvstripouterbraces{2}\skv@keyparser, .bool/compatibility/true/ \ifskv@compatibility \skvAfterProcessOptions{% \skvifpackageloaded{skeyval-bc}{}{% \RequirePackage{skeyval-bc}% } }% \fi , }, .execute options={ tracingkeys,keyparser }, .mega process options={ .options prefix=SKV, .options families={skeyval,definekeys}, .ignore options={}, .copy class options, }, } %\skvshowcs{SKV/skeyval/keyparser.@cbk} \skv@inoptionsecfalse \skv@restorecodes \endinput