summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pgfopts/pgfopts.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/pgfopts/pgfopts.dtx')
-rw-r--r--macros/latex/contrib/pgfopts/pgfopts.dtx606
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