% \iffalse meta-comment % !TeX program = pdfLaTeX %<*internal> \iffalse % %<*readme> pgfopts - LaTeX package options with pgfkeys ============================================ Using key-value options for packages and macros is a good way of handling large numbers of options with a clean interface. The `pgfkeys` package provides a very well designed system for defining and using keys, but does not make this available for handling LaTeX class and package options. The `pgfopts` package adds this ability to `pgfkeys`, in the same way that `kvoptions` extends the `keyval` package. Installation ------------ The package is supplied in `.dtx` format and as a pre-extracted zip file, `pgfopts.tds.zip`. The later is most convenient for most users: simply unzip this in your local `texmf` directory. If you want to unpack the `.dtx` yourself, running `tex pgfopts.dtx` will extract the package whereas 'latex pgfopts.dtx will extract it and also typeset the documentation. Typesetting the documentation requires a number of packages in addition to those needed to use the package. This is mainly because of the number of demonstration items included in the text. To compile the documentation without error, you will need the packages: - `csquotes` - `helvet` - `hypdoc` - `listings` - `lmodern` - `mathpazo` - `microtype` % %<*internal> \fi \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input docstrip.tex \keepsilent \askforoverwritefalse \preamble ---------------------------------------------------------------- pgfopts --- LaTeX package options with pgfkeys E-mail: joseph.wright@morningstar2.co.uk Released under the LaTeX Project Public License v1.3c or later See http://www.latex-project.org/lppl.txt ---------------------------------------------------------------- \endpreamble \postamble Copyright (C) 2008-2011,2013,2014 by Joseph Wright It may be distributed and/or modified under the conditions of the LaTeX Project Public License (LPPL), either version 1.3c of this license or (at your option) any later version. The latest version of this license is in the file: http://www.latex-project.org/lppl.txt This work is "maintained" (as per LPPL maintenance status) by Joseph Wright. This work consists of the file pgfopts.dtx and the derived files pgfopts.ins and pgfopts.pdf. \endpostamble \usedir{tex/latex/pgfopts} \generate{ \file{\jobname.sty}{\from{\jobname.dtx}{package}} } % %\endbatchfile %<*internal> \usedir{source/latex/pgfopts} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \nopreamble\nopostamble \usedir{doc/latex/pgfopts} \generate{ \file{README.txt}{\from{\jobname.dtx}{readme}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*driver> \documentclass[a4paper]{ltxdoc} \usepackage{csquotes,lmodern,pgfopts} \usepackage[osf]{mathpazo} \usepackage[scaled=0.95]{helvet} \usepackage[T1]{fontenc} \usepackage[final]{listings,microtype} \usepackage[numbered]{hypdoc} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % %\GetFileInfo{\jobname.sty} % %\makeatletter % %^^A For creating examples with nice highlighting of code, and so %^^A on; based on the system used in the listings source (lstsample). %\lst@RequireAspects{writefile} %\lstnewenvironment{LaTeXdemo}[1][code and example]^^A % {^^A % \global\let\lst@intname\@empty % \expandafter\let\expandafter\LaTeXdemo@end % \csname LaTeXdemo@#1@end\endcsname % \@nameuse{LaTeXdemo@#1}^^A % } % {\LaTeXdemo@end} %\newcommand*\LaTeXdemo@new[3]{^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1\endcsname}{#2}^^A % \expandafter\newcommand\expandafter*\expandafter % {\csname LaTeXdemo@#1@end\endcsname}{#3}^^A %} %\newcommand*\LaTeXdemo@common{^^A % \setkeys{lst} % { % basicstyle = \small\ttfamily, % basewidth = 0.51em, % gobble = 3, % keywordstyle = \color{blue}, % language = [LaTeX]{TeX}, % moretexcs = % { % pgfkeys , % ProcessPgfOptions , % ProcessPgfPackageOptions , % } % }^^A %} %\newcommand*\LaTeXdemo@input{^^A % \MakePercentComment % \catcode`\^^M=10\relax % \small % \begingroup % \setkeys{lst}^^A % {^^A % SelectCharTable=\lst@ReplaceInput{\^\^I}{\lst@ProcessTabulator} % }^^A % \leavevmode % \input{\jobname.tmp}^^A % \endgroup % \MakePercentIgnore %} %\LaTeXdemo@new{code only}{\LaTeXdemo@common}{} % %\MakeShortVerb\" %\DeleteShortVerb\| % %\providecommand*\file{\texttt} %\providecommand*\opt{\texttt} %\providecommand*\pkg{\textsf} % %\makeatother % %\title{^^A % \textsf{pgfopts} --- LaTeX package options with % \pkg{pgfkeys}\thanks{^^A % This file describes version \fileversion, last revised % \filedate.^^A % }^^A %} %\author{^^A % Joseph Wright\thanks{E-mail: joseph.wright@morningstar2.co.uk}^^A %} %\date{Released \filedate} % %\maketitle % %\changes{v1.0}{2008/06/26}{First public release} %\changes{v2.0}{2009/04/30}{Complete internal rewrite} %\changes{v2.1}{2011/06/02}{Allow for \texttt{.unknown} handler for % class options} %\changes{v2.1a}{2014/07/10}{Fix incorrect \cs{Provides\ldots} line} % %\begin{abstract} % Using key--value options for packages and macros is a good way of % handling large numbers of options with a clean interface. The % \pkg{pgfkeys} package provides a very well designed system for % defining and using keys, but does not make this available for % handling LaTeX class and package options. The \pkg{pgfopts} package % adds this ability to \pkg{pgfkeys}, in the same way that % \pkg{kvoptions} extends the \pkg{keyval} package. %\end{abstract} % %\tableofcontents % %\section{Introduction} % % The key--value method for optional arguments is very popular, as it % allows the class or package author to define a large number of % options with a simple interface. A number of packages can be used % to provide the key management system, most of which load or extent % the parent \pkg{keyval} package. On its own, \pkg{keyval} can only % be used for parsing the arguments of macros. However, a number of % packages have extended the method to processing LaTeX class and % package options. This processing is made available as part of two % general-purpose packages \pkg{xkeyval} and \pkg{kvoptions}; both % allow the author of a class or package to process key--value % options given at load-time. % % The \pkg{pgfkeys} package provides a somewhat different key--value % system to \pkg{keyval} and derivatives. This uses a completely % different model for defining and using keys, although for the % end-user the result appears very similar. The \pkg{pgfopts} package % allows keys defined with \pkg{pgfkeys} to be used as class or % package options, in the same way that \pkg{kvoptions} extends % \pkg{keyval}. % % Users of \pkg{pgfopts} should be familiar with the general methods % used by \pkg{pgfkeys}. These are outlined in the manual for the % Ti\emph{k}z and \pkg{pgf} bundle. % %\section{Installation} % % The package is supplied in \file{dtx} format and as a pre-extracted % zip file, \file{\jobname.tds.zip}. The later is most convenient for % most users: simply unzip this in your local texmf directory and % run \texttt{texhash} to update the database of file locations. If % you want to unpack the \file{dtx} yourself, running % \texttt{tex \jobname.dtx} will extract the package whereas % \texttt{latex \jobname.dtx} will extract it and also typeset the % documentation. % % Typesetting the documentation requires a number of packages in % addition to those needed to use the package. This is mainly % because of the number of demonstration items included in the text. To % compile the documentation without error, you will need the packages: % \begin{itemize} % \item \pkg{csquotes} % \item \pkg{helvet} % \item \pkg{hypdoc} % \item \pkg{listings} % \item \pkg{lmodern} % \item \pkg{mathpazo} % \item \pkg{microtype} %\end{itemize} % %\section{Using the package} % %\subsection{Creating options} % % To create package or class options for use with \pkg{pgfopts}, it is % only necessary to define the appropriate keys. Taking as an % example a package \enquote{\pkg{MyOwnPackage}}, which uses the prefix % \texttt{MOP} on internal macros, creating keys would take the form: %\begin{LaTeXdemo}[code only] % \pgfkeys{ % /MOP/.cd, % keyone/.code=\wlog{Value '#1' given}, % keytwo/.store in=\MOP@store % } %\end{LaTeXdemo} % Here, \opt{keyone} simply writes its argument to the log, while % \opt{keytwo} stores the value given in the \cs{MOP@store} macro. % % An important point to notice is that the key names \emph{do not} % contain a space. This is because the LaTeX kernel removes spaces % from options before they are passed to the class or package. Spaces % can occur in the path to the key, but not in the key name itself. % This restriction only applies to keys used as options. % %\subsection{Processing options} % %\DescribeMacro{\ProcessPgfOptions} % The \cs{ProcessPgfOptions} macro is used to process package or % class options using \pkg{pgfkeys}. When used in a package, it % will also examine the available class options, and use any which % match declared package options. \cs{ProcessPgfOptions} requires % the \pkg{pgfkeys} key \meta{path} to search for options. Thus % for the example of \pkg{MyOwnPackage} given in the previous % section, the appropriate call would be %\begin{LaTeXdemo}[code only] % \ProcessPgfOptions{/MOP} %\end{LaTeXdemo} % Alternatively, \cs{ProcessPgfOptions} can be given with a % star: %\begin{LaTeXdemo}[code only] % \ProcessPgfOptions* %\end{LaTeXdemo} % The macro will then use the current file name as the path. This will % be the name of the current class or package, as appropriate. % %\DescribeMacro{\ProcessPgfPackageOptions} %\changes{v2.0}{2010/05/01}{New \cs{ProcessPgfPackageOptions} % macro} % As a complement to \cs{ProcessPgfOptions}, the macro % \cs{ProcessPgfPackageOptions} is also provided. As the name indicates, % this is intended for use in packages. It does \emph{not} examine the % list of global class options, processing only the list of options % given for the class itself. If used in a class, the behaviour will % be identical to \cs{ProcessPgfOptions}. % %\StopEventually{^^A % \PrintChanges % \PrintIndex %} % %\section{Implementation} % % The code here is based heavily on \pkg{kvoptions}, which has a % similar aim to \pkg{pgfopts}, but works with \pkg{keyval} and derived % packages. % % \begin{macrocode} %<*package> \ProvidesPackage{pgfopts} [2014/07/10 v2.1a LaTeX package options with pgfkeys] % \end{macrocode} % % The only package requires is \pkg{pgfkeys} itself. % \begin{macrocode} \RequirePackage{pgfkeys} % \end{macrocode} % %\begin{macro}{\ifpgfopts@process@class} % The processing of options can apply to those which are given for % a class, or can be limited to those of the package only. % \begin{macrocode} \newif\ifpgfopts@process@class % \end{macrocode} %\end{macro} % %\begin{macro}{\pgfopts@options@clist} % A comma-separated list of options to process. % \begin{macrocode} \newcommand*\pgfopts@options@clist{} % \end{macrocode} %\end{macro} % %\begin{macro}{\pgfopts@options@execute} % A storage macro which specifies the final list of options to % actually execute. % \begin{macrocode} \newcommand*\pgfopts@options@execute{} % \end{macrocode} %\end{macro} % %\begin{macro}{\pgfopts@key@path} %\begin{macro}{\pgfopts@process@options} % The main processing macro first clears the list of options to deal % with, and stores the key path to use. Global and local options are % then added to the \enquote{to do} list before executing the options. % \begin{macrocode} \newcommand*\pgfopts@key@path{} \newcommand\pgfopts@process@options[1]{% \def\pgfopts@options@clist{}% \def\pgfopts@options@execute{}% \def\pgfopts@key@path{#1/}% \ifx\@currext\@clsextension\else \expandafter\pgfopts@check@class@options \fi \pgfopts@process@local@options \pgfopts@options@execute \let\CurrentOption\@empty \AtEndOfPackage{\let\@unprocessedoptions\relax}% } % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\pgfopts@current@option} %\begin{macro}{\pgfopts@check@class@options} %\begin{macro}{\pgfopts@check@class@options@aux} % First, a check to see if class options should be processed, and if so % if there are any. If so, then each option needs to be examined. Any % \texttt{=\meta{value}} is removed, and a test is made to see if % the resulting \meta{key} was defined for the current \meta{path}. % If so, the option is added to the list for processing later, and % it is removed from the list of unused options. The syntax for the % later process is rather complex, but LaTeX2e's function to % achieve that is somewhat awkward. % \begin{macrocode} \newcommand*\pgfopts@current@option{} \newcommand*\pgfopts@check@class@options{% \ifpgfopts@process@class \ifx\@classoptionslist\relax\else \expandafter\expandafter\expandafter \pgfopts@check@class@options@aux \fi \fi } \newcommand*\pgfopts@check@class@options@aux{% \@for\pgfopts@current@option:=\@classoptionslist\do {% \pgfkeysifdefined {% \pgfopts@key@path \pgfopts@get@key@name\pgfopts@current@option /.@cmd% }% {% \pgfopts@list@add\pgfopts@options@clist\pgfopts@current@option \@expandtwoargs\@removeelement\pgfopts@current@option \@unusedoptionlist\@unusedoptionlist }% {}% }% } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\pgfopts@local@options} %\begin{macro}{\pgfopts@process@local@options} %\begin{macro}{\pgfopts@process@local@options@aux@i} %\begin{macro}{\pgfopts@process@local@options@aux@ii} %\begin{macro}{\pgfopts@process@local@options@class} %\begin{macro}{\pgfopts@process@local@options@class@aux} %\begin{macro}{\pgfopts@process@local@options@package} % The first step in processing local options is to see if any exist. % This is done inside a group to avoid polluting the hash table. If % options are found, these are transferred into a storage macro and % the auxiliary function is called. There is then a fork depending on % whether a package or class is being processed. Once the list is % finalised, the execution macro is set up appropriately. % \begin{macrocode} \newcommand*\pgfopts@local@options{} \newcommand*\pgfopts@process@local@options{% \begingroup \@ifundefined{opt@\@currname.\@currext}% {\endgroup}% {% \toks@\expandafter\expandafter\expandafter {\csname opt@\@currname.\@currext\endcsname}% \expandafter\endgroup \expandafter\def\expandafter\pgfopts@local@options \expandafter{\the\toks@}% \pgfopts@process@local@options@aux@i }% } \newcommand*\pgfopts@process@local@options@aux@i{% \ifx\@currext\@clsextension \expandafter\pgfopts@process@local@options@class \else \expandafter\pgfopts@process@local@options@package \fi \ifx\pgfopts@options@clist\@empty\else \expandafter\pgfopts@process@local@options@aux@ii \fi } \newcommand*\pgfopts@process@local@options@aux@ii{% \begingroup \toks@\expandafter{\pgfopts@options@clist}% \edef\pgfopts@options@execute {% \noexpand\pgfkeys {% \pgfopts@key@path .cd,% \the\toks@ }% }% \expandafter\endgroup \expandafter\def\expandafter\pgfopts@options@execute \expandafter{\pgfopts@options@execute}% } % \end{macrocode} % Options given for a class may not be applicable to the class itself, % and so they have to be checked. First, there is a simple test for an % unknown key handler: if it exists then there is no need to look at % each option separately. % \begin{macrocode} \newcommand*\pgfopts@process@local@options@class {% \pgfkeysifdefined{\pgfopts@key@path .unknown/.@cmd}% {\pgfopts@list@add\pgfopts@options@clist\@classoptionslist} {\pgfopts@process@local@options@class@aux}% } \newcommand*\pgfopts@process@local@options@class@aux{% \@for\pgfopts@current@option:=\pgfopts@local@options\do{% \pgfkeysifdefined {% \pgfopts@key@path \pgfopts@get@key@name\pgfopts@current@option /.@cmd% }% {\pgfopts@list@add\pgfopts@options@clist\pgfopts@current@option}% {\pgfopts@list@add\@unusedoptionlist\pgfopts@current@option}% }% } % \end{macrocode} % For packages, the local options are simply added to the list already % set up from the global values. % \begin{macrocode} \newcommand*\pgfopts@process@local@options@package{% \pgfopts@list@add\pgfopts@options@clist\pgfopts@local@options } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\pgfopts@get@key@name} %\begin{macro}{\pgfopts@get@key@name@aux} % A simple function to leave only the key \meta{name} in the input % stream, whether there is a \meta{value} or not. This needs to work % with options which do not contain an equals sign at all. It is % designed to work with a stored value. % \begin{macrocode} \newcommand\pgfopts@get@key@name[1]{% \expandafter\pgfopts@get@key@name@aux#1=\@nil } \def\pgfopts@get@key@name@aux#1=#2\@nil{#1} % \end{macrocode} %\end{macro} %\end{macro} % %\begin{macro}{\pgfopts@list@add@a@toks} %\begin{macro}{\pgfopts@list@add@b@toks} %\begin{macro}{\pgfopts@list@add@temp} %\begin{macro}{\pgfopts@list@add} % This function takes "#1" as the name of a comma-separated list and % "#2" as the name of a macro containing content to add to the list. % After the appropriate checks it adds the content of "#2" to the % right hand end of variable "#1". % \begin{macrocode} \newtoks\pgfopts@list@add@a@toks \newtoks\pgfopts@list@add@b@toks \newcommand*\pgfopts@list@add@temp{} \newcommand\pgfopts@list@add[2]{% \pgfopts@list@add@a@toks\expandafter{#2}% \def\pgfopts@list@add@temp{#2}% \pgfopts@list@add@b@toks\expandafter{#1}% \ifx\pgfopts@options@clist\@empty \edef#1{\the\pgfopts@list@add@a@toks}% \else \ifx\pgfopts@list@add@temp\@empty\else \edef#1% {\the\pgfopts@list@add@b@toks,\the\pgfopts@list@add@a@toks}% \fi \fi } % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} %\end{macro} % %\begin{macro}{\ProcessPgfOptions} %\begin{macro}{\ProcessPgfPackageOptions} %\begin{macro}{\pgfopts@star@check} % The two user functions set the flag for class option processing. % A shared internal function then checks for a star, and either adds % the current name or looks to pick one up from the input stream. % \begin{macrocode} \newcommand*\ProcessPgfOptions{% \pgfopts@process@classtrue \pgfopts@star@check } \newcommand*\ProcessPgfPackageOptions{% \pgfopts@process@classfalse \pgfopts@star@check } \newcommand*\pgfopts@star@check{% \@ifstar {% \begingroup \edef\@tempa {% \endgroup \noexpand\pgfopts@process@options{/\@currname}% }% \@tempa }% {\pgfopts@process@options}% } \@onlypreamble\ProcessPgfOptions \@onlypreamble\ProcessPgfPackageOptions % % \end{macrocode} %\end{macro} %\end{macro} %\end{macro} % %\Finale