From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/pgfkeyx/README | 41 ++ macros/latex/contrib/pgfkeyx/pgfkeyx-test1.tex | 52 ++ macros/latex/contrib/pgfkeyx/pgfkeyx.sty | 912 +++++++++++++++++++++++++ 3 files changed, 1005 insertions(+) create mode 100644 macros/latex/contrib/pgfkeyx/README create mode 100644 macros/latex/contrib/pgfkeyx/pgfkeyx-test1.tex create mode 100644 macros/latex/contrib/pgfkeyx/pgfkeyx.sty (limited to 'macros/latex/contrib/pgfkeyx') diff --git a/macros/latex/contrib/pgfkeyx/README b/macros/latex/contrib/pgfkeyx/README new file mode 100644 index 0000000000..db3cf4ed76 --- /dev/null +++ b/macros/latex/contrib/pgfkeyx/README @@ -0,0 +1,41 @@ +This is the README file for the pgfkeyx package. + +VERSION + +Version 0.0.1, April 2012. + +SUMMARY + +The pgfkeyx package provides extensions and robustness to the +pgfkeys package. In particular, it can deal with active comma, +equality sign, and slash in key parsing. It also introduces new +handlers. + +It requires pgfkeys package to be loaded first. This restriction +may be lifted in the future, if pgfkeyx became independent of +pgfkeys package. + +This is currently a package for LaTeX users only. However, we've +started generating platform-independent code in this package, as +required by pgf/tikz team. + + +LICENSE + +Copyright (c) 2012 Ahmed Musa. + +This software is author-maintained. Permission is granted to copy, +distribute and/or modify this software under the terms of the +LaTeX Project Public License, version 1.3 or higher. This software +is provided 'as it is', without warranty of any kind, either +expressed or implied, including, but not limited to, the implied +warranties of merchantability and fitness for any particular purpose. + + +RELATED PACKAGES + +pgfkeys + +AUTHOR + +Ahmed Musa (amusa22@gmail.com) \ No newline at end of file diff --git a/macros/latex/contrib/pgfkeyx/pgfkeyx-test1.tex b/macros/latex/contrib/pgfkeyx/pgfkeyx-test1.tex new file mode 100644 index 0000000000..70915744aa --- /dev/null +++ b/macros/latex/contrib/pgfkeyx/pgfkeyx-test1.tex @@ -0,0 +1,52 @@ +\documentclass{article} +\usepackage{pgfkeys} +\usepackage{pgfkeyx} +\makeatletter + +\begingroup +\def\iden#1{#1} +\catcode`\/=13 +\catcode`\,=13 +\catcode`\==13 +\iden{\endgroup + \pgfkeys{% + / my family / .is family, + /my family/my keys/.cd, + keya / .code = \def\keyavalue{#1}, + keya/.default = {keya-default}, + keyb / .code = \def\myvalueb{#1}, + keyb /.default=keyb-default, + .normal code=\def\x#1{#1}, + keyc/.code=\pgfqkeysalso\pgfkeyscurrentpath{#1}, + keyc/.value required, + keyd/.is if with no callback = true, + keye/.is if with 1 callback = {true}{\def\x##1{##1-True-#1}}, + keyf/.is if with 2 callbacks = + {true}{\def\x##1{##1-True-#1}}{\def\x##1{##1-False-#1}}, + }% +} + +\pgfkeys{% + /my family/my keys/.cd, + keya={x}, + keyb=aa, + keyc = {keya=aa, keyb=bb}, +} + +\pgfkeys{% + /my family/my keys/.cd, + keya/.restore default, + .restore key defaults={keya,keyb} +} + +\makeatother + +\begin{document} +\pgfkeys{% + /my family/my keys/keyf=true, +} +\ifkeyf + \texttt{`keyf'} is \textsf{true}. +\fi +%\show\x +\end{document} diff --git a/macros/latex/contrib/pgfkeyx/pgfkeyx.sty b/macros/latex/contrib/pgfkeyx/pgfkeyx.sty new file mode 100644 index 0000000000..d29eb4fcf1 --- /dev/null +++ b/macros/latex/contrib/pgfkeyx/pgfkeyx.sty @@ -0,0 +1,912 @@ +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% +% % +% This is file 'pgfkeyx.sty', version 0.0.1, April 2012. % +% % +% This package and accompanying files may be distributed and/or % +% modified under the conditions of the LaTeX Project Public License, % +% either version 1.3 of this license or any later version. The latest % +% version of this license is in http://www.latex-project.org/lppl.txt % +% and version 1.3 or later is part of all distributions of LaTeX % +% version 2005/12/01 or later. % +% % +% The LPPL maintenance status of this software is 'author-maintained'. % +% % +% This software is provided 'as it is', without warranty of any kind, % +% either expressed or implied, including, but not limited to, the % +% implied warranties of merchantability and fitness for a particular % +% purpose. % +% % +% Copyright (c) 2012 Ahmed Musa (amusa22@gmail.com). % +% % +%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++% + +\begingroup +\catcode064 11 % @ +\catcode123 01 % { +\catcode125 02 % } +\catcode044 12 % , +\def\reserved@a{\endgroup + \def\do##1,{% + \ifx##1\do\else + \catcode##1\string=\the\catcode##1 % + \expandafter\do + \fi + }% + \edef\pgfkeys@restorecodes{\do035,064,123,125,061,059,\do,}% +} +\reserved@a +\catcode035 06 % # +\catcode064 11 % @ +\catcode123 01 % { +\catcode125 02 % } +\catcode061 12 % = +\catcode044 12 % , +\def\do#1=#2,{% + \ifx#1\do\else + \edef\pgfkeys@restorecodes{% + \pgfkeys@restorecodes + \catcode#1=\the\catcode#1 % + }% + \catcode#1=#2\relax + \expandafter\do + \fi +} +\do 032=10,033=12,036=03,038=04,040=12,041=12,042=12,043=12,% +059=12,045=12,047=12,058=12,063=12,091=12,093=12,126=13,\do=,% + +\NeedsTeXFormat{LaTeX2e}[2011/06/27] +\ProvidesPackage{pgfkeyx}[2012/04/13 v0.0.1 Patch for pgfkeys (AM)] +\begingroup\expandafter\endgroup\expandafter +\ifx\csname ver@pgfkeys.sty\endcsname\@undefined + \PackageError{pgfkeyx}{'pgfkeys' package not loaded} + {This package requires 'pgfkeys' package to be loaded first.}% + \expandafter\endinput +\fi + +\newif\ifpgfkeys@tempst +\newif\ifpgfkeysloopbreak +\newif\ifpgfkeys@preservebrace % preserve outer braces in key values? +\newif\ifpgfkeys@in +\newif\ifpgfkeys@tracingkeys % include tracing features in the future. +\long\def\pgfkeys@iofi#1{#1} +\long\def\pgfkeys@iofii#1#2{#1} +\long\def\pgfkeys@iiofii#1#2{#2} +\long\protected\def\pgfkeys@ifnextchar@a#1#2#3{% + \let\reserved@d=#1\def\reserved@a{#2}\def\reserved@b{#3}% + \futurelet\pgfkeys@next\pgfkeys@ifnextchar@c +} +\lowercase{\lowercase{\let\pgfkeys@sptoken= } } +\lowercase{\def\pgfkeys@ifnextchar@b} % + {\futurelet\pgfkeys@next\pgfkeys@ifnextchar@c} +\def\pgfkeys@ifnextchar@c{% + \ifx\pgfkeys@next\pgfkeys@sptoken + \let\reserved@c\pgfkeys@ifnextchar@b + \else + \ifx\pgfkeys@next\reserved@d + \let\reserved@c\reserved@a + \else + \let\reserved@c\reserved@b + \fi + \fi + \reserved@c +} +\long\protected\def\ifpgfkeysnextchar#1#2#3{% + \pgfkeys@ifnextchar@a\bgroup + {\pgfkeys@ifnextchar@a{#1}{#2}{#3}}% + {\pgfkeys@ifnextchar{#1}{#2}{#3}}% +} +\long\def\pgfkeys@ifnextchar#1#2#3#4{% + \if\string#1\string#4% + \expandafter\pgfkeys@iofii + \else + \expandafter\pgfkeys@iiofii + \fi + {#2}{#3}#4% +} +\long\protected\def\pgfkeys@starorlong#1{% + \ifpgfkeysstar{\let\l@ngrel@x\relax#1}{\let\l@ngrel@x\long#1}% +} +\long\protected\def\pgfkeys@testopt#1#2{\ifpgfkeysnextchar[{#1}{#1[{#2}]}} +\long\protected\def\ifpgfkeysstar#1{\ifpgfkeysnextchar*{\pgfkeys@iofii{#1}}} +\def\pgfkeys@defcmd#1#2#3{% + \ifdefined#3% + \ifx#3\relax\else + \pgfkeys@error{Command '\string#3' already exists}% + \fi + \fi + \l@ngrel@x + \ifcat$\detokenize{#2}$\else + \ifx#2p\expandafter\expandafter\expandafter\protected\fi + \fi + \csname#1def\endcsname#3% +} +\protected\def\pgfkeysrobustdef{\pgfkeys@starorlong{\pgfkeys@defcmd{}{p}}} +\pgfkeysrobustdef*\pgfkeysrobustgdef{\pgfkeys@starorlong{\pgfkeys@defcmd{g}{p}}} +\pgfkeysrobustdef*\pgfkeysnewdef{\pgfkeys@starorlong{\pgfkeys@defcmd{}{}}} +\pgfkeysrobustdef*\pgfkeysnewedef{\pgfkeys@starorlong{\pgfkeys@defcmd{e}{}}} +\pgfkeysrobustdef*\pgfkeysnewgdef{\pgfkeys@starorlong{\pgfkeys@defcmd{g}{}}} +\pgfkeysrobustdef*\pgfkeysrobustredef{\pgfkeys@starorlong{\pgfkeys@redefcmd{}{p}}} +\pgfkeysrobustdef*\pgfkeysnewredef{\pgfkeys@starorlong{\pgfkeys@redefcmd{}{}}} +\pgfkeysrobustdef*\pgfkeys@redefcmd#1#2#3{% + \ifdefined#3% + \ifpgfkeys@tracingkeys + \immediate\write\m@ne{Command '\string#3' redefined}% + \fi + \fi + \l@ngrel@x + \ifcat$\detokenize{#2}$\else + \ifx#2p\expandafter\expandafter\expandafter\protected\fi + \fi + \csname#1def\endcsname#3% +} + +\pgfkeysrobustdef\pgfkeys@testst#1{% + \ifpgfkeysstar{\pgfkeys@tempsttrue#1}{\pgfkeys@tempstfalse#1}% +} +\pgfkeysrobustdef\pgfkeys@testcl#1{% + \ifpgfkeysnextchar!{\pgfkeys@cltrue#1}{\pgfkeys@clfalse#1}% +} +\pgfkeysrobustdef\pgfkeys@testpl#1{% + \ifpgfkeysnextchar+{\pgfkeys@pltrue#1}{\pgfkeys@plfalse#1}% +} +% \pgfkeysnewlet shouldn't grab second argument! +\pgfkeysrobustdef*\pgfkeysnewlet#1{% + \ifdefined#1% + \pgfkeys@error{Command '\string#1' already exists}% + \expandafter\pgfkeys@gobble + \else + \expandafter\pgfkeys@iofi + \fi + {\let#1 }% +} +\pgfkeysnewlet\pgfkeys@nil\relax +\pgfkeysnewdef\pgfkeys@cmdeq{\pgfkeys@gobble\pgfkeys@cmdeq} +\pgfkeysnewdef\ifpgfkeyscmdeq#1#2{% + \ifx#1#2\pgfkeys@cmdeq\expandafter\pgfkeys@iofii\else + \expandafter\pgfkeys@iiofii\fi +} +\pgfkeysnewdef\pgfkeys@gobble#1{} +\pgfkeysnewdef*\pgfkeys@space{ } +\edef\pgfkeys@backslashchar{\expandafter\pgfkeys@gobble\string\\} +\pgfkeysnewdef\pgfkeys@gobbletwo#1#2{} +\pgfkeysnewdef*\pgfkeys@stripprefix#1>{} +\pgfkeysnewdef\pgfkeys@car#1#2\car@nil{#1} +\lowercase{\pgfkeysnewdef*\pgfkeys@gobblespace} {} +\pgfkeysnewdef\pgfkeysswap#1#2{#2#1} +\pgfkeysnewdef\pgfkeysswapfirstbraced#1#2{#2{#1}} +\pgfkeysnewdef\pgfkeysexpandnext#1#2{% + \expandafter\pgfkeysswap\expandafter{#2}{#1}% +} +\pgfkeysnewdef\pgfkeysexpandbracenext#1#2{% + \expandafter\pgfkeysswap\expandafter{\expandafter{#2}}{#1}% +} +\pgfkeysrobustdef*\pgfkeyscsdef#1{\expandafter\def\csname#1\endcsname} +\pgfkeysrobustdef*\pgfkeyscsedef#1{\expandafter\edef\csname#1\endcsname} +\pgfkeysrobustdef*\pgfkeysnoexpandcs#1{% + \unexpanded\expandafter{\csname#1\endcsname}% +} +\pgfkeysrobustdef*\pgfkeysexpandcsonce#1{% + \unexpanded\expandafter\expandafter\expandafter{\csname#1\endcsname}% +} +\pgfkeysrobustdef\pgfkeysexpanded#1{\begingroup\edef\x{\endgroup#1}\x} +\pgfkeysrobustdef\pgfkeysexpandarg#1#2{% + \begingroup\toks@{#1}% + \pgfkeysexpanded{\endgroup\the\toks@{#2}}% +} +\pgfkeysrobustdef\pgfkeysexpandargonce#1#2{% + \begingroup + \toks@{#1}\toks1\expandafter{#2}% + \pgfkeysexpanded{\endgroup\the\toks@{\the\toks1}}% +} +\pgfkeysrobustdef\pgfkeysexpandsecond#1#2{% + \begingroup\toks@{#1}% + \pgfkeysexpanded{\endgroup\the\toks@#2}% +} +\pgfkeysrobustdef\pgfkeysexpandsecondonce#1#2{% + \begingroup + \toks@{#1}\toks1\expandafter{#2}% + \pgfkeysexpanded{\endgroup\the\toks@\the\toks1}% +} +\pgfkeysnewdef*\ifpgfkeysswitch#1{% + \ifpgfkeysblank{#1}{% + \pgfkeys@iiofii + }{% + \expandafter\pgfkeys@ifswitch\romannumeral-`\q#1\pgfkeys@nil{% + \if#1\expandafter\pgfkeys@iofii\else\expandafter\pgfkeys@iiofii\fi + }{% + \pgfkeys@error{Invalid switch '#1'}% + }% + }% +} +\pgfkeysnewdef*\pgfkeys@ifswitch#1#2\pgfkeys@nil{% + \ifpgfkeysblank{#2}\pgfkeys@iiofii\pgfkeys@iofii +} +\pgfkeysnewdef\ifpgfkeyscond#1\fi{% + #1\relax\expandafter\pgfkeys@iofii\else + \expandafter\pgfkeys@iiofii\fi +} +\pgfkeysnewdef*\ifpgfkeysnum#1#{\ifpgfkeyscond\ifnum#1\fi} +\pgfkeysrobustdef*\pgfkeys@in#1#2{% + \long\def\in@@##1#1##2\in@@{% + \edef\in@@{\unexpanded{##2}}% + \ifx\in@@\pgfkeys@empty\pgfkeys@infalse\else\pgfkeys@intrue\fi + }% + \in@@#2{\in@@}#1\in@@ +} +\pgfkeysrobustdef*\ifpgfkeysin#1#2{% + \pgfkeys@in{#1}{#2}% + \csname pgfkeys@\ifpgfkeys@in iofii\else iiofii\fi\endcsname +} +\pgfkeysrobustdef*\ifpgfkeysnotin#1#2{% + \ifpgfkeysin{#1}{#2}\pgfkeys@iiofii\pgfkeys@iofii +} +\pgfkeysrobustdef*\ifpgfkeysxin#1#2{% + \pgfkeys@expandtwoargs\ifpgfkeysin{#1}{#2}% +} +\pgfkeysrobustdef*\pgfkeys@expandtwoargs#1#2#3{% + % #1 might be a token list: + \begingroup\toks@{#1}% + \edef\x{\endgroup\the\toks@{#2}{#3}}\x +} +\pgfkeysnewdef*\ifpgfkeysdef#1{% + \ifpgfkeysblank{#1}\pgfkeys@iiofii{% + \ifx#1\@undefined + \expandafter\pgfkeys@iiofii + \else + \ifx#1\relax + \expandafter\expandafter\expandafter\pgfkeys@iiofii + \else + \expandafter\expandafter\expandafter\pgfkeys@iofii + \fi + \fi + }% +} +\pgfkeysnewdef*\ifpgfkeyscsdef#1{% + \ifpgfkeysblank{#1}{% + \expandafter\pgfkeys@iiofii\pgfkeys@gobble + }{% + \ifcsname#1\endcsname + \expandafter\pgfkeys@iofi + \else + \expandafter\expandafter\expandafter + \pgfkeys@iiofii\expandafter\pgfkeys@gobble + \fi + }{% + \expandafter\ifpgfkeysdef\csname#1\endcsname + }% +} +\pgfkeysnewdef*\ifpgfkeyskeydef#1{\ifpgfkeyscsdef{pgfk@#1}} +\pgfkeysnewredef*\pgfkeysifdefined#1{% + \pgfkeys@ifcsname pgfk@#1\endcsname + \expandafter\pgfkeys@iofii + \else + \expandafter\pgfkeys@iiofii + \fi +} + +% If you don't want to have \detokenize, here is rather lengthy way for +% \ifnull. Note that \ifnull defers from \ifblank: +\pgfkeysnewdef\ifpgfkeysnull#1#2#3{% + \romannumeral\iffalse{\fi\expandafter\pgfkeys@iiofii\expandafter + {\expandafter{\string#1}\expandafter\pgfkeys@iiofii\string}% + \expandafter\pgfkeys@iofii\expandafter{\iffalse}\fi0 #3}{0 #2}% +} +%\pgfkeysnewdef\ifpgfkeysblank#1{% +% \expandafter\ifpgfkeysnull\expandafter{\pgfkeys@gobble#1.}% +%} +\pgfkeysnewdef\ifpgfkeysblank#1{% + \ifcat$\detokenize\expandafter{\pgfkeys@gobble#1.}$% + \expandafter\pgfkeys@iofii\else\expandafter\pgfkeys@iiofii\fi +} +\pgfkeysnewdef*\ifpgfkeysbool#1{% + \ifpgfkeysblank{#1}{% + \pgfkeys@iiofii + }{% + \ifpgfkeyscsdef{if#1}{% + \csname pgfkeys@i\csname if#1\endcsname ofii\else iofii\fi\endcsname + }{% + \pgfkeys@error{Undefined boolean '#1'}% + }% + }% +} +\pgfkeysrobustdef*\pgfkeysaftergroupdef#1\endgroup{% + \edef\x{\endgroup\edef\noexpand#1{\noexpand\unexpanded + {\unexpanded\expandafter{#1}}}}\x +} + +\ifpgfkeysdef\pdfstrcmp{% + \let\pgfkeys@strcmp\pdfstrcmp +}{% + % Is it true that tikz doesn't load any external packages? If yes, + % then we've to find another way around the need for 'pdftexcmds': + \RequirePackage{pdftexcmds}% + \ifpgfkeysdef\pdf@strcmp{% + \let\pgfkeys@strcmp\pdf@strcmp + }{% + \pgfkeys@error{Neither '\string\pdfstrcmp' nor + '\string\pdf@strcmp' could be found}% + }% +} +\pgfkeysnewdef\ifpgfkeysstrcmp#1#2{% + \csname pgfkeys@i\ifnum\pgfkeys@strcmp{\detokenize{#1}}% + {\detokenize{#2}}=0ofii\else iofii\fi\endcsname +} +\pgfkeysnewdef\ifpgfkeysxstrcmp#1#2{% + \csname pgfkeys@i\ifnum\pgfkeys@strcmp{#1}{#2}=0 + ofii\else iofii\fi\endcsname +} +\pgfkeysnewdef\ifpgfkeysbraced#1{% + \ifpgfkeysblank{#1}\pgfkeys@iiofii{% + \ifpgfkeysxstrcmp{\detokenize\expandafter{\pgfkeys@gobble#1}}{}{% + \ifpgfkeysxstrcmp{\expandafter\pgfkeys@car\detokenize{#1}\car@nil} + {\pgfkeys@leftbracechar}\pgfkeys@iofii\pgfkeys@iiofii + }{% + \pgfkeys@iiofii + }% + }% +} +\pgfkeysnewdef\ifpgfkeysleadspace#1#2#3{% + \romannumeral\csname + pgfkeys@i\ifpgfkeysnull{#1}{iofii}{\iffalse{\fi\pgfkeys@ifleadspace.#1 }}% + \endcsname{0 #2}{0 #3}% +} +\pgfkeysnewdef\pgfkeys@ifleadspace#1 {% don't shift! + \expandafter\ifpgfkeysnull\expandafter{\pgfkeys@gobble#1}{ofii}{iofii}% + \expandafter\pgfkeys@gobble\expandafter{\iffalse}\fi +} +\pgfkeysrobustdef*\pgfkeys@sanitizemacro#1{% + \edef#1{\expandafter\pgfkeys@stripprefix\meaning#1}% +} + +\begingroup +\catcode`\&=7 +\pgfkeysnewgdef\pgfkeystrimspace#1{\pgfkeys@trimspace@a.#1& &} +\pgfkeysnewgdef\pgfkeys@trimspace@a#1 &{\pgfkeys@trimspace@b#1&} +\pgfkeysnewgdef\pgfkeys@trimspace@b#1{% + \unexpanded\expandafter{% + \romannumeral0% + \expandafter\ifpgfkeysleadspace\expandafter{\pgfkeys@gobble#1}{% + \pgfkeys@gobble#1% + }{% + \expandafter\space\pgfkeys@gobble#1% + }% + }% +} +\endgroup + +\pgfkeysrobustdef\pgfkeysdespace#1#2{\edef#2{\pgfkeystrimspace{#1}}} +\pgfkeysrobustdef*\pgfkeysdespacecontent#1{% + \edef#1{\expandafter\pgfkeystrimspace\expandafter{#1}}% +} +\pgfkeysnewdef*\pgfkeysgobblescape#1{% + \ifpgfkeysblank{#1}{}{% + \ifnum\escapechar>255 + \string#1% + \else + \ifnum\escapechar<0 + \string#1% + \else + \ifnum\escapechar=32 + \expandafter\pgfkeys@gobblespace\string#1% + \else + \expandafter\pgfkeys@gobble\string#1% + \fi + \fi + \fi + }% +} +\pgfkeysnewdef*\ifpgfkeysescaped#1{% + \ifnum\escapechar>255 + \expandafter\pgfkeys@iiofii + \else + \ifnum\escapechar<0 + \expandafter\expandafter\expandafter\pgfkeys@iiofii + \else + \ifnum\escapechar=32 + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\pgfkeys@iiofii + \else + \csname pgfkeys@i\if\expandafter\pgfkeys@car\string#1x\@nil + \pgfkeys@backslashchar ofii\else iofii\fi + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter + \endcsname + \fi + \fi + \fi +} +\pgfkeysnewdef\pgfkeys@alloftwo#1#2{#1#2} +\pgfkeysnewdef\ifpgfkeysntype#1{% Bruno Le Floch + \ifpgfkeysxstrcmp + {\detokenize\expandafter{\pgfkeys@alloftwo#1{}{}}}% + {\detokenize{#1{}}}% +} + +% Expandable test option. Use with caution: it can't be used to test +% for explicit braces! +% Examples: +% { +% \catcode`\ =13 +% \gdef\activespace{ } +% } +% \def\cmd[#1]{} +% \def\x{\pgfkeys@xtestopt\cmd{noarg}} +% \x {xy} +% \x [arg] {xy} +% \expandafter\x \activespace {xy} +% \expandafter\x \activespace [arg] {xy} + +\pgfkeysnewdef*\pgfkeys@xtestopt#1#2#3{% + \ifpgfkeysstrcmp{ }{#3}{% + \pgfkeys@xtestopt#1{#2}% + }{% + \ifpgfkeysstrcmp{#3}{[} + {#1[}{\ifpgfkeysntype{#3}{#1[#2]#3}{#1[#2]{#3}}}% + }% +} + +% This can't be used to test for the presence of explicit left or right brace. +\pgfkeysnewdef*\ifpgfkeysxifnextchar#1#2#3#4{% + \ifpgfkeysstrcmp{ }{#4}{% + \ifpgfkeysxifnextchar#1{#2}{#3}% + }{% + \ifpgfkeysstrcmp{#4}{#1}{#2}{\ifpgfkeysntype{#4}{#3#4}{#3{#4}}}% + }% +} + +% \pgfkeysremoveouterbraces[]{} +% To make the test expandable, we need to use expandable testopt. +\pgfkeysnewdef*\pgfkeysremoveouterbraces{% + \pgfkeys@xtestopt\pgfkeys@removeouterbraces{1}% +} +\pgfkeysnewdef*\pgfkeys@removeouterbraces[#1]{% + \romannumeral\expandafter\pgfkeys@r@moveouterbraces\expandafter{% + \romannumeral\ifpgfkeysxstrcmp{\pgfkeystrimspace{#1}}{all}{1000}{#1}000% + }% +} +\pgfkeysnewdef\pgfkeys@r@moveouterbraces#1#2{% + \ifpgfkeysblank{#1}{0 \unexpanded{#2}}{% + \expandafter\ifpgfkeysblank\expandafter{\pgfkeys@gobble#2}{% + \ifpgfkeysbraced{#2}{% + \expandafter\pgfkeysswapfirstbraced\expandafter{\pgfkeys@iofi#2}% + {\expandafter\pgfkeys@r@moveouterbraces\expandafter{\pgfkeys@gobble#1}}% + }{0 \unexpanded{#2}}% + }{0 \unexpanded{#2}}% + }% +} + +\pgfkeysrobustdef*\pgfkeyscsvnormalize{\pgfkeys@testopt\pgfkeys@csvnormalize,} +\pgfkeysrobustdef\pgfkeys@csvnormalize[#1]#2{% + \begingroup + \pgfkeysdeclarenormalizer{#1}% + \@tempswafalse + \pgfkeys@normalizelist{#2}% + \expandafter\endgroup\expandafter\pgfkeys@temptoks\expandafter + {\the\pgfkeys@temptoks}% +} +\pgfkeysrobustdef\pgfkeyskvnormalize#1{% + \begingroup + \pgfkeysdeclarenormalizer{,}% + \@tempswatrue + \pgfkeys@normalizelist{#1^?^}% + \def\reserved@a##1^?^##2\pgfkeys@nil{% + \pgfkeys@parserequalerr##1##2,=\pgfkeys@nil + \pgfkeys@temptoks{##1##2}% + }% + \expandafter\reserved@a\the\pgfkeys@temptoks\pgfkeys@nil + \expandafter\endgroup\expandafter\pgfkeys@temptoks\expandafter + {\the\pgfkeys@temptoks}% +} +\pgfkeysrobustdef\pgfkeysslashnormalize#1{% + \pgfkeys@csvnormalize[/]{x#1}% + \pgfkeys@temptoks\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\expandafter + {\expandafter\expandafter\expandafter\noexpand\expandafter + \pgfkeys@gobble\the\pgfkeys@temptoks}% +} + +% A general list normalizer, for arbitrary list parsers: +\begingroup +\catcode`\~=13 +\catcode`\!=13 +\pgfkeysrobustgdef*\pgfkeysdeclarenormalizer#1{% + \begingroup + \lccode`\~=`#1% + \lccode`\!=`\=% + \lowercase{\endgroup + \def\pgfkeys@normalizelist##1{% + \pgfkeys@temptoks\expandafter{\romannumeral-`\q + \pgfkeys@activeparser#1##1#1~\pgfkeys@nil}% + }% + \def\pgfkeys@activeparser##1~##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \ifpgfkeysbool{@tempswa}{% + \pgfkeys@activeequal##1!\pgfkeys@nil + }{% + \pgfkeys@spaceparser##1 #1\pgfkeys@nil + }% + }{% + \pgfkeys@activeparser##1#1##2\pgfkeys@nil + }% + }% + }% + \begingroup + \uccode`\~=`\=% + \uppercase{\endgroup + \def\pgfkeys@activeequal##1~##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \pgfkeys@spaceparser##1 #1\pgfkeys@nil + }{% + \pgfkeys@activeequal##1=##2\pgfkeys@nil + }% + }% + }% + \def\pgfkeys@spaceparser##1 #1##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \pgfkeys@parserspace##1#1 \pgfkeys@nil + }{% + \pgfkeys@spaceparser##1#1##2\pgfkeys@nil + }% + }% + \def\pgfkeys@parserspace##1#1 ##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \ifpgfkeysbool{@tempswa}{% + \pgfkeys@spaceequal##1 =\pgfkeys@nil + }{% + \pgfkeys@doubleparser##1#1#1\pgfkeys@nil + }% + }{% + \pgfkeys@parserspace##1#1##2\pgfkeys@nil + }% + }% + \def\pgfkeys@spaceequal##1 =##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \pgfkeys@equalspace##1= \pgfkeys@nil + }{% + \pgfkeys@spaceequal##1=##2\pgfkeys@nil + }% + }% + \def\pgfkeys@equalspace##1= ##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \pgfkeys@doubleparser##1#1#1\pgfkeys@nil + }{% + \pgfkeys@equalspace##1=##2\pgfkeys@nil + }% + }% + \def\pgfkeys@doubleparser##1#1#1##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \ifpgfkeysbool{@tempswa}{% + \pgfkeys@doubleequal##1==\pgfkeys@nil + }{% + \ifpgfkeysblank{##1}{}{% + \pgfkeys@remleadparser##1\pgfkeys@nil + }% + }% + }{% + \pgfkeys@doubleparser##1#1##2\pgfkeys@nil + }% + }% + \def\pgfkeys@doubleequal##1==##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{% + \ifpgfkeysblank{##1}{}{% + \pgfkeys@remleadparser##1\pgfkeys@nil + }% + }{% + \pgfkeys@doubleequal##1=##2\pgfkeys@nil + }% + }% + \def\pgfkeys@remleadparser#1##1\pgfkeys@nil{% + \expandafter\space\noexpand##1% + }% + \def\pgfkeys@parserequalerr##1#1=##2\pgfkeys@nil{% + \ifpgfkeysblank{##2}{}{% + \pgfkeys@error{There is '#1=' in your key-value list}% + }% + }% +} +\endgroup + +% I haven't studied all of pgf/tikz's looping macros, but we may sometimes +% need to break out of the loop prematurely. +% Example: +% \pgfkeysdeclarelistparser\myloop{,} +% \chardef\nr=0 +% \myloop{a,b,c}\temp{% +% \edef\nr{\the\numexpr\nr+1}% +% \ifnum\nr=2 \pgfkeysloopbreak\fi % use only a,b +% \edef\y#1{#1\temp}% +% } +\pgfkeysnewlet\pgfkeysloopbreak\pgfkeysloopbreaktrue +\pgfkeysnewdef*\pgfkeys@listparser@nil{\pgfkeys@listparser@nil} +\pgfkeysrobustdef*\pgfkeysdeclarelistparser#1#2{% + \pgfkeysrobustdef#1##1##2##3{% + \pgfkeys@csvnormalize[#2]{##1}% + \edef##2{\the\pgfkeys@temptoks}% + \ifpgfkeyscmdeq##2\pgfkeys@empty{}{% + \pgfkeysexpandnext{% + \csname pgfkeys@listparser@\pgfkeysgobblescape#1\endcsname + ##2{##3}% + }##2#2\pgfkeys@listparser@nil#2% + }% + }% + \pgfkeyscsdef{pgfkeys@listparser@\pgfkeysgobblescape#1}##1##2##3#2{% + \pgfkeys@temptoks{##3}% + \edef##1{\the\pgfkeys@temptoks}% + \ifpgfkeyscmdeq##1\pgfkeys@listparser@nil{}{% + ##2\relax + \ifpgfkeysloopbreak + % To allow nesting of loop: + \pgfkeysloopbreakfalse + \begingroup + \pgfkeyscsdef{pgfkeys@listparser@\pgfkeysgobblescape#1}% + ####1\pgfkeys@listparser@nil#2{% + \endgroup + \pgfkeys@temptoks{####1}% + \edef\pgfkeysremainder{\the\pgfkeys@temptoks}% + }% + \fi + \csname pgfkeys@listparser@\pgfkeysgobblescape#1\endcsname##1{##2}% + }% + }% + % <#1@e> is like #1 but will execute once when + % is empty: + \expandafter\pgfkeysrobustdef + \csname\pgfkeysgobblescape#1@e\endcsname##1##2##3{% + \pgfkeys@csvnormalize[#2]{##1}% + \begingroup + \toks@{\csname pgfkeys@listparser@\pgfkeysgobblescape#1\endcsname##2{##3}}% + \expandafter\endgroup\the\expandafter\toks@ + \the\pgfkeys@temptoks#2\pgfkeys@listparser@nil#2% + }% +} +\pgfkeysdeclarelistparser\pgfkeyscommaloop{,} + +% \pgfkeysnewbools[]{} +\pgfkeysrobustdef*\pgfkeysnewbools{\pgfkeys@testopt\pgfkeys@newbools{}} +\pgfkeysrobustdef*\pgfkeys@newbools[#1]#2{% + \pgfkeyscommaloop{#2}\pgfkeys@tempa{% + \ifpgfkeyscsdef{if#1\pgfkeys@tempa}{% + \pgfkeysnoexpandcs{if#1\pgfkeys@tempa}% + \pgfkeys@err{Boolean '\the\pgfkeys@temptoks' + already exists}% + }{% + \expandafter\newif\csname if#1\pgfkeys@tempa\endcsname + }% + }% +} +\pgfkeysnewbools[pgfkeys@]{cl,pl} + +\pgfkeysrobustdef*\pgfkeys@trimsuffixcomma{% + \begingroup + \def\pgfkeys@tempa{% + \edef\reserved@a{\the\pgfkeys@temptoks}% + \pgfkeys@sanitizemacro\reserved@a + \ifpgfkeysxin{,\pgfkeys@nil}{\reserved@a\pgfkeys@nil}{% + \def\reserved@a####1,\pgfkeys@nil{% + \pgfkeys@temptoks{####1}\pgfkeys@tempa + }% + \expandafter\reserved@a\the\pgfkeys@temptoks\pgfkeys@nil + }{}% + }% + \pgfkeys@tempa + \expandafter\endgroup\expandafter\pgfkeys@temptoks\expandafter + {\the\pgfkeys@temptoks}% +} + +\pgfkeysrobustredef\pgfkeys@@set#1#2{% + \let\pgfkeysdefaultpath\pgfkeys@root + \pgfkeys@set@aux{#1}{#2}% +} +% \pgfkeys@set@aux is also needed by \pgfkeys@@qset: +\pgfkeysrobustdef\pgfkeys@set@aux#1#2{% + \pgfkeysslashnormalize{#2}% + \expandafter\pgfkeyskvnormalize\expandafter{\the\pgfkeys@temptoks}% + \pgfkeys@trimsuffixcomma + \expandafter\pgfkeys@parse\the\pgfkeys@temptoks,\pgfkeys@mainstop + \def\pgfkeysdefaultpath{#1}% +} +\pgfkeysrobustredef\pgfkeys@normal#1,{% + \pgfkeys@unpack@a#1=\pgfkeysnovalue=\pgfkeys@stop + \pgfkeys@parse +} +\pgfkeysrobustdef\pgfkeys@unpack@a#1={% + % No need to despace #1: the list was previously normalized. + \edef\pgfkeyscurrentkey{#1}% + \ifpgfkeysbool{pgfkeys@preservebrace}{% + \pgfkeys@unpack@b\do + }{% + \pgfkeys@unpack@b + }% +} +\pgfkeysrobustdef\pgfkeys@unpack@b#1=#2\pgfkeys@stop{% + % No need to despace #1 here. + \ifpgfkeys@preservebrace + \pgfkeys@temptoks\expandafter{\pgfkeys@gobble#1}% + \else + \pgfkeys@temptoks{#1}% + \fi + % This solution is useful but it isn't yet foolproof because of the way + % the original pgfkeys package delimits arguments by \pgfeov. + % Robustifying this stage will require changes to pgfkeys' style of + % argument grabbing. + \edef\pgfkeyscurrentvalue{% + \ifpgfkeys@preservebrace + \expandafter\ifpgfkeysbraced\expandafter{\the\pgfkeys@temptoks}{% + {\the\pgfkeys@temptoks}% + }{% + \the\pgfkeys@temptoks + }% + \else + \the\pgfkeys@temptoks + \fi + }% + % Using LaTeX-style branches can help offset problems often found with + % parsing unbalanced conditionals. + \ifpgfkeyscmdeq\pgfkeyscurrentkey\pgfkeys@empty{% + % OK, just skip + }{% + \pgfkeys@add@path@as@needed + \ifpgfkeyscmdeq\pgfkeyscurrentvalue\pgfkeysnovalue@text{% + \pgfkeysifdefined{\pgfkeyscurrentkey/.@def}{% + \pgfkeysgetvalue{\pgfkeyscurrentkey/.@def}\pgfkeyscurrentvalue + }{% + % Proposal: + % If there is no user value and no default, we should check if + % their is an handler for the name of this key or if value is + % forbidden. If nothing is found, we should alert the user. + % To reduce the cost of checking, this should be based on user + % preference. + }% + }{}% + \ifpgfkeyscmdeq\pgfkeyscurrentvalue\pgfkeysvaluerequired{% + \pgfkeysvalueof{/errors/value required/.@cmd}\pgfkeyscurrentkey + \pgfkeyscurrentvalue\pgfeov + }{% + \pgfkeys@case@one + }% + }% +} + +\pgfkeysrobustredef\pgfkeysalso#1{% + % First strip all outer brace of #1; otherwise parsing may fail. + \edef\pgfkeys@tempa{\pgfkeysremoveouterbraces[all]{#1}}% + \expandafter\pgfkeysslashnormalize\expandafter{\pgfkeys@tempa}% + \expandafter\pgfkeyskvnormalize\expandafter{\the\pgfkeys@temptoks}% + \pgfkeys@trimsuffixcomma + \expandafter\pgfkeys@parse\the\pgfkeys@temptoks,\pgfkeys@mainstop +} + +% No change to the original \pgfqkeys, but \pgfkeys@@qset requires patching: +\pgfkeysrobustredef*\pgfqkeys{% + \expandafter\pgfkeys@@qset\expandafter{\pgfkeysdefaultpath}% +} +\pgfkeysrobustredef\pgfkeys@@qset#1#2#3{% + \pgfkeysexpandarg\pgfkeysslashnormalize{#2}% + \expandafter\pgfkeyskvnormalize\expandafter{\the\pgfkeys@temptoks}% + \edef\pgfkeysdefaultpath{\the\pgfkeys@temptoks/}% + \pgfkeys@set@aux{#1}{#3}% +} +% \pgfqkeysalso also needs to call the list normalizer: +\pgfkeysrobustredef\pgfqkeysalso#1#2{% + \pgfkeysexpandarg\pgfkeysslashnormalize{#1}% + \expandafter\pgfkeyskvnormalize\expandafter{\the\pgfkeys@temptoks}% + \edef\pgfkeysdefaultpath{\the\pgfkeys@temptoks/}% + \pgfkeysalso{#2}% +} + +\pgfkeysnewdef*\pgfkeys@generateparameters#1#2{% + \ifnum#1<\numexpr#2+1\relax ####\number#1% + \expandafter\pgfkeys@generateparameters + \expandafter{\number\numexpr#1+1\expandafter}% + \expandafter{\number#2\expandafter}% + \fi +} +\pgfkeysnewredef\pgfkeysdefnargs#1#2#3{\pgfkeysdefnargs@{#1}{#2}{#3}{\def}} +\pgfkeysnewredef\pgfkeysedefnargs#1#2#3{\pgfkeysdefnargs@{#1}{#2}{#3}{\edef}} +\pgfkeysnewredef\pgfkeysdefnargs@#1#2#3#4{% + \ifnum#2>9\relax + \pgfkeys@error{\string\pgfkeysdefnargs: + I expected #2<=9 arguments but I saw #2}% + \else + \pgfkeyscsedef{pgfk@#1/.@args}{\pgfkeys@generateparameters{1}{#2}}% + \fi + \pgfkeysgetvalue{#1/.@args}\pgfkeys@tempargs + \def\pgfkeys@temp{\expandafter#4\csname pgfk@#1/.@@body\endcsname}% + \expandafter\pgfkeys@temp\pgfkeys@tempargs{#3}% + \edef\pgfkeys@tempargs{\noexpand\pgfkeysvalueof{#1/.@@body}}% + \def\pgfkeys@temp{\pgfkeysdef{#1}}% + \expandafter\pgfkeys@temp\expandafter{\pgfkeys@tempargs##1}% + \pgfkeyssetvalue{#1/.@body}{#3}% +} + +\pgfkeys{% + % Use default values to set the key. If the key has no default or + % if value is required, an error will be raised: + /handlers/.restore default/.code=\pgfkeys{\pgfkeyscurrentpath}% +} +\pgfkeys{% + /handlers/.restore key defaults/.code=\pgfkeysalso{#1}% +} +\pgfkeys{/handlers/.normal code/.code=#1} + +% New handlers for boolean keys: +% Syntaxes: +% .is if with no callback= +% .is if with 1 callback={}{} +% .is if with 2 callbacks={}{}{} +% In this way, I know I am dealing with , and not with another +% (auxiliary) boolean as in conventional '.is if' handler. +\pgfkeys{% + /handlers/.is if with no callback/.code={% + \pgfkeys@boolean@handler{#1}{##1}{}{}% + }, + /handlers/.is if with 1 callback/.code 2 args={% + \pgfkeys@boolean@handler{#1}{##1}{#2}{}% + }, + /handlers/.is if with one callback/.style 2 args={% + \pgfkeyscurrentpath/.is if with 1 callback={#1}{#2}% + }, + /handlers/.is if with 2 callbacks/.code n args={3}{% + \pgfkeys@boolean@handler{#1}{##1}{#2}{#3}% + } +} +\pgfkeysrobustredef*\pgfkeys@savresname#1{% + \ifcase#1\relax + % The idea is, for a given key '/my path/key/.code', to set + % path := '/my path' + % name := 'key/.code' + % key := '/my path/key/.code' + \let\pgfkeyssavedkey=\pgfkeyscurrentkey + \let\pgfkeyssavedname=\pgfkeyscurrentname + \edef\pgfkeyssavedpath{\pgfkeyscurrentpath}% + \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}% + \pgfkeys@split@path + \let\pgfkeyssavednameb\pgfkeyscurrentname + \or + % Recover: + \let\pgfkeyscurrentkey=\pgfkeyssavedkey + \let\pgfkeyscurrentname=\pgfkeyssavedname + % Don't do \edef\pgfkeyscurrentpath{\pgfkeyssavedpath} here, since + % \pgfkeyscurrentpath is determined by \pgfkeys@pathtoks. + \else + \pgfkeys@error{Number '#1' out of range [0,1]}% + \fi +} +\pgfkeysrobustredef\pgfkeys@boolean@handler#1#2#3#4{% + \pgfkeys@savresname{0}% + % Let's not redefine 'if\pgfkeyscurrentname' is it already exists, + % so that we don't change its current state: + \ifpgfkeyscsdef{if\pgfkeyscurrentname}{}{% + % Can use \outer-defined \newif: + \csname newif\expandafter\endcsname + \csname if\pgfkeyscurrentname\endcsname + }% + \begingroup + \def\reserved@a{\pgfkeyssavedpath/.code=}% + \expandafter\expandafter\expandafter\endgroup\expandafter\expandafter + \expandafter\pgfkeysalso\expandafter\expandafter\expandafter{% + \expandafter\reserved@a\expandafter\pgfkeys@boolean@handler@b + \expandafter{\pgfkeyssavednameb}{#2}{#3}{#4}, + \pgfkeyssavedpath/.default=#1% + }% + \pgfkeys@savresname{1}% +} +\pgfkeysrobustredef\pgfkeys@boolean@handler@b#1#2#3#4{% + \ifpgfkeysxin{,\pgfkeystrimspace{#2},}{,true,false,}{% + \ifpgfkeyscsdef{#1#2}{% + \csname#1#2\endcsname + \ifpgfkeysblank{#3#4}{}{\ifpgfkeysbool{#1}{#3}{#4}}% + }{% + \pgfkeysvalueof{/errors/boolean expected/.@cmd}% + \pgfkeyscurrentkey{#2}\pgfeov + }% + }{% + \pgfkeysvalueof{/errors/boolean expected/.@cmd}% + \pgfkeyscurrentkey{#2}\pgfeov + }% +} + +\pgfkeys@restorecodes +\endinput + +%% End of file 'pgfkeyx.sty' %% -- cgit v1.2.3