summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pgfkeysearch
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-12-28 03:00:45 +0000
committerNorbert Preining <norbert@preining.info>2023-12-28 03:00:45 +0000
commit8806b2d6c55426cb0ba19311d2acf7c4f522a291 (patch)
tree17ec53ef59efff97d2e122e72358b9be18c739df /macros/latex/contrib/pgfkeysearch
parenta017c8624fa1cc7d2781f6f4e59e4bd12e7050f1 (diff)
CTAN sync 202312280300
Diffstat (limited to 'macros/latex/contrib/pgfkeysearch')
-rw-r--r--macros/latex/contrib/pgfkeysearch/README.md39
-rw-r--r--macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdfbin0 -> 158924 bytes
-rw-r--r--macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.tex86
-rw-r--r--macros/latex/contrib/pgfkeysearch/latex/pgfkeysearch.sty238
4 files changed, 363 insertions, 0 deletions
diff --git a/macros/latex/contrib/pgfkeysearch/README.md b/macros/latex/contrib/pgfkeysearch/README.md
new file mode 100644
index 0000000000..58a12659fc
--- /dev/null
+++ b/macros/latex/contrib/pgfkeysearch/README.md
@@ -0,0 +1,39 @@
+pgfkeysearch
+==========
+
+This package offers a way to find keys in a given path 'recursively', unlike pgfkeysvalueof.
+
+--------------
+
+## Requirements
+* none besides a fairly recent LaTeX distribution as recent as 2022/06/01
+(with the new in kernel *\ProcessKeyOptions* and *\NewDocumentCommand*)
+and pgfkeys.
+
+
+## Contacting Author
+
+For bug reports and enhancement suggestions, the preferred way is to use
+[the project's issue page](https://github.com/alceu-frigeri/pgfkeysearch/issues).
+Please be ready to provide an example code showing the bug, if any.
+
+Please do not use the issue page for generic help on how to use the package.
+
+* git: https://github.com/alceu-frigeri/pgfkeysearch
+
+-------------
+Copyright 2023-present by Alceu Frigeri
+
+ This work may be distributed and/or modified under the
+ conditions of
+
+ * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt), version 1.3c (or later), and/or
+ * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html), version 3 (or later)
+
+This work has the LPPL maintenance status *maintained*.
+
+The Current Maintainer of this work is Alceu Frigeri
+
+
+* Version 1.0
+ - Initial setup.
diff --git a/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdf b/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdf
new file mode 100644
index 0000000000..ce036e2a6e
--- /dev/null
+++ b/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdf
Binary files differ
diff --git a/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.tex b/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.tex
new file mode 100644
index 0000000000..5ebd18a090
--- /dev/null
+++ b/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.tex
@@ -0,0 +1,86 @@
+%%%==============================================================================
+%% Copyright 2023 by Alceu Frigeri
+%%
+%% This work may be distributed and/or modified under the conditions of
+%%
+%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
+%% version 1.3c (or later), and/or
+%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
+%% version 3 (or later)
+%%
+%% This work has the LPPL maintenance status *maintained*.
+%%
+%% The Current Maintainer of this work is Alceu Frigeri
+%%
+%% This is version {1.5} {2023/11/28}
+%%
+%% The list of files that compose this work can be found in the README.md file at
+%% https://ctan.org/pkg/pgfkeysearch
+%%
+%%%==============================================================================
+\documentclass[10pt]{article}
+\RequirePackage[verbose,a4paper,marginparwidth=27.5mm,top=2.5cm,bottom=1.5cm,hmargin={40mm,20mm},marginparsep=2.5mm,columnsep=10mm,asymmetric]{geometry}
+\usepackage{codedescribe}
+\usepackage{pgfkeysearch}
+\RequirePackage[inline]{enumitem}
+\SetEnumitemKey{miditemsep}{parsep=0ex,itemsep=0.4ex}
+
+\RequirePackage{pgfkeys}
+
+\RequirePackage[hidelinks,hypertexnames=false]{hyperref}
+\begin{document}
+\tstitle{
+ author={Alceu Frigeri\footnote{\tsverb{https://github.com/alceu-frigeri/pgfkeysearch}}},
+ date={\tsdate},
+ title={A Search Extension for pgfkeys\break Version \PkgInfo{pgfkeysearch}{version}}
+ }
+
+\begin{typesetabstract}
+
+The command \tsobj{\pgfkeysvalueof}, unlike other \tsobj{\pgfkeys} commands, doesn't have a \tsobj[keys]{.unknown} handler, or offers the option to search for a key.
+That's exactly the aim of this, by having a way to find a key in a given path (or collection of paths).
+\end{typesetabstract}
+
+
+\section{Searching for a key}
+\begin{codedescribe}{\pgfkeysearchvalueof,\pgfkeysearchvalueofTF}
+\begin{codesyntax}%
+\tsmacro{\pgfkeysearchvalueof}{path-list,key,macro}
+\tsmacro{\pgfkeysearchvalueofTF}{path-list,key,macro,if-found,if-not}
+\end{codesyntax}
+\tsobj[marg]{path-list} is a comma separated list (clist) of paths (can be a single one). \tsobj[marg]{key} is the desired key and \tsobj[marg]{macro} is the macro/command that will receive (store) the key value (if one was found).
+
+For instance, given a path /A/B/C/D it will look first at /A/B/C/D/\tsobj[marg]{key}, them /A/B/C/\tsobj[marg]{key}, and so on, until /A/\tsobj[marg]{key},
+Stopping at the first hit, returning the value found in the \tsobj[marg]{macro}.
+The branch version will also execute either \tsobj[marg,sep={or}]{if-found,if-not}.
+
+\end{codedescribe}
+\begin{tsremark}
+ Those commands aren't expandable, that's the reason to have them storing the key value in a macro and not just 'placing the value in the input stream'.
+\end{tsremark}
+
+\begin{codestore}[keyval.demo]
+ \pgfkeys{/tikz/A/.cd,
+ keyA/.initial={A keyA},
+ keyB/.initial={A keyB},
+ B/.cd,
+ keyA/.initial={B keyA},
+ keyC/.initial={B keyC},
+ C/.cd,
+ keyX/.initial={C keyX} }
+ \pgfkeysearchvalueof{/tikz/A/B/C}{keyA}{\VALkeyA}
+ \pgfkeysearchvalueof{/tikz/A/B/C}{keyB}{\VALkeyB}
+ \pgfkeysearchvalueof{/tikz/A/B/C}{keyC}{\VALkeyC}
+ \pgfkeysearchvalueof{/tikz/A/B/C}{keyX}{\VALkeyX}
+
+ I got for keyA: \textbf{\VALkeyA} \par
+ I got for keyB: \textbf{\VALkeyB} \par
+ I got for keyC: \textbf{\VALkeyC} \par
+ I got for keyX: \textbf{\VALkeyX} \par
+
+\end{codestore}
+
+\tsdemo[emph={pgfkeysearchvalueof}]{keyval.demo}
+
+
+\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/pgfkeysearch/latex/pgfkeysearch.sty b/macros/latex/contrib/pgfkeysearch/latex/pgfkeysearch.sty
new file mode 100644
index 0000000000..bc1da1ae03
--- /dev/null
+++ b/macros/latex/contrib/pgfkeysearch/latex/pgfkeysearch.sty
@@ -0,0 +1,238 @@
+%%%==============================================================================
+%% Copyright 2023-present by Alceu Frigeri
+%%
+%% This work may be distributed and/or modified under the conditions of
+%%
+%% * The [LaTeX Project Public License](http://www.latex-project.org/lppl.txt),
+%% version 1.3c (or later), and/or
+%% * The [GNU Affero General Public License](https://www.gnu.org/licenses/agpl-3.0.html),
+%% version 3 (or later)
+%%
+%% This work has the LPPL maintenance status *maintained*.
+%%
+%% The Current Maintainer of this work is Alceu Frigeri
+%%
+%% This is version {1.0} {2023/12/27}
+%%
+%% The list of files that compose this work can be found in the README.md file at
+%% https://ctan.org/pkg/pgfkeysearch
+%%
+%%%==============================================================================
+\NeedsTeXFormat{LaTeX2e}[2022/06/01]
+
+
+\ProvidesExplPackage
+ {pgfkeysearch}
+ {2023/12/27}
+ {1.0}
+ {pgfkeys Search Extension}
+
+\ExplSyntaxOn
+%%%%%%%
+%%%
+%%% Just an attempt of having my packages info in a regular way
+%%% Idea being: { <pck-name> / pkg info } for each and all.
+%%%
+%%%%%%%
+\keys_define:nn { pgfkeysearch / pkg info}
+ {
+ name .code:n = {pgfkeysearch} ,
+ prefix .code:n = {pgfkeysearch} ,
+ date .code:n = {2023/12/27},
+ version .code:n = {1.0} ,
+ description .code:n = {pgfkeys Search Extension}
+ }
+\cs_if_exist:NF \__codedesc_pkg_info:nn
+ {
+ \cs_new_protected:Npn \__codedesc_pkg_info:nn #1#2
+ { \keys_set:nn {#1 / pkg info}{#2} }
+ }
+\cs_if_exist:NF \PkgInfo
+ { \NewDocumentCommand \PkgInfo {mm} { \keys_set:nn {#1 / pkg info}{#2} } }
+\cs_if_exist:NF \PkgDescription
+ {
+ \NewDocumentCommand \PkgDescription {m}
+ {
+ \noindent Package~ \textbf{\PkgInfo{#1}{name}}~Version:~\PkgInfo{#1}{version}~ -~ \PkgInfo{#1}{date}\par \emph{\PkgInfo{#1}{description}}~\par
+ }
+ }
+%%%%%%%
+%%% End of cut-n-paste
+%%%%%%%
+
+
+%%%%%%%%%%%%%%%
+%%%
+%%% Expl3 machinery. _keysearch_ allows to find a key,
+%%% if it's defined from 'anywhere' in the tree. I mean, upwards until, likely, /tikz/<key>
+%%% if it isn't defined, returns nothing (no error triggered)
+%%%
+%%%%%%%%%%%%%%%
+\seq_new:N \l__ctikzext_pathterms_seq
+\seq_new:N \l__ctikzext_pathtree_seq
+\tl_new:N \l__ctikzext_key_tl
+\tl_new:N \l__ctikzext_path_tl
+
+
+%%%%%%%%%%%%%%%%
+%%%%
+%%%% This works BUT, it isn't expandable and not a 1-to-1 replacement for pgfkeysvalueof (which is fully expandable)
+%%%% don't use this unless you know what you are doing. To avoid trouble tickets headaches, it's commeted out
+%%%%
+%%%%%%%%%%%%%%%%
+%\cs_new_protected:Npn \__ctikzext_keysearch:n #1
+% {
+% \seq_set_split:Nne \l__ctikzext_pathterms_seq {/} {#1}
+% \seq_pop_right:NN \l__ctikzext_pathterms_seq \l__ctikzext_key_tl
+% \seq_remove_all:Nn \l__ctikzext_pathterms_seq {}
+% \tl_clear:N \l__ctikzext_path_tl
+% \seq_clear:N \l__ctikzext_pathtree_seq
+% \seq_map_inline:Nn \l__ctikzext_pathterms_seq
+% {
+% \tl_put_right:Ne \l__ctikzext_path_tl {/##1}
+% \seq_put_right:Ne \l__ctikzext_pathtree_seq {\l__ctikzext_path_tl}
+% }
+% \seq_reverse:N \l__ctikzext_pathtree_seq
+% \seq_map_inline:Nn \l__ctikzext_pathtree_seq
+% {
+% \cs_if_exist:cT {pgfk@##1/\l__ctikzext_key_tl}
+% {
+% \exp_args:Ne \use:c {pgfk@##1/\l__ctikzext_key_tl}
+% \seq_map_break:
+% }
+% }
+% }
+
+
+
+%%%%%%%%%%%%%%%
+%%%
+%%% Deplecated... single path key search (just a bit faster if a single path)
+%%%
+%%%%%%%%%%%%%%%
+%\prg_new_protected_conditional:Npnn \__ctikzext_keysearch:nn #1#2 {TF,T,F}
+% {
+% \seq_set_split:Nne \l__ctikzext_pathterms_seq {/} {#1}
+% \seq_pop_right:NN \l__ctikzext_pathterms_seq \l__ctikzext_key_tl
+% \seq_remove_all:Nn \l__ctikzext_pathterms_seq {}
+% \tl_clear:N \l__ctikzext_path_tl
+% \seq_clear:N \l__ctikzext_pathtree_seq
+% \seq_map_inline:Nn \l__ctikzext_pathterms_seq
+% {
+% \tl_put_right:Ne \l__ctikzext_path_tl {/##1}
+% \seq_put_right:Ne \l__ctikzext_pathtree_seq {\l__ctikzext_path_tl}
+% }
+% \seq_reverse:N \l__ctikzext_pathtree_seq
+% \bool_set_false:N \l__ctikzext_valuefound_bool
+% \seq_map_inline:Nn \l__ctikzext_pathtree_seq
+% {
+% \cs_if_exist:cT {pgfk@##1/\l__ctikzext_key_tl}
+% {
+% \tl_set:Ne #2 {\exp_not:N \use:c{pgfk@##1/\l__ctikzext_key_tl}}
+% \bool_set_true:N \l__ctikzext_valuefound_bool
+% \seq_map_break:
+% }
+% }
+% \bool_if:nTF {\l__ctikzext_valuefound_bool}
+% { \prg_return_true: }
+% { \prg_return_false: }
+% }
+
+
+
+%%%%%%%%%%%%%%%
+%%%
+%%% Given a path /A/B/C/D it will look after
+%%% /A/B/C/D/<key>
+%%% /A/B/C/<key>
+%%% /A/B/<key>
+%%% /A/<key>
+%%% stoping at the first hit
+%%%
+%%%%%%%%%%%%%%%
+
+\bool_new:N \l__ctikzext_valuefound_bool
+\prg_new_protected_conditional:Npnn \__ctikzext_keysearch:nnn #1#2#3 {TF,T,F}
+ {
+ \seq_set_split:Nne \l__ctikzext_pathterms_seq {/} {#1}
+ \seq_remove_all:Nn \l__ctikzext_pathterms_seq {}
+ \tl_clear:N \l__ctikzext_path_tl
+ \seq_clear:N \l__ctikzext_pathtree_seq
+ \seq_map_inline:Nn \l__ctikzext_pathterms_seq
+ {
+ \tl_put_right:Ne \l__ctikzext_path_tl {/##1}
+ \seq_put_right:Ne \l__ctikzext_pathtree_seq {\l__ctikzext_path_tl}
+ }
+ \seq_reverse:N \l__ctikzext_pathtree_seq
+ \bool_set_false:N \l__ctikzext_valuefound_bool
+ \seq_map_inline:Nn \l__ctikzext_pathtree_seq
+ {
+ \cs_if_exist:cT {pgfk@##1/#2}
+ {
+ \tl_set:Ne #3 {\exp_not:N \use:c{pgfk@##1/#2}}
+ \bool_set_true:N \l__ctikzext_valuefound_bool
+ \seq_map_break:
+ }
+ }
+ \bool_if:nTF {\l__ctikzext_valuefound_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+
+
+
+%%%%%%%%%%%%%%%
+%%%
+%%% #1 shall be a comma separated list of paths (can be a single one)
+%%% it searchs for the key in every path, stoping at the first hit.
+%%%
+%%%%%%%%%%%%%%%
+
+\bool_new:N \l__ctikzext_multisearch_bool
+\prg_new_protected_conditional:Npnn \__ctikzext_multipath_keysearch:nnn #1#2#3 {T,F,TF}
+ {
+ \bool_set_false:N \l__ctikzext_multisearch_bool
+ \clist_map_inline:nn {#1}
+ {
+ \__ctikzext_keysearch:nnnT {##1}{#2}{#3}
+ {
+ \bool_set_true:N \l__ctikzext_multisearch_bool
+ \clist_map_break:
+ }
+ }
+ \bool_if:nTF {\l__ctikzext_multisearch_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_generate_variant:Nn \tl_set:Nn {Ne}
+
+%%%%%%%%%%%%%%%
+%%%
+%%% The caveats: this ins't expandable.
+%%%
+%%%%%%%%%%%%%%%
+%%%
+%%% This is the more generic one.
+%%% #1 is the path (or list of paths)
+%%% #2 is the <key>
+%%% #3 is the macro that will receive the key value (if any)
+%%%
+%%%%%%%%%%%%%%%
+
+\NewDocumentCommand{\pgfkeysearchvalueof}{mmm}
+ {
+ \__ctikzext_multipath_keysearch:nnnF {#1}{#2}{#3}
+ { \tl_set:Nn #3 {} }
+ }
+
+\NewDocumentCommand{\pgfkeysearchvalueofTF}{mmmmm}
+ {
+ \__ctikzext_multipath_keysearch:nnnTF {#1}{#2}{#3}
+ { #4 }
+ {
+ \tl_set:Nn #3 {}
+ #5
+ }
+ }