diff options
author | Norbert Preining <norbert@preining.info> | 2023-12-28 03:00:45 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-12-28 03:00:45 +0000 |
commit | 8806b2d6c55426cb0ba19311d2acf7c4f522a291 (patch) | |
tree | 17ec53ef59efff97d2e122e72358b9be18c739df /macros/latex/contrib/pgfkeysearch | |
parent | a017c8624fa1cc7d2781f6f4e59e4bd12e7050f1 (diff) |
CTAN sync 202312280300
Diffstat (limited to 'macros/latex/contrib/pgfkeysearch')
-rw-r--r-- | macros/latex/contrib/pgfkeysearch/README.md | 39 | ||||
-rw-r--r-- | macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdf | bin | 0 -> 158924 bytes | |||
-rw-r--r-- | macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.tex | 86 | ||||
-rw-r--r-- | macros/latex/contrib/pgfkeysearch/latex/pgfkeysearch.sty | 238 |
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 Binary files differnew file mode 100644 index 0000000000..ce036e2a6e --- /dev/null +++ b/macros/latex/contrib/pgfkeysearch/doc/pgfkeysearch.pdf 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 + } + } |