Skip to content

Commit

Permalink
feat: Introduce library loading mechanism for pgfkeys
Browse files Browse the repository at this point in the history
Signed-off-by: Henri Menke <henri@henrimenke.de>
  • Loading branch information
hmenke committed Feb 1, 2022
1 parent 1dbf7ae commit 719b92f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
1 change: 1 addition & 0 deletions doc/generic/pgf/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ lot of contributed changes. Thanks to everyone who volunteered their time!
- Add rhombic polihedra #1022
- Add Developer Certificate of Origin (DCO) to Pull Request template and enforce
- Add test set for `graphdrawing` (gd)
- pgfkeys gained support for loading libraries

### Fixed

Expand Down
46 changes: 26 additions & 20 deletions doc/generic/pgf/pgfmanual-en-pgfkeysfiltered.tex
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ \subsection{Key Filtering}
setting procedure: library~A may want to set its options directly and
communicate all remaining ones to library~B.

\begin{pgfkeyslibrary}{filtered}
The |filtered| library provides functionality to filter keys and only process
selected ones, while forwarding the others to another namespace.

This library is loaded by default by |pgfkeys|.
\end{pgfkeyslibrary}

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}

Expand Down Expand Up @@ -74,21 +80,21 @@ \subsubsection{Starting With An Example}
%
\noindent and
%
\begin{codeexample}[code only]
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{/pgf/key filters/active families/.install key filter}
\end{codeexample}
%
\noindent After this preparation, we can use |\pgfkeysfiltered| with
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\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}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\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}
Expand Down Expand Up @@ -148,7 +154,7 @@ \subsubsection{Setting Filters}
The following example uses the same settings as in the intro
section~\ref{section-key-filter-example}.
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{/pgf/key filter handlers/append filtered to/.install key filter handler=\remainingoptions}
\def\remainingoptions{}
\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2,
Expand Down Expand Up @@ -177,7 +183,7 @@ \subsubsection{Setting Filters}
existing `|/.@cmd|' suffix. A simple example is a key filter which returns
always true:
%
\begin{codeexample}[code only]
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{/foo/bar/true key filter/.code={\pgfkeysfiltercontinuetrue}}
\pgfkeys{/foo/bar/true key filter/.install key filter}
\end{codeexample}
Expand All @@ -186,7 +192,7 @@ \subsubsection{Setting Filters}
|.install key filter| as well. An example is the |/pgf/key filters/equals|
handler:
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\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}
Expand Down Expand Up @@ -225,7 +231,7 @@ \subsubsection{Handlers For Unprocessed Keys}
Install this filter handler to append any unprocessed options to macro
\marg{macro}.
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{/pgf/key filter handlers/append filtered to/.install key filter handler=\remainingoptions}
\def\remainingoptions{}
\pgfkeysfiltered{/my group/A1=a1, /my group/A2=a2,
Expand Down Expand Up @@ -295,7 +301,7 @@ \subsubsection{Family Support}
Associates the current option with \marg{family name}, which is expected to
be a full path of a family.
%
\begin{codeexample}[code only]
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{/foo/bar/.is family}
\pgfkeys{
/foo/a/.belongs to family=/foo/bar,
Expand Down Expand Up @@ -331,12 +337,12 @@ \subsubsection{Family Support}
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
}%
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\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
Expand Down Expand Up @@ -401,7 +407,7 @@ \subsubsection{Other Key Filters}
\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}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{
/group 1/A/.code={(A:#1)},
/group 1/foo/bar/B/.code={(B:#1)},
Expand All @@ -417,7 +423,7 @@ \subsubsection{Other Key Filters}
\marg{full key}. The filter returns true for any unknown key or if the key
equals \marg{full key}.
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{
/group 1/A/.code={(A:#1)},
/group 1/B/.code={(B:#1)},
Expand All @@ -430,7 +436,7 @@ \subsubsection{Other Key Filters}
\begin{key}{/pgf/key filters/not=\marg{key filter}}
This key filter logically inverts the result of \marg{key filter}.
%
\begin{codeexample}[]
\begin{codeexample}[preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeys{
/group 1/A/.code={(A:#1)},
/group 1/foo/bar/B/.code={(B:#1)},
Expand Down Expand Up @@ -510,7 +516,7 @@ \subsubsection{Programmer Interface}
\meta{deactivate macro name} which deactivates each family in \meta{family
list}.
%
\begin{codeexample}[code only]
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeysactivatefamilies{/family 1,/family 2,/family 3}{\deactivatename}
\pgfkeysfiltered{foo,bar}
\deactivatename
Expand Down Expand Up @@ -570,7 +576,7 @@ \subsubsection{Defining Own Filters Or Filter Handlers}
Evaluates a fully qualified key filter \meta{full key} with argument(s)
\meta{filter arguments}.
%
\begin{codeexample}[code only]
\begin{codeexample}[code only,preamble={\usepgfkeyslibrary{filtered}}]
\pgfkeysevalkeyfilterwith{/pgf/key filters/equals=/tikz}
\end{codeexample}
%
Expand Down
50 changes: 49 additions & 1 deletion tex/generic/pgf/utilities/pgfkeys.code.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,55 @@
\def\:{\pgf@keys@utilxifnch} \expandafter\gdef\: {\futurelet\pgf@keys@utillet@token\pgf@keys@utilifnch}
}

\chardef\pgfkeys@inputcheck0
\def\pgfkeys@IfFileExists#1{%
\openin\pgfkeys@inputcheck=#1
\ifeof\pgfkeys@inputcheck
\expandafter\closein\expandafter\pgfkeys@inputcheck
\expandafter\pgfkeys@secondoftwo
\else
\expandafter\closein\expandafter\pgfkeys@inputcheck
\expandafter\pgfkeys@firstoftwo
\fi
}

% Library system for pgfkeys
\def\usepgfkeyslibrary{\pgf@keys@utilifnextchar[{\pgfkeys@@uselibrary}{\pgfkeys@uselibrary}}
\def\pgfkeys@@uselibrary[#1]{\pgfkeys@uselibrary{#1}}
\def\pgfkeys@uselibrary#1{\pgfkeys@uselibrary@parse#1,\pgfkeys@mainstop}
\def\pgfkeys@uselibrary@parse{%
\pgf@keys@utilifnextchar\pgfkeys@mainstop{\pgfkeys@cleanup}{\pgfkeys@uselibrary@normal}%
}%
\def\pgfkeys@uselibrary@normal#1,{%
\pgfkeys@uselibrary@load{#1}%
\pgfkeys@uselibrary@parse
}
\def\pgfkeys@uselibrary@load#1{%
\expandafter\pgfkeys@spdef\expandafter\pgf@temp\expandafter{#1}%
\ifx\pgf@temp\pgfkeys@empty\expandafter\pgfkeys@firstoftwo\else\expandafter\pgfkeys@secondoftwo\fi{}{%
\pgfkeys@ifcsname{pgfkeys@library@\pgf@temp @loaded}{}{%
\expandafter\let\csname pgfkeys@library@\pgf@temp @loaded\endcsname=\pgfkeys@empty
\expandafter\edef\csname pgfkeys@library@#1@atcode\endcsname{\the\catcode`\@}%
\expandafter\edef\csname pgfkeys@library@#1@barcode\endcsname{\the\catcode`\|}%
\expandafter\edef\csname pgfkeys@library@#1@dollarcode\endcsname{\the\catcode`\$}%
\catcode`\@=11
\catcode`\|=12
\catcode`\$=3
\pgfkeys@IfFileExists{pgfkeyslibrary\pgf@temp.code.tex}{%
\input pgfkeyslibrary\pgf@temp.code.tex
}{%
\pgfkeys@error{I did not find the pgfkeys library '\pgf@temp'. I looked for the
file named pgfkeyslibrary\pgf@temp.code.tex, but could not find it in in the
current texmf trees.}%
}%
\catcode`\@=\csname pgfkeys@library@#1@atcode\endcsname
\catcode`\|=\csname pgfkeys@library@#1@barcode\endcsname
\catcode`\$=\csname pgfkeys@library@#1@dollarcode\endcsname
}%
}%
}

\input pgfkeysfiltered.code.tex
\let\pgfkeys@library@filtered@loaded\pgfkeys@empty
\input pgfkeyslibraryfiltered.code.tex

\endinput
15 changes: 15 additions & 0 deletions tex/latex/pgf/doc/pgfmanual-en-macros.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,21 @@
\end{pgfmanualentry}
}

\newenvironment{pgfkeyslibrary}[1]{%
\begin{pgfmanualentry}%
\pgfmanualentryheadline{%
\pgfmanualpdflabel{#1}{}%
\textbf{\texttt{pgfkeys} Library} \texttt{\declare{#1}}}%
\index{#1@\protect\texttt{#1} library}%
\index{Libraries!#1@\protect\texttt{#1}}%
\vskip.25em
{{\ttfamily\char`\\usepgfkeyslibrary\char`\{\declare{#1}\char`\}\space\space \char`\%\space\space \LaTeX\space and plain \TeX}}\\
{{\ttfamily\char`\\usepgfkeyslibrary[\declare{#1}]\space \char`\%\space\space Con\TeX t}}\\[.5em]%
\pgfmanualbody
}%
{%
\end{pgfmanualentry}%
}


\newenvironment{filedescription}[1]{
Expand Down

0 comments on commit 719b92f

Please sign in to comment.