From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- .../doc/text-en/pgfmanual-en-pgfkeysfiltered.tex | 576 +++++++++++++++++++++ 1 file changed, 576 insertions(+) create mode 100644 graphics/pgf/base/doc/text-en/pgfmanual-en-pgfkeysfiltered.tex (limited to 'graphics/pgf/base/doc/text-en/pgfmanual-en-pgfkeysfiltered.tex') diff --git a/graphics/pgf/base/doc/text-en/pgfmanual-en-pgfkeysfiltered.tex b/graphics/pgf/base/doc/text-en/pgfmanual-en-pgfkeysfiltered.tex new file mode 100644 index 0000000000..d93c8b8c0e --- /dev/null +++ b/graphics/pgf/base/doc/text-en/pgfmanual-en-pgfkeysfiltered.tex @@ -0,0 +1,576 @@ + +\subsection{Key Filtering} +\begingroup + +{\small \emph{An extension by Christian Feuersänger}} +\vspace{0.4cm}% + +\noindent Normally, a call to |\pgfkeys| sets all keys provided in its argument +list. This is usually what users expect it to do. However, implementations of +different packages or \pgfname-libraries may need more control over the key +setting procedure: library~A may want to set its options directly and +communicate all remaining ones to library~B. + +This section describes key filtering methods of \pgfname, including options for +family groupings. If you merely want to use \pgfname\ (or its libraries), you +can skip this section. It is addressed to package (or library) authors. + + +\subsubsection{Starting With An Example} +\label{section-key-filter-example} + +Users of |xkeyval| are familiar with the concept of key families: keys belong +to groups and those keys can be `filtered' out of other options. \pgfname\ +supports family groupings and more abstract key selection mechanism with +|\pgfkeysfiltered|, a variant of |\pgfkeys|. Suppose we have the example key +grouping + +\pgfkeys{ + /my group/A1/.code=(A1:#1), + /my group/A2/.code=(A2:#1), + /my group/A3/.code=(A3:#1), + /my group/B/.code=(B:#1), + /my group/C/.code=(B:#1), + /my group/A/.is family, + /my group/A1/.belongs to family=/my group/A, + /my group/A2/.belongs to family=/my group/A, + /my group/A3/.belongs to family=/my group/A, + /pgf/key filters/active families/.install key filter, + /my group/A/.activate family, +}% +\begin{codeexample}[code only] +\pgfkeys{ + /my group/A1/.code=(A1:#1), + /my group/A2/.code=(A2:#1), + /my group/A3/.code=(A3:#1), + /my group/B/.code=(B:#1), + /my group/C/.code=(B:#1), +} +\end{codeexample} + +\noindent and we want to set options |A1|, |A2| and |A3| only. A call to +|\pgfkeys| yields +% +\begin{codeexample}[] +\pgfkeys{/my group/A1=a1, /my group/A2=a2, /my group/B=b, /my group/C=c} +\end{codeexample} +% +\noindent because all those command option are processed consecutively. + +Now, let's define a family named |A| which contains |A1|, |A2| and |A3| and set +only family members of |A|. We prepare our key settings with +% +\begin{codeexample}[code only] +\pgfkeys{ + /my group/A/.is family, + /my group/A1/.belongs to family=/my group/A, + /my group/A2/.belongs to family=/my group/A, + /my group/A3/.belongs to family=/my group/A, +} +\end{codeexample} +% +\noindent and +% +\begin{codeexample}[code only] +\pgfkeys{/pgf/key filters/active families/.install key filter} +\end{codeexample} +% +\noindent After this preparation, we can use |\pgfkeysfiltered| with +% +\begin{codeexample}[] +\pgfkeys{/my group/A/.activate family} +\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2, + /my group/B=b, /my group/C=c} +\end{codeexample} +% +\noindent or +% +\begin{codeexample}[] +\pgfkeys{/my group/A/.activate family} +\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2, + /my group/B=b, /my group/C=c, /tikz/color=blue, /my group/A3=a3} +\end{codeexample} +% +\noindent to set only keys which belong to an `active' family -- in our case, +only family~|A| was active, so the remaining options have not been processed. +The family processing is quite fast and allows an arbitrary number of active +key families. + +Unprocessed options can be collected into a macro (similar to |xkeyval|'s +|\xkv@rm|), discarded or handled manually. The details of key selection and +family declaration are described in the following sections. + + +\subsubsection{Setting Filters} + +The command |\pgfkeysfiltered| is the main tool to process only selected +options. It works as follows. +% +\begin{command}{\pgfkeysfiltered\marg{key--value-list}} + Processes all options in exactly the same way as + |\pgfkeys|\marg{key--value-list}, but a key filter is considered as soon as + key identification is complete. + + The key filter tells |\pgfkeysfiltered| whether it should continue to apply + the current option (return value is `true') or whether something different + shall be done (filter returns `false'). + + There is exactly one key filter in effect, and it is installed by the + |.install key filter| handler or by |\pgfkeysinstallkeyfilter|. + + If the key filter returns `false', a unique key filter handler gets + control. This handler is installed by the |.install key filter handler| + method and has access to the key's full name, value and (possibly) path. + + Key filtering applies to any (possibly nested) call to |\pgfkeys|, + |\pgfkeysalso|, |\pgfqkeys| and |\pgfqkeysalso| during the evaluation of + \marg{key--value-list}. It does \emph{not} apply to routines like + |\pgfkeyssetvalue| or |\pgfkeysgetvalue|. Furthermore, keys belonging to + |/errors| are always processed. Key filtering routines can't be nested: you + can't combine different key filters automatically. +\end{command} + +\begin{command}{\pgfqkeysfiltered\marg{default-path}\marg{key--value-list}} + A variant of |\pgfkeysfiltered| which uses the `quick' search path setting. + It is the |\pgfqkeys| variant of |\pgfkeysfiltered|, see the documentation + for |\pgfqkeys| for more details. +\end{command} + +\begin{command}{\pgfkeysalsofrom\marg{macro}} + A variant of |\pgfkeysalso| which loads its key list from \marg{macro}. + + It is useful in conjunction with the + |/pgf/key filter handlers/append filtered to=|\meta{macro} handler. + + The following example uses the same settings as in the intro + section~\ref{section-key-filter-example}. + % +\begin{codeexample}[] +\pgfkeys{/pgf/key filter handlers/append filtered to/.install key filter handler=\remainingoptions} +\def\remainingoptions{} +\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2, + /my group/B=b, /my group/C=c, /tikz/color=blue, /my group/A3=a3} + +Remaining: `\remainingoptions'. +\pgfkeysalsofrom{\remainingoptions} +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfkeysalsofiltered\marg{key--value-list}} + This command works as |\pgfkeysfiltered|, but it does not change the + current default path. See the documentation of |\pgfkeysalso| for more + details. +\end{command} + +\begin{command}{\pgfkeysalsofilteredfrom\marg{macro}} + A variant of |\pgfkeysalsofiltered| which loads its key list from + \marg{macro}. +\end{command} + +\begin{handler}{{.install key filter}|=|\meta{optional arguments}} + This handler installs a key filter. A key filter is a command key which + sets the \TeX-boolean |\ifpgfkeysfiltercontinue|, that means a key with + existing `|/.@cmd|' suffix. A simple example is a key filter which returns + always true: + % +\begin{codeexample}[code only] +\pgfkeys{/foo/bar/true key filter/.code={\pgfkeysfiltercontinuetrue}} +\pgfkeys{/foo/bar/true key filter/.install key filter} +\end{codeexample} + % + If key filters require arguments, they are installed by + |.install key filter| as well. An example is the |/pgf/key filters/equals| + handler: + % +\begin{codeexample}[] +\pgfkeys{/pgf/key filters/equals/.install key filter={/my group/A1}} +\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2, +/my group/B=b, /my group/C=c, /tikz/color=blue, /my group/A3=a3} +\end{codeexample} + % + If a key filter requires more than one argument, you need to provide the + complete argument list in braces like |{{first}{second}}|. + + You can also use |\pgfkeysinstallkeyfilter|\meta{full key}\meta{optional + arguments}, it has the same effect. + + See section~\ref{section-key-writing-filters} for how to write key filters. +\end{handler} + +\begin{handler}{{.install key filter handler}|=|\meta{optional arguments}} + This handler installs the routine which will be invoked for every + \emph{unprocessed} option, that means any option for which the key filter + returned `false'. + + The |.install key filter handler| is used in the same way as + |.install key filter|. There exists a macro version, + |\pgfkeysinstallkeyfilterhandler|\meta{full key}\meta{optional arguments}, + which has the same effect. + + See section~\ref{section-key-writing-filters} for how to write key filter + handlers. +\end{handler} + + +\subsubsection{Handlers For Unprocessed Keys} + +Each option for which key filters decided to skip them is handed over to a `key +filter handler'. There are several predefined key filter handlers. + +\begin{key}{/pgf/key filter handlers/append filtered to=\marg{macro}} + Install this filter handler to append any unprocessed options to macro + \marg{macro}. + % +\begin{codeexample}[] +\pgfkeys{/pgf/key filter handlers/append filtered to/.install key filter handler=\remainingoptions} +\def\remainingoptions{} +\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2, + /my group/B=b, /my group/C=c, /tikz/color=blue} + +Remaining options: `\remainingoptions'. +\end{codeexample} + % + This example uses the same keys as defined in the intro + section~\ref{section-key-filter-example}. +\end{key} + +\begin{key}{/pgf/key filter handlers/ignore} + Install this filter handler if you simply want to ignore any unprocessed + option. This is the default. +\end{key} + +\begin{key}{/pgf/key filter handlers/log} + This key filter handler writes messages for any unprocessed option to your + logfile (and terminal). +\end{key} + + +\subsubsection{Family Support} + +\pgfname{} supports a family concept: every option can be associated with (at +most) one family. Families form loose key groups which are independent of the +key hierarchy. For example, |/my tree/key1| can belong to family |/tikz|. + +It is possible to `activate' or `deactivate' single families. Furthermore, it +is possible to set only keys which belong to active families using appropriate +key filter handlers. + +The family support is fast: if there are $N$ options in a key--value-list and +there are $K$ active families, the runtime for |\pgfkeysfiltered| is $O(N+K)$ +(activate every family $O(K)$, check every option $O(N)$, deactivate every +family $O(K)$). + +\begin{handler}{{.is family}} + Defines a new family. This option has already been described in + section~\ref{section-is family-handler} on page~\pageref{section-is + family-handler}. +\end{handler} + +\begin{handler}{{.activate family}} + Activates a family. The family needs to be defined, otherwise + |/errors/family unknown| will be raised. + + Activation means a \TeX-boolean will be set to |true|, indicating that a + family should be processed. + + You can also use |\pgfkeysactivatefamily|\meta{full path} to get the same + effect. Furthermore, you can use |\pgfkeysactivatefamilies|\meta{list of + families}\meta{macro name for de-activation} to activate a list of families + (see section~\ref{section-key-filter-api}). +\end{handler} + +\begin{handler}{{.deactivate family}} + Deactivates a family. The family needs to be defined, otherwise + |/errors/family unknown| will be raised. + + You can also use |\pgfkeysdeactivatefamily|\meta{full path} to get the same + effect. +\end{handler} + +\begin{handler}{{.belongs to family}|=|\marg{family name}} + Associates the current option with \marg{family name}, which is expected to + be a full path of a family. + % +\begin{codeexample}[code only] +\pgfkeys{/foo/bar/.is family} +\pgfkeys{ + /foo/a/.belongs to family=/foo/bar, + /foo/b/.belongs to family=/foo/bar +} +\end{codeexample} + % + Each option can have up to one family, |.belongs to family| overwrites any + old setting. +\end{handler} + +\begin{key}{/pgf/key filters/active families} + Install this key filter if |\pgfkeysfiltered| should only process activated + families. If a key does not belong to any family, it is not processed. If a + key is completely unknown within the default path, the normal `unknown' + handlers of |\pgfkeys| are invoked. +\end{key} + +\begin{key}{/pgf/key filters/active families or no family=\marg{key filter 1}\marg{key filter 2}} + This key filter configures |\pgfkeysfiltered| to work as follows. + % + \begin{enumerate} + \item If the current key belongs to a family, set + |\ifpgfkeysfiltercontinue| to true if and only if its family is + active. + \item If the current key does \emph{not} belong to a family, assign + |\ifpgfkeysfiltercontinue| as result of \marg{key filter 1}. + \item If the current key is unknown within the default path, assign + |\ifpgfkeysfiltercontinue| as result of \marg{key filter 2}. + \end{enumerate} + % + The arguments \marg{key filter 1} and \marg{key filter 2} are other key + filters (possibly with options) and allow fine-grained control over the + filtering process. + % +\begin{codeexample}[code only] + \pgfkeysinstallkeyfilter + {/pgf/key filters/active families or no family} + {{/pgf/key filters/is descendant of=/tikz}% for keys without family + {/pgf/key filters/false}% for unknown keys + }% +\end{codeexample} + % + This key filter will return true for any option with active family. If an + option has no family, the return value is true if and only if it belongs to + |/tikz|. If the option is unknown, the return value is |false| and unknown + handlers won't be called. +\end{key} + +\begin{key}{/pgf/key filters/active families or no family DEBUG=\marg{key filter 1}\marg{key filter 2}} + A variant of |active families or no family| which protocols each action on + your terminal (log-file). +\end{key} + +\begin{key}{/pgf/key filters/active families and known} + A fast alias for + + |/pgf/key filters/active families or no family=|\par + \noindent\hskip10pt|{/pgf/keys filters/false}|\par + \noindent\hskip10pt|{/pgf/keys filters/false}|. +\end{key} +% +\begin{key}{/pgf/key filters/active families or descendants of=\marg{path prefix}} + A fast alias for + + |/pgf/key filters/active families or no family=|\par + \noindent\hskip10pt|{/pgf/keys filters/is descendant of=|\marg{path prefix}|}|\par + \noindent\hskip10pt|{/pgf/keys filters/false}|. +\end{key} + +\begin{command}{\pgfkeysactivatefamiliesandfilteroptions\marg{family list}\marg{key--value-list}} + A simple shortcut macro which activates any family in the comma separated + \marg{family list}, invokes |\pgfkeysfiltered|\meta{key--value-list} and + deactivates the families afterwards. + + Please note that you will need to install a family key filter, otherwise + family activation has no effect. +\end{command} +% +\begin{command}{\pgfqkeysactivatefamiliesandfilteroptions\marg{family list}\marg{default path}\marg{key--value-list}} + The `quick' default path variant of |\pgfkeysactivatefamiliesandfilteroptions|. +\end{command} + +\begin{command}{\pgfkeysactivatesinglefamilyandfilteroptions\marg{family name}\marg{key--value-list}} + A shortcut macro which activates a single family and invokes |\pgfkeysfiltered|. + + Please note that you will need to install a family key filter, otherwise + family activation has no effect. +\end{command} +% +\begin{command}{\pgfqkeysactivatesinglefamilyandfilteroptions\marg{family name}\marg{default path}\marg{key--value-list}}% + The `quick' default path variant of |\pgfkeysactivatesinglefamilyandfilteroptions|. +\end{command} + + +\subsubsection{Other Key Filters} + +There are some more key filters which have nothing to do with family handling. +% +\begin{key}{/pgf/key filters/is descendant of=\marg{path}} + Install this key filter to process only options belonging to the key tree + \meta{path}. It returns true for every key whose key path is equal to + \meta{path}. It also returns true for any unknown key, that means unknown + keys are processed using the standard unknown handlers of \pgfname. + % +\begin{codeexample}[] +\pgfkeys{ +/group 1/A/.code={(A:#1)}, +/group 1/foo/bar/B/.code={(B:#1)}, +/group 2/C/.code={(C:#1)}, +/pgf/key filters/is descendant of/.install key filter=/group 1} +\pgfkeysfiltered{/group 1/A=a,/group 1/foo/bar/B=b,/group 2/C=c} +\end{codeexample} + % +\end{key} + +\begin{key}{/pgf/key filters/equals=\marg{full key}} + Install this key filter to process only the fully qualified option + \marg{full key}. The filter returns true for any unknown key or if the key + equals \marg{full key}. + % +\begin{codeexample}[] +\pgfkeys{ +/group 1/A/.code={(A:#1)}, +/group 1/B/.code={(B:#1)}, +/pgf/key filters/equals/.install key filter=/group 1/A} +\pgfqkeysfiltered{/group 1}{A=a,B=b} +\end{codeexample} + % +\end{key} + +\begin{key}{/pgf/key filters/not=\marg{key filter}} + This key filter logically inverts the result of \marg{key filter}. + % +\begin{codeexample}[] +\pgfkeys{ +/group 1/A/.code={(A:#1)}, +/group 1/foo/bar/B/.code={(B:#1)}, +/group 2/C/.code={(C:#1)}, +/pgf/key filters/not/.install key filter= + {/pgf/key filters/is descendant of=/group 1}} +\pgfkeysfiltered{/group 1/A=a,/group 1/foo/bar/B=b,/group 2/C=c} +\end{codeexample} + % + Please note that unknown keys will be handed to the usual unknown handlers. +\end{key} + +\begin{key}{/pgf/key filters/and=\marg{key filter 1}\marg{key filter 2}} + This key filter returns true if and only if both, \marg{key filter 1} and + \marg{key filter 2} return true. +\end{key} + +\begin{key}{/pgf/key filters/or=\marg{key filter 1}\marg{key filter 2}} + This key filter returns true if one of \marg{key filter 1} and \marg{key + filter 2} returns true. +\end{key} + +\begin{key}{/pgf/key filters/true} + This key filter returns always true. +\end{key} + +\begin{key}{/pgf/key filters/false} + This key filter returns always false (including unknown keys). +\end{key} + +\begin{key}{/pgf/key filters/defined} + This key filter returns false if the current key is unknown, which avoids + calling the unknown handlers. +\end{key} + + +\subsubsection{Programmer Interface} +\label{section-key-filter-api} + +\begin{plainenvironment}{{pgfkeysinterruptkeyfilter}} + Temporarily disables key filtering inside the environment. If key filtering + is not active, this has no effect at all. + + Please note that no \TeX-group is introduced. +\end{plainenvironment} + +\begin{command}{\pgfkeyssavekeyfilterstateto\marg{macro}} + Creates \marg{macro} which contains commands to re-activate the current key + filter and key filter handler. It can be used to temporarily switch the key + filter. +\end{command} + +\begin{command}{\pgfkeysinstallkeyfilter\marg{full key}\marg{optional arguments}} + The command + |\pgfkeysinstallkeyfilter{|\meta{full key}|}{|\meta{optional arguments}|}| + has the same effect as + |\pgfkeys{|\meta{full key}|/.install key filter={|\meta{optional arguments}|}}|. +\end{command} + +\begin{command}{\pgfkeysinstallkeyfilterhandler\marg{full key}\marg{optional arguments}} + The command + |\pgfkeysinstallkeyfilterhandler{|\meta{full key}|}{|\meta{optional arguments}|}| + has the same effect as + |\pgfkeys{|\meta{full key}|/.install key filter handler={|\meta{optional arguments}|}}|. +\end{command} + +\begin{command}{\pgfkeysactivatefamily\marg{family name}} + Equivalent to |\pgfkeys{|\meta{family name}|/.activate family}|. +\end{command} + +\begin{command}{\pgfkeysdeactivatefamily\marg{family name}} + Equivalent to |\pgfkeys{|\meta{family name}|/.deactivate family}|. +\end{command} + +\begin{command}{\pgfkeysactivatefamilies\marg{family list}\marg{deactivate macro name}} + Activates each family in \meta{family list} and creates a macro + \meta{deactivate macro name} which deactivates each family in \meta{family + list}. + % +\begin{codeexample}[code only] +\pgfkeysactivatefamilies{/family 1,/family 2,/family 3}{\deactivatename} +\pgfkeysfiltered{foo,bar} +\deactivatename +\end{codeexample} + % +\end{command} + +\begin{command}{\pgfkeysiffamilydefined\marg{family}\marg{true case}\marg{false case}}% + Checks whether the full key \meta{family} is a family and executes either + \meta{true case} or \meta{false case}. +\end{command} + +\begin{command}{\pgfkeysisfamilyactive\marg{family}} + Sets the \TeX-boolean |\ifpgfkeysfiltercontinue| to whether \meta{family} + is active or not. +\end{command} + +\begin{command}{\pgfkeysgetfamily\marg{key}\marg{resultmacro}} + Returns the family associated to a full key \meta{key} into macro + \meta{resultmacro}. +\end{command} + +\begin{command}{\pgfkeyssetfamily\marg{key}\marg{family}} + The command |\pgfkeyssetfamily|\marg{full key}\marg{family} has the same + effect as |\pgfkeys{|\meta{full key}|/.belongs to family=|\marg{family}|}|. +\end{command} + + +\subsubsection{Defining Own Filters Or Filter Handlers} +\label{section-key-writing-filters} + +During |\pgfkeysfiltered|, the key filter code will be invoked. At this time, +the full key path including key name is available as |\pgfkeyscurrentkey|, the +key name before default paths have been considered as |\pgfkeyscurrentkeyRAW| +and the values as |\pgfkeyscurrentvalue|. + +Furthermore, the macro |\pgfkeyscasenumber| contains the current key's type as +an integer: +% +\begin{itemize} + \item[\meta{1}] The key is a command key (i.e. |.../.@cmd| exists). + \item[\meta{2}] The key contains its value directly. + \item[\meta{3}] The key is handled (for example it is |.code| or |.cd|). + + In this case, the macros |\pgfkeyscurrentname| and + |\pgfkeyscurrentpath| are set to the handlers name and path, + respectively. Invoke |\pgfkeyssplitpath{}| to extract these values for + non-handled keys. + \item[\meta{0}] The key is unknown. +\end{itemize} +% +Any key filter or key filter handler can access these variables. Key filters +are expected to set the \TeX-boolean |\ifpgfkeysfiltercontinue| to whether the +current key shall be processed or not. + +\begin{command}{\pgfkeysevalkeyfilterwith\marg{full key}=\marg{filter arguments}} + Evaluates a fully qualified key filter \meta{full key} with argument(s) + \meta{filter arguments}. + % +\begin{codeexample}[code only] +\pgfkeysevalkeyfilterwith{/pgf/key filters/equals=/tikz} +\end{codeexample} + % +\end{command} + +\endgroup -- cgit v1.2.3