diff options
Diffstat (limited to 'macros/latex/contrib/pgfopts/pgfopts.dtx')
-rw-r--r-- | macros/latex/contrib/pgfopts/pgfopts.dtx | 606 |
1 files changed, 606 insertions, 0 deletions
diff --git a/macros/latex/contrib/pgfopts/pgfopts.dtx b/macros/latex/contrib/pgfopts/pgfopts.dtx new file mode 100644 index 0000000000..0a33eb88dc --- /dev/null +++ b/macros/latex/contrib/pgfopts/pgfopts.dtx @@ -0,0 +1,606 @@ +% \iffalse meta-comment +% !TeX program = pdfLaTeX +%<*internal> +\iffalse +%</internal> +%<*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` +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*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 <joseph.wright@morningstar2.co.uk> + +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}} +} +%</install> +%<install>\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 +%</internal> +%<*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} +%</driver> +% \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 +%</package> +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\Finale |