diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex | 1667 |
1 files changed, 1667 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex new file mode 100644 index 00000000000..74667335805 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex @@ -0,0 +1,1667 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqkeys.code.tex +%% Exposes: \sseqset +%% +%% Sets up the keys for sseqpages. There are a lot of them... +%% + + + +\def\sseq@pgfqkeysdirlist#1#2{% + \sseq@temptoks{#2}% + \sseq@pgfqkeysdirlist@#1,\sseq@nil +} + +\def\sseq@pgfqkeysdirlist@#1,{% + \sseq@eval{\@nx\pgfqkeys{#1}{\the\sseq@temptoks}}% + \@ifnextchar\sseq@nil{\@gobble}{\sseq@pgfqkeysdirlist@}% +} + +%%%% Interface macros: +% These are the things that are used outside of this section: +\let\sseq@pgfkeys@error@save\pgfkeys@error +\pgfkeys{/sseqpages/userstyles/.unknown/.code={\sseq@passoptionto{\sseq@sseqsetdirectory}}} +\def\sseqset#1{\pgfqkeys{/sseqpages/userstyles}{#1}} + +\def\sseq@sseqsetdirectory{/sseqpages/global/default} + +\def\sseq@set{\pgfqkeys{/sseqpages}} + +%%% +%%% Local Keys +%%% + +% This is where and how we are going to store the results of our local options. Note that definitions need to be local to allow recursion. +\def\sseq@savedoptioncode{} +\def\sseq@d@addto@options{\sseq@d@addto@macro\sseq@savedoptioncode} +\def\sseq@e@addto@options{\sseq@e@addto@macro\sseq@savedoptioncode} + +% #1 -- name of key +% #2 -- options +% This is the main way that we use options. (We also use \pgfqkeys{/sseqpages/global} and some similar things) +% Dumps out code that the option indexes into \sseq@savedoptioncode +% This is because \pgfkeys has a high performance cost, so instead of using \pgfkeys once per page, +% we use this once when putting together the spectral sequence and save the result. +\def\sseq@processoptions#1#2{% + \def\sseq@savedoptioncode{}% + \sseq@protectedeval{\@nx % TODO: get rid of this protectedeval + \pgfqkeys{/sseqpages/#1}{#2} + }% +} + +% First pass versus second pass: +% Lots of options mainly do stuff on the drawing run, but still need to warn the sseq setup algorithms that they're around +% on the first pass. Some only do things on the first pass or only do things on the second pass. +% For example, shifts: shifts apply a coordinate transform on the second pass, but also need to factor into the coordinates of +% classes etc which are computed at specification time not at draw time. So xshift=2 increases \sseq@x by 2 on it's first pass and +% applies a coordinate transfrom by 2cm on the second pass. + +% normal mode does the firstpass options now and saves the secondpass options in \sseq@savedoptioncode for later use. +% firstpass mode does the firstpass options and throws away the secondpass options. +% secondpass mode throws away the firstpass options and does the secondpass options NOW +% bothpass mode does both firstpass and secondpass options NOW +% We spend the vast majority of our time in normal mode. + +\def\sseq@options@use#1{#1} +\def\sseq@options@normalmode{\let\sseq@options@firstpass\sseq@options@use\let\sseq@options@secondpass\sseq@d@addto@options} +\def\sseq@options@firstpassmode{\let\sseq@options@firstpass\sseq@options@use\let\sseq@options@secondpass\@gobble} +\def\sseq@options@secondpassmode{\let\sseq@options@firstpass\@gobble\let\sseq@options@secondpass\sseq@options@use} +\def\sseq@options@bothpassmode{\let\sseq@options@firstpass\sseq@options@use\let\sseq@options@secondpass\sseq@options@use} +\sseq@options@normalmode + +\pgfqkeys{/handlers}{ + .sseq @ first pass code/.code={ + \pgfkeysalso{\pgfkeyscurrentpath/.code={\sseq@options@firstpass{#1}}} + }, + .sseq @ first pass append code/.code={ + \pgfkeysalso{\pgfkeyscurrentpath/.append code={\sseq@options@firstpass{#1}}} + }, + .sseq @ second pass code/.code={ + \pgfkeysalso{\pgfkeyscurrentpath/.code={\sseq@options@secondpass{#1}}} + }, + .sseq @ second pass append code/.code={ + \pgfkeysalso{\pgfkeyscurrentpath/.append code={\sseq@options@secondpass{#1}}} + }, + .sseq @ second pass store in/.code={ + \pgfkeysalso{\pgfkeyscurrentpath/.code={\sseq@options@secondpass{\def#1{##1}}}} + }, + .sseq @ code/.code 2 args={ + \pgfkeysalso{\pgfkeyscurrentpath/.code={\sseq@options@firstpass{#1}}} + \pgfkeysalso{\pgfkeyscurrentpath/.append code={\sseq@options@secondpass{#1}}} + }, + .sseq @ transform/.code={ + \sseq@keys@lastpart + \edef\sseq@temppath{\pgfkeyscurrentpath/\sseq@temp} + \pgfkeysalso{\sseq@temppath/.code/.expanded={\@nx\sseq@checktransform{\sseq@temp}\unexpanded{{##1}}}} + \pgfkeysalso{\sseq@temppath/.sseq @ second pass append code/.expanded={\@nx\sseq@pgfkeysdocommand{\sseq@temp}\unexpanded{{##1}}}}% + }, + .sseq @ stdparse do transform/.code={ + \sseq@keys@lastpart + \edef\sseq@temppath{\pgfkeyscurrentpath/\sseq@temp} + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text + \pgfkeysalso{\sseq@temppath/.code/.expanded={\@nx\sseq@standardparse\@nx\sseq@options@secondpass{\@nx\sseq@pgfkeysdocommand{\sseq@temp}\unexpanded{{##1}}}}} + \else + \pgfkeysalso{\sseq@temppath/.code/.expanded={\@nx\sseq@standardparse\@nx\sseq@options@secondpass{\@nx\sseq@pgfkeysdocommand{\sseq@temp}{#1}}}s} + \fi + }, + .sseq @ illegal/.code={ + \sseq@keys@lastpart + \edef\sseq@temppath{\pgfkeyscurrentpath/\sseq@temp} + \pgfkeysalso{\sseq@temppath/.code/.expanded={\@nx\sseq@error@n{option-illegal}{\sseq@temp}}} + }, + .sseq @ illegal as global/.code={ + \sseq@keys@lastpart + \pgfkeysalso{/sseqpages/global/\sseq@temp/.code/.expanded={\@nx\sseq@error@n{option-illegal-as-global}{\sseq@temp}}} + }, + .sseq @ global only/.code={ + \sseq@keys@lastpart + \pgfkeysalso{/sseqpages/\sseq@temp/.code/.expanded={\@nx\sseq@error@n{option-global-only}{\sseq@temp}}} + } +} + + +%%% Some easy internal macros + +% This is for .unknown handlers. Try same key in different directory #1. +\def\sseq@passoptionto#1{\sseq@eval{\@nx\pgfqkeys{#1}{\pgfkeyscurrentname={\unexpanded\@xp{\pgfkeyscurrentvalue}}}}} + +\def\sseq@pgfkeysdocommand#1#2{ + \sseq@tempiffalse + \sseq@pgfkeysdocommand@try{/tikz/#1}{#2} + \sseq@pgfkeysdocommand@try{/pgf/#1}{#2} + % is this really an internal error? Maybe we should have failed earlier? + \ifsseq@tempif\else\sseq@error@internal@nn{do-command-failed}{#1}{#2}\fi +} + +\def\sseq@pgfkeysdocommand@try#1#2{ + \ifsseq@tempif\else + \pgfkeysifdefined{#1/.@cmd}{ + \sseq@tempiftrue + \pgfkeysgetvalue{#1/.@cmd}{\pgfkeys@code}% + \pgfkeys@code#2\pgfeov + }{ + \pgfkeysifdefined{#1}{ + \sseq@tempiftrue + \pgfkeyssetvalue{#1}{#2} + }{} + } + \fi +} + +%%% +% Our main unknown option handler +% This is copied from the standard tikz .unknown handler, but instead of running the code it stores it in \sseq@savedoptioncode. +% When it tries the key in /tikz and in /pgf it also recursively expands \pgfkeysalso's. + +\def\sseq@keys@unknown@error@normal{\sseq@error{unknown-key}} % a hook so we can turn off errors if we like +\let\sseq@keys@unknown@error\sseq@keys@unknown@error@normal % This is used in .sseq style +\let\sseq@add@tikzkey@to@options\sseq@e@addto@options % another hook for .sseq style + +\def\sseq@keys@unknown{% + \let\tikz@key\pgfkeyscurrentname + \sseq@keys@try@addtooptions{/sseqpages/userstyles,/tikz,/pgf}{}{% + \@xp\pgfutil@in@\@xp!\@xp{\tikz@key}% + \ifpgfutil@in@% + % this is a color! + \sseq@keys@unknown@handlecolor + \else% + \pgfutil@doifcolorelse{\tikz@key}% + {% + \sseq@keys@unknown@handlecolor + }% + {% + % Ok, second chance: This might be an arrow specification: + \@xp\pgfutil@in@\@xp-\@xp{\tikz@key}% + \ifpgfutil@in@% + % Ah, an arrow spec! + \sseq@add@tikzkey@to@options{\@nx\tikz@processarrows{\tikz@key}}% + \else% + % Ok, third chance: A shape! + \@xp\ifx\csname pgf@sh@s@\tikz@key\endcsname\relax% + \sseq@keys@unknown@error% + \else% + \sseq@add@tikzkey@to@options{\def\@nx\tikz@shape{\tikz@key}}% + \fi% + \fi% + }% + \fi% + }% +} + +\def\sseq@keys@unknown@handlecolor{% + \sseq@add@tikzkey@to@options{\@nx\tikz@addoption{\@nx\tikz@compat@color@set{\tikz@key}}}% + \sseq@add@tikzkey@to@options{\def\@nx\tikz@textcolor{\tikz@key}}% +} + +%%% \sseq@keys@try@addtooptions +% #1 -- a comma separated list of directories +% #2 -- success code +% #3 -- failure code +% +% This is for the main .unknown handler and for \sseq@addstylecodetooptions (which pretends to be \pgfkeys executed in a directory with only a .unknown) +% Tries to run the current key (\pgfkeyscurrentname=\pgfkeyscurrentvalue) in each of the directories in turn. +% If it finds the key in one of the directories, recursively expand the \pgfkeysalso in the code, +% add the final result to \sseq@savedoptioncode, and run success code. Otherwise run failure code. +% +% The goal is to avoid storing any commands that require the use of pgfkeys. +% This is only a partial solution, because it misses \tikzset, \pfgqkeys, etc. +% \pgfkeysalso is particularly dangerous though because we might not remember what directory it was supposed to happen in. +% In order to get the recursive expansion of \pgfkeysalso's we need to modify the pgfkeys algorithm so that it +% passes control back to \sseq@keys@addtooptions@checkalso when it's done. +% Modifies tikz commands \pgfkeys@case@one and \pgfkeys@case@two@extern from file /pgf/utilities/pgfkeys.code.tex lines 352 and 365 +\def\sseq@keys@try@addtooptions#1{% + \sseq@keys@try@addtooptions@#1,\sseq@nil +} +\def\sseq@keys@try@addtooptions@#1,{% + \bgroup + \def\pgfkeysdefaultpath{#1/}% + \def\next{\egroup\@ifnextchar\sseq@nil{\@xp\@secondoftwo\@gobble}{\sseq@keys@try@addtooptions@}}% + \pgfkeysifdefined{#1/\pgfkeyscurrentname/.@cmd}{% + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text% Hmm... no value + \pgfkeysifdefined{#1/\pgfkeyscurrentname/.@def}% + {\pgfkeysgetvalue{#1/\pgfkeyscurrentname/.@def}{\pgfkeyscurrentvalue}} + {}% no default, so leave it + \fi% + \pgfkeysgetvalue{#1/\pgfkeyscurrentname/.@cmd}{\pgfkeys@code}% + \sseq@eval{\@nx\sseq@keys@addtooptions@checkalso{\unexpanded\@xptwo{\@xp\pgfkeys@code\pgfkeyscurrentvalue\pgfeov}}}% + \sseq@smuggle@macro\sseq@savedoptioncode + \egroup + \def\next{\@xp\@firstoftwo\sseq@gobble@to@nil}% + }{% + \pgfkeysifdefined{#1/\pgfkeyscurrentname}{% + \egroup + \sseq@add@tikzkey@to@options{\@nx\pgfkeyssetvalue{#1/\pgfkeyscurrentname}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}% + \def\next{\@xp\@firstoftwo\sseq@gobble@to@nil}% + }{}% + }% + \next +} + +\def\sseq@keys@addtooptions@checkalso#1{% + \let\pgfkeys@case@one\sseq@pgfkeys@case@one@store + \let\pgfkeys@case@two@extern\sseq@pgfkeys@case@two@extern@store + \sseq@keys@addtooptions@checkalso@#1\pgfkeysalso\sseq@nil +} +\def\sseq@keys@addtooptions@checkalso@#1\pgfkeysalso#2{% + \sseq@add@tikzkey@to@options{\unexpanded{#1}}% + \ifx\sseq@nil#2% + \let\pgfkeys@case@one\sseq@pgfkeys@case@one@save + \let\pgfkeys@case@two@extern\sseq@pgfkeys@case@two@extern@save + \else + \pgfkeysalso{#2}% + \@xp\sseq@keys@addtooptions@checkalso@ + \fi +} + +\let\sseq@pgfkeys@case@one@save\pgfkeys@case@one +\let\sseq@pgfkeys@case@two@extern@save\pgfkeys@case@two@extern +\def\sseq@pgfkeys@case@one@store{% + \pgfkeysifdefined{\pgfkeyscurrentkey/.@cmd}{% + \pgfkeysgetvalue{\pgfkeyscurrentkey/.@cmd}{\pgfkeys@code}% + % The following line is the only change, it used to be \@xp\pgfkeys@code\pgfkeyscurrentvalue\pgfeov which would just run the code. + % Instead we recursively expand the \pgfkeysalso's and then store in it \sseq@savedoptioncode + \sseq@eval{\@nx\sseq@keys@addtooptions@checkalso{\unexpanded\@xptwo{\@xp\pgfkeys@code\pgfkeyscurrentvalue\pgfeov}}}% + }{\pgfkeys@case@two}% +} +\def\sseq@pgfkeys@case@two@extern@store{% + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text% + \pgfkeysvalueof{\pgfkeyscurrentkey}% this probably isn't a real case + \else% + % The following line is the only change, it used to be (roughly) \pgfkeyssetvalue{\pgfkeyscurrentkey}{\pgfkeyscurrentvalue} + % which would immediately set the value. Instead we store in it \sseq@savedoptioncode + \sseq@add@tikzkey@to@options{\@nx\pgfkeyssetvalue{\pgfkeyscurrentkey}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}% + \fi% +} + +\pgfkeys{% + /sseqpages/.is family, + /sseqpages/.unknown/.code={\sseq@keys@unknown}, +% + /sseqpages/class/.unknown/.code={% + \expandafter\ifx\csname pgf@sh@s@\pgfkeyscurrentname\endcsname\relax % is it the name of a shape? + \sseq@passoptionto{/sseqpages}% + \else + \sseq@e@addto@options{\def\@nx\tikz@shape{\pgfkeyscurrentname}}% if so, store it + \fi + }, + /sseqpages/.is family, + /sseqpages/scope/.is family, + /sseqpages/scope/.unknown/.code={\sseq@passoptionto{/sseqpages}}, + /sseqpages/class/.is family, + /sseqpages/class/label/.is family, + /sseqpages/class/label/.unknown/.code={\sseq@keys@unknown}, + /sseqpages/class/node texts/.is family, + /sseqpages/class/node texts/.unknown/.code={\sseq@passoptionto{/tikz}}, + /sseqpages/differential/.is family, + /sseqpages/differential/.unknown/.code={\sseq@passoptionto{/sseqpages}}, + /sseqpages/struct line/.is family, + /sseqpages/struct line/.unknown/.code={\sseq@passoptionto{/sseqpages}}, + /sseqpages/label/.is family, + /sseqpages/label/.unknown/.code={\sseq@keys@unknown}, + /sseqpages/tikz primitives/.is family, + /sseqpages/tikz primitives/.unknown/.code={\sseq@keys@unknown}, + % One off directories + /sseqpages/fit/.unknown/.code={\sseq@passoptionto{/sseqpages}}, + /sseqpages/foreach/.unknown/.code={\sseq@passoptionto{/pgf/foreach}}, + /sseqpages/class placement/.unknown/.code={\sseq@passoptionto{/tikz}} +} + +\pgfqkeys{/sseqpages/class}{shape/.code={\edef\tikz@shape{\pgfkeyscurrentname}}} % shape=whatever shape passing + +\pgfqkeys{/sseqpages/class/label}{% maybe implement multipart node labels this way? No way! + node/.sseq @ first pass code={\sseq@classlabelfalse}, + inside/.sseq @ first pass code={\sseq@classlabelfalse} +} + +%% label directions +\def\sseq@labeldirectionlist{\\{above}\\{below}\\{left}\\{right}\\{above left}\\{above right}\\{below left}\\{below right}} +\def\sseq@setlabeldirectionkeys#1{ + \@ifnextchar[{\sseq@setlabeldirectionkeys@{#1}}{\sseq@setlabeldirectionkeys@{#1}[/.code]}%] +} +\def\sseq@setlabeldirectionkeys@#1[#2]#3{ + \def\sseq@temp##1{#3} + \sseq@temptoks{} + \def\\##1{ + \sseq@eval{\sseq@temptoks{\the\sseq@temptoks##1#2={\unexpanded\@xp{\sseq@temp{##1}}},}} + } + \sseq@labeldirectionlist + \sseq@eval{\@nx\pgfqkeys{#1}{\the\sseq@temptoks}} +} + +\def\\#1{\@xp\sseq@addtostorelist\csname sseq@default@#1@distance\endcsname{1ex}} +\sseq@labeldirectionlist +\def\sseq@defaultlabeldistance#1{\@xp\csname sseq@default@#1@distance\endcsname} +\def\sseq@setdefaultlabeldistance#1#2{\sseq@savedpaths@add{\@xp\gdef\csname sseq@default@#1@distance\endcsname{#2}}} +\def\sseq@setdefaultlabeldistances#1{\def\\##1{\sseq@setdefaultlabeldistance{##1}{#1}}\sseq@labeldirectionlist} + + + +\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.sseq @ first pass code] + {\sseq@classlabeltrue\def\sseq@class@labelposition@name{#1}\def\sseq@class@labelposition@distance{##1}} +\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.sseq @ second pass append code]{\sseq@class@positionlabel{#1}{##1}} +\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.default]{\sseq@defaultlabeldistance{#1}} +\sseq@setlabeldirectionkeys{/sseqpages/global/class/label}[/.default]{\sseq@defaultlabeldistance{#1}} + +\sseq@setlabeldirectionkeys{/sseqpages/global}[ label distance/.code]{\sseq@setdefaultlabeldistance{#1}{##1}} +\sseq@setlabeldirectionkeys{/sseqpages}[ label distance/.code]{\sseq@setdefaultlabeldistance{#1}{##1}} + +\sseq@pgfqkeysdirlist{/sseqpages/global,/sseqpages}{ + label distance/.code={\sseq@setdefaultlabeldistances{#1}} +} + +\def\sseq@class@positionlabel#1#2{\sseq@pgfkeysdocommand{#1}{#2}} + + + +\sseq@addtostorelist\sseq@classlabeltextfn{} % \sseq@classlabeltextfn is public via "class label handler" +\let\sseq@classlabeltextfn@default\@gobble +\def\sseq@labeltextfn#1{#1} % labeltextfn is private +\def\sseq@labeltextfn@rotatescale#1{% + \@nx\ifmmode + \@nx\scalebox{\sseq@labletext@scale@factor}{\@nx\rotatebox{\sseq@labletext@rotate@angle}{$#1$}}% + \@nx\else + \@nx\scalebox{\sseq@labletext@scale@factor}{\@nx\rotatebox{\sseq@labletext@rotate@angle}{#1}}% + \@nx\fi +} +\def\sseq@labletext@rotate@angle{0} +\def\sseq@labletext@scale@factor{1} + +\bgroup\lccode`8=`p\lccode`9=`t\lowercase{\egroup +\def\sseq@eatpt#189{#1} +} + +\sseq@pgfqkeysdirlist{/sseqpages/label,/sseqpages/class/label}{ + rotate/.code={% + \let\sseq@labeltextfn\sseq@labeltextfn@rotatescale + \edef\sseq@labletext@rotate@angle{\@xp\sseq@eatpt\the\dimexpr\sseq@labletext@rotate@angle pt+#1pt}% + }, + scale/.code={% + \let\sseq@labeltextfn\sseq@labeltextfn@rotatescale + \edef\sseq@labletext@scale@factor{\@xp\sseq@eatpt\the\dimexpr\sseq@labletext@scale@factor pt*#1}% + }, +% shift/.sseq @ second pass code={\pgfkeysalso{xshift=\sseq@shift@getx#1}\pgfkeysalso{yshift=\sseq@shift@gety#1}} +} + + +\pgfqkeys{/sseqpages/global}{ + background color/.initial=white +} +\pgfqkeys{/sseqpages/label}{ + description/.code={% + \edef\sseq@edgeoptionhook{\@nx\pgfkeys{/tikz/fill=\pgfkeysvalueof{/sseqpages/global/background color}}}% + }, + description/.sseq @ second pass append code={% + \pgfkeysalso{/tikz/anchor=center}% + } +} + +\def\sseq@edgeoptionhook{}% This is just to make description work. + +%% Quote handling +% \sseq@handlequote will be installed later as the 'first char syntax' for ". +\def\sseq@protectlabel{\@nx\sseq@protectlabel\@nx} +\def\sseq@handlequote#1{\pgfkeysalso{handle quote=#1}} +\pgfkeys{% + /sseqpages/class/handle quote/.code={% + \let\tikz@quotes@as@save\tikz@quotes@as + \let\tikz@quotes@as\sseq@handleclassquotes + \tikz@quote@parser{#1}% + \let\tikz@quotes@as\tikz@quotes@as@save + }, + /sseqpages/handle quote/.code={% + \begingroup % group gets ended by handleedgequotes + \let\tikz@quotes@as\sseq@handleedgequotes + \tikz@quote@parser{#1}% + } +} + + +\def\sseq@processlabels@default{% + \global\let\sseq@classnodetext\pgfutil@empty + \global\let\sseq@classnodetextoptions\pgfutil@empty + \global\let\sseq@classlabelnodes\pgfutil@empty +} +\let\sseq@processlabels\sseq@processlabels@default + +\def\sseq@handlescopequotes#1#2{% We use this via \let\tikz@quotes@as\sseq@handleclassquotes + /utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out. + \global\let\sseq@classnodetext\pgfutil@empty% + \global\let\sseq@classnodetextoptions\pgfutil@empty% + \global\let\sseq@classlabelnodes\pgfutil@empty% + \sseq@handleclassquotes@inner{#1}{#2}% + } +} + +% We use this via \let\tikz@quotes@as\sseq@handleclassquotes +% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out. +\def\sseq@handleclassquotes#1#2{/utils/exec={\sseq@d@addto@macro\sseq@processlabels{\sseq@handleclassquotes@inner{#1}{#2}}}} + +\def\sseq@handleclassquotes@inner#1#2{% + \begingroup\pgfscope + \sseq@options@firstpassmode + \sseq@thesseqstyle + \sseq@thelabelstyle + \sseq@theclasslabelstyle + \the\sseq@scope@toks + \sseq@options@normalmode + \sseq@processoptions{class/label}{#2}% + \ifx\sseq@classlabeltextfn\@gobble + \def\processedlabel{#1}% + \else + \sseq@classlabeltextfn{#1}% labeltextfn is a private handler, classlabeltextfn is exposed via "class label handler" + \fi + \ifsseq@classlabel + \sseq@options@firstpassmode + \the\sseq@outerclasslabelstyle + \sseq@xprotected@addto@macro\sseq@classlabelnodes{ + \@nx\ifsseq@needstikz + node[ + /sseqpages/class/label, + /utils/exec={ + \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform + \let\@nx\tikz@transform\relax % The next line was set up to fix the classlabelstyle glitch + \the\sseq@sseqstyle\@nx\the\sseq@sseqstyle@page + \the\sseq@labelstyle\@nx\the\sseq@labelstyle@page\the\sseq@classlabelstyle\@nx\the\sseq@classlabelstyle@page + \sseq@theouterclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode}% + % \@nx\iftikz@fullytransformed\@nx + % \@nx\tikz@fullytransformedtrue + % \else + % \@nx{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform} + % \@nx\fi + \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save + }% + ]{\sseq@labeltextfn{\processedlabel}}% + \@nx\else + \@nx\node[ + /sseqpages/class/label, + /utils/exec={ + \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform + \let\@nx\tikz@transform\relax % The next line was set up to fix the classlabelstyle glitch + \the\sseq@sseqstyle\@nx\the\sseq@sseqstyle@page + \the\sseq@labelstyle\@nx\the\sseq@labelstyle@page\the\sseq@classlabelstyle\@nx\the\sseq@classlabelstyle@page + \sseq@theouterclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode} + % \@nx\iftikz@fullytransformed\@nx + % \@nx\tikz@fullytransformedtrue + % \else + % \@nx{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform} + % \@nx\fi + \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save + } + ]{\unexpanded\@xp{\@xp\sseq@labeltextfn\@xp{\processedlabel}}};% + \@nx\fi + }% + \else + \sseq@options@firstpassmode + \the\sseq@innerclasslabelstyle + \sseq@options@normalmode + \sseq@protectedeval{\@nx\pgfqkeys{/sseqpages/class/label}{#2}}% + \sseq@protected@xdef\sseq@classnodetext{\processedlabel}% + \xdef\sseq@classnodetextoptions{% + %\unexpanded{\def\pgfkeysdefaultpath{/sseqpages/class/node texts/}}% + \sseq@thelabelstyle\sseq@theinnerclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode}% + }% + \fi + \endpgfscope\endgroup +} + +\def\sseq@handleedgequotes#1#2{% We use this via \let\tikz@quotes@as\sseq@handleedgequotes + /utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out. + \endgroup + \let\sseq@savedoptioncode@save\sseq@savedoptioncode + \sseq@processoptions{label}{#2} + \sseq@needstikztrue + \let\sseq@temp\sseq@savedoptioncode + \let\sseq@savedoptioncode\sseq@savedoptioncode@save + \sseq@e@addto@options{ + \@nx\tikzset{ + every to/.append style={ + edge node={ + node [/sseqpages/label, + /utils/exec={ + \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform + \let\@nx\tikz@transform\relax + \@nx\sseq@thelabelstyle\@nx\sseq@theedgelabelstyle + \unexpanded\@xp{\sseq@temp} + \ifsseq@rotatelabels\iftikz@fullytransformed\else\@nx\tikz@fullytransformedtrue\@nx\tikz@addtransform{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform}\fi\fi + \unexpanded\@xp{\sseq@edgeoptionhook} % this is just to make description work + \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save + } + ]{\sseq@labeltextfn{#1}} + } + } + } + } + } +} + + +\def\sseq@checktransform@error{\sseq@error@nn{illegal-transform}} +\let\sseq@checktransform\sseq@checktransform@error + + +%% Parsing, background vs foreground, and context +\def\sseq@standardparse{% + \let\sseq@tikzprimitives@coords@maybeclass\sseq@tikzprimitives@coords@notaclass + \let\sseq@checktransform\@gobbletwo + \let\sseq@tikz@shifttransform\sseq@okayshifttransform + %(((((((((((((((((( + \def\class##1){\sseq@setthiscall{\string\class##1)}\sseq@error@x{standard-parse}{\string\class}}% + \def\replaceclass##1){\sseq@setthiscall{\string\replaceclass##1)}\sseq@error@x{standard-parse}{\string\replaceclass}}% + \def\classoptions##1){\sseq@setthiscall{\string\classoptions##1)}\sseq@error@x{standard-parse}{\string\classoptions}}% + \def\d##1){\sseq@setthiscall{\string\d##1)}\sseq@error@x{standard-parse}{\string\d}}% + \def\doptions##1){\sseq@setthiscall{\string\doptions##1)}\sseq@error@x{standard-parse}{\string\doptions}}% + \def\structline##1)##2){\sseq@setthiscall{\string\structline##1)##2)}\sseq@error@x{standard-parse}{\string\structline}}% + \def\structlineoptions##1)##2){\sseq@setthiscall{\string\structlineoptions##1)##2)}\sseq@error@x{standard-parse}{\string\structlineoptions}}% +} + +\def\sseq@nodeparse{% + \let\sseq@tikzprimitives@coords@maybeclass\sseq@tikzprimitives@coords@maybeclass@save + \let\sseq@tikzprimitives@coords@maybeclass + \def\sseq@transform{\sseq@error@nn{illegal-transform}} % Disallow most coordinate transforms + \let\sseq@shifttransform\sseq@checkshifttransform + \let\class\sseq@class + \let\replaceclass\sseq@replaceclass + \let\structline\sseq@structline +} + + +\sseq@pgfqkeysdirlist{/sseqpages,/sseqpages/tikz primitives}{% + standard parse/.code={ + \let\sseq@firstpass@shifttransform\@gobbletwo + \sseq@d@addto@options{\sseq@standardparse} + \pgfkeys{/sseqpages/tikz primitives/shift/.sseq @ second pass code={\tikzset{shift={##1}}}} + }, + node parse/.code={ % This is never used, probably broken, and likely shouldn't exist + \let\sseq@firstpass@shifttransform\sseq@firstpass@checkshifttransform + \let\sseq@checktransform\sseq@checktransform@error + \sseq@d@addto@options{\sseq@nodeparse} + }, + background/.code={\sseq@setsavedpaths{background}\pgfkeysalso{standard parse}}, + foreground/.code={\ifsseq@keepchanges\sseq@setsavedpaths{standard}\else\sseq@setsavedpaths{temporary}\fi\pgfkeysalso{node parse}} +} + +\pgfkeys{ + /sseqpages/tikz primitives/handle quote/.sseq @ second pass code={\tikzset{#1}}, + /tikz/handle quote/.code={\sseq@error{tikz-edge-quotes}} +} + +\sseq@pgfqkeysdirlist{/sseqpages/class,/sseqpages/differential}{ + standard parse/.sseq @ first pass code={\sseq@error@n{option-tikz-prims-only}{standard parse}}, + background/.sseq @ first pass code={\sseq@error@n{option-tikz-prims-only}{background}} +} + +\def\sseq@class@tag{} +\def\sseq@class@tagprefix{} +\def\sseq@class@name{} +\def\sseq@namehandler{}%\@xp\sseq@normalizepolynomial\@xp{\sseq@class@name}\let\sseq@class@name\sseq@polynomial} +\def\sseq@currenttag{\sseq@class@tag}% for the user ?? +\def\sseq@tooltip{} +\pgfqkeys{/sseqpages/scope}{ + tag/.code={\pgfkeys@spdef\sseq@class@tag{#1}}, + tag prefix/.code={\pgfkeys@spdef\temp{#1}\sseq@e@addto@macro\sseq@class@tagprefix{\unexpanded\@xp{#1}}} +} + +\pgfqkeys{/sseqpages/class}{ + name/.code={\def\sseq@class@name{#1}\pgfkeysalso{/sseqpages/alias=#1}}, + show name/.code={\def\sseq@class@showname{#1}}, + page/.code={\sseq@getnumrange\sseq@class@page{#1}},% page & gen are only for \classoptions. + generation/.code={\sseq@getnumrange\sseq@gen{#1}}, % \class tests if \sseq@class@page is set and throw an error if so. + tag/.code={\sseq@d@addto@macro\sseq@class@tag{#1}}, + offset/.code={\def\sseq@tempoffset{#1}}, + tooltip/.sseq @ first pass code={\def\sseq@tooltip{#1}} +} + +\pgfqkeys{/sseqpages/struct line}{ + page/.code={\sseq@getnumrange\sseq@structline@page{#1}} +} + +\def\sseq@fitalso{} +\pgfqkeys{/sseqpages/fit}{ + fit/.sseq @ first pass code={\sseq@d@addto@macro\sseq@fitalso{#1}}, + page/.code={\sseq@getnumrange\sseq@fit@page{#1}} +} + +\def\sseq@getnumrange#1#2{ + \pgfutil@in@{--}{#2}\ifpgfutil@in@ + \sseq@getnumrange@range#1#2\sseq@nil + \else + \edef#1{\the\numexpr#2} + \fi +} +\def\sseq@getnumrange@range#1#2--#3\sseq@nil{\edef#1{\the\numexpr#2}\@xp\edef\csname\sseq@macroname#1max\endcsname{\the\numexpr#3}} + +%% Needs tikz +% Force \class or \d to fall back to using tikz to render their output +% Rather than using the faster direct \pgf primitives (largely copied from tikz to maximize compatibility) +% Drawing with tikz is slower, but I don't want to reimplement these features +\def\sseq@needstikzandpass#1#2{\sseq@needstikzandpass@{#1}#2,\@nil} +\def\sseq@needstikzandpass@#1#2,{% + \pgfqkeys{#1}{#2/.code={\sseq@options@firstpass{\sseq@needstikztrue}\sseq@options@secondpass{\sseq@pgfkeysdocommand{#2}{##1}\sseq@needstikztrue}}}% + \@ifnextchar\@nil{\@gobble}{\sseq@needstikzandpass@{#1}}% +} + +\pgfqkeys{/sseqpages}{needs tikz/.code=\sseq@needstikztrue} +\sseq@needstikzandpass{/sseqpages}{% + shade, blend mode, pattern, path picture, path fading, decorate, pin, label +} + +\sseq@needstikzandpass{/sseqpages/differential}{% + bend left, bend right, in, out, relative, looseness, in looseness, out looseness, + min distance, max distance, out min distance, out max distance, in min distance, in max distance, distance, + controls, in control, out control, + loop, loop above, loop below, loop left, loop right % maybe delete the loops and replace them with errors? It's pretty pointless to use these. +} + +\sseq@needstikzandpass{/sseqpages/struct line}{% + bend left, bend right, in, out, relative, looseness, in looseness, out looseness, + min distance, max distance, out min distance, out max distance, in min distance, in max distance, distance, + controls, in control, out control, + loop, loop above, loop below, loop left, loop right % maybe delete the loops and replace them with errors? It's pretty pointless to use these. +} + +% circle split/.code=\sseq@needstikzandpass, +% circle solidus/.code=\sseq@needstikzandpass, +% ellipse split/.code=\sseq@needstikzandpass, +% rectangle split/.code=\sseq@needstikzandpass, +% align/.code=\sseq@needstikzandpass, + +\sseq@addtostorelist\sseq@runoffarrow@start@differential@spec{...} +\sseq@addtostorelist\sseq@runoffarrow@end@differential@spec{...} +\sseq@addtostorelist\sseq@runoffarrow@start@structline@spec{...} +\sseq@addtostorelist\sseq@runoffarrow@end@structline@spec{...} +\sseq@pgfqkeysdirlist{/sseqpages/global,/sseqpages}{ + run off differentials/.code args={#1-#2}{\def\sseq@runoffarrow@start@differential@spec{#1}\def\sseq@runoffarrow@end@differential@spec{#2}}, + run off struct lines/.code args={#1-#2}{\def\sseq@runoffarrow@start@structline@spec{#1}\def\sseq@runoffarrow@end@structline@spec{#2}}, + run off/.forward to=/sseqpages/run off differentials, + run off/.forward to=/sseqpages/run off struct lines +} + + +\sseq@pgfqkeysdirlist{/sseqpages/differential,/sseqpages/struct line}{ + source anchor/.sseq @ second pass store in=\sseq@edgesourceanchor, + target anchor/.sseq @ second pass store in=\sseq@edgetargetanchor, + shorten >/.sseq @ second pass code={\sseq@pgfkeysdocommand{shorten >}{#1}}, + shorten </.sseq @ second pass code={\sseq@pgfkeysdocommand{shorten <}{#1}}, +} +\pgfqkeys{/sseqpages/differential}{ + /sseqpages/differential/invisible/.sseq @ first pass code={\sseq@drawdifferentialfalse} +} +\newif\ifsseq@drawdifferential +\sseq@drawdifferentialtrue + +%%% +%%% Global Keys +%%% + +%%% Style options + +%% Add key code to \sseq@savedoptioncode +% #1 -- a list of directories to search +% #2 -- keys +% This is a faster and sloppier way of doing: +%\def\sseq@temp{#1} +%\pgfqkeys{/sseqpages/alwaysunknown}{#2} +% and defining an event handler: alwaysunknown/.unknown/.code={\@xp\sseq@keys@try@addtooptions\@xp{\sseq@temp}{}{\sseq@keys@unknown} +% Copied with modification from /pgf/utilities/pfgkeys.code.tex +\def\sseq@addstylecodetooptions#1#2{% + \def\sseq@directorylist{#1}% + \sseq@simple@pgfkeys@parse#2,\pgfkeys@mainstop +} + +\def\sseq@simple@pgfkeys@parse{\futurelet\pgfkeys@possiblerelax\sseq@simple@pgfkeys@parse@main} +\def\sseq@simple@pgfkeys@parse@main{% + \ifx\pgfkeys@possiblerelax\pgfkeys@mainstop% + \@xp\@gobble + \else% + \@xp\sseq@simple@pgfkeys@@normal + \fi% +} + +\def\sseq@simple@pgfkeys@@normal#1,{% + \sseq@simple@pgfkeys@unpack#1=\pgfkeysnovalue=\pgfkeys@stop + \sseq@simple@pgfkeys@parse +} + +\def\sseq@simple@pgfkeys@unpack#1=#2=#3\pgfkeys@stop{% + \pgfkeys@spdef\pgfkeyscurrentkey{#1}% + \pgfkeys@spdef\pgfkeyscurrentvalue{#2}% + \ifx\pgfkeyscurrentkey\pgfkeys@empty\else + \def\next{\@xp\sseq@keys@try@addtooptions\@xp{\sseq@directorylist}{}{\sseq@addstylecodetooptions@unknown}}% + \sseq@simple@pgfkeys@checkquote#1\sseq@nil{% + \def\pgfkeyscurrentname{handle quote}% + \def\pgfkeyscurrentvalue{#1}% + }{% + \edef\pgfkeyscurrentkey{\pgfkeyscurrentkey}% + \ifx\pgfkeyscurrentkey\pgfkeys@empty + \let\next\relax + \else% + \let\pgfkeyscurrentname\pgfkeyscurrentkey + \fi + }% + \@xp\next + \fi +} +\let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown + +\long\def\sseq@simple@pgfkeys@checkquote#1#2\sseq@nil{% + \ifx#1"% + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi +} + +\def\sseq@sseqstyle@globalpart{} + + +\def\sseq@stylelist{} +\def\sseq@clearchangestyles{} + + +\def\sseq@newstyles#1#2{\def\sseq@temppath{#1}\sseq@newstyles@#2,\sseq@nil} +\def\sseq@newstyles@#1,{\sseq@newsseqstyle{\sseq@trimleadingspaces#1}\@ifnextchar\sseq@nil{\@gobble}{\sseq@newstyles@}} + +\def\sseq@set@newstyle#1{\pgfqkeys{/sseqpages}{#1}\pgfqkeys{/sseqpages/global}{#1}\pgfqkeys{/sseqpages/global/default}{#1}\pgfqkeys{/sseqpages/first pass}{#1}} + +\def\sseq@newsseqstyle#1{% + \sseq@setmacronospaces\sseq@tempcmd{sseq@#1style}% + \edef\sseq@tempcmdb{\csname\@xp\sseq@macroname\sseq@tempcmd @page\endcsname}% + \sseq@setmacronospaces\sseq@tempcmdc{sseq@the#1style}% + \@xp\edef\sseq@tempcmdc{\@nx\the\@xp\@nx\sseq@tempcmd\@nx\the\sseq@tempcmdb}% + \@xp\newtoks\sseq@tempcmd + \@xp\newtoks\sseq@tempcmdb + \sseq@x@addto@macro\sseq@stylelist{\sseq@tempcmd{\@nx\the\sseq@tempcmd}}% + \sseq@x@addto@macro\sseq@clearchangestyles{\sseq@tempcmdb{}}% + \sseq@set@newstyle{% + #1s/.ecode={% + \let\@nx\sseq@savedoptioncode@store\@nx\sseq@savedoptioncode + \edef\@nx\sseq@savedoptioncode{\@nx\the\sseq@tempcmd}% + \@nx\sseq@addstylecodetooptions{\sseq@temppath}{##1}% + \sseq@tempcmd\@nx\@xp{\@nx\sseq@savedoptioncode}% + \@nx\ifsseq@inprogress + \@nx\sseq@savedpaths@xadd{\sseq@tempcmd{\@nx\the\sseq@tempcmd}}% + \@nx\fi + \let\@nx\sseq@savedoptioncode\@nx\sseq@savedoptioncode@store + },% + change #1s/.ecode={% + \@nx\ifsseq@ispageenv\@nx\else\@nx\sseq@error@nn{change-style-data}{#1}{##1}\@nx\fi + \@nx\ifsseq@hasname\@nx\else\@nx\sseq@error@nn{change-style-standalone}{#1}{##1}\@nx\fi + \let\@nx\sseq@savedoptioncode@store\@nx\sseq@savedoptioncode + \edef\@nx\sseq@savedoptioncode{\@nx\the\sseq@tempcmdb}% + \@nx\sseq@addstylecodetooptions{\sseq@temppath}{##1}% + \sseq@tempcmdb\@nx\@xp{\@nx\sseq@savedoptioncode}% + \let\@nx\sseq@savedoptioncode\@nx\sseq@savedoptioncode@store + } + }% +} + + +\newtoks\sseq@sseqstyle +\newtoks\sseq@sseqstyle@page +\def\sseq@thesseqstyle{\the\sseq@sseqstyle\the\sseq@sseqstyle@page} + +% sseqs has to be handled separately, because it must decide whether an option is a global option or not +% and handle them at different times. This makes the code a little trickier. +\sseq@g@addto@macro\sseq@stylelist{\sseq@sseqstyle{\the\sseq@sseqstyle}}% +\sseq@g@addto@macro\sseq@clearchangestyles{\sseq@sseqstyle@page{}}% +\sseq@set@newstyle{ + sseqs/.code={% + \let\sseq@savedoptioncode@store\sseq@savedoptioncode + \let\sseq@savedoptioncode\sseq@sseqstyle@globalpart + \def\sseq@addstylecodetooptions@unknown{% + \let\sseq@sseqstyle@globalpart\sseq@savedoptioncode + \edef\sseq@savedoptioncode{\the\sseq@sseqstyle}% + \sseq@keys@unknown + \sseq@sseqstyle\@xp{\sseq@savedoptioncode}% + \let\sseq@savedoptioncode\sseq@sseqstyle@globalpart + }% + \sseq@addstylecodetooptions{/sseqpages/global}{#1}% + \let\sseq@sseqstyle@globalpart\sseq@savedoptioncode + \ifsseq@inprogress + \sseq@savedpaths@xadd{\sseq@sseqstyle{\the\sseq@sseqstyle}}% + \fi + \let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown + \let\sseq@savedoptioncode\sseq@savedoptioncode@store + },% + change sseqs/.code={% + \ifsseq@ispageenv\else\sseq@error@nn{change-style-data}{sseq}{#1}\fi + \ifsseq@hasname\else\sseq@error@nn{change-style-standalone}{sseq}{#1}\fi + \let\sseq@savedoptioncode@store\sseq@savedoptioncode + \edef\sseq@savedoptioncode{\the\sseq@sseqstyle@page}% + \sseq@addstylecodetooptions{\sseq@temppath}{#1}% + \sseq@sseqstyle@page\@xp{\sseq@savedoptioncode}% + \let\sseq@savedoptioncode\sseq@savedoptioncode@store + } +} + + +%\sseq@newstyles{/sseqpages/}{sseq}% DON'T make this /global/default! Bad things will happen. +\sseq@newstyles{/sseqpages/label,/sseqpages}{edge, label, edge label, differential label, struct line label} +\sseq@newstyles{/sseqpages/class,/sseqpages}{class, permanent cycle, transient cycle, this page cycle} +\sseq@newstyles{/sseqpages/differential,/sseqpages}{differential} +\sseq@newstyles{/sseqpages/struct line,/sseqpages}{struct line, this page struct line} +\sseq@newstyles{/sseqpages/class/label}{class label, inner class label, outer class label} +\sseq@newstyles{/sseqpages/tikz primitives}{tikz primitive} +\sseq@newstyles{/sseqpages/fit}{circle class} + + +\sseq@set@newstyle{sseq/.style={sseqs={#1}},change sseq/.style={change sseqs={#1}}, + classes/.style={classs={#1}},change classes/.style={change classs={#1}}, + circle classes/.style={circle classs={#1}},change circle classes/.style={change circle classs={#1}}, +}% "class" has a nonstandard plural +\sseq@set@newstyle{ + cycles/.code={\pgfkeysalso{classes={#1}}}, + permanent classes/.code={\pgfkeysalso{permanent cycles={#1}}}, + transient classes/.code={\pgfkeysalso{transient cycles={#1}}}, + this page classes/.code={\pgfkeysalso{this page cycles={#1}}}, + cycle style/.code={\pgfkeysalso{class style={#1}}}, + permanent class style/.code={\pgfkeysalso{permanent cycle style={#1}}}, + transient class style/.code={\pgfkeysalso{transient cycle style={#1}}}, + this page class style/.code={\pgfkeysalso{this page cycle style={#1}}}, + class label position/.code={\pgfkeysalso{class label positions={#1}}} +}% + +\def\sseq@newplotstyle#1{ + \sseq@setmacronospaces\sseq@tempcmd{sseq@#1style} + \sseq@setmacronospaces\sseq@tempcmdb{sseq@#1style@default} + \sseq@eval{\@nx\sseq@addtostorelist\@xp\@nx\sseq@tempcmd{\@xp\@nx\sseq@tempcmdb}} + \@xp\def\sseq@tempcmdb{} + \pgfqkeys{/sseqpages/global}{% + #1 style/.ecode={ + \unexpanded{\let\sseq@savedoptioncode@store\sseq@savedoptioncode} + \let\@nx\sseq@savedoptioncode\@xp\@nx\sseq@tempcmd + \unexpanded{\sseq@addstylecodetooptions{/tikz}}{##1} + \let\@xp\@nx\sseq@tempcmd\@nx\sseq@savedoptioncode + \unexpanded{\let\sseq@savedoptioncode\sseq@savedoptioncode@store} + } + } + % Only difference here is \sseq@tempcmdb -- which puts it in the default code -- instead of \sseq@tempcmd + \pgfqkeys{/sseqpages/global/default}{% + #1 style/.ecode={ + \unexpanded{\let\sseq@savedoptioncode@store\sseq@savedoptioncode} + \let\@nx\sseq@savedoptioncode\@xp\@nx\sseq@tempcmdb + \unexpanded{\sseq@addstylecodetooptions{/tikz}}{##1} + \let\@xp\@nx\sseq@tempcmdb\@nx\sseq@savedoptioncode + \unexpanded{\let\sseq@savedoptioncode\sseq@savedoptioncode@store} + } + } +} + + +\def\sseq@newplotstyles#1{\def\sseq@temppath{#1}\sseq@newplotstyles@#1,\sseq@nil} +\def\sseq@newplotstyles@#1,{\sseq@newplotstyle{\sseq@trimleadingspaces#1}\@ifnextchar\sseq@nil{\@gobble}{\sseq@newplotstyles@}} + +\sseq@newplotstyles{x tick, y tick} + + +%%% Global keys handlers and infrastructure + +\def\sseq@keys@lastpart{% + \edef\pgfkeyscurrentkey{\pgfkeyscurrentpath}% + \pgfkeys@split@path + \edef\sseq@temp{\pgfkeyscurrentname}% + \edef\sseq@temp@ii{\pgfkeyscurrentkey}% +} + +\pgfqkeys{/handlers}{ + .sseq store in/.code 2 args={% + \sseq@addtostorelist#1{#2}% + \sseq@keys@lastpart + \pgfkeys{% + \sseq@temp@ii/.store in=#1,% + /sseqpages/global/default/\sseq@temp/.store in/.expand once=\csname \sseq@macroname#1@default\endcsname + }% + }, + .sseq append to style/.code 2 args={% + \sseq@addkeytostorelist{#1}{\pgfkeysalso{#2}}% + \sseq@keys@lastpart + \pgfkeys{% + \sseq@temp@ii/.style={#1/.append style={##1}},% + /sseqpages/global/default/\sseq@temp/.ecode={% + \@nx\apptocmd\@xp\@nx\csname pgfk@#1/.@cmd@default\endcsname{\@nx\pgfkeysalso{##1}}{}{\@nx\sseq@error{this-shouldnt-happen}}% + \global\let\@xp\@nx\csname pgfk@#1/.@cmd@default\endcsname\@xp\@nx\csname pgfk@#1/.@cmd@default\endcsname + }% + }% + }, + .sseq is if/.code={% + \sseq@addiftostorelist@truedefault{#1}% + \sseq@keys@lastpart + \pgfkeys{% + \sseq@temp@ii/.is if=sseq@#1,% + /sseqpages/global/default/\sseq@temp/.code={\@xp\edef\csname sseq@#1@default\endcsname{\global\@xp\@nx\csname sseq@#1##1\endcsname}},% + /sseqpages/global/default/\sseq@temp/.default=true,% + }% + }, + .sseq is if false/.code={% + \sseq@keys@lastpart + \pgfkeys{% + /sseqpages/global/\sseq@temp/.code/.expanded={\@xp\@nx\csname sseq@#1false\endcsname}, + /sseqpages/global/\sseq@temp/.value forbidden, + % value forbidden and ecode don't work correctly together so we have to use .code/.expanded . + % I made a thread here: https://sourceforge.net/p/pgf/discussion/477362/thread/3e75d813/ + /sseqpages/global/default/\sseq@temp/.code/.expanded={\def\@xp\@nx\csname sseq@#1@default\endcsname{\global\@xp\@nx\csname sseq@#1false\endcsname}}, + /sseqpages/global/default/\sseq@temp/.value forbidden, + }% + }, + .sseq default code/.code={% + \sseq@keys@lastpart + \pgfkeys{/sseqpages/global/default/\sseq@temp/.code={#1}}% + }, + .sseq default code 2 args/.code={% + \sseq@keys@lastpart + \pgfkeys{/sseqpages/global/default/\sseq@temp/.code 2 args={#1}}% + }, + .sseq default error/.code={% + \sseq@keys@lastpart + \pgfkeys{/sseqpages/global/default/\sseq@temp/.ecode={\@nx\sseq@error@n{option-no-default-allowed}{\sseq@temp}}}% + }, + .sseq x y alias/.code={% + \sseq@keys@lastpart + \ifx\pgfkeysnovalue#1% + \edef\sseq@tempb##1{##1 \sseq@temp}% + \else + \def\sseq@tempb##1{#1}% + \sseq@usedparam\sseq@tempb + \fi + \pgfkeys{% + /sseqpages/global/\sseq@temp/.ecode={\@nx\pgfkeysalso{\sseq@tempb{x}={##1},\sseq@tempb{y}={##1}}},% + /sseqpages/global/default/\sseq@temp/.ecode={\@nx\pgfkeysalso{\sseq@tempb{x}={##1},\sseq@tempb{y}={##1}}}% + }% + } +} + +\bgroup\lccode`*=`#\lowercase{\egroup + \def\sseq@usedparam#1{ + \@xp\sseq@usedparam@\@xp#1\meaning#1*\@nil + } + \def\sseq@usedparam@#1#2->#3*#4\@nil{ + \sseq@ifempty{#4}{ + \@xp\def\@xp#1\@xp##\@xp1\@xp{\@xp##\@xp1\@xp\space#1{}} + }{} + } +} + +\def\sseq@add@tikzkey@to@options@forstylehander#1{\sseq@e@addto@options{\@nx\sseq@options@secondpass{#1}}} +\pgfqkeys{/handlers}{ % defines sseq style, etc + sseq @@ make style handler/.style 2 args={% + .sseq #1/.code={% + \sseq@keys@lastpart + \let\sseq@savedoptioncode@store\sseq@savedoptioncode + \def\sseq@keys@unknown@error{}% + \def\sseq@savedoptioncode{}% + \let\sseq@add@tikzkey@to@options\sseq@add@tikzkey@to@options@forstylehander + \sseq@addstylecodetooptions{/sseqpages/scope}{##1}% + \sseq@eval{\@nx\pgfkeys{/sseqpages/scope/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \def\sseq@savedoptioncode{}% + \sseq@addstylecodetooptions{/sseqpages/class}{##1}% + \sseq@eval{\@nx\pgfkeys{/sseqpages/class/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \def\sseq@savedoptioncode{}% + \sseq@addstylecodetooptions{/sseqpages/differential}{##1}% + \sseq@eval{\@nx\pgfkeys{/sseqpages/differential/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \def\sseq@savedoptioncode{}% + \sseq@addstylecodetooptions{/sseqpages/struct line}{##1}% + \sseq@eval{\@nx\pgfkeys{/sseqpages/struct line/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \def\sseq@savedoptioncode{}% + \sseq@addstylecodetooptions{/sseqpages/circle classes}{##1} + \sseq@eval{\@nx\pgfkeys{/sseqpages/circle classes/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \def\sseq@savedoptioncode{}% + \sseq@addstylecodetooptions{/sseqpages/tikz primitives}{##1}% + \sseq@eval{\@nx\pgfkeys{/sseqpages/tikz primitives/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}% + \let\sseq@savedoptioncode\sseq@savedoptioncode@store + \let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown + \let\sseq@keys@unknown@error\sseq@keys@unknown@error@normal + \let\sseq@add@tikzkey@to@options\sseq@e@addto@options + }% + },% + sseq @@ make code handler/.style={% + .sseq #1/.code={% + \sseq@keys@lastpart + \pgfkeys{ + /sseqpages/class/\sseq@temp/.#1={##1},% + /sseqpages/differential/\sseq@temp/.#1={##1},% + /sseqpages/struct line/\sseq@temp/.#1={##1}% + }% + }% + }, +% + sseq @@ make style handler={style}{code}, + sseq @@ make style handler={prefix style}{prefix code}, + sseq @@ make style handler={append style}{append code}, + sseq @@ make code handler=code, + sseq @@ make code handler=prefix code, + sseq @@ make code handler=append code, +% + .global sseq style/.code={\pgfkeys{\pgfkeyscurrentpath/.code=\pgfkeysalso{#1}}}, + .global sseq prefix style/.code={\pgfkeys{\pgfkeyscurrentpath/.add code={\pgfkeysalso{#1}}{}}}, + .global sseq append style/.code={\pgfkeys{\pgfkeyscurrentpath/.add code={}{\pgfkeysalso{#1}}}}, +% +% + .sseq grading/.code 2 args={% + \sseq@keys@lastpart + \pgfkeys{% + /sseqpages/global/\sseq@temp/.estyle={\unexpanded{degree={#1}{#2}}},%I'm not really sure why these need to be estyle and \unexpanded but it does... + /sseqpages/global/default/\sseq@temp/.estyle={\unexpanded{degree={#1}{#2}}},% + /sseqpages/\sseq@temp/.sseq @ global only + }% + }, + Adams grading/.sseq grading={-1}{#1}, + homological Serre grading/.sseq grading={-#1}{#1-1}, + cohomological Serre grading/.sseq grading={#1}{1-#1}, +} + +%%% Define global keys setter +\gdef\sseq@globalkeys#1{% + \let\sseq@storetilde~% + \def~{}% + \pgfqkeys{/sseqpages/global}{#1}% + \sseq@globalkeys@#1,\sseq@nil + \let~\sseq@storetilde +} + +\def\sseq@globalkeys@#1,{% + \sseq@tempiftrue + \sseq@keys@removehandler{#1}% + \ifsseq@tempif + \pgfkeys{/sseqpages/\sseq@temp/.sseq @ global only}% + \pgfkeysifdefined{/sseqpages/global/default/\sseq@temp/.@cmd}{}{% + \pgfkeys{/sseqpages/global/default/\sseq@temp/.ecode={\@nx\pgfkeysalso{sseqs={\sseq@temp}}}}% + }% + \fi + \sseq@globalkeys@next +} + +\def\sseq@globalkeys@eatentry#1,{% + \sseq@globalkeys@next +} + +\def\sseq@globalkeys@next{% + \@ifnextchar\sseq@nil{\@gobble}{% + \@ifnextchar~{\sseq@globalkeys@eatentry}{% + \@ifnextchar,{\sseq@globalkeys@eatentry}{% + \sseq@globalkeys@ + }% + }% + }% +} + +\def\sseq@keys@ignorehandlers{% + \\{value forbidden}\\{value required}\\{default}%\\{sseq store in}\\{sseq is if}% + \\{sseq default code}\\{sseq default code 2 args}% +} +\def\sseq@keys@removehandler#1{\sseq@keys@removehandler@#1=\sseq@nil} +\def\sseq@keys@removehandler@#1/.#2=#3\sseq@nil{% + \def\sseq@temp{#2}% + \def\\##1{\def\sseq@tempii{##1}\ifx\sseq@tempii\sseq@temp \sseq@tempiffalse\let\\\@gobble\fi}% + \sseq@keys@ignorehandlers + \def\sseq@temp{#1}% +} + + +%%% Define global keys +\def\sseq@currentoptionpath{default} +\pgfkeys{ + % \sseq@currentoptionpath is set to \sseq@thename in \sseqdata, then "temp" in \sseqpage + /sseqpages/global/.unknown/.code={% + \let\sseq@tempa\pgfkeyscurrentname + \let\sseq@tempb\pgfkeyscurrentvalue + \sseq@eval{\@nx\pgfqkeys{/sseqpages/global}{/sseqpages/userstyles/\sseq@tempa/.try={\unexpanded\@xp{\sseq@tempb}}}} + \ifpgfkeyssuccess\else + \pgfkeysifdefined{/tikz/\pgfkeyscurrentname/.@cmd}{\@firstofone}{\pgfkeysifdefined{/tikz/\pgfkeyscurrentname}{\@firstofone}{% + \sseq@error{unknown-global}\@gobble + }}{% + \pgfkeysalso{{\sseq@currentoptionpath} options/.append code/.expand twice={\@xp\@xp\@xp\tikzset\@xp\@xp\@xp{\@xp\sseq@tempa\@xp=\@xp{\sseq@tempb}}}}% + \sseq@eval{% + \global\let\@xp\@nx\csname pgfk@/sseqpages/global/{\sseq@currentoptionpath} options/.@cmd\endcsname + \@xp\@nx\csname pgfk@/sseqpages/global/{\sseq@currentoptionpath} options/.@cmd\endcsname + }% + }% + \fi + }, + /sseqpages/global/default/.unknown/.code={% + \sseq@passoptionto{/sseqpages/global}% + }, + /sseqpages/global/{default} options/.code={}, + /sseqpages/global/name only/.unknown/.code={}, + /sseqpages/global/sseqstyle/.unknown/.code={} +} + +\pgfqkeys{/sseqpages/global/name only}{ + name/.code={\def\sseq@thename{#1}\sseq@hasnametrue}, + name/.value required, + keep changes/.is if=sseq@keepchanges, + update existing/.code={\ifsseq@ispageenv\sseq@error{page-update-existing}\fi\sseq@updateexistingtrue}, + update existing/.sseq default code={\sseq@updateexistingtrue} +} + +\sseq@addtostorelist\sseq@grid{\relax} +\sseq@addiftostorelist{hasdegree} +\let\sseq@maybemathswitch\relax +\sseq@globalkeys{% + name/.code={}, + name/.sseq default error, + ~page/.code={ + \ifsseq@hasname + \sseq@ifintexpr{#1}{ + \def\sseq@thepage{#1}\sseq@thepagecount=#1\relax\let\page\sseq@thepage + }{ + \sseq@error{invalid-page}{#1} + } + \else + \sseq@error{page-no-name} + \fi + }, + ~page/.sseq default error,% implement page default? + degree/.code 2 args={\def\sseq@targetx##1{#1}\def\sseq@targety##1{#2}}, + degree/.sseq default code 2 args={\def\sseq@targetx@default##1{#1}\def\sseq@targety@default##1{#2}}, + strict degree/.sseq is if=strictdegree, + lax degree/.sseq is if false=strictdegree, + update existing/.code={}, % processed with "name" key and "keep changes" key in /sseqpages/global/name only + keep changes/.code={% + \ifsseq@hasname\else\sseq@error{keep-changes-no-name}\fi + \ifsseq@ispageenv\else\sseq@error{keep-changes-sseqdata}\fi + }, + grid/.code={\ifcsname sseq@grid@#1\endcsname\@xp\let\@xp\sseq@grid\csname sseq@grid@#1\endcsname\else\sseq@error@n{unknown-grid}{#1}\fi}, + grid/.sseq default code={\ifcsname sseq@grid@#1\endcsname\@xp\let\@xp\sseq@grid@default\csname sseq@grid@#1\endcsname\else\sseq@error@n{unknown-grid}{#1}\fi}, + math nodes/.sseq is if=mathnodes, % TODO: make this locally toggleable + custom clip/.sseq store in=\sseq@customclip{}, + clip/.sseq is if=clip, + draw differentials/.sseq is if=drawdifferentials, + no differentials/.sseq is if false={drawdifferentials}, + draw struct lines/.sseq is if=drawstructlines, + no struct lines/.sseq is if false={drawstructlines}, + draw orphan edges/.sseq is if=draworphanedges, + no orphan edges/.sseq is if false={draworphanedges}, + class pattern/.sseq store in=\sseq@classpattern{standard}, + class pattern/.append code={\ifcsname sseq@\sseq@classpattern xoffset1/1\endcsname\else\sseq@error{unknown-class-pattern}\fi}, + class placement transform/.code={% + \bgroup + \let\tikz@transform\pgfutil@empty + \pgfqkeys{/sseqpages/class placement}{#1}% + \global\let\sseq@classplacementtransform\tikz@transform + \egroup + }, + class placement transform/.sseq default code={% + \bgroup + \let\tikz@transform\pgfutil@empty + \pgfqkeys{/sseqpages/class placement}{#1}% + \global\let\sseq@classplacementtransform@default\tikz@transform + \egroup + }, + class placement transform/.value required, + add class placement transform/.code={% + \bgroup + \let\tikz@transform\pgfutil@empty + \pgfqkeys{/sseqpages/class placement}{#1}% + \sseq@x@addto@macro\sseq@classplacementtransform{\unexpanded\@xp\tikz@transform} + \egroup + }, + add class placement transform/.sseq default code={% + \bgroup + \let\tikz@transform\pgfutil@empty + \pgfqkeys{/sseqpages/class placement}{#1}% + \sseq@x@addto@macro\sseq@classplacementtransform@default{\unexpanded\@xp\tikz@transform} + \egroup + }, + add class placement transform/.value required, +} + +\sseq@mathnodestrue + +\sseq@addtostorelist\sseq@targetx{}\sseq@addtostorelist\sseq@targety{} +\sseq@addtostorelist\sseq@xtickstep{1}\sseq@addtostorelist\sseq@ytickstep{1} +\sseq@addtostorelist\sseq@classplacementtransform{} + + +\sseq@addiftostorelist@truedefault{borderxaxis}\sseq@addiftostorelist@truedefault{borderyaxis} +\sseq@addtostorelist\sseq@xaxisorigin{0}\sseq@addtostorelist\sseq@yaxisorigin{0} + +%%% Range keys and commands +\sseq@globalkeys{% + x range/.code 2 args={\sseq@xrange{#1}{#2}}, + x range/.sseq default code 2 args={\sseq@xrange@default{#1}{#2}}, + y range/.code 2 args={\sseq@yrange{#1}{#2}}, + y range/.sseq default code 2 args={\sseq@yrange@default{#1}{#2}}, + xrange/.forward to=/sseqpages/global/x range, + yrange/.forward to=/sseqpages/global/y range +} + +% These are set up so that if the user specifies no \xrange, the minimum position of any node can be calculated on the fly. +\@xp\sseq@addtostorelist\@xp\sseq@xmin\@xp{\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@ymin\@xp{\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@xmax\@xp{\@xp-\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@ymax\@xp{\@xp-\sseq@infinity} +\sseq@addtostorelist\xmin{\protect\sseq@xmin} +\sseq@addtostorelist\ymin{\protect\sseq@ymin} +\sseq@addtostorelist\xmax{\protect\sseq@xmax} +\sseq@addtostorelist\ymax{\protect\sseq@ymax} +% These are used to decide whether to add a certain node to savedpaths. +% In general the check is whether xmin<=xcoord<=xmax, but since Latex has no <=, set xminmm=xmin-1, xmaxpp=xmax+1. +% If the user doesn't specify a range, all nodes should be rendered +% To ensure that xminmm<xccord<xminpp in that case, set the default to xminmm=-\infty, xmaxpp=+\infty. +\@xp\sseq@addtostorelist\@xp\sseq@xminmm\@xp{\@xp-\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@yminmm\@xp{\@xp-\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@xmaxpp\@xp{\sseq@infinity} +\@xp\sseq@addtostorelist\@xp\sseq@ymaxpp\@xp{\sseq@infinity} + +\def\sseq@xrange#1#2{% + \global\let\sseq@xminmax\@gobbletwo % Don't need to calculate range of nodes if user specifies it + \gdef\sseq@xmin{#1}% + \gdef\sseq@xmax{#2}% + \let\xmin\sseq@xmin + \let\xmax\sseq@xmax + % Need to know decremented \xmin and incremented \xmax to decide which nodes to print + \sseq@tempcount=#1 \advance\sseq@tempcount-1\xdef\sseq@xminmm{\the\sseq@tempcount}% + \sseq@tempcount=#2 \advance\sseq@tempcount1\xdef\sseq@xmaxpp{\the\sseq@tempcount}% +} +\def\sseq@yrange#1#2{% + \global\let\sseq@yminmax\@gobbletwo % + \gdef\sseq@ymin{#1}% + \gdef\sseq@ymax{#2}% + \let\ymin\sseq@ymin + \let\ymax\sseq@ymax + \sseq@tempcount=#1 \advance\sseq@tempcount-1\xdef\sseq@yminmm{\the\sseq@tempcount}% + \sseq@tempcount=#2 \advance\sseq@tempcount1\xdef\sseq@ymaxpp{\the\sseq@tempcount}% +} + +\def\sseq@xrange@default#1#2{% + \global\let\sseq@xminmax\@gobbletwo % Don't need to calculate range of nodes if user specifies it + \gdef\sseq@xmin@default{#1}% + \gdef\sseq@xmax@default{#2}% + % Need to know decremented \xmin and incremented \xmax to decide which nodes to print + \sseq@tempcount=#1 \advance\sseq@tempcount-1\xdef\sseq@xminmm@default{\the\sseq@tempcount}% + \sseq@tempcount=#2 \advance\sseq@tempcount1\xdef\sseq@xmaxpp@default{\the\sseq@tempcount}% +} +\def\sseq@yrange@default#1#2{% + \global\let\sseq@yminmax\@gobbletwo % + \gdef\sseq@ymin@default{#1}% + \gdef\sseq@ymax@default{#2}% + \sseq@tempcount=#1 \advance\sseq@tempcount-1\xdef\sseq@yminmm@default{\the\sseq@tempcount}% + \sseq@tempcount=#2 \advance\sseq@tempcount1\xdef\sseq@ymaxpp@default{\the\sseq@tempcount}% +} + +% If #1 is less than \xmin or greater than \xmax, update \xmin or \xmax appropriately +% Gets set to \@gobble if user specifies range +\def\sseq@xminmax@active#1#2{% + \ifnum#1<\sseq@xmin\relax + \ifx\sseq@yminmax\@gobbletwo + \ifnum#2>\sseq@yminmm\relax + \ifnum#2<\sseq@ymaxpp\relax + \xdef\sseq@xmin{#1}% + \fi + \fi + \else + \xdef\sseq@xmin{#1}% + \fi + \fi + \ifnum#1>\sseq@xmax\relax + \ifx\sseq@yminmax\@gobbletwo + \ifnum#2>\sseq@yminmm\relax + \ifnum#2<\sseq@ymaxpp\relax + \xdef\sseq@xmax{#1}% + \fi + \fi + \else + \xdef\sseq@xmax{#1}% + \fi + \fi +} + +\def\sseq@yminmax@active#1#2{% + \ifnum#2<\sseq@ymin\relax + \ifx\sseq@xminmax\@gobbletwo + \ifnum#1>\sseq@xminmm\relax + \ifnum#1<\sseq@xmaxpp\relax + \xdef\sseq@ymin{#2}% + \fi + \fi + \else + \xdef\sseq@ymin{#2}% + \fi + \fi + \ifnum#2>\sseq@ymax\relax + \ifx\sseq@xminmax\@gobbletwo + \ifnum#1>\sseq@xminmm\relax + \ifnum#1<\sseq@xmaxpp\relax + \xdef\sseq@ymax{#2}% + \fi + \fi + \else + \xdef\sseq@ymax{#2}% + \fi + \fi +} + +%%% Axes and Layout options +\sseq@addtostorelist{\sseq@xtickfn}{} % These should initially be the identity macro, but addtostorelist doesn't accept functions as default +\sseq@addtostorelist{\sseq@ytickfn}{} % so the default is instated in begin{sseqdata} / begin{sseqpicture}. +\sseq@globalkeys{% + title/.sseq store in=\sseq@title{}, + title style/.sseq append to style={/sseqpages/global/every title}{at={(0.5*\xmin+0.5*\xmax,\ymax)}}, + draw title/.sseq is if=drawtitle, + no title/.code=\sseq@drawtitlefalse, +% + x label/.sseq store in=\sseq@xaxislabel{}, + y label/.sseq store in=\sseq@yaxislabel{}, + x label style/.sseq append to style={/sseqpages/global/every x axis label}{at={(0.5*\xmin+0.5*\xmax,\ymin)}}, + y label style/.sseq append to style={/sseqpages/global/every y axis label}{at={(\xmin ,0.5*\ymax+0.5*\ymin)}}, + label style/.sseq x y alias, + draw x label/.sseq is if=drawxaxislabel, + draw y label/.sseq is if=drawyaxislabel, + no x label/.sseq is if false={drawxaxislabel}, + no y label/.sseq is if false={drawyaxislabel}, + no labels/.sseq x y alias=no #1 label, + draw labels/.sseq x y alias=draw #1 label, +% + no x axis/.sseq is if false={drawxaxis}, + no y axis/.sseq is if false={drawyaxis}, + no axes/.value forbidden, + no axes/.sseq x y alias=no #1 axis, + draw x axis/.sseq is if=drawxaxis, + draw y axis/.sseq is if=drawyaxis, + draw axes/.sseq x y alias=draw #1 axis, + rotate labels/.sseq is if=rotatelabels, +% + draw x ticks/.sseq is if=drawxaxisticks, + no x ticks/.sseq is if false=drawxaxisticks, + draw y ticks/.sseq is if=drawyaxisticks, + no y ticks/.sseq is if false=drawyaxisticks, + no ticks/.sseq x y alias=no #1 ticks, + no ticks/.value forbidden, + draw ticks/.sseq x y alias=draw #1 ticks, + draw ticks/.default=true, + tick step/.sseq x y alias, + tick step/.value required, + x tick step/.sseq store in=\sseq@xtickstep{1}, + y tick step/.sseq store in=\sseq@ytickstep{1}, + x tick handler/.code={\def\sseq@xtickfn##1{#1}}, + x tick handler/.sseq default code={\def\sseq@xtickfn@default##1{#1}}, + y tick handler/.code={\def\sseq@ytickfn##1{#1}}, + y tick handler/.sseq default code={\def\sseq@ytickfn@default##1{#1}}, + class label handler/.code = {\long\def\sseq@classlabeltextfn##1{#1}}, % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...) + class label handler/.sseq default code={\long\def\sseq@classlabeltextfn@default##1{#1}}, + x tick style/.sseq store in=\sseq@xtickstyle{}, + y tick style/.sseq store in=\sseq@ytickstyle{}, + tick style/.sseq x y alias, +% + x axis style/.is choice, + y axis style/.is choice, + axes style/.sseq x y alias=axis style, + ~x axis style/border/.code={\sseq@drawxaxistrue\sseq@borderxaxistrue}, + ~y axis style/border/.code={\sseq@drawyaxistrue\sseq@borderyaxistrue}, + ~x axis style/center/.code={ + \sseq@drawxaxistrue\sseq@borderxaxisfalse + \ifx\sseq@xaxisgap\sseq@xaxisgap@default + \def\sseq@xaxisgap{0cm} + \fi + }, + ~y axis style/center/.code={\sseq@drawyaxistrue\sseq@borderyaxisfalse\ifx\sseq@yaxisgap\sseq@yaxisgap@default\def\sseq@yaxisgap{0cm}\fi}, + ~x axis style/none/.code={\sseq@drawxaxisfalse}, + ~y axis style/none/.code={\sseq@drawyaxisfalse}, + x axis origin/.sseq store in=\sseq@xaxisorigin{0}, + y axis origin/.sseq store in=\sseq@yaxisorigin{0}, + axes origin/.sseq x y alias=axis origin, +} +\pgfqkeys{/sseqpages}{% + class label handler/.code = {\long\def\sseq@classlabeltextfn##1{#1}} +} + +\sseq@globalkeys{ + axes gap/.sseq x y alias=axis gap, + axes gap/.value required, + x axis gap/.sseq store in=\sseq@xaxisgap{0.5cm}, + y axis gap/.sseq store in=\sseq@yaxisgap{0.5cm}, + tick gap/.sseq x y alias, + tick gap/.value required, + x tick gap/.sseq store in=\sseq@xlabelgap{0.5cm}, + y tick gap/.sseq store in=\sseq@ylabelgap{0.5cm}, + x axis extend start/.sseq store in=\sseq@xaxis@start@extend{0.9cm}, + y axis extend start/.sseq store in=\sseq@yaxis@start@extend{0.9cm}, + axes extend start/.sseq x y alias=axis extend start, + x axis extend end/.sseq store in=\sseq@xaxis@end@extend{0.5cm}, + y axis extend end/.sseq store in=\sseq@yaxis@end@extend{0.5cm}, + axes extend end/.sseq x y alias=axis extend end, + x axis clip padding/.sseq store in=\sseq@xclip@axisgap{0.1cm}, + y axis clip padding/.sseq store in=\sseq@yclip@axisgap{0.1cm}, + axes clip padding/.sseq x y alias=axis clip padding, + right clip padding/.sseq store in=\sseq@clip@padding@right{0.1cm}, + left clip padding/.sseq store in=\sseq@clip@padding@left{0.4cm}, + top clip padding/.sseq store in=\sseq@clip@padding@top{0.1cm}, + bottom clip padding/.sseq store in=\sseq@clip@padding@bottom{0.4cm} +} + +%%% +%%% Coordinate transformations +%%% + +%%% Global Coordinate Transformations +\sseq@globaldetonetrue +\sseq@addtostorelist\sseq@globaldetonetransform{} +\sseq@addtostorelist\sseq@globalrotatetransform{} +\sseq@addtostorelist\sseq@globalscaletransform{} + +\def\sseq@globaldetoneoption#1#2{% + \ifsseq@globaldetone\else + \sseq@error@n{det-one-after-scale}{#2} + \fi + \@xp\gdef\@xp\sseq@globaldetonetransform\@xp{\sseq@globaldetonetransform #1}% + #1 +} +\def\sseq@globalscaleoption#1{% + \sseq@globaldetonefalse + \@xp\gdef\@xp\sseq@globalscaletransform\@xp{\sseq@globalscaletransform#1}#1% +} +\pgfqkeys{/sseqpages/global}{% + x/.sseq @ illegal, + y/.sseq @ illegal, + z/.sseq @ illegal, + xshift/.sseq @ illegal as global, + yshift/.sseq @ illegal as global, + shift/.sseq @ illegal as global, + scale around/.sseq @ illegal as global, + rotate around/.sseq @ illegal as global, + rotate/.code={% + \@xp\gdef\@xp\sseq@globalrotatetransform\@xp{\sseq@globalrotatetransform\pgftransformrotate{#1}}% + \sseq@globaldetoneoption{\pgftransformrotate{#1}}{rotate}% + }, + rotate/.value required, + xslant/.code={\sseq@globaldetoneoption{\pgftransformxslant{#1}}{xslant}}, + xslant/.value required, + yslant/.code={\sseq@globaldetoneoption{\pgftransformyslant{#1}}{yslant}}, + yslant/.value required, + xmirror/.code={\sseq@globaldetoneoption{\pgftransformxscale{-1}}{xmirror}}, + xmirror/.value forbidden, + ymirror/.code={\sseq@globaldetoneoption{\pgftransformyscale{-1}}{ymirror}}, + ymirror/.value forbidden, + mirror/.forward to=/sseqpages/global/xmirror, + mirror/.forward to=/sseqpages/global/ymirror, + xscale/.code={% + \pgfmathparse{int(#1-1)}% + \ifnum\pgfmathresult<\z@% + \sseq@error@nn{negative-scale}{x}{#1}% + \fi + \sseq@globalscaleoption{\pgftransformxscale{#1}}% + }, + xscale/.value required, + yscale/.code={% + \pgfmathparse{int(#1-1)}% + \ifnum\pgfmathresult<\z@ + \sseq@error@nn{negative-scale}{y}{#1}% + \fi + \sseq@globalscaleoption{\pgftransformyscale{#1}}% + }, + yscale/.value required, + scale/.code={% + \pgfmathparse{int(#1-1)}% + \ifnum\pgfmathresult<\z@ + \sseq@error@nn{negative-scale}{}{#1}% + \fi + \sseq@globalscaleoption{\pgftransformscale{#1}}% + }, + scale/.value required +} + +%%% Local Coordinate transformations + +\pgfqkeys{/sseqpages/class placement}{ + x shift/.code={\sseq@error@nn{class-placement-shift}{x shift}{#1}}, + y shift/.code={\sseq@error@nn{class-placement-shift}{y shift}{#1}}, + shift/.code={\sseq@error@nn{class-placement-shift}{shift}{#1}} +} + +%% setup for coordinate transformation keys +\def\sseq@checktransform{\sseq@error@nn{illegal-transform}} +\pgfqkeys{/sseqpages}{% + x/.code={\sseq@error@n{option-illegal}{#1}}, + y/.code={\sseq@error@n{option-illegal}{#1}}, + z/.code={\sseq@error@n{option-illegal}{#1}}, + xshift/.sseq @ second pass code={\sseq@shifttransform{x}{#1}}, % I don't know why it has to be this way, + xshift/.sseq @ first pass append code={\sseq@firstpass@shifttransform{x}{#1}}, % but it definitely breaks if I change it... + xshift/.value required, + yshift/.sseq @ second pass code={\sseq@shifttransform{y}{#1}}, + yshift/.sseq @ first pass append code={\sseq@firstpass@shifttransform{y}{#1}}, + yshift/.value required, + shift/.sseq @ transform, shift/.value required, + shift only/.sseq @ transform, + xscale/.sseq @ transform, xscale/.value required, + yscale/.sseq @ transform, yscale/.value required, + scale/.sseq @ transform, scale/.value required, + scale around/.sseq @ transform, scale around/.value required, + xslant/.sseq @ transform, xslant/.value required, + yslant/.sseq @ transform, yslant/.value required, + rotate/.sseq @ transform, rotate/.value required, + rotate around/.sseq @ transform, rotate around/.value required, + cm/.sseq @ transform, cm/.value required, + reset cm/.sseq @ transform, reset cm/.value forbidden, + transform canvas/.sseq @ transform, transform canvas/.value required +} + +% These two should be exactly the same +\def\sseq@shift@firstpassprocess#1{\sseq@shift@firstpassprocess@#1\sseq@nil} +\def\sseq@shift@firstpassprocess@#1#2\sseq@nil{\ifx#1\pgfpointxy\sseq@shift@firstpassprocess@@#2\else\sseq@standardparse\fi} +\def\sseq@shift@firstpassprocess@@#1#2{ + \sseq@tikz@firstpass@checkshifttransform{x}{#1} + \sseq@tikz@firstpass@checkshifttransform{y}{#2} +} + +\def\sseq@shift@secondpassprocess#1{\sseq@shift@secondpassprocess@#1\sseq@nil} +\def\sseq@shift@secondpassprocess@#1#2\sseq@nil{\ifx#1\pgfpointxy\sseq@shift@secondpassprocess@@#2\else\sseq@standardparse \pgftransformshift{#1#2}\fi} +\def\sseq@shift@secondpassprocess@@#1#2{ + \sseq@tikz@shifttransform{x}{#1} + \sseq@tikz@shifttransform{y}{#2} +} + +\sseq@pgfqkeysdirlist{/sseqpages/scope,/sseqpages/tikz primitives}{ + shift/.code={ + \sseq@options@firstpass{\tikz@scan@one@point\sseq@shift@firstpassprocess#1\relax} + \sseq@options@secondpass{\tikz@scan@one@point\sseq@shift@secondpassprocess#1\relax} % TODO: maybe try to save the work of processing the point twice? + }, + xshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{x}{#1}, + yshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{y}{#1}, + xshift/.sseq @ second pass append code=\sseq@tikz@shifttransform{x}{#1}, + yshift/.sseq @ second pass append code=\sseq@tikz@shifttransform{y}{#1}, + rotate around/.sseq @ second pass code={\sseq@standardparse\sseq@pgfkeysdocommand{rotate}{#1}}, + rotate/.sseq @ stdparse do transform, rotate/.value required, + xslant/.sseq @ stdparse do transform, xslant/.value required, + yslant/.sseq @ stdparse do transform, yslant/.value required, + xmirror/.sseq @ stdparse do transform={-1}, xmirror/.value forbidden, + ymirror/.sseq @ stdparse do transform={-1}, ymirror/.value forbidden, + xscale/.sseq @ stdparse do transform, xscale/.value required, + yscale/.sseq @ stdparse do transform, yscale/.value required, + scale/.sseq @ stdparse do transform, scale/.value required, + scale around/.sseq @ stdparse do transform, scale around/.value required +} + +%%% Error checking for nonglobal transformations: + +\def\sseq@firstpass@checkshifttransform#1#2{% + \pgfmathparse{#2}% + \sseq@ifpgfmathresultisunitlessint{% + \@xp\pgfmathint\@xp{\pgfmathresult}% + \@xp\advance\csname sseq@#1\endcsname\pgfmathresult\relax + }{\sseq@error@n{illegal-transform}{#1shift}}% +} +\let\sseq@firstpass@shifttransform\sseq@firstpass@checkshifttransform + +\def\sseq@checkshifttransform#1#2{% + \pgfmathparse{#2}% + \sseq@ifpgfmathresultisunitlessint{% + \@xp\pgfmathint\@xp{\pgfmathresult}% + \@xp\advance\csname sseq@#1\endcsname\pgfmathresult\relax + \sseq@pgfkeysdocommand{#1shift}{#2cm} + }{\sseq@error@n{illegal-transform}{#1shift}}% +} + +\def\sseq@okayshifttransform#1#2{% + \pgfmathparse{#2} + \ifpgfmathunitsdeclared + \sseq@pgfkeysdocommand{#1shift}{#2} + \else + \sseq@pgfkeysdocommand{#1shift}{#2cm} + \fi +} + +\def\sseq@tikz@firstpass@checkshifttransform#1#2{% + \pgfmathparse{#2}% + \sseq@ifpgfmathresultisunitlessint{% + \@xp\pgfmathint\@xp{\pgfmathresult}% + \@xp\advance\csname sseq@\sseq@getfirstchar#1\sseq@nil\endcsname\pgfmathresult\relax + }{\sseq@standardparse}% +} + +\def\sseq@tikz@shifttransform#1#2{% + \pgfmathparse{#2}% + \sseq@ifpgfmathresultisunitlessint{% + \@xp\pgfmathint\@xp{\pgfmathresult}% + \@xp\advance\csname sseq@\sseq@getfirstchar#1\sseq@nil\endcsname\pgfmathresult\relax + \sseq@pgfkeysdocommand{#1shift}{#2cm} + }{ + \sseq@standardparse + \ifpgfmathunitsdeclared + \sseq@pgfkeysdocommand{#1shift}{#2} + \else + \sseq@pgfkeysdocommand{#1shift}{#2cm} + \fi + }% +} + +\def\sseq@ifpgfmathresultisunitlessint{\ifpgfmathunitsdeclared\@xp\@secondoftwo\else\sseq@ifpgfmathresultisint{\@xp\@firstoftwo}{\@xp\@secondoftwo}\fi} +\def\sseq@ifpgfmathresultisint{\@xp\sseq@ifpgfmathresultisint@\pgfmathresult..\sseq@nil} +\def\sseq@ifpgfmathresultisint@#1.#2.#3\sseq@nil{\ifx\sseq@nil#2\sseq@nil\@xp\@firstoftwo\else \ifnum#2=\z@ \@xp\@xp\@xp\@firstoftwo\else \@xp\@xp\@xp\@secondoftwo\fi\fi} + +%%%% Options for Tikz primitives + +\def\sseq@pageconstraint{1} +\def\sseq@pageconstraint@true{1} + +\sseq@pgfqkeysdirlist{/sseqpages/scope,/sseqpages/tikz primitives}{ + page constraint/.code={ + \sseq@updatepageconstraint{#1}{&&} + }, + page constraint or/.code={ + \sseq@updatepageconstraint{#1}{||} + }, + page/.code={\sseq@getnumrange\temp{#1}\sseq@updatepageconstraintrange}, + set page constraint/.store in=\sseq@pageconstraint, + background/.code={\sseq@standardparse\sseq@setsavedpaths{background}\pgfkeysalso{standard parse}}, +} + +\sseq@pgfqkeysdirlist{/sseqpages/scope,/sseqpages/tikz primitives,/sseqpages/fit}{ + class style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theclassstyle\the\sseq@scope@toks}}, + cycle style/.forward to=/sseqpages/tikz primitives/class style, + permanent class style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theclassstyle\sseq@thepermanentcyclestyle\the\sseq@scope@toks}}, + permanent cycle style/.forward to=/sseqpages/tikz primitives/permanent class style, + transient class style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theclassstyle\sseq@thetransientcyclestyle\the\sseq@scope@toks}}, + transient cycle style/.forward to=/sseqpages/tikz primitives/transient class style, + this page class style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theclassstyle\sseq@thetransientcyclestyle\sseq@thethispagecyclestyle\the\sseq@scope@toks}}, + this page cycle style/.forward to=/sseqpages/tikz primitives/this page class style, + differential style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theedgestyle\sseq@thedifferentialstyle\the\sseq@scope@toks}}, + struct line style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theedgestyle\sseq@thestructlinestyle\the\sseq@scope@toks}}, + tikz primitive style/.code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@thetikzprimitivestyle\the\sseq@scope@toks}} + %this page struct line style/.sseq @ first pass code={\sseq@d@addto@options{\sseq@thesseqstyle\sseq@theedgestyle\sseq@thestructlinestyle\the\sseq@scope@toks}} +} |