%--------------------------------------------------------------------------- % Copyright 2015 Daan Leijen, Microsoft Corporation. % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) 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. %--------------------------------------------------------------------------- \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{options}[2015/03/01, Daan Leijen, Provides convenient path-value (or key-value) options] \RequirePackage{etoolbox} \RequirePackage{xcolor} \newif\ifopt@debug \DeclareOption{debug}{\opt@debugtrue} \ProcessOptions\relax % -------------------------------------------------------- % make the package robust agains catcode changes of = and , % -------------------------------------------------------- \edef\opt@restore@catcodes{% \catcode`\noexpand\=\the\catcode`\=\relax \catcode`\noexpand\,\the\catcode`\,\relax \let\noexpand\opt@catcodes\relax } \catcode`\=12\relax \catcode`\,12\relax % -------------------------------------------------------- % Extensions to etoolbox % -------------------------------------------------------- \providecommand*\@swaparg[2]{#2{#1}} \providecommand*\expandnext[2]{\expandafter\@swaparg\expandafter{#2}{#1}} \providecommand*\@swaptwo[2]{#2#1} \providecommand*\expandnextcmds[2]{\expandafter\@swaptwo\expandafter{#2}{#1}} % unsafe expand next if the command is a single token.. \providecommand*\expandnextsingle[2]{\expandafter#1\expandafter{#2}} \providecommand*\eifstrequal[1]{\expandnextsingle\ifstrequal{#1}} \providecommand*\eifblank[1]{\expandnextsingle\ifblank{#1}} \providecommand*\ontoggle[2]{\iftoggle{#1}{#2}{}} \providerobustcmd*\providelength[1]{\ifdef{#1}{}{\newlength#1}} \providerobustcmd*\csnewlength[1]{\expandafter\newlength\csname #1\endcsname} \providerobustcmd*\csprovidelength[1]{\ifcsdef{#1}{}{\expandafter\newlength\csname #1\endcsname}} \providerobustcmd*\cssetlength[2]{\expandafter\setlength\csname #1\endcsname{#2}} % -------------------------------------------------------- % Basic option commands % \option{} returns the value of a path % \letoption{}\cmd let's \cmd to the value of % -------------------------------------------------------- \newcommand*\optionname[1]{optk@#1} \newcommand*\option[1]{\csname optk@#1\endcsname} \newcommand*\letoption[2]{\expandafter\let\expandafter#2\csname optk@#1\endcsname} % \letoption@ will not be redefined for debugging and can be used to test if an option exists \let\letoption@\letoption % -------------------------------------------------------- % options, optionsalso % main path setting routine % -------------------------------------------------------- \newif\ifopt@allowsearch % allow searching along search-also handlers \newif\ifopt@ignoreunknown % ignore unknown options? \newif\ifopt@unknownwarnonly % issue just a warning on an unknown option? (instead of an error) % process options together with remaining ones from a previous run \newrobustcmd*\optionswithremaining[1]{% \letoptionlist{/options/remaining}\opt@savedremaining \options{#1}% %\typeout{now process: \meaning\opt@savedremaining, in default: \option@defaultpath}% \expandnextsingle\optionsalso{\opt@savedremaining}% } % process options \newrobustcmd*\options{% \def\option@defaultpath{}% \opt@allowsearchtrue% \opt@ignoreunknownfalse% \opt@unknownwarnonlyfalse% \optionsalso% } % track nesting level of options (due to calls to options in an argument) \newif\ifopt@nested \newcount\opt@nesting % Process options in the context of an other options call % For efficiency, only save state if nested \newrobustcmd*\optionsalso[1]{% \ifopt@nested \optionsalso@save{#1}% save state in a nested context for chained handlers \else \opt@nestedtrue \opt@parse#1,\opt@stop,% \opt@nestedfalse \fi } % this saves and restores any nested state: for now only about chained handlers \newrobustcmd*\optionsalso@save[1]{% \opt@savestate{\the\opt@nesting}% \advance\opt@nesting 1\relax \opt@parse#1,\opt@stop,% \advance\opt@nesting -1\relax \opt@restorestate{\the\opt@nesting}% } \newrobustcmd*\opt@savestate[1]{% \cslet{option@handlernext#1}\option@handlernext% \cslet{option@handlerpath#1}\option@handlerpath% \cslet{optionvalue#1}\optionvalue% \def\option@handlernext{}% \def\option@handlerpath{}% } \newrobustcmd*\opt@restorestate[1]{% \letcs\option@handlernext{option@handlernext#1}% \letcs\option@handlerpath{option@handlerpath#1}% \letcs\optionvalue{optionvalue#1}% } % Qualified options -- mostly for here for compatibility with pgfqkeys \newrobustcmd*\qoptions[2]{% \def\option@defaultpath{#1}% \opt@allowsearchtrue% \opt@ignoreunknownfalse% \optionsalso{#2}% } % Qualified optionsalso \newrobustcmd*\qoptionsalso[2]{% \def\option@defaultpath{#1}% \optionsalso{#2}% } %----------------------------------------------------------------------- % The main option processing % % For an option