diff options
author | Karl Berry <karl@freefriends.org> | 2017-06-19 21:07:40 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-06-19 21:07:40 +0000 |
commit | 787b1d312f205766480ce986a9f98548cc396dae (patch) | |
tree | a01010a46833874f9247534568d49f35446a3cc7 /Master/texmf-dist | |
parent | 24274bfce4fb35c537447dace80be3d48d7c250b (diff) |
spectralsequences (19jun17)
git-svn-id: svn://tug.org/texlive/trunk@44639 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
42 files changed, 12995 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/spectralsequences/README b/Master/texmf-dist/doc/latex/spectralsequences/README new file mode 100644 index 00000000000..f581a8129a1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/README @@ -0,0 +1,8 @@ +Package: spectralsequences version 1.0 +Author: Hood Chatham +Email: hood@mit.edu +Date: 2017-06-18 +License: All files have the Latex Project Public License. +Description: Print spectral sequence diagrams using pgf/tikz. + +See the file manual/spectralsequencesmanual.pdf for a manual. Email me at hood@mit.edu to submit bug reports, request new features, etc. The current development copy is hosted at https://github.com/hoodmane/spectralsequences.
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.pdf Binary files differnew file mode 100644 index 00000000000..9367b1ce253 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.tex new file mode 100644 index 00000000000..7d1ab32c7f2 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_A1_May_SS.tex @@ -0,0 +1,82 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_bo_May_SS.tex +%% +%% Draws the May spectral sequence computing Ext_{A(1)} ( F_2, F_2 ), which by a change of rings and a simple argument that the ASS has to collapse, +%% is telling us pi_* bo. See the Green Book for reference. +%% The main purpose of this example from my perspective is to illustrate the utility of class "tags". +%% + + +\documentclass{article} +\usepackage{spectralsequences} +\NewSseqGroup\tower {} { + \class(0,0) + \foreach\i in {1,...,11}{ + \class(0,\i) + \structline(0,\i-1,-1)(0,\i,-1) + } +} +\NewSseqGroup\hvee {} { + \tower(0,0) + \foreach\i in {1,...,11}{ + \class(\i,\i) + \structline(\i-1,\i-1,-1)(\i,\i,-1) + } +} + +\begin{document} +\begin{sseqdata}[ + name=A1 May, + x range={0}{10}, y range={0}{10}, + degree={-1}{1}, + classes={fill, tooltip = {(\xcoord,\ycoord)}}, + class labels={below=3pt}, + run off differentials= ->, + no orphan edges, +] +\foreach\i in {0,1,2}{ + \begin{scope}[xshift=4*\i,yshift=2*\i,tag prefix=\i.] + \hvee[tag=id](0,0) + \hvee[tag=h0h1](1,2) + \hvee[tag=h20](2,1) + \foreach\j in {1,...,10}{ + \d1(2,\j,h20,h0h1) + } + \foreach\j in {1,...,10}{ + \d1(2+\j,1+\j,h20,h0h1) + } + \end{scope} +} + + +\foreach\i in {0,...,7}{ + \d2(4+\i,2+\i,1.id,0.id) +} +\class(12,6) +\d2(12,6,,1) + +%\classoptions["h_0"](0,1) +\classoptions["h_1"](1,1) +\classoptions["h_{20}"](2,1) +\classoptions["h_{20}^2"](4,2) +\classoptions["h_{20}^3"](6,3) +\classoptions["h_{20}^4"](8,4) +\classoptions["h_{20}^5"](10,5) + +\doptions[shorten >=3pt]1(10,10,2.h20,2.h0h1) +\end{sseqdata} + +\printpage[name=A1 May,page=1] +\newpage +\printpage[name=A1 May,page=2] +\newpage +\begin{sseqpage}[name=A1 May,page=3] +\classoptions["h_0h_{20}^2"](4,3,1.id) +\end{sseqpage} +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.pdf Binary files differnew file mode 100644 index 00000000000..8b5dc4f6293 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.tex new file mode 100644 index 00000000000..c4a5f3650e2 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_EO2_3.tex @@ -0,0 +1,74 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_EO2_3.tex +%% +%% This is the homotopy fixed point spectral sequence for EO_2 at the prime 3. The maximal finite subgroup of the Morava stabilizer for E_{p-1} is +%% of size 2p(p-1)^2 = 24, and so there is a norm element v in degree 24. There's also a bunch of trace classes on the zero line, but the trace map +%% E_* --> H^*( G ; E_* ) is induced by the trace map E_n --> EO_n, so all of these classes are permanent cycles. They are hard to compute and we don't draw them. +%% We also have classes \alpha and \beta coming from the stabilizer action, which are the images of \alpha_1 and \beta_1 in the ANSS. +%% By looking at cobar representatives, we can see that v*\beta_1 is the image of \beta_{3/3}. +%% Thus, the Toda differential in the ANSS d_3(\beta_{3/3}) = \alpha \beta^3 forces also that d_3(v) = \alpha \beta^2. Likewise, the Toda "Kudo" differential +%% d_9( \alpha \beta_{3/3}^2 ) = \beta^7 gives us upon dividing by \beta twice that d_9(\alpha v^2) = \beta^5. At this point, there are no possible differentials. +%% We see that v^3 survives so EO_n* is 72 = 2p^2(p-1)^2 periodic. The picture is exactly the same at other odd primes. At 2, this degenerates to the +%% HFPSS for KO = KU^{hC_2} (see example_KUHFPSS). +%% + +\documentclass{article} +\usepackage{spectralsequences} +\usepackage[landscape,margin=0cm,top=2cm]{geometry} + +\begin{document} +\begin{sseqdata}[name=EO(2),Adams grading, + y range={0}{14},x range={0}{160}, + xscale=0.15, x tick step=5, + classes={fill, tooltip={(\xcoord,\ycoord)}} +] +\foreach \v in {0,...,8}{ + \foreach \b in {0,...,11}{ + \foreach \a in {0,1}{ + \class(3*\a + 10*\b+24*\v,\a+2*\b) + \ifnum\b>0\relax + \structline(3*\a+10*\b-10+24*\v,\a+2*\b-2) (3*\a + 10*\b+24*\v,\a+2*\b) + \fi + } + \structline(10*\b+24*\v,2*\b)(3 + 10*\b + 24*\v,2*\b+1) + \ifnum \v = \numexpr\v/3*3\relax + + \else + \ifnum\b<9\relax + \d5(10*\b+24*\v,2*\b) + \fi + \fi + } +} + +% v^2ab^2 is in degree 2*24 + 3 + 2*10 = 71, 5 +% b^{pn+1} = b^{7} is in degree 7*10 = 70,14 +\foreach \v in {2,5}{ + \foreach \b in {0,...,6}{ + \d9(\v*24 + 3 +10*\b,1+2*\b) + } +} +\end{sseqdata} +\printpage[name=EO(2),page=0] +\newpage +\printpage[name=EO(2),page=5] +\newpage +\printpage[name=EO(2),page=9] +\newpage +\begin{sseqpage}[name=EO(2),page=10] +\classoptions["a" left](3,1) +\classoptions["b" right](10,2) +\classoptions["ab" left](13,3) +\classoptions["b^2" right](20,4) +\classoptions["b^3" right](30,6) +\classoptions["b^4" right](40,8) + +\classoptions["v^3" right](72,0) +\end{sseqpage} +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.pdf Binary files differnew file mode 100644 index 00000000000..7535a796aa9 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.tex new file mode 100644 index 00000000000..dad6f608b58 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KF3n.tex @@ -0,0 +1,330 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_KF3n.tex +%% +%% This is a computation of the Z_3 cohomology of K(F_3,n). This was part of a way-too-hard problem on Haynes Algebraic Topology II problem set which asked to compute +%% the smallest k>0 such that H_{n+k}(K(--,n);Z_p) : Ab --> Ab is not the zero functor and to compute what functor it is. One of the main ideas is to use the Bockstein +%% spectral sequence, because it handles the badness of integral Kunneth for us too. +%% + +\documentclass{article} +\usepackage[margin=0.2in,top=0.4in,landscape]{geometry} +\usepackage{spectralsequences} +\usepackage{amssymb} +\def\Z{\mathbb{Z}} +\begin{document} +\sseqset{ + cohomological Serre grading, + title={Page \page}, + class placement transform={scale=3, rotate=90}, + class pattern=linear, + classes={draw=none}, + class label handler = {\sseqnormalizemonomial{#1}}, + bocksteinSS/.style={ + page=0, y range={-1}{0}, + no differentials, no labels, no y ticks, no title, + yscale=1.5, x axis extend end=40pt, y axis extend end = 40pt, x axis gap =50pt, + class label handler = {}, + } + %class labels=above, +} + +\begin{sseqdata}[name=K(Z/3;2), + x range={0}{8}, xscale=2.2, yscale=1.5, + x label={$H^*(K(\Z/3,2),\Z/3)$}, + y label={$H^*(K(\Z/3,1),\Z/3)$}, + right clip padding=20pt, x axis gap=20pt, +] +\foreach \x/\xlabel in + { 0/1, 2/\iota_2, 3/\beta\iota_2, 4/\iota_2^2, 5/\iota_2\beta\iota_2, 6/\iota_2^3, + 7/\iota_2^2\beta\iota_2, 7/P^1\beta\iota_2, 8/\iota_2^4, 8/\beta P^1\beta\iota_2 } +\foreach \y/\ylabel in + { 0/1, 1/\alpha, 2/x, 3/\alpha x, 4/x^2, 5/\alpha x^2, 6/x^3} { + \class["\ylabel\xlabel"](\x,\y) +} + +\class(9,0)\class(9,0) +\class(9,1) +\class(9,2) +\class(9,3) +\class(9,4) +\class(9,5) + +\class(10,0)\class(10,0)\class(10,0) +\class(10,2)\class(10,2) +\class(10,4)\class(10,4) + +\class(11,0)\class(11,0) +\class(11,2) + +\class(12,0) +\class(13,0) +\class(14,0) +\class(15,0) +%\class["(\beta\iota_2)^2"](6,0) + + +\d2(0,1) %d2(a)=i + + + +\d3(0,2) %d3(x) = b(i) +\d2(0,3) % d2(ax) = ix +\d3(0,4) % d2(x^2) = xb(i) +\d2(0,5) % d2(ax^2) = ix^2 +%\d7 + + +\d2(2,1) % d2(ai) = i^2 +\d2(2,3) % d2(axi) = xi^2 +\d2(2,5) % d2(ax^2i)=x^2i^2) + +\d2(3,1) % d2(abi)=ib(i) +\d2(3,3) +\d2(3,5) + +\d2(4,1) % d2(ai^2)=i^3 +\d2(4,3) +\d2(4,5) + +\d2(5,1,,1) %d2(ai_2bi_2) = i_2^2 bi_2 +\d2(5,3,,1) +\d2(5,5,,1) + +\d2(6,1,,1) %d2(ai_2^3) = i_2^4 +\d2(6,3,,1) +\d2(6,5,,1) + +\d2(7,1,1) % d2(ai_2^2bi_2) = i_2^3 bi_2 +\d2(7,3,1) +\d2(7,5,1) + +\d2(7,1,2) % d2(aP^1bi_2) = i_2 P^1bi_2 +\d2(7,3,2) +\d2(7,5,2) + +\d3(7,2,2) % d3(x P^1bi_2) = bi_2 P^1bi_2 +\d3(7,4,2) + +\d2(8,1,1,2) % d2(a i_2^4) = i_2^5 +\d2(8,3,1,2) +\d2(8,5,1,2) + +\d2(8,1,2,2) % d2(a bP^1bi_2) = i_2 bP^1bi_2 +\d2(8,3,2,2) +\d2(8,5,2,2) + +\d3(8,2,2) % d3(x bP^1bi_2) = bi_2 bP^1bi_2 +\d3(8,4,2) + + +\d5(3,4,,2) % d5(x^2i_2) = bP^1bi_2 -- Kudo differential + +\d7(0,6,,2) % d7(x^3) = P^1bi_2 +\d7(2,6,,2) +\d7(3,6,,3) +\d7(4,6,,2) +\d7(5,6) +\d7(6,6) +\d7(7,6,1) +\d7(7,6,2) +\d7(8,6,1) +\d7(8,6,2) + + +\end{sseqdata} + +\printpage[name=K(Z/3;2),page=2] +\newpage +\printpage[name=K(Z/3;2),page=3] +\newpage +\printpage[name=K(Z/3;2),page=5] +\newpage +\printpage[name=K(Z/3;2),page=6] +\newpage +\printpage[name=K(Z/3;2),page=7] +\newpage + +\begin{sseqpage}[ + name=K(Z/3;2), bocksteinSS, + x axis extend end = 30pt, y axis gap=30pt, +] +\begin{scope}[background] +\node[anchor=west] at (-2,0) { H^*(K(\Z/3,2),\Z/3)}; +\node[anchor=west] at (-2,-1) { H^*(K(\Z/3,2),\Z)}; +\end{scope} + +\draw[->] (2,0) to[bend left=30, "\beta^1"] (3,0); +\draw[->] (4,0) to[bend left=30, "\beta^1"{pos = 0.55}] (5,0); +\draw[->] (6,0) to[bend right=30, "\beta^2"'] (7,0,1); +\draw[->] (7,0,2) to[bend left=30, "\beta^1"] (8,0,2); +\draw[->] (8,0,1) to[bend right=30, "\beta^1"' {pos = 0.46}] (9,0); + +\class["\Z\{1\}"](0,-1) +\class["\Z/3\{\beta\iota_3\}"](2,-1) +\class["\Z/3\{\beta\iota_2^2\}"](5,-1) +\class["\Z/9\{\beta\iota_2^3\}"](7,-1) +\class["\Z/3\{\beta P^1\iota_2\}"](8,-1) +\end{sseqpage} + + +\newpage +\begin{sseqdata}[name=K(Z/3;3),xscale=2.2,yscale=1.7,y axis gap=40pt,x axis gap=30pt, x range={0}{9}, + x label={$H^*(K(\Z/3,2),\Z/3)$}, + y label={$H^*(K(\Z/3,1),\Z/3)$} +] + +\foreach \x/\ymax/\xlabel in { 0/6/1, 3/6/\iota_3, 4/3/{{\beta\iota_3}} } +\foreach \y/\ylabel in { 0/1, 2/\iota_2, 3/{{\beta\iota_2}}, 4/\iota_2^2, 5/\iota_2{\beta\iota_2}, 6/\iota_2^3 } { + \class["\ylabel\xlabel"](\x,\y) +} + +\sseqset{class label handler = {}} + +\class["P^1\beta\iota_2"](0,7) +\class["\iota_2^2\beta\iota_2"](0,7) +\class["\beta P^1\beta\iota_2"](0,8) +\class["\iota_2^4"](0,8) + + +\class["P^1\iota_3"](7,0) +\class["\iota_3\beta\iota_3"](7,0) +\class["\beta P^1\iota_3"](8,0) +\class["(\beta\iota_3)^2"](8,0) +\class["P^1\beta\iota_3"](8,0) +\class["\beta P^1\beta\iota_3"](9,0) + + +\d3(0,2) +\d4(0,3) +\d3(0,4) +\d3(0,5) +\d7(0,6,,1) +\d3(0,7,2) +\d8(0,7,1,3) +\d3(0,8,2) +\d9(0,8,1) +\d5(3,4,,1) + +\d3(4,2,,2) +\d4(4,3,,2) +\end{sseqdata} + +\printpage[name=K(Z/3;3),page=3] +\newpage +\printpage[name=K(Z/3;3),page=4] +\newpage +\printpage[name=K(Z/3;3),page=5] +\newpage +\printpage[name=K(Z/3;3),page=7] +\newpage +\printpage[name=K(Z/3;3),page=9] +\newpage + +\begin{sseqpage}[ name=K(Z/3;3), bocksteinSS ] +\begin{scope}[background] +\node[anchor=west] at (-2.2,0) { H^*(K(\Z/3,3),\Z/3)}; +\node[anchor=west] at (-2.2,-1) { H^*(K(\Z/3,3),\Z)}; +\end{scope} + +\draw[->] (3,0) to[bend left=30, "\beta^1"] (4,0); +\draw[->] (7,0,1) to[bend right=30, "\beta^1"' {pos=0.6}] (8,0,1); +\draw[->] (7,0,2) to[bend left=30, "\beta^1" {pos=0.43}] (8,0,2); +\draw[->] (8,0,3) to[bend left=30, "\beta^1"{pos=0.37}] (9,0); + +\class["\Z\{1\}"](0,-1) +\class["\Z/3\{\beta\iota_3\}"](4,-1) +\class["\Z/3\{\beta P^1\iota_3\}"](8,-1) +\class["\Z/3\{\beta(\iota_3\beta\iota_3)\}"](8,-1) +\class["\Z/3\{\beta P^1\beta\iota_3\}"](9,-1) +\end{sseqpage} + + + +\begin{sseqdata}[name=K(Z/3;4), + xscale=2,yscale=1.5,y axis gap=20pt,x axis gap=30pt, x range={0}{10}, + x label = {$H^*(K(\Z/3,3),\Z/3)$}, + y label = {$H^*(K(\Z/3,4),\Z/3)$}, + class label handler = {} +] + +\class["1"](0,0) +\class["\iota_3"](0,3) +\class["\beta\iota_3"](0,4) +\class["P^1\iota_3"](0,7) +\class["\beta P^1\iota_3"](0,8) +\class["\iota_3\beta\iota_3"](0,7) +\class["(\beta\iota_3)^2"](0,8) +\class["P^1\beta\iota_3"](0,8) +\class["\beta P^1\beta\iota_3"](0,9) + + +\class["\iota_4"](4,0) +\class["\iota_3\iota_4"](4,3) +\class["\beta\iota_3\iota_4"](4,4) + +\class["\beta\iota_4"](5,0) +\class["\iota_3\beta\iota_4"](5,3) +\class["\beta\iota_3\beta\iota_4"](5,4) + +\class["\iota_4^2"](8,0) +\class["P^1\iota_4"](8,0) + +\class["\iota_4 \beta\iota_4"](9,0) +\class["P^1\beta\iota_4"](9,0) +\class["\beta P^1\iota_4"](9,0) + +\class["\beta P^1\beta\iota_4"](10,0) + +\d4(0,3) % d4(i_3) = i_4 +\d4(0,7,2) +\d4(4,3,,1) +\d4(5,3,,1) + +\d5(0,4) + +\d8(0,7,1,2) + +\d9(0,8,1,2) +\d5(0,8,2) +\d9(0,8,3,3) +\d10(0,9) + +%\d +\end{sseqdata} + +\printpage[name=K(Z/3;4),page=4] +\newpage +\printpage[name=K(Z/3;4),page=5] +\newpage +\printpage[name=K(Z/3;4),page=8] +\newpage +\printpage[name=K(Z/3;4),page=9] +\newpage +\printpage[name=K(Z/3;4),page=10] +\newpage + +\begin{sseqpage}[ name=K(Z/3;4), bocksteinSS, yscale=1.3 ] +\begin{scope}[background] +\node[anchor=west] at (-2.2,0) { H^*(K(\Z/3,4),\Z/3)}; +\node[anchor=west] at (-2.2,-1) { H^*(K(\Z/3,4),\Z)}; +\end{scope} + +\draw[->] (4,0) to[bend left=30, "\beta^1"] (5,0); +\draw[->] (8,0,1) to[bend right=30, "\beta^1"' {pos=0.6}] (9,0,1); +\draw[->] (8,0,2) to[bend left=30, "\beta^1" {pos=0.6}] (9,0,3); +\draw[->] (9,0,2) to[ "\beta^1"] (10,0); + +\class["\Z\{1\}"](0,-1) +\class["\Z/3\{\beta\iota_4\}"](5,-1) +\class["\Z/3\{\beta P^1\iota_4\}"](9,-1) +\class["\Z/3\{\beta(\iota_4^2)\}"](9,-1) +\class["\Z/3\{\beta P^1\beta\iota_4\}"](10,-1) +\end{sseqpage} + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KRHFPSS.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KRHFPSS.pdf Binary files differnew file mode 100644 index 00000000000..3aff1b1fe8b --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KRHFPSS.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.pdf Binary files differnew file mode 100644 index 00000000000..c1d593951c7 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.tex new file mode 100644 index 00000000000..7207b38a986 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KUHFPSS.tex @@ -0,0 +1,92 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_KUHFPSS.tex +%% +%% I think this is one of Eric Peterson's favorite spectral sequences, and his enthusiasm for it has rubbed off on me a bit. +%% Here our group is C_2 which acts on the periodicity element by -1, so again we have a norm element v in degree 2|G| = 4. +%% There are easier ways to understand this, but I explained the EO_3 one in terms of the comparison map from the ANSS, +%% and that's interesting here too. In the ANSS at 2, there is a differential d3(\alpha_3) = \alpha_1^4. Here a cobar calculation +%% shows that \alpha v = \alpha_3, so dividing the differential by \alpha gives d3(v) = \alpha_1^3. Now there's no Kudo differential +%% because the prime is 2, and the spectral sequence immediately collapses. +%% +%% Second, a demonstration of the falsehood of ku^{hC_2} = ko -- ku^{hC_2} has an extra generator as a ring, which is in degree -4. +%% In particular, it's not even connective. +%% + +\documentclass{article} +\usepackage[landscape,margin=2cm]{geometry} +\usepackage{spectralsequences} +\begin{document} +\sseqset{ + Z2class/.sseq style={circle,inner sep=0.3ex,fill=black}, + Zclass/.sseq style={fill=none,draw,inner sep=0.6ex}, + 2Zclass/.sseq style={fill=none,rectangle,draw,inner sep=0.6ex,outer sep=0.5ex} +} +\begin{sseqdata}[ + name=KRHFPSS, + x range={-12}{14}, + y range={0}{10}, + y axis style=center, + y axis gap=0.425cm, + tick step=4, + classes=Z2class, + differentials=->, + degree={-1}{#1-1}, + scale=0.85, + right clip padding=0.1cm, + top clip padding=0.05cm, + x axis extend start=0cm, + x axis extend end=0.33cm, + y axis extend end=0.3cm, +] + +\draw[background,xshift=-0.5cm,yshift=-0.51cm,step=1cm,gray,very thin] (\xmin+0.01,\ymin+0.01) grid (\xmax+0.9,\ymax+0.9); + +\pgfmathsetmacro\xitstart{int(int(\xmin/8)*8-16)} +\pgfmathsetmacro\xitgap{int(\xitstart+4)} +\pgfmathsetmacro\xitend{int(\xmax+2)} +\pgfmathsetmacro\xmaxpp{int(\xmax+2)} + +\foreach \x in {\xitstart,\xitgap,...,\xitend} { + \class[Zclass](\x,0) + \foreach \z in {0,...,\xmaxpp} { + \class(\x+\z+1,\z+1) + \structline(\x+\z,\z)(\x+\z+1,\z+1) + } +} + +\pgfmathsetmacro\xitstart{int(\xitgap)} +\pgfmathsetmacro\xitgap{int(\xitstart+8)} + +\foreach \x in {\xitstart,\xitgap,...,\xitend} { + \foreach\z in {0,...,\xmax}{ + \d4(\x+\z,\z) + } + \replaceclass[2Zclass](\x,0) +} +\end{sseqdata} +\printpage[name=KRHFPSS,page=0] +\newpage +\printpage[name=KRHFPSS,page=5] + + +\newpage +\begin{sseqpage}[name=KRHFPSS,page=0,keep changes] +\pgfmathsetmacro\antidiag{min(-\xmin,\ymax+0.8)} +\clip[background,xshift=0.28cm,yshift=-0.4cm](-\antidiag,\antidiag)--(-1,1)--(-0.4,0)--(\xmax+2,0)--(\xmax+2,\antidiag)--cycle; +\foreach \z in {2,6}{ + \doptions[draw=none]4(-\z-1,\z-1) + \structlineoptions[draw=none](-\z-1,\z-1)(-\z,\z) + \structlineoptions[draw=none](-\z-3,\z+1)(-\z-2,\z+2) + \replaceclass(-\z-2,\z+2) +} +\structlineoptions[draw=none](-3,1)(-2,2) +\end{sseqpage} +\newpage +\printpage[name=KRHFPSS,page=5] +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.pdf Binary files differnew file mode 100644 index 00000000000..d0da6d62c7e --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.tex new file mode 100644 index 00000000000..94cf1fb643d --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_KZ3.tex @@ -0,0 +1,139 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_KZ3.tex +%% +%% This was one of the first spectral sequences I ever worked out (probably after the one for loops S^n), in the summer of 2013 with Kevin Donoghue. +%% + +\documentclass{article} +\usepackage[landscape,margin=0.5cm,top=2cm]{geometry} +\usepackage[]{sseqpages} +\usepackage{amssymb} +\def\Z{\mathbb{Z}} +% Last time test: 1.1 sec +\begin{document} +\def\column#1[#2]{\foreach \y in {0,...,6} {\class[#2](#1,2*\y)}} +\sseqset{classes={draw=none}} +\begin{sseqdata}[ + name={K(Z,3)}, + x range={0}{12}, + y range={0}{10}, + cohomological Serre grading, + differentials={->}, + labels=below, + xscale=1.8, + y axis gap=0.7cm, + math nodes, + x axis extend end=0.8cm, + this page cycles=red, + title=\textup{Serre SS Page \page{}}, + x label = {$H^*(K(\Z,3))$}, + y label = {$H^*(K(\Z,2))$} +] +%\tracingall +\column0["\Z\{\ifnum\y>0\relax x\ifnum\y>1\relax ^{\y}\fi\else1\fi\}"] +%\error +\column3["\Z\{a\ifnum\y>0x\ifnum\y>1 ^{\y}\fi\fi\}"] + + +\foreach\y in {1,...,6} {\d["\cdot \y"']3(0,2*\y)} +\replaceclass["\Z/3"](3,4) +\replaceclass["\Z/5"](3,8) + + +\column6["\Z/2"] +\d3(3,2) +\d3(3,6) +\d3(3,10) +\replaceclass["\Z/2"](3,6) +\replaceclass["\Z/3"](3,10) +\column8["\Z/3"] +\d5(3,4) +\d5(3,10) +\column9["\Z/2"] +\d3(6,2) +\d3(6,6) +\d3(6,10) +\column10["\Z/2"] +\d7(3,6) +\column11["\Z/3"] +\d3(8,2) +\d3(8,4) +\d3(8,8) +\d3(8,10) +\column12["\Z/2\oplus\Z/5"] +\column13["\Z/2"] +\column15["\Z/2\oplus\Z/2\oplus\Z/5"] +\d3(9,2) +\d3(9,6) +\d3(9,10) +\d3(10,2) +\d3(10,6) +\d3(10,10) +\d3(10,12) +\d3(12,2) +\d3(12,4) +\d3(12,6) +\d3(12,8) +\d3(12,10) +\d3(12,4) +\replaceclass["\Z/5"](12,0) +\replaceclass["\Z/5"](12,4) +\replaceclass["\Z/5"](12,8) +\d9(3,8) + + +\replaceclass["\Z/5"](12,10) +\replaceclass["\Z/2"](15,0) +\replaceclass["\Z/2\oplus\Z/2"](15,4) + +\d5(10,4) + +\class["\Z/3"](16,0) +\class["\Z/3"](16,6) +\d5(11,4) +\d5(11,10) + +\class["\Z/2"] (17,0) + +\class["\Z/2"](17,8) + +\d5(12,12) + +\class["\Z/2"](19,0) +\d9(10,8) + +\class["\Z/5"](23,0) +\d11(12,10) + +\replaceclass["\Z/6"](16,0) +\d13(3,12) + +%\replaceclass["\Z/6"](21,0) +%\d13(8,12) +\class["\Z/3"](24,0) +\d13(11,12) +\end{sseqdata} + + +\printpage[name={K(Z,3)}, page=0,no differentials] +\newpage +\printpage[name={K(Z,3)}, page=0] +\newpage +\printpage[name={K(Z,3)}, page=3] +\newpage +\printpage[name={K(Z,3)}, page=5] +\newpage +\printpage[name={K(Z,3)}, page=7] +\newpage +\printpage[name={K(Z,3)}, page=9] +\newpage +\printpage[name={K(Z,3)}, page=11] +\newpage +\printpage[name={K(Z,3)}, page=12] +\end{document} diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.pdf Binary files differnew file mode 100644 index 00000000000..00050e20386 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.tex new file mode 100644 index 00000000000..b3d801acf6b --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_anss3.tex @@ -0,0 +1,88 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_anss3.tex +%% +%% Draws the Adams Novikov spectral sequence at the prime 3 through the 45 stem. +%% In this range, all we see is the Toda differential d_{2p-1}(\beta_{p/p}) = \alpha\beta^p +%% Thanks to Eric Peterson for contributing this diagram. +%% + +\documentclass{article} +\usepackage{spectralsequences} +\usepackage[landscape]{geometry} +\begin{document} +% tower definitions +\NewSseqCommand\alphaclass{d()}{ + \IfNoValueTF{#1}{}{\pushstack(#1)} + \class(\lastx+3,\lasty+1) + \structline(\lastclass)(\lastclass1) +} + +\NewSseqCommand\betaclass{d()}{ + \IfNoValueTF{#1}{}{\pushstack(#1)} + \class(\lastx+7,\lasty+1) + \structline(\lastclass)(\lastclass1) +} + +\begin{sseqpage}[ + Adams grading, + classes = { tooltip = {(\xcoord,\ycoord)} }, + class labels = above left, + label distance=3pt, + differentials={-{>[width=4]}, target anchor=-60}, + y range={0}{10}, + x range={0}{45}, + x tick step=5, + xscale=0.375 +] +\class[rectangle,fill,inner sep=3pt](0,0) + +\class["\alpha_1"](3,1) \structline(0,0)(3,1) +\class["\alpha_2"](7,1) +\class[circlen=2,"\alpha_{3/2}"](11,1) +\class["\alpha_4"](15,1) +\class["\alpha_5"](19,1) +\class[circlen=2,"\alpha_{6/2}"](23,1) +\class["\alpha_7"](27,1) +\class["\alpha_8"](31,1) +\class[circlen=3,"\alpha_{9/3}"](35,1) +\class["\alpha_{10}"](39,1) +\class["\alpha_{11}"](43,1) + +\class["\beta_1"](10,2) \structline(3,1)(10,2) +\class["\beta_2"](26,2) +\class["\beta_{3/3}" {xshift = -2pt, yshift=-2pt}](34,2) +\class["\beta_{3/2}"](38,2) +\class["\beta_3"](42,2) + +% tower off of beta_1 +\alphaclass(10,2)\betaclass +\alphaclass\betaclass +\alphaclass\betaclass +\alphaclass\betaclass + +% tower off of beta_2 +\alphaclass(26,2)\betaclass +\alphaclass\betaclass +\alphaclass + + +% tower off of beta_3/3 +\alphaclass(34,2)\betaclass +\alphaclass\betaclass + +% tower off of beta_3 +\class[fill,circlen=2](45,3) \structline(42,2,-1)(45,3,-1) +\betaclass + +% d5s +\d5(34,2) +\d5(44,4) +\end{sseqpage} + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.pdf Binary files differnew file mode 100644 index 00000000000..d5ab3fb620a --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.tex new file mode 100644 index 00000000000..fcfca3ae84c --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_ass.tex @@ -0,0 +1,359 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_ass.tex +%% +%% Draws the Adams Spectral Sequence at the prime 2 through the 45 stem. +%% See pages 146 - 147 of Green book +%% https://mathoverflow.net/questions/102316/differentials-in-the-adams-spectral-sequence-for-spheres-at-the-prime-p-2 +%% https://en.wikipedia.org/wiki/Homotopy_groups_of_spheres#Table_of_stable_homotopy_groups +%% + + +\documentclass{article} +\usepackage[landscape,paperheight=14in,margin=0.1in]{geometry} +\usepackage{spectralsequences} + + +\begin{document} +\NewSseqGroup\tower {m} { + \class(0,0) + \foreach \y in {2,...,#1} { + \class(0, \y-1) + \structline(0, \y-2, -1)(0, \y-1, -1) + } +} + +\def\etaclass(#1,#2){ + \class(#1+1,#2+1) + \structline(#1,#2, -1)(#1+1,#2+1, -1) +} +\def\etasqclass(#1,#2){ + \class(#1+1,#2+1) + \class(#1+2,#2+2) + \structline(#1,#2, -1)(#1+1,#2+1, -1) + \structline(#1+1,#2+1, -1)(#1+2,#2+2, -1) +} +\def\etacubclass(#1,#2){ + \class(#1+1,#2+1) + \class(#1+2,#2+2) + \class(#1+3,#2+3) + \structline(#1,#2, -1)(#1+1,#2+1, -1) + \structline(#1+1,#2+1, -1)(#1+2,#2+2, -1) + \structline(#1+2,#2+2, -1)(#1+3,#2+3, -1) +} +\def\divtwoclass[#1](#2,#3){ + \class[#1](#2,#3-1) + \structline(#2,#3-1,-1)(#2,#3 ,-1) +} +\def\divfourclass[#1](#2,#3){ + \class(#2,#3-1) + \structline(#2,#3-1,-1)(#2,#3 ,-1) + \class[#1](#2,#3-2) + \structline(#2,#3-2,-1)(#2,#3-1,-1) +} +\def\diveightclass[#1](#2,#3){ + \class(#2,#3-1) + \structline(#2,#3-1,-1)(#2,#3 ,-1) + \class(#2,#3-2) + \structline(#2,#3-2,-1)(#2,#3-1,-1) + \class[#1](#2,#3-3) + \structline(#2,#3-3,-1)(#2,#3-2,-1) + +} +\def\nuclass(#1,#2){ + \class(#1+3,#2+1) + \structline(#1,#2,-1)(#1+3,#2+1,-1) +} +\def\nustruct(#1,#2){ + \structline(#1,#2,-1)(#1+3,#2+1,-1) +} + +\begin{sseqdata}[ + name = S0ASS, + Adams grading, + classes=fill, + class labels={above left=0.2em}, + x range={0}{45}, + y range={0}{23}, + xscale=0.7, + yscale=0.8, + differentials = red, + right clip padding = 3em, + classes = { tooltip = { (\xcoord,\ycoord) } }, + grid = go +] +\tower(0,0){25} + +% multiples of eta +\etacubclass(0,0) +\classoptions["h_1"](1,1) + +% divisibilities of nu +\divfourclass["h_2" below](3,3) + +\nustruct(0,0) + +\nuclass(3,1) + + + +\tower(7,1){4} +%\classoptions["h_3" left](7,1) +\etasqclass(7,1) +\structline(6,2)(9,3) + +\class["c_0" above](8,3) +\etaclass(8,3) + + + +\class["Ph_1"](9,5) +\etasqclass(9,5) +\divfourclass["Ph_2" below](11,7) + +\tower(14,2){2} +\classoptions["h_3^2" left](14,2) +\tower(14,4){3} +\classoptions["d_0" left](14,4) + +\tower(15,1){8} +\classoptions["h_4" left](15,1) +\d2(15,1) % d2(h_4) = h_0h_3^2 +\d3(15,2)\d3(15,3) % d2(h_0h_4) = h_0d_0 + +\etacubclass(15,1) +\divfourclass[](18,4) +\nustruct(15,1)\nustruct(15,2)\nustruct(15,3) + + +\nuclass(18,2) + +\etacubclass(14,4) +\diveightclass["e_0" left](17,7) +\nustruct(14,6)\nustruct(14,5)\nustruct(14,4) + +\nuclass(17,5) +\divfourclass["g" {below = 0.3em}](20,6) +\etaclass(17,4) +\divtwoclass["f_0" {below right=0em}](18,5) +\etaclass(20,4) +\nustruct(18,4) + +\classoptions["h_3^3" below](21,3) + +\d2(17,4)\d2(18,5)\d2(18,4,-1) % d2(e_0) = h1^2 d0, d2(f_0) = h0^2 e0 +\nustruct(17,4)\nuclass(20,5) +\divtwoclass[](23,6)\nustruct(20,4) +\nuclass(23,5) + +\tower(23,7){6} +\classoptions["i" left](23,7) + +\class["Pc_0" {xshift=3pt}](16,7)\etaclass(16,7) +\class["P^2c_0" {xshift=5pt,yshift=2pt}](24,11)\etaclass(24,11) + +\class["c_1" {above=0em}](19,3) +\nuclass(19,3) + +\class["h_4c_0" below](23,4) +\etaclass(23,4) + + +\class["P^2h_1"](17,9)\etasqclass(17,9) +\divfourclass["P^2h_2" {below=0em}](19,11) +\nuclass(19,9) +\divfourclass["Pd_0" left](22,10) +\etacubclass(22,8) +\diveightclass["Pe_0" below](25,11) +\etaclass(25,8)\divfourclass["j" below](26,9) +\d2(23,7)\d2(23,8) % d2(i)=h_0Pd_0 +\d2(25,8) % d2(Pe_0) = h_1^2 Pd +\d2(26,9)\d2(26,8)\d2(26,7) % d2(j) = h_0 Pe_0 + +\nustruct(22,10)\nustruct(22,9)\nustruct(22,8) + + +\class["P^3h_1"](25,13)\etasqclass(25,13) +\divfourclass["P^3h_2" {below=0em}](27,15) +\nuclass(27,13) +\divfourclass["P^2d_0" {left=0.2em}](30,14) +\etacubclass(30,12) +\diveightclass["P^2e_0" {below=0em}](33,15) +\d2(33,12) % d2(P^2e_0) = h_1^2 P^2d_0 +\nustruct(30,14)\nustruct(30,13)\nustruct(30,12) +\etaclass(33,12) +\divfourclass["Pj" {right}](34,13) +\d2(34,11)\d2(34,12)\d2(34,13) % d2(Pj) = h0 P^2e_0 + + + +\class(28,10)\divfourclass["{Pg=d_0^2}" {below left=-0.5em}](28,10) +\etaclass(28,8)\divfourclass["k" below](29,9) +\d2(29,7)\d2(29,8) % d2(k) = h_0 Pg = h_0 d_0^2 +\class["r" below](30,6) \d3(30,6) % d3(r) = h0^2 k +\tower(30,7){5} +\classoptions["s" below](30,7) + +\tower(30,2){4} +\classoptions["h_4^2" below](30,2) +\etaclass(30,2) + +\tower(31,1){16}\classoptions["h_5" below](31,1) +\d2(31,1)\d2(31,2)\d2(31,3,-1) % d2(h_5) = h_0 h_4^2 +\d3(31,4)\d3(31,5)\d3(31,6)\d3(31,7) \d3(31,8,1) % \d3(h_0^3 h_5) = s +\replaceclass[offset={(0,0)}](31,8) % d_0e_0 + h_0^7h_5 +\structline(31,8)(31,9) +\d4(31,8)\d4(31,9)\d4(31,10) % d4(d_0e_0 + h_0^7h_5) = P^2d_0, d4(h_0^8 h_5) = h_0 P^2d_0 +\etacubclass(31,1) +\divfourclass[](34,4) +\nustruct(31,3)\nustruct(31,2)\nustruct(31,1) +\nuclass(34,2) + +\class["n" above](31,5)\nuclass(31,5) + +\class(31,10) +\divfourclass["d_0e_0" {below right=0em,xshift=-5pt}](31,10) +\etaclass(31,8) +\divfourclass["l" {right=0em}](32,9) +\d3(31,8,-1) % d3(d_0e_0) = h_0^4 s = d3(h_0^7 h_5), see replaceclass above + +\d2(32,7,,-1)\d2(32,8,,-1) % d2(l) = h_0 d_0 e_0 +\d4(32,9,-1) % d4(h_0^2 l) = h_1 P^2d_0 + +\class["q"](32,6)\etaclass(32,6) + +\class["d_1"](32,4)\etaclass(32,4) +\nuclass(32,4)\nuclass(35,5) +\divtwoclass["p" above right](33,5) + +\class["P^3c_0"{xshift=4pt,yshift=2pt}](32,15)\etaclass(32,15) + +\class["P^4h_1"](33,17)\etasqclass(33,17) +\divfourclass["P^4h_2" right](35,19) + +\class(34,10) +\divfourclass["d_0g" left](34,10) +\etaclass(34,8) +\divfourclass["m" right](35,9) +\d2(35,7)\d2(35,8) % d2(m) = h_0 d_0 g + + +\class["t"](36,6)\etaclass(36,6) +\nustruct(34,6) + +\class(36,14) +\divfourclass["P^2g" left](36,14) +\etaclass(36,12) +\divfourclass["Pk" {right=0em}](37,13) +\d2(37,11)\d2(37,12) % d_2(P^1k) = h_0 P^2g + + +\tower(37,5){6}\classoptions["x"](37,5) + +\class["e_0g"](37,8)\etaclass(37,8) +\diveightclass["y" right](38,9) +\d4(37,8,-1) \d4(38,9)% d4(e_0g) = P^2g +\d2(38,6,-1)\d2(38,7,-1)\d2(38,8,-1) % d2(y) = h_0^3x + +\class(38,5) +\diveightclass["h_3h_5" below](38,5) +\etasqclass(38,2) + +\class["e_1" {below=0em,xshift=2pt}](38,4)\etasqclass(38,4) +\divfourclass["f_1" right](40,6) +\d3(38,4) % d_3(e_1) = h_2^2 n = h_1 t, see Bruner "A New Differential in the ASS" + +\tower(39,15){6}\classoptions["P^2i" {right=0em}](39,15) + +\class(38,18)\divfourclass["P^3d_0" {below left=0em}](38,18) +\etacubclass(38,16)\diveightclass["P^3e_0" {below=0em}](41,19) +\nustruct(38,18)\nustruct(38,17)\nustruct(38,16) +\etaclass(41,16)\divfourclass["P^2j" {below=0em}](42,17) +\d2(39,15)\d2(39,16) % d2(P^2i) = h_0 P^3d_0 +\d2(41,16,,1)\d2(42,17,,1) % d2(P^3e_0) = h_1^2 P^3d_0 +\d2(42,15)\d2(42,16) % d2(P^2j) = h_0 P^3e_0 + + + +\class["c_0 h_5" {below=-0.3em}](39,4)\etaclass(39,4) + +\d4(38,2,1,-1) \d4(38,3,1,-1) % d4(h_3h_5) = h_0x + + +\class(39,14) +\divfourclass["Pd_0e_0" {below=-0.2em}](39,14) +\etaclass(39,12) +\divfourclass["Pl" {below=0em}](40,13) +\d2(40,11)\d2(40,12) % d2(Pl) = h_0 P^2g +\d4(39,12)\d4(40,13,,-1) % d4(Pd_0e_0) = P^3d_0 + + + +\class["c_1g"](39,7) +\class["g^2"](40,8) +\class["u"](39,9)\etasqclass(39,9) +\divtwoclass["z"](41,11) +\class(41,5)\divfourclass["c_2"](41,5) +\class["v"](42,9) +\d2(42,9) % d2(v) = h_1^2 u + +\class["d_0^3"](42,12) + +\class["Ph_1h_5" {right=0em}](40,6)\etasqclass(40,6) +\divfourclass["Ph_2h_5" {right=0em}](42,8) + + +\class["P^4c_0"](40,18)\etaclass(40,18) + + +\class["P^5h_1"](41,20)\etasqclass(41,20) +\divfourclass["P^5h_2" right](43,22) + +\class(44,5)\divfourclass["g_2" below](44,5) +\etaclass(44,3) + +\class(44,18)\divfourclass["P^3g" left](44,18) +\etaclass(44,16)\divfourclass["P^2k" below](45,17) +\class["P^2r"](46,14) +\d2(45,15)\d2(45,16) % d2(P^2k) = h_0 P^3g +\d3(46,14)% d3(P^2r) = h0^2 P^2k +\class(45,4)\divtwoclass["h_4^3" below](45,4) + +\class(45,6)\divfourclass["h_5d_0" right](45,6) +\etaclass(45,4) + +\class["w"](45,9) + +\class["Pc_0g" left](45,12) +\d4(45,12) % d4(Pc_0g) = P^3g +\end{sseqdata} + +\printpage[name=S0ASS,page=0] + +\printpage[name=S0ASS,page=2] + +\printpage[name=S0ASS,page=3] + +\printpage[name=S0ASS,page=4] + +\begin{sseqpage}[name=S0ASS,page=5] +\structline[dashed,bend right=20](15,4)(16,7) +\structline[dashed](21,5)(22,8) +\structline[dashed,bend right=20](20,6)(23,9,-1) +\structline[dashed,bend right=20](23,6)(23,9,-1) +%\structline[dashed,bend right=20](32,6)(33,9) +%\structline[dashed,bend right=20](32,6)(33,9) +\classoptions["h_0^2i" left](23,9) +\classoptions["h_0^{10}h_5" left](31,11) +\classoptions["h_1h_5" below](32,2) +\classoptions["h_2h_5" below](34,2) +%\classoptions["h_0^2h_3h_5" {left=-0.1em}](38,4,1) +\classoptions["h_1h_3h_5" {below=-.4em}](39,3,1) +\classoptions["P^4h_3" {below=0em}](39,17) +\end{sseqpage} +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.pdf Binary files differnew file mode 100644 index 00000000000..a2189c047b4 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.tex new file mode 100644 index 00000000000..001bdff30ad --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_duggarKRAHSS.tex @@ -0,0 +1,79 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_duggarKRAHSS.tex +%% +%% Draws the Atiyah Hirzebruch spectral sequence for KR. +%% To be honest, I can't really remember what this is, but based on the title, I copied it out of Duggar's paper computing KR. +%% + + + +\documentclass{article} +\usepackage[landscape]{geometry} +\usepackage{spectralsequences} +\begin{document} +\sseqset{Zclass/.sseq style={fill=none,draw,inner sep=0.6ex},2Zclass/.style={fill=none,rectangle,draw,inner sep=0.6ex}} +\begin{sseqdata}[ + name=KRAHSS, + Adams grading, + x range={-18}{17}, + y range={-10}{10}, + classes=fill, + no orphan edges, + run off differentials = {->}, + scale=0.5, + axes style=center, + tick step=4, + x tick gap=0.2cm, + y tick gap=0.4cm, + x axis gap=0.25cm, + y axis gap=0.25cm, + x axis extend start=0cm, + y axis extend start=0cm, + x axis extend end=0.25cm, + y axis extend end=0.25cm +] + +\draw[background,xshift=-0.5cm,yshift=-0.5cm,step=1cm,gray,very thin] (\xmin+0.1,\ymin+0.1) grid (\xmax+0.7,\ymax+0.7); +\pgfmathparse{\xmax+2} +\foreach \x in {0,4,...,\pgfmathresult} { + \class[Zclass](\x,0) + \foreach \z in {0,...,\pgfmathresult} { + \class(\x+\z+1,\z+1) + \structline(\x+\z,\z)(\x+\z+1,\z+1) + } +} + +\foreach \x in {4,12}{ + \foreach\z in {0,...,\xmax}{ + \d3(\x+\z,\z) + } + \replaceclass[2Zclass](\x,0) +} + +\foreach\x in {-4,-8,...,-\pgfmathresult}{ + \class[Zclass](\x,0) + \class(\x-2,0) + \foreach \z in {-1,...,-\pgfmathresult}{ + \class(\x+\z-2,\z) + \structline(\x+\z-1,\z+1)(\x+\z-2,\z) + } +} + +\foreach \x in {-6,-14}{ + \foreach\z in {-3,...,-\xmax}{ + \d3(\x+\z,\z) + } +} + +\end{sseqdata} +\printpage[name=KRAHSS,page=0] +\newpage +\printpage[name=KRAHSS,page=5] + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.pdf Binary files differnew file mode 100644 index 00000000000..f0fcae52c21 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.tex new file mode 100644 index 00000000000..a2a5245f43d --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_endofVFoS.tex @@ -0,0 +1,139 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_endofVFoS.tex +%% +%% This is the drawing that got me started making the package. To this day, I don't know what it is. I copied it from Matt Ando's handwritten notes on +%% Haynes 1990(?) class on Vector Fields on Spheres. It's on the very last page of the second part of the notes, so it must have been the last day of class. +%% Looking back, I seem to have inferred a bunch of stuff that wasn't actually written down on the page, but I'm not sure how so there's a chance some of it is wrong. +%% + +\documentclass{article} +\usepackage[landscape,margin=0cm,top=2cm]{geometry} +\usepackage{amssymb} +\usepackage{spectralsequences} + +\NewSseqCommand\row { m } {\foreach \x in {1,...,35}{\class(\x,#1)}} +\NewSseqCommand\twoptrow { m } {\foreach \x in {1,...,35}{\class(\x,#1)\class(\x,#1)}} +\begin{document} +\begin{sseqdata}[ + name=mysseq, + x range={1}{25}, + y range={0}{19}, + homological Serre grading, + classes=fill, + permanent classes={circle,red}, + transient cycles={black}, + differentials={blue}, + grid = go, + scale=0.9 +] + +\foreach \x in {1,3,5,...,35} {\class(\x,0)} + +\row{1} +\row{2} +\row{3} + +\foreach \y in {7,15,23}{ + \row{\y} + \row{\y+1} + \twoptrow{\y+2} + \row{\y+3} + \row{\y+4} +} + +\foreach \x in {9,13,...,25}{ + \d2(\x,0) +% + \foreach \y in {7,15}{ + \d2 (\x,\y) + \d2 (\x,\y+1,,2) + \d2 (\x,\y+2,1,) + } +} + + + +\foreach \x in {4,8,...,24}{ + \d2 (\x,1) + \d2 (\x,2) + \foreach \y in {7,15}{ + \d2 (\x,\y+1,,2) + \d2 (\x,\y+2,1,) + \d2 (\x,\y+3) + } +} + + +\foreach \x in {4,8,..., 24,28} + \foreach \y in {7,15}{ + \d3 (\x+2,\y,,1) + \d3 (\x,\y+2,2,) +} + +\foreach \x in {11,19,27}{ + \d4(\x,0) +} + +\foreach \x in {12,20,28} + \foreach \y in {7,15}{ + \d5(\x,\y) +} + + + +\foreach \x in {10,18,26,34}{ + \d7(\x,1) + \d7(\x-1,2) + \d7(\x-2,3,,2) + + \foreach \y in {9,17}{ + \d7(\x,\y,1) + \d7(\x-1,\y+1) + \d7(\x-2,\y+2,,2) + } +} + +\d9(15,0) +\d9(14,1,,2) +\d10(13,2) + +\d8(23,0) +\d8(22,1) +\foreach \x in {23,31} { + \d8(\x-2,2,,2) + \d9(\x-3,3) +} +\foreach \x in {16,24,32} { + \d9(\x,7) + \d8(\x-2,9,1,) + \d8(\x-3,10,,2) + \d9(\x-4,11) +} +\end{sseqdata} + + +\printpage[name=mysseq, page=0] +\newpage +\printpage[name=mysseq, page=2] +\newpage +\printpage[name=mysseq, page=3] + +\newpage +\printpage[name=mysseq, page=4] +\newpage +\printpage[name=mysseq, page=5] +\newpage +\printpage[name=mysseq, page=7] +\newpage +\printpage[name=mysseq, page=8] +\newpage +\printpage[name=mysseq, page=9] +\newpage +\printpage[name=mysseq, page=10] +\end{document} diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.pdf Binary files differnew file mode 100644 index 00000000000..ddf0032ed0d --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.tex new file mode 100644 index 00000000000..a200354d1f1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_hatcher.tex @@ -0,0 +1,126 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_hatcher.tex +%% +%% This comes from Hatcher's spectral sequences book. I think it's a good demonstration of the flexibility of sseqpages. +%% Thanks to Antonio Ruiz for suggesting it. +%% + +\documentclass{article} +\usepackage[landscape,margin=1cm,top=2cm]{geometry} +\usepackage{spectralsequences} +\usepackage{amssymb} +\def\Z{\mathbb{Z}} + +\begin{document} +\sseqset{ + 0/.sseq style={"0",draw=none}, + homological Serre grading, + classes={draw=none,inner sep=0.2em}, + tick gap=0.7em, +} +\begin{sseqdata}[ + name=hatcherex1, + permanent cycles={draw,minimum width={width("$Z_2$")+0.85em}}, + yscale=0.6, + axes gap=1.2em, + axes clip padding=0em +] +\begin{scope}[background,opacity=0.1] +\foreach \n in {1,3,...,9}{ + \fill(-1.1,\n-0.5)--(-1.1,\n+0.5)--(0,\n+0.5)--(\n+0.5,0)--(\n+0.5,-1.6)--(\n-0.5,-1.6)--(\n-0.5,0)--(0,\n-0.5)--cycle; +} +\end{scope} + +\class["\Z"](0,0) +\foreach\x in {1,3,...,9}{ + \class["\Z_2"](\x,0) +} +\foreach \x in {2,4,...,8}{ + \class[0](\x,0) +} +\foreach\y in {1,3,...,9}{ + \pgfmathparse{9-\y} + \let\xmax\pgfmathresult + \foreach\x in {0,...,\xmax}{ + \class["\Z_2"](\x,\y) + } +} + +\foreach \y in {2,4,...,8}{ + \pgfmathparse{9-\y} + \let\xmax\pgfmathresult + \foreach\x in {0,...,\xmax}{ + \class[0](\x,\y) + } +} + +\foreach \x in {3,5,...,9}{ + \d2(\x,0) +} + +\d3(4,1) +\d3(6,1) +\d3(8,1) +\d3(4,3) +\d3(6,3) +\d3(4,5) +\end{sseqdata} +\printpage[name=hatcherex1,page=0] + +\begin{sseqdata}[ + name=hatcherex2, + yscale=0.6, + x axis gap=0.3cm, +] + +\begin{scope}[background,opacity=0.1] +\foreach \n in {1,3,...,9}{ + \fill(-1.1,\n-0.5)--(-1.1,\n+0.7)--(0,\n+0.7)--(\n+0.5,0)--(\n+0.5,-1.6)--(\n-0.5,-1.6)--(\n-0.5,0)--(0,\n-0.5)--cycle; +} +\end{scope} + + +\foreach\x in {0,2,...,8}{ + \class["\Z"](\x,0) +} +\foreach \x in {1,3,...,9}{ + \class[0](\x,0) +} +\foreach\y in {1,3,...,9}{ + \pgfmathparse{9-\y} + \let\xmax\pgfmathresult + \foreach\x in {0,...,\xmax}{ + \pgfmathparse{int(mod(\x,2))} + \ifnum\pgfmathresult=0\relax + \class["\Z_2"](\x,\y) + \else + \class[0](\x,\y) + \fi + } +} + +\d2(2,0) +\foreach \x in {4,6,...,8}{ + \foreach\r in {2,4,...,\x}{ + \d\r(\x,0) + \replaceclass["\Z"](\x,0) + } +} + +\foreach \y in {2,4,...,8}{ + \pgfmathparse{9-\y} + \let\xmax\pgfmathresult + \foreach\x in {0,...,\xmax}{ + \class[0](\x,\y) + } +} + +\end{sseqdata} +\printpage[name=hatcherex2,page=0] +\end{document} diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.pdf Binary files differnew file mode 100644 index 00000000000..d8e47ee1d18 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.tex new file mode 100644 index 00000000000..fd48445ca0c --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_mayss.tex @@ -0,0 +1,129 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_mayss.tex +%% +%% I think this is the May SS for the sphere. May spectral sequences are annoying to draw neatly it turns out -- there's too much stuff in them. +%% It helps a lot if you start at E_2 though, since E_1 is polynomial. They also have the problem with their crappy grading that makes all +%% differentials the same length. I seem to have graded this weirdly, probably because the normal grading looked too bad. +%% + +\documentclass{article} +\usepackage{fullpage} +\usepackage{spectralsequences} + +\begin{document} +\NewSseqGroup\tower {m} { + \class["#1"](0,0) + \foreach\i in {1,...,14}{ + \class(0,\i) + \structline(0,\i-1,-1)(0,\i,-1) + } +} + +\NewSseqGroup\hone {m} { + \foreach\i in {1,...,#1}{ + \class(\i,\i) + \structline(\i-1,\i-1,-1)(\i,\i,-1) + } +} + +\NewSseqCommand\dtower {u(u)} { + \foreach\i in {0,...,10}{ + \d[yshift=\i]#1(#2) + } +} + + +\def\single(#1)#2{\class["#2"](#1)} + +\NewSseqGroup\htwo {m} { + \foreach \n in {0,...,5}{ + \tower(3*\n,\n){\sseqifempty{#1}{}{#1}\sseqpowerempty{h_2}{\n}} + \ifnum\n>0\relax + \structline(3*\n-3,\n-1,-1)(3*\n,\n,-1) + \fi + } +} + +\NewSseqGroup\htwosinglejoin {mm} { + \foreach \n in {0,...,5}{ + \single(3*\n,\n){\sseqifempty{#1}{}{#1}\sseqpowerempty{h_2}{\n}} + \ifnum\n>0\relax + \structline(3*\n-3,\n-1,-1)(3*\n,\n,-1) + \fi + } + \foreach \n in {0,...,#2}{ + \structline(3*\n,\n,-1)(3*\n,\n+1,-1) + } +} + + + +\begin{sseqdata}[name=may, degree={-1}{1-#1},x range={0}{13}, y range={0}{13},class labels=below right,differentials=blue,x axis extend end=23pt,draw] +\tower(7,1){h_3} +\htwo(0,0){} +\classoptions[label position=above left](9,3) +\hone(0,0){3} +\htwo[label position={xshift=3pt,yshift=2pt}](4,4){b_{2,0}} +\dtower2(4,4,-1,-1) % d2(b_{2,0}h_0^n) = h_2h_0^{n+2} +\d2(4,4,-1,1) % d2(b_{2,0})= h_2h0^2 + h1^3 + +%\hone(4,4){3} +\htwo(8,8){b_{2,0}^2} +\hone(8,8){3} +\dtower4(8,8,,1) % d4(b_{2,0}^2) = h3 h0^4 +%\hone(8,8){3} +\hone(7,1){2} + + +\htwosinglejoin(7,4){x_7}{4} +\dtower2(7,4,2,-1) +\hone(7,4){2} +\htwosinglejoin(11,8){x_7b_{2,0}}{4} +\htwosinglejoin(10,4){b_{2,1}}{3} +%\hone(10,4){1} +\d2(10,4,-1,2) % d2(b21)=h2^3+h3h1^2 +\dtower2(10,4,1,1) % d2(b21 h0^n) = h2^3 h0^n + + +\tower(11,5){h_3b_{2,0}} +\tower(12,6){b_{3,0}} +\dtower2(12,6,-1,-1) + +\htwo(12,12){b_{2,0}^3} +\dtower2(12,12,-1,1) % d2(b20^3 h_0^n) = h0^n b20^2 d2(b20) = h0^{n+2} h2 b20^2 +\d2(12,12,-1,2) % d2(b_{2,0}^3)= b20^2 d2(b20) = h_2 h0^2 b20^2 + h1^3 b20^2 +\hone(12,12){3} +\replaceclass(11,11) + +\structline(11,10)(11,11) +\structline(10,10,2)(11,11) + +\replaceclass(3,3) + +\structline(2,2)(3,3) +\structline(3,2)(3,3) + + + + + +\replaceclass(9,3) +\structline(6,2)(9,3) +\structline(8,2)(9,3) + + + +%\dtower2(12,6,2,-1) +\end{sseqdata} +\printpage[name=may] +\newpage +\printpage[name=may, page=4] +\newpage +\printpage[name=may, page=5] +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.pdf Binary files differnew file mode 100644 index 00000000000..0939e810f49 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.tex new file mode 100644 index 00000000000..a16a581d681 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfass.tex @@ -0,0 +1,292 @@ +%% +%% Package: sseqpages.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_tmfass.tex +%% +%% From "The Homotopy Groups of tmf and of its Localizations" http://math.mit.edu/conferences/talbot/2007/tmfproc/Chapter16/TmfHomotopy.pdf +%% This file has really bad performance. +%% + + +% 9.8 sec + +% 1.7 seconds to set up +% 1.8 seconds to draw the classes +% 2.1 seconds to draw the edges +% --> ~5.7 seconds to draw page 0. + +% edge drawing time: +% 1.0s to calculate but discard without off page handling +% 0.6s to deal with off-page edges +% 0.3s to draw + +% 17 seconds to draw all pages =( +% 17 ~~ 1.7s setup + 5 page * 3 s/pp +% +% deleting off page edge handling cuts off 1.4s (1s?) so I haven't found any of the big time holes yet. WHY IS THIS SO SLOW?? + +\documentclass{article} +\usepackage[landscape,margin=0cm,top=2cm]{geometry} +\usepackage{spectralsequences} + +\begin{document} + +\NewSseqGroup\tower {} {% 25 + \class(0,0) + \foreach \y in {1,...,22}{ + \class(0,\y) + \structline(0,\y-1,-1) (0,\y,-1) + } +} + +\NewSseqGroup\towergroup {} {%9 + 25 = 36 + \tower(0,0) + \class(1,1) + \class(3,1) + \class(2,2) + \class(3,2) + \class(3,3) + \class(6,2) + \structline(3,1,-1)(3,2,-1) + \structline(3,2,-1)(3,3,-1) + \structline(0,0,-1)(1,1,-1) + \structline(1,1,-1)(2,2,-1) + \structline(2,2,-1)(3,3,-1) + \structline(0,0,-1)(3,1,-1) + \structline(3,1,-1)(6,2,-1) + \structline(0,1,-1)(3,2,-1) + \structline(0,2,-1)(3,3,-1) +} + + +\NewSseqGroup\towergroupa {} {%25*2+9+21 = 80 + \towergroup(0,0) + \tower(4,-1) +% + \class(6,0) + \class(6,1) + \class(7,-1) + \class(7,0) + \class(7,1) + \class(9,0) + \class(9,1) + \class(9,2) + \class(10,0) + \class(10,1) + \class(12,0) + \class(12,1) + \class(12,2) + \class(13,1) + \structline(6,0,-1)(6,1,-1) + \structline(6,1,-1)(6,2,-1) + \structline(7,-1,-1)(7,0,-1) + \structline(7,0,-1)(7,1,-1) + \structline(9,0,-1)(9,1,-1) + \structline(9,1,-1)(9,2,-1) + \structline(10,0,-1)(10,1,-1) + \structline(12,0,-1)(12,1,-1) + \structline(12,1,-1)(12,2,-1) +% + \structline(4,-1,-1)(7,0,-1) + \structline(4,0,-1)(7,1,-1) + \structline(6,0,-1)(9,1,-1) + \structline(6,1,-1)(9,2,-1) + \structline(6,0,-1)(7,1,-1) + \structline(7,-1,-1)(10,0,-1) + \structline(7,0,-1)(10,1,-1) + \structline(9,0,-1)(12,1,-1) + \structline(9,1,-1)(12,2,-1) + \structline(9,0,-1)(10,1,-1) + \structline(10,0,-1)(13,1,-1) + \structline(12,0,-1)(13,1,-1) +% + \d2(4,-1,-1,-1) + \d2(4,0,-1,-1) + \d2(4,1,-1,-1) + \d2(7,-1,-1,-1) + \d2(7,0,-1,-1) + \d2(10,0,-1,-1) +} + +\NewSseqGroup\towergroupb {} {%80 + 25 + 15 = 120 + \towergroupa(0,0) + \tower(8,-2) + \class(10,-1) + \class(11,-1) + \class(10,-2) + \class(9,-3) + \class(11,-2) + \structline(8,-2)(11,-1) + \structline(11,-1)(10,-2) + \structline(10,-2)(9,-3) + \structline(11,-2)(11,-1) + + \class(13,-1) + \class(13,0) + \class(14,-2) + \class(15,0) + \class(16,-1)\class(16,-1) + \class(16,0) + \class(16,1) + \class(17,0) + \class(18,0) + \class(18,1) + \class(19,-1) + \structline(10,-1,-1)(10,0,-1) + \structline(13,0,-1)(13,1,-1) + \structline(13,-1,-1)(13,0,-1) + \structline(16,0,-1)(16,1,-1) + \structline(16,-1,-2)(16,0,-1) + \structline(16,-1,-1)(16,0,-1) + + \structline(10,-1,-1)(13,0,-1) + \structline(13,-1,-1)(16,0,-1) + \structline(13,0,-1)(16,1,-1) + \structline(15,0,-1)(18,1,-1) + \structline(15,0,-1)(16,1,-1) + \structline(16,-1,-1)(17,0,-1) + \structline(17,0,-1)(18,1,-1) + \structline(18,1,-1)(18,0,-1) + \d2(10,-1,-1,-1) + \d2(13,-1,-1,-1) + \d2(13,0,-1,-1) + \d3(14,-2,-1,-1) + \d2(19,-1,-1,-1) +} + +\begin{sseqdata}[ + x range={0}{50}, + y range={0}{20}, + x tick step=2, + Adams grading, + classes={fill,inner sep=0.3ex,tooltip={(\xcoord,\ycoord)}}, + differentials={->,blue}, + struct lines=red, %no struct lines, no differentials, + yscale=0.6, xscale=0.5, + x axis extend end=0.2cm, + name=tmfass, + grid=go, + run off differentials=-> +] + +\towergroup(0,0) % 36 + +\class(8,3)\class(9,4) +\structline(8,3)(9,4) +\towergroupa(8,4) % 80 + +\foreach \n in {2,3,4}{ + \towergroupb(8*\n,4*\n) % 120 +} + +\foreach \n in {1,2,3,4}{ + \begin{scope}[xshift=8*\n,yshift=4*\n] + \class(8,3) + \class(9,4) + \structline(8,3,-1)(9,4,-1) + \d3(9,0,-1,-1) + \d3(10,1,-1,-1) + \end{scope} +} + + +\foreach \n in {1,2,3,5,6,7}{ + \class(35+2*\n,7+\n) +} + +%\d2(18,4) +\d3(24,6) + +\class(36,9) +\d2(36,9) +\d4(37,8) +\d4(45,12) + + +\class(44,13) +\d2(44,13) +\class(45,9) +\class(47,10) +\class(49,11) +\d4(49,11,,1) +\d4(49,11,,2) +\replaceclass(48,15,1) +\towergroupb(40,20) +\towergroup(48,8) +\foreach \n in {0,...,5}{ + \class(40+2*\n,8+\n) +} + +\d3(42,9) +\d4(44,10) +\d4(47,16) +\d2(48,8) +\d4(48,9) +\d3(49,9,,2) +\d3(50,13) +\class(50,10) +\d4(50,10,1) +\d4(50,10,2) +\replaceclass[offset={(0,0)}](50,10) +\class(51,12) +\d4(51,12) +\class(52,17) +\d2(52,17) + +\foreach \n in {0,4,8}{ + \d3(32+2*\n,10+\n,1) + \d4(31+2*\n,8+\n) +} +\end{sseqdata} + + +\printpage[name=tmfass,page=0] +%\end{document} + + +\printpage[name=tmfass,page=2] + +\printpage[name=tmfass,page=3] + +\printpage[name=tmfass,page=4] + +\begin{sseqpage}[name=tmfass,page=5,class labels={below=0.2em},tikz primitives=dashed] +\classoptions["\eta" {right=0.1em}](1,1) +\classoptions["\nu" below right](3,1) +\classoptions["\epsilon"](8,3) +\classoptions["c_4+\epsilon" left](8,4) +\classoptions["2c_6"](12,6) +\classoptions["\kappa"](14,4) +\classoptions["c_4^2"](16,8) +\classoptions["\overline\kappa"](20,4) +\classoptions["8\Delta"](24,7) +\classoptions["\eta\Delta"](25,5) +\classoptions["2\nu\Delta"](27,6) +\classoptions["c_4\Delta+q" left](32,7,1) +\classoptions["q"](32,7,2) +\classoptions["\overline\kappa^2"](40,8) +\classoptions["4\Delta^2"](48,10) +\draw(6,2)--(9,4); +\draw(21,5)--(22,8); +\draw[bend left=20] (25,5) to (28,8); +\draw (27,6) -- (28,8); +\draw(32,7,1)--(33,9); +\draw[bend right=10](32,7,2) to (35,10); +\draw(34,8) -- (35,10); +\draw(39,9)--(40,11,2); +\draw(39,9)--(42,12); +\draw(40,8)--(40,11,2); +\draw(40,11,1)--(41,13); +\draw(40,8)--(41,10) -- (42,12); +\draw(45,9)--(46,11); +\draw(48,15,1)--(48,16,1); +\draw[bend right=20] (48,15,1) to (49,17); +\structline[black](50,10,2)(51,11) +\end{sseqpage} + +\end{document} + diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.pdf b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.pdf Binary files differnew file mode 100644 index 00000000000..db413adf758 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.tex b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.tex new file mode 100644 index 00000000000..c4041a6eb5e --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/examples/example_tmfmayss.tex @@ -0,0 +1,242 @@ +%% +%% Package: sseqpages.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: example_tmfmayss.tex +%% +%% I got this from Mike Hill's note: https://pdfs.semanticscholar.org/ddbb/8d584e4e81a71400088117b16cd241238c6c.pdf +%% + + + +\documentclass{article} +\usepackage[landscape,left=1cm]{geometry} +\usepackage{spectralsequences} +\begin{document} +\sseqset{htwostructstyle/.sseq style = {gray,very thin, run off=-}} +%\pgfkeys{/sseqpages/struct line/htwostructstyle/.show code} + + +\NewSseqCommand\twods{ O{} U( r() m m }{ + \def\temp{#1,#2,#3,#4,#5} + \getdtarget\target#2{#3} % Store the target position in \target + \nameclass{source}(#3) % naming the classes gives us a speed boost + \nameclass{target1}(\target,#4) % by preventing sseqpages from reparsing the coordinate + \nameclass{target2}(\target,#5) % it also makes the code easier to read +% + \circleclasses[ differential style, #1, + name path = circ, page = #2--#2 ] + (target1)(target2) % Circle the classes, use differential style +% + \d[invisible]#2(source)(target1) % don't draw anything, but record source and targets as hit. + \d[invisible]#2(source)(target2) +% + \path(target1)--(target2) + coordinate[midway](midpt);% put a coordinate in the center of the two classes + \path[name path = lin] (source) -- (midpt);% save path from start to midpoint +% + % draw line in "differential style" from start to intersection point of circ and lin + \draw[ differential style, #1, page constraint= { \page == #2 }, + name intersections = { of = circ and lin } ] + (source) -- (intersection-1); +} + + +\NewSseqCommand \tower { O{} d() } { + \IfNoValueF{#2}{ + \pushstack(#2) + } + \savestack + \edef\towermax{\the\numexpr9-\lasty0} + \begin{scope}[#1] + \foreach\i in {1,...,\towermax}{ + \class(\lastx,\lasty+1) + \structline(\lastclass1)(\lastclass) + } + \end{scope} + \restorestack +} + +\NewSseqCommand\honetower {O{}} { + \savestack + \begin{scope}[#1] + \edef\towermax{\the\numexpr9-\lasty0} + \foreach\i in {1,...,\towermax}{ + \class(\lastx+1,\lasty+1) + \structline(\lastclass1)(\lastclass) + } + \end{scope} + \restorestack +} + +\NewSseqCommand\htwo { O{} d() } { + \IfNoValueF{#2}{ + \pushstack(#2) + } + \class[#1](\lastx+3,\lasty+1) + \structline[htwostructstyle](\lastclass1)(\lastclass) +} + +\NewSseqCommand \htwotower { O{} d() } { + \IfNoValueF{#2}{ + \pushstack(#2) + } + \edef\towermax{\the\numexpr-\lasty+8} + \begin{scope}[#1] + \gettag\thetag(\lastclass) + \class(\lastx+3,\lasty+1) + \structline[htwostructstyle](\lastclass)(\lastclass1) + \savestack + \foreach\i in {1,...,\towermax}{ + \class(\lastx,\lasty+1) + \structline(\lastclass1)(\lastclass) + \structline[htwostructstyle](\lastx-3,\lasty-1,\thetag)(\lastclass) + } + \restorestack + \end{scope} +} + + +\NewSseqCommand\dtower {u(u)} { + \foreach\i in {0,...,10}{ + \d[yshift=\i]#1(#2) + } +} + +\begin{sseqdata}[name=tmfmayss,y range={0}{8}, x range={0}{25}, classes=fill, class labels={below=3pt},degree={-1}{1},differentials=blue, + class pattern=linear, classes={ tooltip = {(\xcoord,\ycoord)} }, xscale=0.8, + title = {Page \page}, + run off differentials = -> +] +\class[tag= h0^i](0,0) \tower[tag=h0^i] +\honetower \classoptions["h_1"](1,1) + +\htwotower[tag=h0^i h2] +\classoptions["h_2"](3,1) +\htwotower[tag=h0^i h2^2] +\htwotower[tag=h0^i h2^3] +\htwotower[tag=h0^i h2^4] +\htwotower[tag=h0^i h2^5] +\htwotower[tag=h0^i h2^6] +\htwotower[tag=h0^i h2^7] +\htwotower[tag=h0^i h2^8] +\htwo%\htwotower[tag=h0^i h2^9] + + +\class["b_{20}",name=b20,tag=h1^i b20](4,2) +\tagclass{h0^i b20}(4,2) +\honetower[tag=h1^i b20] +\tower[tag=h0^i b20] +\class["x_7",tag=h0^i x7,name=x7](7,2) \honetower +\htwotower[tag=h0^i x7](b20) +\structline(\lastclass)(x7) % h0 x7 = h2 b20 + + +\class["b_{21}", tag=h0^i b21,name=b21](10,2) +\honetower[tag=h1^i b21] +%\structline(\lastclass)(h2^2 b20) % h2 (h0 x7) = h2 (h2 b20) + +\htwotower[tag=h0^i b21](x7) +\structline(b21)(\lastclass) + + + +\htwotower[tag=h0^i h2 b21](b21) +\htwotower[tag=h0^i h2^2 b21] +\htwotower[tag=h0^i h2^3 b21] +\htwotower[tag=h0^i h2^4 b21] +\htwotower[tag=h0^i h2^5 b21] +\htwotower[tag=h0^i h2^6 b21] + +\class["b_{30}",tag=h1^i b30](12,2) +\tagclass{h0^i b30}(12,2) +\tower[tag=h0^i b30]\honetower[tag=h1^i b30] +\htwotower[tag=h0^i h2 b30] +\htwotower[tag=h0^i h2^2 b30] +\htwotower[tag=h0^i h2^3 b30] +\htwotower[tag=h0^i h2^4 b30] +\htwotower[tag=h0^i h2^5 b30] + + + +% + +\class[tag=h0^i x7^2](14,4) +\classoptions["x_7^2",page=0--3](\lastclass) +\classoptions["d",page=4--100](\lastclass) +\tower[tag=h0^i x7^2] \honetower + +\htwotower[tag=h0^i h2 x7^2] +\htwotower[tag=h0^i h2^2 x7^2] +\htwotower[tag=h0^i h2^3 x7^2] +\htwotower[tag=h0^i h2^4 x7^2] +\htwo%\htwotower[tag=h0^i h2^5 x7^2] + + +\class["b_{20}^2",tag=h0^i b_{20}^2](8,4) +\tower[tag=h0^i b_{20}^2] +\honetower +\htwotower[tag=h0^i h2 b_{20}^2] +\htwotower[tag=h0^i h2^2 b_{20}^2] +\htwotower[tag=h0^i h2^3 b_{20}^2] +\htwotower[tag=h0^i h2^4 b_{20}^2] +\htwo%\htwotower[tag=h0^i h2^5, b_{20}^2] + +\class[tag=h0^i b21^2](20,4) +\classoptions["b_{21}^2",page=0--3](\lastclass) +\classoptions["g",page=4--100](\lastclass) +\honetower +\tower[tag=h0^i b21^2] + +\htwotower[tag=h0^i h2 b21^2] +\htwotower[tag=h0^i h2^2 b21^2] + +\class["b_{30}^2",tag=h0^i b30^2](24,4) +\tower[tag=h0^i b30^2] +\honetower +\htwotower +%\htwotower[tag=h0^i h2^3 b21^2] + + + +\twods3(4,2,-1){1}{2} % d3(b20) = h1^3 + h0^2 h2 +\replaceclass[offset={(0,0)}](3,3) +\structline(3,2)(3,3) +\structline(2,2)(3,3) +\structline[htwostructstyle](0,2)(3,3) + +\foreach\y in {3,...,8} {\d3(4,\y,-1,-1)} % d3( h0^i b20 ) = h0^{2+i} h2 +\foreach\n in {3,...,8} {\d3(2+\n,\n,h1^i b20,1)} % d3(h1^i b20) = h1^{3+i} +\foreach \y in {2,...,8} {\d3(7,\y,h0^i x7,h0^i h2^2)} + +\foreach \y in {2,...,8} {\d3(10,\y,h0^i b21,h0^i h2^3)} + +\foreach \y in {3,...,8} {\d3(13,\y, h0^i h2 b21 ,h0^i h2^4)} +\foreach \y in {3,...,7} {\d3(16,\y+1,h0^i h2^2 b21,h0^i h2^5)} +\foreach \y in {3,...,6} {\d3(19,\y+2,h0^i h2^3 b21,h0^i h2^6)} +\foreach \y in {3,...,5} {\d3(22,\y+3,h0^i h2^4 b21,h0^i h2^7)} +\foreach \y in {3,...,4} {\d3(25,\y+4,h0^i h2^5 b21,h0^i h2^8)} + +\foreach \n in {0,...,6} {\d3(12+\n,2+\n,h1^i b30,h1^i b21)} + +\foreach \n in {0,...,4} {\d5(24,4+\n,-1,-1)} + + +\classoptions[page=4--100,"c_0"](8,3) +\classoptions[page=4--100,"a"](12,3) +\classoptions[page=4--100,"b"](15,3) + + + +\end{sseqdata} +\printpage[name=tmfmayss,page=2] +\newpage +\printpage[name=tmfmayss,page=3] +\newpage +\printpage[name=tmfmayss,page=5] +\newpage +\printpage[name=tmfmayss,page=8,title={Page $\infty$}] +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/manual/pgfmanual-en-macros.tex b/Master/texmf-dist/doc/latex/spectralsequences/manual/pgfmanual-en-macros.tex new file mode 100644 index 00000000000..ab7022b1e4a --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/manual/pgfmanual-en-macros.tex @@ -0,0 +1,1762 @@ +% Copyright 2006 by Till Tantau +% +% This file may be distributed and/or modified +% +% 1. under the LaTeX Project Public License and/or +% 2. under the GNU Free Documentation License. +% +% See the file doc/generic/pgf/licenses/LICENSE for more details. + +% $Header: /cvsroot/pgf/pgf/doc/generic/pgf/macros/pgfmanual-en-macros.tex,v 1.81 2014/03/20 10:07:44 tantau Exp $ + + +\providecommand\href[2]{\texttt{#1}} +\providecommand\hypertarget[2]{\texttt{#1}} +\providecommand\hyperlink[2]{\texttt{#1}} + + +\colorlet{examplefill}{yellow!80!black} +\definecolor{graphicbackground}{rgb}{0.96,0.96,0.8} +\definecolor{codebackground}{rgb}{0.9,0.9,1} + +\newenvironment{pgfmanualentry}{\list{}{\leftmargin=2em\itemindent-\leftmargin\def\makelabel##1{\hss##1}}}{\endlist} +\newcommand\pgfmanualentryheadline[1]{\itemsep=0pt\parskip=0pt{\raggedright\item\strut{#1}\par}\topsep=0pt} +\newcommand\pgfmanualbody{\parskip3pt} + +\let\origtexttt=\texttt +\def\texttt#1{{\def\textunderscore{\char`\_}\def\textbraceleft{\char`\{}\def\textbraceright{\char`\}}\origtexttt{#1}}} +\def\exclamationmarktext{!} +\def\atmarktext{@} + +{ + \catcode`\|=12 + \gdef\pgfmanualnormalbar{|} + \catcode`\|=13 + \AtBeginDocument{\gdef|{\ifmmode\pgfmanualnormalbar\else\expandafter\verb\expandafter|\fi}} +} + + + +\newenvironment{pgflayout}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \texttt{\string\pgfpagesuselayout\char`\{\declare{#1}\char`\}}\oarg{options}% + } + \index{#1@\protect\texttt{#1} layout}% + \index{Page layouts!#1@\protect\texttt{#1}}% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + +\newenvironment{command}[1]{ + \begin{pgfmanualentry} + \extractcommand#1\@@ + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\makeatletter + +\def\includeluadocumentationof#1{ + \directlua{require 'pgf.manual.DocumentParser'} + \directlua{pgf.manual.DocumentParser.include '#1'} +} + +\newenvironment{luageneric}[4]{ + \pgfmanualentry + \pgfmanualentryheadline{#4 \texttt{#1\declare{#2}}#3} + \index{#2@\protect\texttt{#2} (Lua)}% + \def\temp{#1} + \ifx\temp\pgfutil@empty\else + \index{#1@\protect\texttt{#1}!#2@\protect\texttt{#2} (Lua)}% + \fi + \pgfmanualbody +}{\endpgfmanualentry} + +\newenvironment{luatable}[3]{ + \medskip + \luageneric{#1}{#2}{ (declared in \texttt{#3})}{\textbf{Lua table}} +}{\endluageneric} + +\newenvironment{luafield}[1]{ + \pgfmanualentry + \pgfmanualentryheadline{Field \texttt{\declare{#1}}} + \pgfmanualbody +}{\endpgfmanualentry} + + +\newenvironment{lualibrary}[1]{ + \pgfmanualentry + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Graph Drawing Library} \texttt{\declare{#1}}% + } + \index{#1@\protect\texttt{#1} graph drawing library}% + \index{Libraries!#1@\protect\texttt{#1}}% + \index{Graph drawing libraries!#1@\protect\texttt{#1}}% + \vskip.25em + {\ttfamily\char`\\usegdlibrary\char`\{\declare{#1}\char`\}\space\space \char`\%\space\space \LaTeX\space and plain \TeX}\\ + {\ttfamily\char`\\usegdlibrary[\declare{#1}]\space \char`\%\space\space Con\TeX t}\smallskip\par + \pgfmanualbody +}{\endpgfmanualentry} + +\newenvironment{luadeclare}[4]{ + \pgfmanualentry + \def\manual@temp@default{#3}% + \def\manual@temp@initial{#4}% + \def\manual@temp@{#3#4}% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + {\ttfamily/graph + drawing/\declare{#1}\opt{=}}\opt{#2}\hfill% + \ifx\manual@temp@\pgfutil@empty\else% + (\ifx\manual@temp@default\pgfutil@empty\else% + default {\ttfamily #3}\ifx\manual@temp@initial\pgfutil@empty\else, \fi% + \fi% + \ifx\manual@temp@initial\pgfutil@empty\else% + initially {\ttfamily #4}% + \fi% + )\fi% + }% + \index{#1@\protect\texttt{#1} key}% + \pgfmanualbody + \gdef\myname{#1}% +% \keyalias{tikz} +% \keyalias{tikz/graphs} +}{\endpgfmanualentry} + +\newenvironment{luadeclarestyle}[4]{ + \pgfmanualentry + \def\manual@temp@para{#2}% + \def\manual@temp@default{#3}% + \def\manual@temp@initial{#4}% + \def\manual@temp@{#3#4}% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + {\ttfamily/graph drawing/\declare{#1}}\ifx\manual@temp@para\pgfutil@empty\else\opt{\texttt=}\opt{#2}\fi\hfill% + (style\ifx\manual@temp@\pgfutil@empty\else, % + \ifx\manual@temp@default\pgfutil@empty\else% + default {\ttfamily #3}\ifx\manual@temp@initial\pgfutil@empty\else, \fi% + \fi% + \ifx\manual@temp@initial\pgfutil@empty\else% + initially {\ttfamily #4}% + \fi% + \fi)% + }% + \index{#1@\protect\texttt{#1} key}% + \pgfmanualbody% + \gdef\myname{#1}% +% \keyalias{tikz} +% \keyalias{tikz/graphs} +}{\endpgfmanualentry} + +\newenvironment{luanamespace}[2]{ + \luageneric{#1}{#2}{}{\textbf{Lua namespace}} +}{\endluageneric} + +\newenvironment{luafiledescription}[1]{}{} + +\newenvironment{luacommand}[4]{ + \hypertarget{pgf/lua/#1}{\luageneric{#2}{#3}{\texttt{(#4)}}{\texttt{function}}} +}{\endluageneric} + +\newenvironment{luaparameters}{\par\emph{Parameters:}% + \parametercount=0\relax% + \let\item=\parameteritem% + \let\list=\restorelist% +} +{\par +} + +\newenvironment{luareturns}{\par\emph{Returns:}% + \parametercount=0\relax% + \let\item=\parameteritem% + \let\list=\restorelist% +} +{\par +} + +\newcount\parametercount + +\newenvironment{parameterdescription}{\unskip% + \parametercount=0\relax% + \let\item=\parameteritem% + \let\list=\restorelist% +} +{\par +} +\let\saveditemcommand=\item +\let\savedlistcommand=\list +\def\denselist#1#2{\savedlistcommand{#1}{#2}\parskip0pt\itemsep0pt} +\def\restorelist{\let\item=\saveditemcommand\denselist} +\def\parameteritem{\pgfutil@ifnextchar[\parameteritem@{}}%} +\def\parameteritem@[#1]{\advance\parametercount by1\relax\hskip0.15em plus 1em\emph{\the\parametercount.}\kern1ex\def\test{#1}\ifx\test\pgfutil@empty\else#1\kern.5em\fi} + +\makeatother +\newenvironment{commandlist}[1]{% + \begin{pgfmanualentry} + \foreach \xx in {#1} {% + \expandafter\extractcommand\xx\@@ + }% + \pgfmanualbody +}{% + \end{pgfmanualentry} +}% +\makeatletter + +% \begin{internallist}[register]{\pgf@xa} +% \end{internallist} +% +% \begin{internallist}[register]{\pgf@xa,\pgf@xb} +% \end{internallist} +\newenvironment{internallist}[2][register]{% + \begin{pgfmanualentry} + \foreach \xx in {#2} {% + \expandafter\extractinternalcommand\expandafter{\xx}{#1}% + }% + \pgfmanualbody +}{% + \end{pgfmanualentry} +}% +\def\extractinternalcommand#1#2{% + \removeats{#1}% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{\textbackslash\strippedat}{}% + Internal #2 \declare{\texttt{\string#1}}}% + \index{Internals!\strippedat @\protect\myprintocmmand{\strippedat}}% + \index{\strippedat @\protect\myprintocmmand{\strippedat}}% +} + +%% MW: START MATH MACROS +\def\mvar#1{{\ifmmode\textrm{\textit{#1}}\else\rmfamily\textit{#1}\fi}} + +\makeatletter + +\def\extractmathfunctionname#1{\extractmathfunctionname@#1(,)\tmpa\tmpb} +\def\extractmathfunctionname@#1(#2)#3\tmpb{\def\mathname{#1}} + +\makeatother + +\newenvironment{math-function}[1]{ + \def\mathdefaultname{#1} + \extractmathfunctionname{#1} + \edef\mathurl{{math:\mathname}}\expandafter\hypertarget\expandafter{\mathurl}{}% + \begin{pgfmanualentry} + \pgfmanualentryheadline{\texttt{#1}}% + \index{\mathname @\protect\texttt{\mathname} math function}% + \index{Math functions!\mathname @\protect\texttt{\mathname}}% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\pgfmanualemptytext{} +\def\pgfmanualvbarvbar{\char`\|\char`\|} + +\newenvironment{math-operator}[4][]{% + \begin{pgfmanualentry} + \csname math#3operator\endcsname{#2}{#4} + \def\mathtest{#4}% + \ifx\mathtest\pgfmanualemptytext% + \def\mathtype{(#3 operator)} + \else% + \def\mathtype{(#3 operator; uses the \texttt{#4} function)} + \fi% + \pgfmanualentryheadline{\mathexample\hfill\mathtype}% + \def\mathtest{#1}% + \ifx\mathtest\pgfmanualemptytext% + \index{#2@\protect\texttt{#2} #3 math operator}% + \index{Math operators!#2@\protect\texttt{#2}}% + \fi% + \pgfmanualbody +} +{\end{pgfmanualentry}} + +\newenvironment{math-operators}[5][]{% + \begin{pgfmanualentry} + \csname math#4operator\endcsname{#2}{#3} + \def\mathtest{#5}% + \ifx\mathtest\pgfmanualemptytext% + \def\mathtype{(#4 operators)} + \else% + \def\mathtype{(#4 operators; use the \texttt{#5} function)} + \fi% + \pgfmanualentryheadline{\mathexample\hfill\mathtype}% + \def\mathtest{#1}% + \ifx\mathtest\pgfmanualemptytext% + \index{#2#3@\protect\texttt{#2\protect\ #3} #4 math operators}% + \index{Math operators!#2#3@\protect\texttt{#2\protect\ #3}}% + \fi% + \pgfmanualbody +} +{\end{pgfmanualentry}} + +\def\mathinfixoperator#1#2{% + \def\mathoperator{\texttt{#1}}% + \def\mathexample{\mvar{x}\space\texttt{#1}\space\mvar{y}}% +} + +\def\mathprefixoperator#1#2{% + \def\mathoperator{\texttt{#1}}% + \def\mathexample{\texttt{#1}\mvar{x}}% +} + +\def\mathpostfixoperator#1#2{% + \def\mathoperator{\texttt{#1}} + \def\mathexample{\mvar{x}\texttt{#1}}% +} + +\def\mathgroupoperator#1#2{% + \def\mathoperator{\texttt{#1\ #2}}% + \def\mathexample{\texttt{#1}\mvar{x}\texttt{#2}}% +} + +\expandafter\let\csname matharray accessoperator\endcsname=\mathgroupoperator +\expandafter\let\csname matharrayoperator\endcsname=\mathgroupoperator + +\def\mathconditionaloperator#1#2{% + \def\mathoperator{#1\space#2} + \def\mathexample{\mvar{x}\ \texttt{#1}\ \mvar{y}\ {\texttt{#2}}\ \mvar{z}} +} + +\newcommand\mathcommand[1][\mathdefaultname]{% + \expandafter\makemathcommand#1(\empty)\stop% + \expandafter\extractcommand\mathcommandname\@@% + \medskip +} +\makeatletter + +\def\makemathcommand#1(#2)#3\stop{% + \expandafter\def\expandafter\mathcommandname\expandafter{\csname pgfmath#1\endcsname}% + \ifx#2\empty% + \else% + \@makemathcommand#2,\stop, + \fi} +\def\@makemathcommand#1,{% + \ifx#1\stop% + \else% + \expandafter\def\expandafter\mathcommandname\expandafter{\mathcommandname{\ttfamily\char`\{#1\char`\}}}% + \expandafter\@makemathcommand% + \fi} +\makeatother + +\def\calcname{\textsc{calc}} + +\newenvironment{math-keyword}[1]{ + \extracttikzmathkeyword#1@ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\texttt{\color{red}\mathname}\mathrest}% + \index{\mathname @\protect\texttt{\mathname} tikz math function}% + \index{TikZ math functions!\mathname @\protect\texttt{\mathname}}% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\extracttikzmathkeyword#1#2@{% + \def\mathname{#1}% + \def\mathrest{#2}% +} + +%% MW: END MATH MACROS + + +\def\extractcommand#1#2\@@{% + \removeats{#1}% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{\textbackslash\strippedat}{}% + \declare{\texttt{\string#1}}#2% + }% + \index{\strippedat @\protect\myprintocmmand{\strippedat}} +} + +\def\luaextractcommand#1#2\relax{% + \declare{\texttt{\string#1}}#2\par% +% \removeats{#1}% + % \index{\strippedat @\protect\myprintocmmand{\strippedat}} + % \pgfmanualpdflabel{\textbackslash\strippedat}{}% +} + + +% \begin{environment}{{name}\marg{arguments}} +\renewenvironment{environment}[1]{ + \begin{pgfmanualentry} + \extractenvironement#1\@@ + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\extractenvironement#1#2\@@{% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + {\ttfamily\char`\\begin\char`\{\declare{#1}\char`\}}#2% + }% + \pgfmanualentryheadline{{\ttfamily\ \ }\meta{environment contents}}% + \pgfmanualentryheadline{{\ttfamily\char`\\end\char`\{\declare{#1}\char`\}}}% + \index{#1@\protect\texttt{#1} environment}% + \index{Environments!#1@\protect\texttt{#1}} +} + + +\newenvironment{plainenvironment}[1]{ + \begin{pgfmanualentry} + \extractplainenvironement#1\@@ + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\extractplainenvironement#1#2\@@{% + \pgfmanualentryheadline{{\ttfamily\declare{\char`\\#1}}#2}% + \pgfmanualentryheadline{{\ttfamily\ \ }\meta{environment contents}}% + \pgfmanualentryheadline{{\ttfamily\declare{\char`\\end#1}}}% + \index{#1@\protect\texttt{#1} environment}% + \index{Environments!#1@\protect\texttt{#1}}% +} + + +\newenvironment{contextenvironment}[1]{ + \begin{pgfmanualentry} + \extractcontextenvironement#1\@@ + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\extractcontextenvironement#1#2\@@{% + \pgfmanualentryheadline{{\ttfamily\declare{\char`\\start#1}}#2}% + \pgfmanualentryheadline{{\ttfamily\ \ }\meta{environment contents}}% + \pgfmanualentryheadline{{\ttfamily\declare{\char`\\stop#1}}}% + \index{#1@\protect\texttt{#1} environment}% + \index{Environments!#1@\protect\texttt{#1}}} + + +\newenvironment{shape}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Shape} {\ttfamily\declare{#1}}% + }% + \index{#1@\protect\texttt{#1} shape}% + \index{Shapes!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{pictype}[2]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Pic type} {\ttfamily\declare{#1}#2}% + }% + \index{#1@\protect\texttt{#1} pic type}% + \index{Pic Types!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{shading}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Shading} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} shading}% + \index{Shadings!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + +\newenvironment{graph}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Graph} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} graph}% + \index{Graphs!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{gdalgorithm}[2]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Layout} {\ttfamily/graph drawing/\declare{#1}\opt{=}}\opt{\meta{options}}}% + \index{#1@\protect\texttt{#1} layout}% + \index{Layouts!#1@\protect\texttt{#1}}% + \foreach \algo in {#2} + {\edef\marshal{\noexpand\index{#2@\noexpand\protect\noexpand\texttt{#2} algorithm}}\marshal}% + \index{Graph drawing layouts!#1@\protect\texttt{#1}} + \item{\small alias {\ttfamily/tikz/#1}}\par + \item{\small alias {\ttfamily/tikz/graphs/#1}}\par + \item{\small Employs {\ttfamily algorithm=#2}}\par + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{dataformat}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Format} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} format}% + \index{Formats!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{stylesheet}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Style sheet} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} style sheet}% + \index{Style sheets!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{handler}[1]{ + \begin{pgfmanualentry} + \extracthandler#1\@nil% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\gobble#1{} +\def\extracthandler#1#2\@nil{% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{/handlers/#1}{}% + \textbf{Key handler} \meta{key}{\ttfamily/\declare{#1}}#2}% + \index{\gobble#1@\protect\texttt{#1} handler}% + \index{Key handlers!#1@\protect\texttt{#1}} +} + + +\makeatletter + + +\newenvironment{stylekey}[1]{ + \begin{pgfmanualentry} + \def\extrakeytext{style, } + \extractkey#1\@nil% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\def\choicesep{$\vert$}% +\def\choicearg#1{\texttt{#1}} + +\newif\iffirstchoice + +% \mchoice{choice1,choice2,choice3} +\newcommand\mchoice[1]{% + \begingroup + \firstchoicetrue + \foreach \mchoice@ in {#1} {% + \iffirstchoice + \global\firstchoicefalse + \else + \choicesep + \fi + \choicearg{\mchoice@}% + }% + \endgroup +}% + +% \begin{key}{/path/x=value} +% \begin{key}{/path/x=value (initially XXX)} +% \begin{key}{/path/x=value (default XXX)} +\newenvironment{key}[1]{ + \begin{pgfmanualentry} + \def\extrakeytext{} + %\def\altpath{\emph{\color{gray}or}}% + \extractkey#1\@nil% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +% \insertpathifneeded{a key}{/pgf} -> assign mykey={/pgf/a key} +% \insertpathifneeded{/tikz/a key}{/pgf} -> assign mykey={/tikz/a key} +% +% #1: the key +% #2: a default path (or empty) +\def\insertpathifneeded#1#2{% + \def\insertpathifneeded@@{#2}% + \ifx\insertpathifneeded@@\empty + \def\mykey{#1}% + \else + \insertpathifneeded@#2\@nil + \ifpgfutil@in@ + \def\mykey{#2/#1}% + \else + \def\mykey{#1}% + \fi + \fi +}% +\def\insertpathifneeded@#1#2\@nil{% + \def\insertpathifneeded@@{#1}% + \def\insertpathifneeded@@@{/}% + \ifx\insertpathifneeded@@\insertpathifneeded@@@ + \pgfutil@in@true + \else + \pgfutil@in@false + \fi +}% + +% \begin{keylist}[default path] +% {/path/option 1=value,/path/option 2=value2} +% \end{keylist} +\newenvironment{keylist}[2][]{% + \begin{pgfmanualentry} + \def\extrakeytext{}% + \foreach \xx in {#2} {% + \expandafter\insertpathifneeded\expandafter{\xx}{#1}% + \expandafter\extractkey\mykey\@nil% + }% + \pgfmanualbody +}{% + \end{pgfmanualentry} +}% + +\def\extractkey#1\@nil{% + \pgfutil@in@={#1}% + \ifpgfutil@in@% + \extractkeyequal#1\@nil + \else% + \pgfutil@in@{(initial}{#1}% + \ifpgfutil@in@% + \extractequalinitial#1\@nil% + \else + \pgfmanualentryheadline{% + \def\mykey{#1}% + \def\mypath{}% + \gdef\myname{}% + \firsttimetrue% + \pgfmanualdecomposecount=0\relax% + \decompose#1/\nil% + {\ttfamily\declare{#1}}\hfill(\extrakeytext no value)}% + \fi + \fi% +} + +\def\extractkeyequal#1=#2\@nil{% + \pgfutil@in@{(default}{#2}% + \ifpgfutil@in@% + \extractdefault{#1}#2\@nil% + \else% + \pgfutil@in@{(initial}{#2}% + \ifpgfutil@in@% + \extractinitial{#1}#2\@nil% + \else + \pgfmanualentryheadline{% + \def\mykey{#1}% + \def\mypath{}% + \gdef\myname{}% + \firsttimetrue% + \pgfmanualdecomposecount=0\relax% + \decompose#1/\nil% + {\ttfamily\declare{#1}=}#2\hfill(\extrakeytext no default)}% + \fi% + \fi% +} + +\def\extractdefault#1#2(default #3)\@nil{% + \pgfmanualentryheadline{% + \def\mykey{#1}% + \def\mypath{}% + \gdef\myname{}% + \firsttimetrue% + \pgfmanualdecomposecount=0\relax% + \decompose#1/\nil% + {\ttfamily\declare{#1}\opt{=}}\opt{#2}\hfill (\extrakeytext default {\ttfamily#3})}% +} + +\def\extractinitial#1#2(initially #3)\@nil{% + \pgfmanualentryheadline{% + \def\mykey{#1}% + \def\mypath{}% + \gdef\myname{}% + \firsttimetrue% + \pgfmanualdecomposecount=0\relax% + \decompose#1/\nil% + {\ttfamily\declare{#1}=}#2\hfill (\extrakeytext no default, initially {\ttfamily#3})}% +} + +\def\extractequalinitial#1 (initially #2)\@nil{% + \pgfmanualentryheadline{% + \def\mykey{#1}% + \def\mypath{}% + \gdef\myname{}% + \firsttimetrue% + \pgfmanualdecomposecount=0\relax% + \decompose#1/\nil% + {\ttfamily\declare{#1}}\hfill (\extrakeytext initially {\ttfamily#2})}% +} + +% Introduces a key alias '/#1/<name of current key>' +% to be used inside of \begin{key} ... \end{key} +\def\keyalias#1{\vspace{-3pt}\item{\small alias {\ttfamily/#1/\myname}}\vspace{-2pt}\par + \pgfmanualpdflabel{/#1/\myname}{}% +} + +\newif\iffirsttime +\newcount\pgfmanualdecomposecount + +\makeatother + +\def\decompose/#1/#2\nil{% + \def\test{#2}% + \ifx\test\empty% + % aha. + \index{#1@\protect\texttt{#1} key}% + \index{\mypath#1@\protect\texttt{#1}}% + \gdef\myname{#1}% + \pgfmanualpdflabel{#1}{} + \else% + \advance\pgfmanualdecomposecount by1\relax% + \ifnum\pgfmanualdecomposecount>2\relax% + \decomposetoodeep#1/#2\nil% + \else% + \iffirsttime% + \begingroup% + % also make a pdf link anchor with full key path. + \def\hyperlabelwithoutslash##1/\nil{% + \pgfmanualpdflabel{##1}{}% + }% + \hyperlabelwithoutslash/#1/#2\nil% + \endgroup% + \def\mypath{#1@\protect\texttt{/#1/}!}% + \firsttimefalse% + \else% + \expandafter\def\expandafter\mypath\expandafter{\mypath#1@\protect\texttt{#1/}!}% + \fi% + \def\firsttime{}% + \decompose/#2\nil% + \fi% + \fi% +} + +\def\decomposetoodeep#1/#2/\nil{% + % avoid too-deep nesting in index + \index{#1/#2@\protect\texttt{#1/#2} key}% + \index{\mypath#1/#2@\protect\texttt{#1/#2}}% + \decomposefindlast/#1/#2/\nil% +} +\makeatletter +\def\decomposefindlast/#1/#2\nil{% + \def\test{#2}% + \ifx\test\pgfutil@empty% + \gdef\myname{#1}% + \else% + \decomposefindlast/#2\nil% + \fi% +} +\makeatother +\def\indexkey#1{% + \def\mypath{}% + \decompose#1/\nil% +} + +\newenvironment{predefinedmethod}[1]{ + \begin{pgfmanualentry} + \extractpredefinedmethod#1\@nil + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} +\def\extractpredefinedmethod#1(#2)\@nil{% + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + Method \declare{\ttfamily #1}\texttt(#2\texttt) \hfill(predefined for all classes)} + \index{#1@\protect\texttt{#1} method}% + \index{Methods!#1@\protect\texttt{#1}} +} + + +\newenvironment{ooclass}[1]{ + \begin{pgfmanualentry} + \def\currentclass{#1} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Class} \declare{\texttt{#1}}} + \index{#1@\protect\texttt{#1} class}% + \index{Class #1@Class \protect\texttt{#1}}% + \index{Classes!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{method}[1]{ + \begin{pgfmanualentry} + \extractmethod#1\@nil + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} +\def\extractmethod#1(#2)\@nil{% + \def\test{#1} + \ifx\test\currentclass + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + Constructor \declare{\ttfamily #1}\texttt(#2\texttt)} + \else + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + Method \declare{\ttfamily #1}\texttt(#2\texttt)} + \fi + \index{#1@\protect\texttt{#1} method}% + \index{Methods!#1@\protect\texttt{#1}} + \index{Class \currentclass!#1@\protect\texttt{#1}}% +} + +\newenvironment{attribute}[1]{ + \begin{pgfmanualentry} + \extractattribute#1\@nil + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} +\def\extractattribute#1=#2;\@nil{% + \def\test{#2}% + \ifx\test\@empty + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + Private attribute \declare{\ttfamily #1} \hfill (initially empty)} + \else + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + Private attribute \declare{\ttfamily #1} \hfill (initially {\ttfamily #2})} + \fi + \index{#1@\protect\texttt{#1} attribute}% + \index{Attributes!#1@\protect\texttt{#1}} + \index{Class \currentclass!#1@\protect\texttt{#1}}% +} + + + +\newenvironment{predefinednode}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Predefined node} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} node}% + \index{Predefined node!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{coordinatesystem}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{Coordinate system} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} coordinate system}% + \index{Coordinate systems!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{snake}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\textbf{Snake} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} snake}% + \index{Snakes!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{decoration}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\textbf{Decoration} {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} decoration}% + \index{Decorations!#1@\protect\texttt{#1}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + +\def\pgfmanualbar{\char`\|} +\makeatletter +\newenvironment{pathoperation}[3][]{ + \begin{pgfmanualentry} + \def\pgfmanualtest{#1}% + \pgfmanualentryheadline{% + \ifx\pgfmanualtest\@empty% + \pgfmanualpdflabel{#2}{}% + \fi% + \textcolor{gray}{{\ttfamily\char`\\path}\ + \ \dots} + \declare{\texttt{\noligs{#2}}}#3\ \textcolor{gray}{\dots\texttt{;}}}% + \ifx\pgfmanualtest\@empty% + \index{#2@\protect\texttt{#2} path operation}% + \index{Path operations!#2@\protect\texttt{#2}}% + \fi% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} +\newenvironment{datavisualizationoperation}[3][]{ + \begin{pgfmanualentry} + \def\pgfmanualtest{#1}% + \pgfmanualentryheadline{% + \ifx\pgfmanualtest\@empty% + \pgfmanualpdflabel{#2}{}% + \fi% + \textcolor{gray}{{\ttfamily\char`\\datavisualization}\ + \ \dots} + \declare{\texttt{\noligs{#2}}}#3\ \textcolor{gray}{\dots\texttt{;}}}% + \ifx\pgfmanualtest\@empty% + \index{#2@\protect\texttt{#2} (data visualization)}% + \index{Data visualization!#2@\protect\texttt{#2}}% + \fi% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} +\makeatother + +\def\doublebs{\texttt{\char`\\\char`\\}} + + +\newenvironment{package}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + {\ttfamily\char`\\usepackage\char`\{\declare{#1}\char`\}\space\space \char`\%\space\space \LaTeX}} + \index{#1@\protect\texttt{#1} package}% + \index{Packages and files!#1@\protect\texttt{#1}}% + \pgfmanualentryheadline{{\ttfamily\char`\\input \declare{#1}.tex\space\space\space \char`\%\space\space plain \TeX}} + \pgfmanualentryheadline{{\ttfamily\char`\\usemodule[\declare{#1}]\space\space \char`\%\space\space Con\TeX t}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + +\newenvironment{pgfmodule}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + {\ttfamily\char`\\usepgfmodule\char`\{\declare{#1}\char`\}\space\space\space + \char`\%\space\space \LaTeX\space and plain \TeX\space and pure pgf}} + \index{#1@\protect\texttt{#1} module}% + \index{Modules!#1@\protect\texttt{#1}}% + \pgfmanualentryheadline{{\ttfamily\char`\\usepgfmodule[\declare{#1}]\space\space \char`\%\space\space Con\TeX t\space and pure pgf}} + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{pgflibrary}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{\tikzname\ Library} \texttt{\declare{#1}}} + \index{#1@\protect\texttt{#1} library}% + \index{Libraries!#1@\protect\texttt{#1}}% + \vskip.25em% + {{\ttfamily\char`\\usepgflibrary\char`\{\declare{#1}\char`\}\space\space\space + \char`\%\space\space \LaTeX\space and plain \TeX\space and pure pgf}}\\ + {{\ttfamily\char`\\usepgflibrary[\declare{#1}]\space\space \char`\%\space\space Con\TeX t\space and pure pgf}}\\ + {{\ttfamily\char`\\usetikzlibrary\char`\{\declare{#1}\char`\}\space\space + \char`\%\space\space \LaTeX\space and plain \TeX\space when using \tikzname}}\\ + {{\ttfamily\char`\\usetikzlibrary[\declare{#1}]\space + \char`\%\space\space Con\TeX t\space when using \tikzname}}\\[.5em] + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{purepgflibrary}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{{\small PGF} Library} \texttt{\declare{#1}}} + \index{#1@\protect\texttt{#1} library}% + \index{Libraries!#1@\protect\texttt{#1}}% + \vskip.25em% + {{\ttfamily\char`\\usepgflibrary\char`\{\declare{#1}\char`\}\space\space\space + \char`\%\space\space \LaTeX\space and plain \TeX}}\\ + {{\ttfamily\char`\\usepgflibrary[\declare{#1}]\space\space \char`\%\space\space Con\TeX t}}\\[.5em] + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + +\newenvironment{tikzlibrary}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{% + \pgfmanualpdflabel{#1}{}% + \textbf{\tikzname\ Library} \texttt{\declare{#1}}} + \index{#1@\protect\texttt{#1} library}% + \index{Libraries!#1@\protect\texttt{#1}}% + \vskip.25em% + {{\ttfamily\char`\\usetikzlibrary\char`\{\declare{#1}\char`\}\space\space \char`\%\space\space \LaTeX\space and plain \TeX}}\\ + {{\ttfamily\char`\\usetikzlibrary[\declare{#1}]\space \char`\%\space\space Con\TeX t}}\\[.5em] + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + + +\newenvironment{filedescription}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{File {\ttfamily\declare{#1}}}% + \index{#1@\protect\texttt{#1} file}% + \index{Packages and files!#1@\protect\texttt{#1}}% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + +\newenvironment{packageoption}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{{\ttfamily\char`\\usepackage[\declare{#1}]\char`\{pgf\char`\}}} + \index{#1@\protect\texttt{#1} package option}% + \index{Package options for \textsc{pgf}!#1@\protect\texttt{#1}}% + \pgfmanualbody +} +{ + \end{pgfmanualentry} +} + + + +\newcommand\opt[1]{{\color{black!50!green}#1}} +\newcommand\ooarg[1]{{\ttfamily[}\meta{#1}{\ttfamily]}} + +\def\opt{\afterassignment\pgfmanualopt\let\next=} +\def\pgfmanualopt{\ifx\next\bgroup\bgroup\color{black!50!green}\else{\color{black!50!green}\next}\fi} + + + +\def\beamer{\textsc{beamer}} +\def\pdf{\textsc{pdf}} +\def\eps{\texttt{eps}} +\def\pgfname{\textsc{pgf}} +\def\tikzname{Ti\emph{k}Z} +\def\pstricks{\textsc{pstricks}} +\def\prosper{\textsc{prosper}} +\def\seminar{\textsc{seminar}} +\def\texpower{\textsc{texpower}} +\def\foils{\textsc{foils}} + +{ + \makeatletter + \global\let\myempty=\@empty + \global\let\mygobble=\@gobble + \catcode`\@=12 + \gdef\getridofats#1@#2\relax{% + \def\getridtest{#2}% + \ifx\getridtest\myempty% + \expandafter\def\expandafter\strippedat\expandafter{\strippedat#1} + \else% + \expandafter\def\expandafter\strippedat\expandafter{\strippedat#1\protect\printanat} + \getridofats#2\relax% + \fi% + } + + \gdef\removeats#1{% + \let\strippedat\myempty% + \edef\strippedtext{\stripcommand#1}% + \expandafter\getridofats\strippedtext @\relax% + } + + \gdef\stripcommand#1{\expandafter\mygobble\string#1} +} + +\def\printanat{\char`\@} + +\def\declare{\afterassignment\pgfmanualdeclare\let\next=} +\def\pgfmanualdeclare{\ifx\next\bgroup\bgroup\color{red!75!black}\else{\color{red!75!black}\next}\fi} + + +\let\textoken=\command +\let\endtextoken=\endcommand + +\def\myprintocmmand#1{\texttt{\char`\\#1}} + +\def\example{\par\smallskip\noindent\textit{Example: }} +\def\themeauthor{\par\smallskip\noindent\textit{Theme author: }} + + +\def\indexoption#1{% + \index{#1@\protect\texttt{#1} option}% + \index{Graphic options and styles!#1@\protect\texttt{#1}}% +} + +\def\itemcalendaroption#1{\item \declare{\texttt{#1}}% + \index{#1@\protect\texttt{#1} date test}% + \index{Date tests!#1@\protect\texttt{#1}}% +} + + + +\def\class#1{\list{}{\leftmargin=2em\itemindent-\leftmargin\def\makelabel##1{\hss##1}}% +\extractclass#1@\par\topsep=0pt} +\def\endclass{\endlist} +\def\extractclass#1#2@{% +\item{{{\ttfamily\char`\\documentclass}#2{\ttfamily\char`\{\declare{#1}\char`\}}}}% + \index{#1@\protect\texttt{#1} class}% + \index{Classes!#1@\protect\texttt{#1}}} + +\def\partname{Part} + +\makeatletter +\def\index@prologue{\section*{Index}\addcontentsline{toc}{section}{Index} + This index only contains automatically generated entries. A good + index should also contain carefully selected keywords. This index is + not a good index. + \bigskip +} +\c@IndexColumns=2 + \def\theindex{\@restonecoltrue + \columnseprule \z@ \columnsep 29\p@ + \twocolumn[\index@prologue]% + \parindent -30pt + \columnsep 15pt + \parskip 0pt plus 1pt + \leftskip 30pt + \rightskip 0pt plus 2cm + \small + \def\@idxitem{\par}% + \let\item\@idxitem \ignorespaces} + \def\endtheindex{\onecolumn} +\def\noindexing{\let\index=\@gobble} + + +\newenvironment{arrowtipsimple}[1]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\textbf{Arrow Tip Kind} {\ttfamily#1}} + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \def\currentarrowtype{#1} + \pgfmanualbody} +{ + \end{pgfmanualentry} +} + +\newenvironment{arrowtip}[4]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\textbf{Arrow Tip Kind} {\ttfamily#1}} + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \pgfmanualbody + \def\currentarrowtype{#1} + \begin{minipage}[t]{10.25cm} + #2 + \end{minipage}\hskip5mm\begin{minipage}[t]{4.75cm} + \leavevmode\vskip-2em + \tikz{ + \draw [black!50,line width=5mm,-{#1[#3,color=black]}] (-4,0) -- (0,0); + \foreach \action in {#4} + { \expandafter\processaction\action\relax } + } + \end{minipage}\par\smallskip + } +{ + \end{pgfmanualentry} +} + +\newenvironment{arrowcap}[5]{ + \begin{pgfmanualentry} + \pgfmanualentryheadline{\textbf{Arrow Tip Kind} {\ttfamily#1}} + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \pgfmanualbody + \def\currentarrowtype{#1} + \begin{minipage}[t]{10.25cm} + #2 + \end{minipage}\hskip5mm\begin{minipage}[t]{4.75cm} + \leavevmode\vskip-2em + \tikz{ + \path [tips, line width=10mm,-{#1[#3,color=black]}] (-4,0) -- (0,0); + \draw [line width=10mm,black!50] (-3,0) -- (#5,0); + \foreach \action in {#4} + { \expandafter\processaction\action\relax } + } + \end{minipage}\par\smallskip + } +{ + \end{pgfmanualentry} +} + +\def\processaction#1=#2\relax{ + \expandafter\let\expandafter\pgf@temp\csname manual@action@#1\endcsname + \ifx\pgf@temp\relax\else + \pgf@temp#2/0/\relax + \fi +} +\def\manual@action@length#1/#2/#3\relax{% + \draw [red,|<->|,semithick,xshift=#2] ([yshift=4pt]current bounding + box.north -| -#1,0) coordinate (last length) -- node + [above=-2pt] {|length|} ++(#1,0); +} +\def\manual@action@width#1/#2/#3\relax{% + \draw [overlay, red,|<->|,semithick] (.5,-#1/2) -- node [below,sloped] {|width|} (.5,#1/2); +} +\def\manual@action@inset#1/#2/#3\relax{% + \draw [red,|<->|,semithick,xshift=#2] ([yshift=-4pt]current bounding + box.south -| last length) -- node [below] {|inset|} ++(#1,0); +} + +\newenvironment{arrowexamples} +{\begin{tabbing} + \hbox to \dimexpr\linewidth-5.5cm\relax{\emph{Appearance of the below at line width} \hfil} \= + \hbox to 1.9cm{\emph{0.4pt}\hfil} \= \hbox to 2cm{\emph{0.8pt}\hfil} \= \emph{1.6pt} \\ + } +{\end{tabbing}\vskip-1em} + +\newenvironment{arrowcapexamples} +{\begin{tabbing} + \hbox to \dimexpr\linewidth-5.5cm\relax{\emph{Appearance of the below at line width} \hfil} \= + \hbox to 1.9cm{\emph{1ex}\hfil} \= \hbox to 2cm{\emph{1em}\hfil} \\ + } +{\end{tabbing}\vskip-1em} + +\def\arrowcapexample#1[#2]{\def\temp{#1}\ifx\temp\pgfutil@empty\arrowcapexample@\currentarrowtype[{#2}]\else\arrowcapexample@#1[{#2}]\fi} +\def\arrowcapexample@#1[#2]{% + {\sfcode`\.1000\small\texttt{#1[#2]}} \> + \kern-.5ex\tikz [baseline,>={#1[#2]}] \draw [line + width=1ex,->] (0,.5ex) -- (2em,.5ex); \> + \kern-.5em\tikz [baseline,>={#1[#2]}] \draw [line + width=1em,->] (0,.5ex) -- (2em,.5ex); \\ +} + +\def\arrowexample#1[#2]{\def\temp{#1}\ifx\temp\pgfutil@empty\arrowexample@\currentarrowtype[{#2}]\else\arrowexample@#1[{#2}]\fi} +\def\arrowexample@#1[#2]{% + {\sfcode`\.1000\small\texttt{#1[#2]}} \> + \tikz [baseline,>={#1[#2]}] \draw [line + width=0.4pt,->] (0,.5ex) -- (2em,.5ex); thin \> + \tikz [baseline,>={#1[#2]}] \draw [line + width=0.8pt,->] (0,.5ex) -- (2em,.5ex); \textbf{thick} \> + \tikz [baseline,>={#1[#2]}] \draw [line + width=1.6pt,->] (0,.5ex) -- (3em,.5ex); \\ +} +\def\arrowexampledup[#1]{\arrowexample[{#1] \currentarrowtype[}]} +\def\arrowexampledupdot[#1]{\arrowexample[{#1] . \currentarrowtype[}]} + +\def\arrowexampledouble#1[#2]{\def\temp{#1}\ifx\temp\pgfutil@empty\arrowexampledouble@\currentarrowtype[{#2}]\else\arrowexampledouble@#1[{#2}]\fi} +\def\arrowexampledouble@#1[#2]{% + {\sfcode`\.1000\small\texttt{#1[#2]} on double line} \> + \tikz [baseline,>={#1[#2]}] + \draw [double equal sign distance,line width=0.4pt,->] (0,.5ex) -- (2em,.5ex); thin \> + \tikz [baseline,>={#1[#2]}] + \draw [double equal sign distance,line width=0.8pt,->] (0,.5ex) -- (2em,.5ex); \textbf{thick} \> + \tikz [baseline,>={#1[#2]}] + \draw [double equal sign distance, line width=1.6pt,->] (0,.5ex) -- (3em,.5ex); \\ +} + + + +\newcommand\symarrow[1]{% + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \texttt{#1}& yields thick + \begin{tikzpicture}[arrows={#1-#1},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} and thin + \begin{tikzpicture}[arrows={#1-#1},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} +} +\newcommand\symarrowdouble[1]{% + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \texttt{#1}& yields thick + \begin{tikzpicture}[arrows={#1-#1},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} + and thin + \begin{tikzpicture}[arrows={#1-#1},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture}, double + \begin{tikzpicture}[arrows={#1-#1},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw[double,double equal sign distance] (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} and + \begin{tikzpicture}[arrows={#1-#1},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw[double,double equal sign distance] (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} +} + +\newcommand\sarrow[2]{% + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \index{#2@\protect\texttt{#2} arrow tip}% + \index{Arrow tips!#2@\protect\texttt{#2}}% + \texttt{#1-#2}& yields thick + \begin{tikzpicture}[arrows={#1-#2},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} and thin + \begin{tikzpicture}[arrows={#1-#2},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} +} + +\newcommand\sarrowdouble[2]{% + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \index{#2@\protect\texttt{#2} arrow tip}% + \index{Arrow tips!#2@\protect\texttt{#2}}% + \texttt{#1-#2}& yields thick + \begin{tikzpicture}[arrows={#1-#2},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} and thin + \begin{tikzpicture}[arrows={#1-#2},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture}, double + \begin{tikzpicture}[arrows={#1-#2},thick,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw[double,double equal sign distance] (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} and + \begin{tikzpicture}[arrows={#1-#2},thin,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.1cm,2ex); + \fill [black!15] (1cm,-.5ex) rectangle (1.1cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw[double,double equal sign distance] (0pt,.5ex) -- (1cm,.5ex); + \end{tikzpicture} +} + +\newcommand\carrow[1]{% + \index{#1@\protect\texttt{#1} arrow tip}% + \index{Arrow tips!#1@\protect\texttt{#1}}% + \texttt{#1}& yields for line width 1ex + \begin{tikzpicture}[arrows={#1-#1},line width=1ex,baseline] + \useasboundingbox (-1mm,-0.5ex) rectangle (1.6cm,2ex); + \fill [black!15] (1.5cm,-.5ex) rectangle (1.6cm,1.5ex) (-1mm,-.5ex) rectangle (0mm,1.5ex) ; + \draw (0pt,.5ex) -- (1.5cm,.5ex); + \end{tikzpicture} +} +\def\myvbar{\char`\|} +\newcommand\plotmarkentry[1]{% + \index{#1@\protect\texttt{#1} plot mark}% + \index{Plot marks!#1@\protect\texttt{#1}} + \texttt{\char`\\pgfuseplotmark\char`\{\declare{\noligs{#1}}\char`\}} & + \tikz\draw[color=black!25] plot[mark=#1,mark options={fill=examplefill,draw=black}] coordinates{(0,0) (.5,0.2) (1,0) (1.5,0.2)};\\ +} +\newcommand\plotmarkentrytikz[1]{% + \index{#1@\protect\texttt{#1} plot mark}% + \index{Plot marks!#1@\protect\texttt{#1}} + \texttt{mark=\declare{\noligs{#1}}} & \tikz\draw[color=black!25] + plot[mark=#1,mark options={fill=examplefill,draw=black}] + coordinates {(0,0) (.5,0.2) (1,0) (1.5,0.2)};\\ +} + + + +\ifx\scantokens\@undefined + \PackageError{pgfmanual-macros}{You need to use extended latex + (elatex) or (pdfelatex) to process this document}{} +\fi + +\begingroup +\catcode`|=0 +\catcode`[= 1 +\catcode`]=2 +\catcode`\{=12 +\catcode `\}=12 +\catcode`\\=12 |gdef|find@example#1\end{codeexample}[|endofcodeexample[#1]] +|endgroup + +% define \returntospace. +% +% It should define NEWLINE as {}, spaces and tabs as \space. +\begingroup +\catcode`\^=7 +\catcode`\^^M=13 +\catcode`\^^I=13 +\catcode`\ =13% +\gdef\returntospace{\catcode`\ =13\def {\space}\catcode`\^^I=13\def^^I{\space}} +\gdef\showreturn{\show^^M} +\endgroup + +\begingroup +\catcode`\%=13 +\catcode`\^^M=13 +\gdef\commenthandler{\catcode`\%=13\def%{\@gobble@till@return}} +\gdef\@gobble@till@return#1^^M{} +\gdef\@gobble@till@return@ignore#1^^M{\ignorespaces} +\gdef\typesetcomment{\catcode`\%=13\def%{\@typeset@till@return}} +\gdef\@typeset@till@return#1^^M{{\def%{\char`\%}\textsl{\char`\%#1}}\par} +\endgroup + +% Define tab-implementation functions +% \codeexample@tabinit@replacementchars@ +% and +% \codeexample@tabinit@catcode@ +% +% They should ONLY be used in case that tab replacement is active. +% +% This here is merely a preparation step. +% +% Idea: +% \codeexample@tabinit@catcode@ will make TAB active +% and +% \codeexample@tabinit@replacementchars@ will insert as many spaces as +% /codeexample/tabsize contains. +{ +\catcode`\^^I=13 +% ATTENTION: do NOT use tabs in these definitions!! +\gdef\codeexample@tabinit@replacementchars@{% + \begingroup + \count0=\pgfkeysvalueof{/codeexample/tabsize}\relax + \toks0={}% + \loop + \ifnum\count0>0 + \advance\count0 by-1 + \toks0=\expandafter{\the\toks0\ }% + \repeat + \xdef\codeexample@tabinit@replacementchars@@{\the\toks0}% + \endgroup + \let^^I=\codeexample@tabinit@replacementchars@@ +}% +\gdef\codeexample@tabinit@catcode@{\catcode`\^^I=13}% +}% + +% Called after any options have been set. It assigns +% \codeexample@tabinit@catcode +% and +% \codeexample@tabinit@replacementchars +% which are used inside of +%\begin{codeexample} +% ... +%\end{codeexample} +% +% \codeexample@tabinit@catcode is either \relax or it makes tab +% active. +% +% \codeexample@tabinit@replacementchars is either \relax or it inserts +% a proper replacement sequence for tabs (as many spaces as +% configured) +\def\codeexample@tabinit{% + \ifnum\pgfkeysvalueof{/codeexample/tabsize}=0\relax + \let\codeexample@tabinit@replacementchars=\relax + \let\codeexample@tabinit@catcode=\relax + \else + \let\codeexample@tabinit@catcode=\codeexample@tabinit@catcode@ + \let\codeexample@tabinit@replacementchars=\codeexample@tabinit@replacementchars@ + \fi +} + +\newif\ifpgfmanualtikzsyntaxhilighting + +\pgfqkeys{/codeexample}{% + width/.code= {\setlength\codeexamplewidth{#1}}, + graphic/.code= {\colorlet{graphicbackground}{#1}}, + code/.code= {\colorlet{codebackground}{#1}}, + execute code/.is if=code@execute, + code only/.code= {\code@executefalse}, + pre/.store in=\code@pre, + post/.store in=\code@post, + % #1 is the *complete* environment contents as it shall be + % typeset. In particular, the catcodes are NOT the normal ones. + typeset listing/.code= {#1}, + render instead/.store in=\code@render, + vbox/.code= {\def\code@pre{\vbox\bgroup\setlength{\hsize}{\linewidth-6pt}}\def\code@post{\egroup}}, + ignorespaces/.code= {\let\@gobble@till@return=\@gobble@till@return@ignore}, + leave comments/.code= {\def\code@catcode@hook{\catcode`\%=12}\let\commenthandler=\relax\let\typesetcomment=\relax}, + tabsize/.initial=0,% FIXME : this here is merely used for indentation. It is just a TAB REPLACEMENT. + every codeexample/.style={width=4cm+7pt, tikz syntax=true}, + from file/.code={\codeexamplefromfiletrue\def\codeexamplesource{#1}}, + tikz syntax/.is if=pgfmanualtikzsyntaxhilighting, +} + + +\newread\examplesource + + +% Opening, reading and closing the results file + +\def\opensource#1{ + \immediate\openin\examplesource=#1 +} +\def\do@codeexamplefromfile{% + \immediate\openin\examplesource\expandafter{\codeexamplesource}% + \def\examplelines{}% + \readexamplelines + \closein\examplesource + \expandafter\endofcodeexample\expandafter{\examplelines}% +} + +\def\readexamplelines{ + \ifeof\examplesource% + \else + \immediate\read\examplesource to \exampleline + \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\examplelines\expandafter\expandafter\expandafter{\expandafter\examplelines\exampleline} + \expandafter\readexamplelines% + \fi +} + +\let\code@pre\pgfutil@empty +\let\code@post\pgfutil@empty +\let\code@render\pgfutil@empty +\def\code@catcode@hook{} + +\newif\ifcodeexamplefromfile +\newdimen\codeexamplewidth +\newif\ifcode@execute +\newbox\codeexamplebox +\def\codeexample[#1]{% + \begingroup% + \code@executetrue + \pgfqkeys{/codeexample}{every codeexample,#1}% + \pgfmanualswitchoncolors% + \ifcodeexamplefromfile\begingroup\fi + \codeexample@tabinit% assigns \codeexample@tabinit@[catcode,replacementchars] + \parindent0pt + \begingroup% + \par% + \medskip% + \let\do\@makeother% + \dospecials% + \obeylines% + \@vobeyspaces% + \catcode`\%=13% + \catcode`\^^M=13% + \code@catcode@hook% + \codeexample@tabinit@catcode + \relax% + \ifcodeexamplefromfile% + \expandafter\do@codeexamplefromfile% + \else% + \expandafter\find@example% + \fi} +\def\endofcodeexample#1{% + \endgroup% + \ifcode@execute% + \setbox\codeexamplebox=\hbox{% + \ifx\code@render\pgfutil@empty% + {% + {% + \returntospace% + \commenthandler% + \xdef\code@temp{#1}% removes returns and comments + }% + \catcode`\^^M=9% + \colorbox{graphicbackground}{\color{black}\ignorespaces% + \code@pre\expandafter\scantokens\expandafter{\code@temp\ignorespaces}\code@post\ignorespaces}% + }% + \else% + \colorbox{graphicbackground}{\color{black}\ignorespaces% + \code@render}% + \fi% + }% + \ifdim\wd\codeexamplebox>\codeexamplewidth% + \def\code@start{\par}% + \def\code@flushstart{}\def\code@flushend{}% + \def\code@mid{\parskip2pt\par\noindent}% + \def\code@width{\linewidth-6pt}% + \def\code@end{}% + \else% + \def\code@start{% + \linewidth=\textwidth% + \parshape \@ne 0pt \linewidth + \leavevmode% + \hbox\bgroup}% + \def\code@flushstart{\hfill}% + \def\code@flushend{\hbox{}}% + \def\code@mid{\hskip6pt}% + \def\code@width{\linewidth-12pt-\codeexamplewidth}% + \def\code@end{\egroup}% + \fi% + \code@start% + \noindent% + \begin{minipage}[t]{\codeexamplewidth}\raggedright + \hrule width0pt% + \footnotesize\vskip-1em% + \code@flushstart\box\codeexamplebox\code@flushend% + \vskip-1ex + \leavevmode% + \end{minipage}% + \else% + \def\code@mid{\par} + \def\code@width{\linewidth-6pt} + \def\code@end{} + \fi% + \code@mid% + \colorbox{codebackground}{% + \pgfkeysvalueof{/codeexample/prettyprint/base color}% + \begin{minipage}[t]{\code@width}% + {% + \let\do\@makeother + \dospecials + \frenchspacing\@vobeyspaces + \normalfont\ttfamily\footnotesize + \typesetcomment% + \codeexample@tabinit@replacementchars + \@tempswafalse + \def\par{% + \if@tempswa + \leavevmode \null \@@par\penalty\interlinepenalty + \else + \@tempswatrue + \ifhmode\@@par\penalty\interlinepenalty\fi + \fi}% + \obeylines + \everypar \expandafter{\the\everypar \unpenalty}% + \pgfkeysvalueof{/codeexample/typeset listing/.@cmd}{#1}\pgfeov + } + \end{minipage}}% + \code@end% + \par% + \medskip + \endcodeexample\endgroup +} + +\def\endcodeexample{\endgroup} + + +\makeatother + +\usepackage{pgfmanual} + + +% autoxref is now always on + +% \makeatletter +% % \pgfautoxrefs will be defined by 'make dist' +% \pgfutil@ifundefined{pgfautoxrefs}{% +% \renewcommand\pgfmanualpdflabel[3][]{#3}% NO-OP +% \def\pgfmanualpdfref#1#2{#2}% +% \pgfkeys{ +% /pdflinks/codeexample links=false,% DISABLED. +% }% +% }{} +% \makeatother + +\newdimen\pgfmanualcslinkpreskip + +% Styling of the pretty printer +\pgfkeys{ + /codeexample/syntax hilighting/.style={ + /codeexample/prettyprint/key name/.code={\textcolor{keycolor}{\pgfmanualpdfref{##1}{\noligs{##1}}}}, + /codeexample/prettyprint/key name with handler/.code 2 args={\textcolor{keycolor}{\pgfmanualpdfref{##1}{\noligs{##1}}}/\textcolor{blue!70!black}{\pgfmanualpdfref{/handlers/##2}{\noligs{##2}}}}, + /codeexample/prettyprint/key value display only/.code={\textcolor{keycolor}{{\itshape{\let\pgfmanualwordstartup\relax\pgfmanualprettyprintcode{##1}}}}}, + /codeexample/prettyprint/cs/.code={\textcolor{cscolor}{\pgfmanualcslinkpreskip4.25pt\pgfmanualpdfref{##1}{\noligs{##1}}}}, + /codeexample/prettyprint/cs with args/.code 2 args={\textcolor{black}{\pgfmanualcslinkpreskip4.25pt\pgfmanualpdfref{##1}{\noligs{##1}}}\{\textcolor{black}{\pgfmanualprettyprintcode{##2}}\pgfmanualclosebrace}, + /codeexample/prettyprint/cs arguments/pgfkeys/.initial=1, + /codeexample/prettyprint/cs/pgfkeys/.code 2 args={\textcolor{black}{\pgfmanualcslinkpreskip4.25pt\pgfmanualpdfref{##1}{\noligs{##1}}}\{\textcolor{black}{\pgfmanualprettyprintpgfkeys{##2}}\pgfmanualclosebrace}, + /codeexample/prettyprint/cs arguments/begin/.initial=1, + /codeexample/prettyprint/cs/begin/.code 2 args={\textcolor{black}{##1}\{\textcolor{cscolor}{\pgfmanualpdfref{##2}{\noligs{##2}}}\pgfmanualclosebrace}, + /codeexample/prettyprint/cs arguments/end/.initial=1, + /codeexample/prettyprint/cs/end/.code 2 args={\textcolor{black}{##1}\{\textcolor{cscolor}{\pgfmanualpdfref{##2}{\noligs{##2}}}\pgfmanualclosebrace}, + /codeexample/prettyprint/word/.code={\pgfmanualwordstartup{\begingroup\pgfkeyssetvalue{/pdflinks/search key prefixes in}{}\pgfmanualpdfref{##1}{\noligs{##1}}\endgroup}}, + /codeexample/prettyprint/point/.code={\textcolor{pointcolor}{\noligs{##1}}},% + /codeexample/prettyprint/point with cs/.code 2 args={\textcolor{pointcolor}{(\pgfmanualpdfref{##1}{\noligs{##1}}:\noligs{##2}}},% + /codeexample/prettyprint/comment font=\itshape, + /codeexample/prettyprint/base color/.initial=\color{basecolor}, + /pdflinks/render hyperlink/.code={% + {\setbox0=\hbox{##1}% + \rlap{{\color{linkcolor}\dimen0\wd0\advance\dimen0by-\pgfmanualcslinkpreskip\hskip\pgfmanualcslinkpreskip\vrule width\dimen0 height-1pt depth1.6pt}}% + \box0% + }% + } + },/codeexample/syntax hilighting +} + +\colorlet{keycolor}{black} +\colorlet{cscolor}{black} +\colorlet{pointcolor}{black} +\colorlet{basecolor}{black} +\colorlet{linkcolor}{black!8} + +\def\pgfmanualswitchoncolors{% + \colorlet{keycolor}{green!50!black}% + \colorlet{cscolor}{blue!70!black} + \colorlet{pointcolor}{violet} + \colorlet{basecolor}{black!55} + \colorlet{linkcolor}{white} +} + +\makeatletter + +\def\pgfmanualwordstartup{\textcolor{black}} + +\def\noligs#1{\pgfmanualnoligs#1\kern0pt--\pgf@stop}% +\def\pgfmanualnoligs#1--{% + \pgfutil@ifnextchar\pgf@stop{#1\pgfutil@gobble}{#1-\kern0pt-\kern0pt\pgfmanualnoligs}% +} +\makeatother + + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: "beameruserguide" +%%% End: diff --git a/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.pdf b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.pdf Binary files differnew file mode 100644 index 00000000000..268315a27a4 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.pdf diff --git a/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex new file mode 100644 index 00000000000..7b5a499f3e4 --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex @@ -0,0 +1,1836 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: spectralsequencesmanual.tex +%% +%% Manual content +%% + +% +% TODO: +% explain / cross reference examples folder? +% + + + +\input spectralsequencesmanualpreamble + + +\begin{document} +\newgeometry{margin = 4cm,nohead} +\begin{titlepage} +\title{\sseqpages} +\author{Hood Chatham\\\mailtoHC} +\date{\version\\\today} + \maketitle \thispagestyle{empty} + +\begin{abstract} +\noindent +The \sseqpages\space package is a specialized tool built on top of \pgfpkg/\tikzpkg\space for drawing spectral sequences. It provides a powerful, concise syntax for specifying the data of a spectral sequence, and then allows the user to print various pages of spectral sequence, automatically choosing which subset of the classes, differentials, and structure lines to display on each page. It also handles most of the details of the layout. At the same time, \sseqpages\space is extremely flexible. It is closely integrated with \tikzpkg\space to ensure that users can take advantage of as much as possible of its expressive power. It is possible to turn off most of the automated layout features and draw replacements using \tikzpkg\space commands. \sseqpages\space also has a carefully designed error reporting system intended to ensure that it is as clear as possible what is going wrong. + +Many thanks to the authors of \tikzpkg\space for producing such a wonderful package with such thorough documentation. I would have needed to spend a lot more time reading the \tikzpkg\space code if the documentation weren't so excellent. I took ideas or code or both from \tikzcdpkg\ (part of the code for turning quotes into class or edge labels), \pgfplotspkg\ (axes labels), and \sseqpkg\ (the grid styles, the stack). I lifted a fair amount of code from tex stack exchange. Thanks to Eric Peterson for being a very early adopter and reporting many bugs, to Eva Belmont for many productive conversations and for the idea of adding the stack traces for errors and to Vishal Arul and Catherine Ray for helpful suggestions. Also thanks to all my friends, family, and acquaintances listened to me talk about \LaTeX\ programming even though they probably found it dreadfully boring. +\end{abstract} +\end{titlepage} + +\restoregeometry +\stepcounter{page} +\newpage +\thispagestyle{empty} % Should the table of contents have a page number? +\tableofcontents +\newpage +\section{Introduction} +The \sseqpages\space package consists of two main environments -- the \sseqdataenv\space environment, which specifies the data for a named spectral sequence diagram, and the \sseqpageenv\space environment, which prints a single page of a spectral sequence diagram. The |\printpage| command is also available as a synonym for a \sseqpageenv\space environment with an empty body. + +Here is a basic example: +\begin{codeexample}[width = 9cm] +\begin{sseqdata}[ name = ex1, scale = 0.6, + cohomological Serre grading ] +\class(0,0) +\class(0,2) +\class(3,0) +\class(3,2) +\d3(0,2) +\end{sseqdata} +\printpage[ name = ex1, page = 3 ] \quad +\printpage[ name = ex1, page = 4 ] +\end{codeexample} +%TODO: +|\begin{sseqdata}[|| name = ex1, cohomological Serre grading]| starts the declaration of the data of a spectral sequence named |ex1| whose page $\mathtt{r}$ differentials go $\mathtt{r}$ to the right and down $\mathtt{r-1}$ -- that is, it has cohomological Serre grading. Then we specify four classes and one page 3 differential, and we ask \sseqpages\space to print the third and fourth pages of the spectral sequence. Note that on the fourth page, the source and target of the differential have disappeared. + +\subsection{A warning about fragile macros}%TODO: does this go here? somewhere else +All the data in a \sseqpages\space environment is stored and used later. As a result, most of the \sseqpages\space commands currently cannot tolerate fragile macros. Unfortunately, it is impossible for \sseqpages\space to warn you about this situation -- if you use a fragile command in a place that it doesn't belong, the result will be an incomprehensible error message. If you are getting nonsense error messages, this is probably why. The solution is to convert fragile macros into robust ones. \href{http://www.tex.ac.uk/FAQ-protect.html}{See here for more information.} + +\section{The Environments} +\begin{environment}{{sseqdata}\moptions} +The \sseqdataenv\space environment is for storing a spectral sequence to be printed later. This environment is intended for circumstances where you want to print multiple pages of the same spectral sequence. When using the \sseqdataenv\space environment, you must use the |name| option to tell \sseqpages\space where to store the spectral sequence so that you can access it later. +\end{environment} + +\begin{environment}{{sseqpage}\ooptions} +This environment is used for printing a page of existing spectral sequence that was already specified using the \sseqdataenv\space environment. The body of the environment adds local changes -- classes, differentials, structure lines, and arbitrary \tikzpkg\space options that are by default only printed on this particular page. The \sseqpageenv\space environment can also be used to print a standalone page of a spectral sequence -- that is, if you only want to print a single page of the spectral sequence, you can skip using the \sseqdataenv\space environment. +\end{environment} + +\needspace{5\baselineskip} +\begin{command}{\printpage\moptions} +This command prints a single page of an existing spectral sequence as-is. This is equivalent to a \sseqpageenv\space environment with an empty body. +\end{command} + + +\section{The main commands} +\begin{command}{\class\ooptions\parargtwo{x}{y}} +This places a class at |(x,y)| where |x| and |y| are integers. If multiple classes occur at the same position, \sseqpages\space will automatically arrange them in a pre-specified pattern. This pattern may be altered using the |class pattern| option. +\begin{codeexample}[] +\begin{sseqpage}[ no axes, ymirror, yscale = 0.8 ] +\class(0,0) +\class(1,0) \class(1,0) +\class(0,1) \class(0,1) \class(0,1) +\class(1,1) \class(1,1) \class(1,1) \class(1,1) +\class(0,2) \class(0,2) \class(0,2) \class(0,2) \class(0,2) +\class(1,2) \class(1,2) \class(1,2) \class(1,2) \class(1,2) \class(1,2) +\end{sseqpage} +\end{codeexample} + +The effect of the |\class| command is to print a \tikzpkg\ node on a range of pages. Any option that would work for a \tikzpkg\ |\node| command will also work in the same way for the |\class|, |\replaceclass|, and |\classoptions| commands. + +If a class is the source or the target of a differential on a certain page, then the page of the class is set to that page, and the class is only rendered on pages up to that number: +\begin{codeexample}[width = 8cm] +\begin{sseqdata}[ name = class example, + Adams grading, + yscale = 0.53 ] +\class(1,0) +\class(0,2) +\class(0,3) +\d2(1,0) +\end{sseqdata} +\printpage[ name = class example, page = 2 ] +\quad +\printpage[ name = class example, page = 3 ] +\end{codeexample} + +See the \pgfmanualpdfref{class options}{class options} section for a list of the sort of options available for classes. +\end{command} + +\begin{commandlist}{{\replaceclass\ooptions\parargthreeopt{x}{y}{n}},\replaceclass\ooptions\pararg{classname}} +After a class is the source or target of a differential, it disappears on the next page. However, some differentials are not injective or not surjective. Using the command |\replaceclass| causes a new symbol to appear on the page after a class supported or accepted a differential (or both). If there are multiple classes at the coordinate |(x,y)| you may specify which using an integer or a |tag| $n$. By default, this command will affect the first class placed in that position. You can also provide the |class:name| of a class. +\begin{codeexample}[] +\begin{sseqdata}[name = replace class example, Adams grading, classes = {draw = none } ] +\class["\mathbb{Z}"](0,3) +\class["\mathbb{Z}"](1,1) +\class["\mathbb{Z}"](1,0) +\d["\cdot 2"]2(1,1) +\replaceclass["\mathbb{Z}/2"](0,3) +\d[->>]3(1,0) +\replaceclass["2\mathbb{Z}"](1,0) +\end{sseqdata} +\printpage[ name = replace class example, page = 2 ] +\hskip1cm +\printpage[ name = replace class example, page = 3 ] +\hskip1cm +\printpage[ name = replace class example, page = 4 ] +\end{codeexample} +Note that this will not restore any structlines coming into or off of the class, if you want the structlines to persist, you must call |\structline| again (or use the structline |structline:page| option) +\end{commandlist} + +\begin{commandlist}{{\classoptions\moptions\parargthreeopt{x}{y}{n}},\classoptions\moptions\pararg{classname}} +This adds options to a class that already exists. This can be used in a \sseqpageenv\space environment to modify the appearance of a class for just one drawing of the spectral sequence, for instance to highlight it for discussion purposes. + +If there are multiple classes at the coordinate |(x,y)| you may specify which using an integer or a |tag| $n$. By default, this command will affect the first class placed in that position. You can also provide the |class:name| of a class. +\begin{codeexample}[width = 6cm] +\begin{sseqdata}[ name = class options example, + classes = fill ] +\class(2,1) +\foreach \x in {0,...,2} \foreach \y in {0,1} { + \class(\x,\y) +} +\end{sseqdata} +\begin{sseqpage}[ name = class options example, + right clip padding = 0.6cm ] +\classoptions[red](2,1,2) % Only is red on this page! +\node[ background, text width = 10em ] at (0.3,-2.2) + {\textup{The red class is the problem}}; +\end{sseqpage} +\end{codeexample} +Another reason to use this is to give a label to one instance of a class that shows up in a loop or a command defined using |\NewSseqGroup|: +\begin{codeexample}[width = 6cm] +\NewSseqGroup\mygroup {} { + \class(0,0) + \class(0,1) + \class(0,2) + \class(1,1) + \class(2,2) + \structline(0,0)(0,1) + \structline(0,1)(0,2) + \structline(0,0)(1,1) + \structline(1,1)(2,2) +} +\begin{sseqpage}[ classes = fill, class labels = { left = 0.3em } ] +\mygroup(0,0) +\mygroup(1,2) +\classoptions["2"](0,1) +\classoptions["\eta"](1,1) +\end{sseqpage} +\end{codeexample} +See the \pgfmanualpdfref{class options}{class options} section for a list of the sort of options available for classes. +\end{commandlist} + +\begin{commandlist}{ + {\d\ooptions\meta{page}\pars{\meta{x},\meta{y}\opt{,\sourcen,\targetn}}}, + {\d\ooptions\meta{page}\pars{\sourcename\opt{,\targetn}}}, + {\d\ooptions\meta{page}\pars{\sourcecoord}\pars{\targetcoord}}% +} +Calling |\d\meta{page}|\parargtwo{x}{y} creates a differential starting at \parargtwo{x}{y} of length determined by the specified page. In order to use the |\d| command like this, you must first specify the |degree| of the differentials as an option to the \sseqdataenv\space or \sseqpageenv\space environment. The degree indicates how far to the right and how far up a page $\mathtt{r}$ differential will go as a function of $\mathtt{r}$. If there is a page $\mathtt{r}$ differential, on page $\mathtt{r+1}$, the source, target, and any |\structline|s connected to the source and target of the differential disappear. + +If there are multiple nodes in the source or target, you may specify which one the differential should go to using an index or tag for \sourcen\space or \targetn. It is also possible to provide the name of the source coordinate and an optional target, or to separately provide the source and target coordinate, either as names or as \parargthree{x}{y}{n}. Using |\d| with explicit source and target coordinates works even if you did not provide a |degree| to the spectral sequence. If you did provide a |degree|, then \sseqpages\space will check whether the difference between the source and target is appropriate for a differential of a given page, and if not it will throw an error. If this is undesirable, you can use the |lax degree| option. +\begin{codeexample}[width = 7.5cm] +\begin{sseqdata}[ name = d example, degree = {-1}{#1}, + struct lines = blue, yscale = 1.3 ] +\class(0,2) +\class(1,2) +\class(1,1) +\class(1,0) +\structline(1,2)(0,2) +\structline(1,2)(1,1) +\structline(1,1)(1,0) +\d2(1,0) +\end{sseqdata} +\printpage[ name = d example, page = 2 ] +\hskip0.3cm +\printpage[ name = d example, page = 3 ] +\end{codeexample} +If there are multiple nodes in the source or target coordinate, then there is a funny syntax for indicating which one should be the source and target: +|\d\meta{page}\pars{\meta{x},\meta{y}\opt{,\sourcen,\targetn}}| +\begin{codeexample}[width = 7.5cm] +\begin{sseqpage}[ Adams grading, yscale = 0.8 ] +\class(1,0) \class(1,0) +\class(0,2) \class(0,2) +\d2(1,0,1,2) +\class(2,0) \class(2,0) +\class(1,2) +\d2(2,0,2) +\class(3,0) +\class(2,2) \class(2,2) +\d2(3,0,,2) +\end{sseqpage} +\end{codeexample} +Negative indices will count from the most recent class in the coordinate (so |-1| is the most recent, |-2| is the second most recent, etc). You can also use a |tag|, which works better if the situation is complicated. +\begin{codeexample}[width = 7.5cm] +\begin{sseqpage}[ Adams grading, yscale = 0.65 ] +\class(1,0) +\class(0,2) \class(0,2) +\d[blue]2(1,0,-1,-1) +\class(1,0) +\class(0,2) +\d[orange]2(1,0,-1,-1) +\class(1,0) +\d[red]2(1,0,-1,-2) +\end{sseqpage} +\end{codeexample} +\end{commandlist} + +\begin{commandlist}{ + {\doptions\moptions\meta{page}\pars{\meta{x},\meta{y}\opt{,\sourcen,\targetn}}}, + {\doptions\moptions\meta{page}\pars{\sourcename\opt{,\targetn}}}, + {\doptions\moptions\meta{page}\pars{\sourcecoord}\pars{\targetcoord}}% +} +This command adds options to an existing differential, just like |\classoptions| except for differentials. Its syntax is identical to that of |\d|. +\end{commandlist} + +\begin{command}{\structline\ooptions\pars{\sourcecoord}\pars{\targetcoord}} +This command creates a structure line from \sourcecoord\space to \targetcoord. The source and target coordinates are either of the form \pars{\meta{x},\meta{y}\opt{,\meta{n}}} or \pararg{class name}. If there are multiple classes at $\mathtt{(x,y)}$, then \meta{n} specifies which of the classes at $\mathtt{(x,y)}$ the structline starts and ends at -- if n is positive, then it counts from the first class in that position, if n is negative, it counts backwards from the most recent. You can also use a |tag| for n. + +If the source or target of a structure line is hit by a differential, then on subsequent pages, the structure line disappears. + +If the source or target has had multiple generations (i.e., they got hit and you used |\replaceclass|), then the |\structline| will only appear starting on the first page where the current generation of both the source and target are present. If this is undesirable, you can use the |structline:page| option to change it. +\begin{codeexample}[width = 9cm] +\DeclareSseqGroup\tower {} { + \class(0,0) + \foreach \y in {1,...,5} { + \class(0,\y) + \structline(\lastclass1)(\lastclass) + } + \class(0,2) + \structline(0,1,-1)(\lastclass) + \structline(\lastclass)(0,3,-1) +} +\begin{sseqdata}[ name = structline example, + classes = { circle, fill }, + Adams grading, no axes, + yscale = 1.39 ] +\class(1,1) \class(1,2) +\class(2,3) \class(2,3) \class(2,5) +\tower[classes = blue](0,0) +\tower[struct lines = dashed,orange](1,0) +\tower[struct lines = red](2,0) +\d2(1,1,2) +\end{sseqdata} +\printpage[name = structline example, page = 2] +\hskip1cm +\printpage[name = structline example, page = 3] +\end{codeexample} +\end{command} + +\begin{command}{\structlineoptions\moptions\pars{\sourcecoord}\pars{\targetcoord}} +This command adds options to an existing structure line, just like |\classoptions| except for structure lines. Its syntax is identical to |\structline|. +\end{command} + +\begin{command}{\circleclasses\ooptions\pars{\sourcecoord}\pars{\targetcoord}} +This command is a lot like |\structline| except that it puts a circle around the classes instead of connecting them with a line. It might take a certain amount of fiddling with options to get |\circleclasses| to produce good results. There is no |\circleclassesoptions| command because it doesn't seem necessary and (more importantly) I didn't feel like making one. Maybe someday I'll put one in. +\end{command} + +\begin{commandlist}{\draw,\path,\node,\clip} +Any code that would work in a \tikzpictureenv\space environment will also work unchanged in a \sseqdataenv\space or \sseqpageenv\space environment, with a few minor differences. This is a very flexible way to add arbitrary background or foreground features to the spectral sequence: +\begin{codeexample}[] +\begin{sseqdata}[ name = tikz example, Adams grading, math nodes = false, + tikz primitives = { blue, font = \tiny, <- }, circle classes = tikz primitive style, + x range = {0}{2}, x axis extend end = 2em ] +\class(0,0) +\class(1,0) +\class(0,2) +\d2(1,0) +\end{sseqdata} + +\begin{sseqpage}[ name = tikz example ] +\circleclasses[ name path = myellipse, inner sep = 3pt, ellipse ratio = 1.6 ] (1,0) (0,2) +\path[ name path = myline ] (1.3,1.25) -- (0.6,1); +\draw[ name intersections = { of = myellipse and myline } ] + (intersection-1) to (1.3,1.25) node[ right, text width = 1.6cm ] {Consider this differential}; +\end{sseqpage} \qquad + +\begin{sseqpage}[ name = tikz example ] +\draw[ xshift = 1 ] (0,0) to (0.6,0.2) node[ right, text width = 1.1cm ] {This is the source}; +\draw[ yshift = 2 ] (0,0) to (0.6,0.2) node[ right, text width = 1.1cm ] {This is the target}; +\end{sseqpage} \qquad + +\begin{sseqpage}[ page = 3, name = tikz example ] +\circleclasses[ name path = myellipse, inner sep = 3pt, ellipse ratio = 1.6 ] (1,0)(0,2) +\node[ right, font = \tiny ] at (1.2,1.2) {Now it's gone!}; +\end{sseqpage} +\end{codeexample} +\end{commandlist} + + +\section{Options for the main commands} +\subsection{Universal options} +The following options work with all of the drawing commands in this package, including |\class|, |\d|, and |\structline|, their friends |\replaceclass|, |\classoptions|, |\doptions|, and |\structlines|, as well as with \tikzpkg\ primitives. +\begin{keylist}{xshift = \meta{integer},yshift = \meta{integer}} +Shifts by integer values are the only coordinate changes that are allowed to be applied to |\class|, |\d|, |\structline|, their relatives, or to a \scopeenv\space environment that contains any of these commands. These shift commands help with reusing code. For instance: +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ cohomological Serre grading, yscale = 0.45 ] +\foreach \x in {0,1} \foreach \y in {0,1} { + \begin{scope}[ xshift = \x, yshift = \y ] + \class(2,0) + \class(0,1) + \d2(0,1) + \end{scope} +} +\end{sseqpage} +\end{codeexample} +This code segment is very useful so \sseqpages\space has the command |\NewSseqGroup| which to make code like this more convenient. The following code produces the same output as above: +\begin{codeexample}[code only,width = 6cm] +\NewSseqGroup\examplegroup {} { + \class(2,0) + \class(0,1) + \d2(0,1) +} +\begin{sseqpage} +\examplegroup(0,0) +\examplegroup(0,1) +\examplegroup(1,0) +\examplegroup(1,1) +\end{sseqpage} +\end{codeexample} + + +A word of warning: the behavior of |xshift| in \sseqpages\space is incompatible with the normal behavior of |xshift| in \tikzpkg. For some reason, saying |xshift = 1| in \tikzpkg\ does not shift the coordinate |(0,0)| to the coordinate |(1,0)| -- instead it shifts by 1pt. In \sseqpages\space, saying |xshift = 1| moves the coordinate |(0,0)| to the coordinate |(1,0)|. This includes \tikzpkg\ primitives: saying \codeverb|\draw[ xshift = 1 ] (0,0) -- (1,0);| inside a \sseqdataenv\space or \sseqpageenv\space environment is the same as saying \codeverb|\draw(1,0) -- (2,0);| despite the fact that this is not the case in the \tikzpictureenv\ environment. +\end{keylist} + +\begin{manualentry}{Colors} +These come from the \LaTeX\space \colorpkg\space package via \tikzpkg, so see the \href{\colormanualurl}{\colorpkg\space package documentation} for more information. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ classes = {fill,inner sep = 0.4em}, + no axes, scale = 1.3 ] +\class[red](0,0) +\class[blue](1,0) +\class[green](2,0) +\class[cyan](0,1) +\class[magenta](1,1) +\class[yellow](2,1) +\class[blue!50!red](0,2) % a 50-50 blend of blue and red +\class[green!30!yellow](1,2) % 70% green, 30% yellow +\class[blue!50!black](2,2) +\end{sseqpage} +\end{codeexample} +\end{manualentry} + +\begin{manualentry}{\pgfmanualpdflabel{""quotes}{}|"|\meta{text}|"|\opt{\meta{options}}} +Specify a label for a class, a differential, or a structure line. This uses the \tikzpkg\ quotes syntax. The options include anything you might pass as an option to a \tikzpkg\ node, including arbitrary coordinate transforms, colors, opacity options, shapes, fill, draw, etc. The behavior is a little different depending on whether you use it on a class or on a differential or struct line. + +For a class, the \meta{text} is placed in the position |inside| the node by default -- in effect, the \meta{text} becomes the label text of the node (so saying |\class["label text"](0,0)| causes a similar effect to saying |\node at (0,0) {label text};|). There are other position options such as |left|, |above left|, etc which cause the label text to be placed in a separate node positioned appropriately. If the placement is above, left, etc, then any option that you may pass to a \tikzpkg\ node will also work for the label, including general coordinate transformations. If the placement is ``inside'', then the only relevant \opt{\meta{options}} are those that alter the appearance of text, such as opacity and color. +\begin{codeexample}[width = 4cm] +\begin{sseqpage}[ classes = { minimum width = width("a") + 0.5em }, no axes ] +\class["a"](0,0) +\class["a",red](1,0) +\class["a" black,red](2,0) +\class["b" above](0,1) +\class["b" {below right,yshift = 0.1cm}](1,1) +\class["a" {above right = {1em}}](2,1) +\end{sseqpage} +\end{codeexample} +You can adjust the default behavior of class labels using the |labels| style option or its relatives |class labels|, |inner class labels| or |outer class labels|. +Note that it is also possible to give a label to a |\node| this way, although the behavior is slightly different. In particular, the label defaults to the |above| position instead of going in the |\node| text by default. Also, this won't respect the various label style options like |labels|, etc. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ no axes ] +\class(0,0) +\class(2,0) +\node[circle,fill,"a"] at (1,0) {}; +\end{sseqpage} +\end{codeexample} + +For either a |\structline| or a |\class| the label normally goes on the right side of the edge. The special |'| option makes it go in the opposite position from the default. I imitated the label handling in the \tikzcdpkg\ package, so if you use \tikzcdpkg, this should be familiar. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ Adams grading, yscale = 0.63 ] +\class(0,0) +\class(0,1) +\class(0,2) +\structline["a"' blue](0,0)(0,1) +\class(1,0) +\class(1,1) +\structline["b"](1,0)(1,1) +\d[ "\cdot 2" { pos = 0.7, yshift = -5pt } ] 2 (1,0) +\end{sseqpage} +\end{codeexample} +You can use the style options |labels|, |edge labels|, |differential labels|, and |struct line labels| to adjust the styling of edge labels. For instance, if you would prefer for the labels to default to the left hand side of the edge rather than the right hand side, you could say |edge labels = {auto = left}|. +You can also use quotes to label edges drawn with \tikzpkg\ primitives: +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ yscale = 0.58, no axes ] +\class(0,0) +\class(1,1) +\draw (1,0) to["hi"'{ pos = 0.7, yshift = -0.5em }] (0,1); +\end{sseqpage} +\end{codeexample} +The special option ``description,'' stolen from \tikzcdpkg, places the label on top of the edge. In order to make this option work correctly, if the background coolor is not the default white, you must inform sseqpages about this using the key |background color = |\meta{color}. In this document, the background color is called \textit{graphicbackground}. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ no axes, background color = graphicbackground ] +\foreach \x in {0,1,2} \foreach \y in {0,1} { + \class(\x,\y) +} +\structline["a" red](0,0)(0,1) +\structline["a'"'blue,"b"{yshift = 1em}](1,0)(1,1) +\structline["c" description](2,0)(2,1) +\end{sseqpage} +\end{codeexample} +\end{manualentry} + + + +\subsection{Options for \sectionstring\class}\pgfmanualpdflabel{class options}{} +Because the main job of the |\class| command is to print a \tikzpkg\ |\node| on the appropriate pages of the spectral sequence, most options that would work for a \tikzpkg\ node also work for the commands |\class|, |\replaceclass|, and |\classoptions|. Here are a few that you might care about: +\begin{manualentry}{A \tikzpkg\ shape} +If you give the name of a \tikzpkg\ shape, the class node will be of that shape. The standard \tikzpkg\ shapes are |circle| and |rectangle|. \sseqpages\ defines two new shapes: +\begin{key}{circlen = \meta{n}} +This draws $n$ concentric circles. It's intended for indicating a $\mathbb{Z}/p^n$ summand. For large values of $n$ the result isn't all that appealing. +\begin{codeexample}[] +\begin{sseqpage}[ no axes ] +\class[circlen = 2](0,0) +\class[circlen = 2,fill](1,0) +\class[circlen = 3](0,1) +\class[circlen = 4](1,1) +\end{sseqpage} +\end{codeexample} +\end{key} + +\begin{keylist}{newellipse,ellipse ratio = \meta{ratio}} +This shape is used for |\circleclasses|. It's a variant on the |ellipse| shape that gives more control over the ellipse's aspect ratio. +\end{keylist} + +There are many more \tikzpkg\ shapes in the shapes library, which you can load using the command |\usetikzlibrary{shapes}|. The following are some examples: +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ no axes, classes = { inner sep = 0.4em }, + class placement transform = { scale = 2 }, + yscale = 1.63 ] +\class(0,0) +\class[isosceles triangle](2,0) +\class[rectangle](1,0) +\class[diamond](0,1) +\class[semicircle](1,1) +\class[regular polygon, regular polygon sides = 5](2,2) +\class[regular polygon, regular polygon sides = 6](2,2) +\class[regular polygon, regular polygon sides = 7](2,2) +\class[regular polygon, regular polygon sides = 8](2,2) +\end{sseqpage} +\end{codeexample} +See the \href{\pgfmanualurl#section.49}{\tikzpkg\space manual} for more information. +\end{manualentry} + +\begin{keylist}{minimum width = \meta{dimension}, minimum height = \meta{dimension}, minimum size = \meta{dimension}, inner sep = \meta{dimension}, outer sep = \meta{dimension}} +These options control the size of a node. This is typically useful to make the size of nodes consistent independent of the size of their label text. For instance: +\begin{codeexample}[width = 5cm] +\begin{sseqdata}[ name = minimum width example, no axes, yscale = 0.8 ] +\class["ab"](0,0) +\class["a"](0,1) +\class(0,2) +\end{sseqdata} +\printpage[ name = minimum width example ] +\printpage[ name = minimum width example, + change classes = { blue, minimum width = width("ab") + 0.5em } ] +\end{codeexample} +\end{keylist} + +\begin{key}{class:name = \meta{node name}} +The |\class| command makes a \tikzpkg\ node on appropriate pages. You can refer to this node using \tikzpkg\ commands by using coordinates. Using the |class:name| option, you can give the node a second shorter name. One potential benefit to this is that it is immune to coordinate transformations. For example, in the following code, |xshift| does not apply to the nodes specified by |(id)| and |(eta)| but does apply to the coordinate specified by |(1,1)|: + +\begin{codeexample}[width = 6cm] +\begin{sseqpage} +\class[class:name = id](0,0) +\class[class:name = eta](1,1) +\class(2,1) +\draw[xshift = 1] (id) -- (eta); +\draw[xshift = 1,blue] (id) -- (1,1); +\end{sseqpage} +\end{codeexample} +\end{key} + +\begin{key}{tag = \meta{tag}} +This key adds a tag to the current class. Tags are used for identifying which of multiple classes in the same position you are referring to. They are useful when you have groups of related classes and want a family of differentials connecting them. For instance: +\begin{codeexample}[width = 8cm] +\DeclareSseqGroup\tower {} { + \class(0,0) + \foreach \i in {1,...,11} { + \class(0,\i) + \structline(0,\i-1,-1)(0,\i,-1) + } +} +\NewSseqGroup\hvee {} { + \tower(0,0) + \foreach \i in {1,...,11} { + \class(\i,\i) + \structline(\i-1,\i-1,-1)(\i,\i,-1) + } +} +\begin{sseqpage}[ degree = {-1}{1}, yscale = 1.1, + x range = {0}{5}, y range = {0}{5} ] +\tower(3,0) +\hvee[tag = id](0,0) +\hvee[tag = h21](4,2) +\foreach \n in {0,...,5} { + \d2(4+\n,2+\n,h21,id) +} +\end{sseqpage} +\end{codeexample} +We want each differential to go from the |h21| vee to the |id| vee, independent of which classes are in the same position of the two vees. The easy way to accomplish this is by giving tags to each of the two vees. +\end{key} + +\begin{key}{offset = \{\pars{\meta{x offset},\meta{y offset}}\}} +By default, a class uses the offset specified by |class pattern|. Occasionally this is undesirable. In this case, you can specify the offset for a particular class by hand. For example if the sum of two classes is hit by a differential, it looks better for the class replacing them to be centered: +\begin{codeexample}[width = 9cm] +\begin{sseqdata}[ name = offset example, + xscale = 0.7, + Adams grading, + class placement transform = {scale = 1.8} ] +\class(0,1) +\class(0,2)\class(0,2) +\draw(0,1)--(0,2); +\class(1,0) +\d2(1,0,,1) +\d2(1,0,,2) +\replaceclass(0,2) +\end{sseqdata} +\printpage[name = offset example, page=2] +\printpage[name = offset example, page=3] +\begin{sseqpage}[name = offset example, page=3] +\classoptions[offset = {(0,0)}](0,2) +\end{sseqpage} +\end{codeexample} +\end{key} + +\begin{key}{tooltip = \meta{text}} +This key generates a ``tooltip'' over the given class. That is, if you hover your mouse over it, a little window will popup with the tooltip text. This is particularly useful to give the coordinates or names of classes in large diagrams where it may be hard to tell from looking at the picture what position the class is in, or there may not be room to supply names to classes. + +The tooltip is made using the |\pdftooltip| command from the |pdfcomment| package. This cannot handle math, but it will print math expressions into tex input form. Not all pdf viewers will display the tooltip correctly. If this concerns you, the command |\sseqtooltip| is used to produce the tooltip, and you can redefine it as any other command that takes |\sseqtooltip|\marg{text}\marg{tooltip text} and produces a tooltip. For instance, on \href{https://tex.stackexchange.com/a/164186/23866}{this stack exchange post}, there is code that supposedly produces tooltips that work with Evince. I have not tested whether it works by itself or whether it works with my package, but you could. You could potentially figure out how to get math to work in tooltips too -- if you find a satisfactory method, please let me know. + +Anyways, here's an example: +\begin{codeexample}[] +\begin{sseqpage}[classes = {tooltip = {(\xcoord,\ycoord)}}] +\class(0,0) +\class(0,1) +\class(1,0) +\class(1,1) +\end{sseqpage} +\end{codeexample} + +There's another example at the beginning of the section on the \hyperref[sec:class stack]{class stack}. +\end{key} + +\begin{keylist}{class:page = \meta{page}\opt{-{}-\meta{page max}},generation = \meta{generation}\opt{-{}-\meta{generation max}}} +These options only work in |\classoptions|. The |page| option gives a range of pages for which the options apply to. If only one page is specified, it is the minimum page and the option applies to all larger pages. +\begin{codeexample}[width = 6cm] +\begin{sseqdata}[ name = page_example, no axes, + title = \page, title style = {yshift = -0.5cm} ] +\class(0,0) +\classoptions[class:page = {2--3},fill,blue](0,0) +\end{sseqdata} + +\printpage[ name = page_example, page = 1 ] \qquad +\printpage[ name = page_example, page = 2 ] \qquad +\printpage[ name = page_example, page = 4 ] +\end{codeexample} +A ``generation'' of a class is the interval from one call of |\class| or |\replaceclass| to the page on which it next supports or is hit by a differential. +By default the |\classoptions| command adds options only to the most recent generation of the class in a \sseqdataenv\space environment, or on the generation appropriate to the current page in a \sseqpageenv\space environment. Using the |generation| option allows you to provide a single generation or range of generations of the class that the options should apply to. The first generation is generation 0, and the most recent generation is generation -1. Larger negative values count backwards. +\begin{codeexample}[] +\begin{sseqdata}[ name = page_example2, Adams grading, xscale = 0.6, yscale = 0.5 ] +\class(0,2)\class(1,0) +\d2(1,0) +\replaceclass(1,0) +\class(0,3) +\d3(1,0) +\replaceclass(1,0) +\classoptions[fill,red](1,0) % (a) applies to most recent (last) generation. +\end{sseqdata} + +\printpage[ name = page_example2, page = 1 ] % generation 0 of (1,0), not styled +\quad +\begin{sseqpage}[ name = page_example2, page = 1, keep changes ] +\classoptions[fill,blue](1,0) % (b) applies to the generation present on page 1, that is, generation 0. +\end{sseqpage} \quad + +% generation 0 of (1,0), so class is blue from (b) +\printpage[ name = page_example2, page = 2 ] \quad + +% generation 1 of (1,0), class is not styled +\printpage[ name = page_example2, page = 3 ] \quad + +% generation 2 of (1,0), class is red from (a) +\printpage[ name = page_example2, page = 4 ] +\end{codeexample} + +\begin{codeexample}[] +\begin{sseqdata}[ name = page_example2, Adams grading,update existing ] +% (c) applies to all generations, overwrites (b) and (a): +\classoptions[fill, red, generation = 0 ---- -1](1,0) +\end{sseqdata} + +\printpage[ name = page_example2, page = 1 ]% generation 0 of (1,0), so class is red +\quad +\begin{sseqpage}[ name = page_example2, page = 1, keep changes ] +\classoptions[fill,blue](1,0) % (d) applies to the generation present on page 1, that is, generation 0. +\end{sseqpage} \quad + +% generation 0 of (1,0), class is blue from (d) +\printpage[ name = page_example2,page = 2 ] \quad + +% generation 1 of (1,0), class is red from (c) +\printpage[ name = page_example2, page = 3 ] +\quad +\printpage[ name = page_example2, page = 4 ] % generation 2 of (1,0), class is red from (c) +\end{codeexample} +\end{keylist} + +\begin{commandlist}{\xcoord,\ycoord} +These commands represent the $\mathtt{x}$ and $\mathtt{y}$ coordinate of the current class when used in class options. The only use I have for them is in the |tooltip| option, but maybe there is some other purpose for them. +\end{commandlist} + + +\subsection{Options for \sectionstring\d\ and \sectionstring\structline} +Because the main job of the |\d| and |\structline| commands is to print an edge on the appropriate pages of the spectral sequence, most \tikzpkg\ options that you could apply to a \tikzpkg\ ``to'' operator (as in |\draw (x1,y1) to (x2,y2);|) can be applied to both |\d| and |\structline|. Some such options are as follows: + +\begin{keylist}{source anchor = \meta{anchor}, target anchor = \meta{anchor}} +Because you can't use the normal \tikzpkg\ mechanism for specifying the source and target anchors, \sseqpages\space has these two keys for |\d| and |\structline|: +\begin{codeexample}[width = 4cm] +\begin{sseqpage}[ no axes, yscale = 1.24 ] +\foreach \x in {0,1} \foreach \y in {0,1} { + \class(\x,\y) +} +\structline(0,0)(0,1) +\structline[ source anchor = north west, target anchor = -30 ](1,0)(1,1) +\end{sseqpage} +\end{codeexample} +\end{keylist} + + +\begin{keylist}{shorten > = \meta{distance}, shorten < = \meta{distance}} +These behave exactly like the corresponding options from \tikzpkg\space, shortening the end and beginning of the edge respectively. Note that you can lengthen the edge by shortening by a negative amount. +\end{keylist} + +\begin{manualentry}{Dash patterns:} +See the \href{\pgfmanualurl#subsubsection.15.3.2}{\tikzpkg\space manual} for a complete explanation of the dash pattern related options. Some examples: +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ no axes, yscale = 1.6 ] +\foreach \x in {0,1,2} \foreach \y in {0,1} { + \class(\x,\y) +} +\structline[densely dotted](0,0)(0,1) +\structline[dashed,red, "a"](1,0)(1,1) +\structline[dash dot,red, "a" black](2,0)(2,1) +\end{sseqpage} +\end{codeexample} +% +\end{manualentry} + +\begin{keylist}{bend left = \meta{angle}, bend right = \meta{angle}, *in = \meta{anchor}, *out = \meta{anchor}} +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[no axes,yscale = 1.6] +\foreach \x in {0,1,2} \foreach \y in {0,1} { + \class(\x,\y) +} +\structline[bend left = 20](0,0)(0,1) +\structline[bend right = 20](1,0)(1,1) +\structline[in = 20,out = north](2,0)(2,1) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\begin{key}{invisible} +This key is only for |\d|. It prevents a differential from being drawn at all. The typical reason you might want this is so that you can draw your own differential using \tikzpkg\space commands. See |\getdtarget| for an example of this. +\end{key} + +\begin{key}{structline:page = \meta{page}\opt{-{}-\meta{page max}}} +This key is only for |\structline| and |\structlineoptions|. By default, the |\structline| command only adds a structline starting on the page where the most recent generation of the source or target is born: + +\begin{codeexample}[width = 7.6cm] +\begin{sseqdata}[ name = structpage example, + title = \page, yscale = 0.53 ] +\class(0,2) +\class(0,4) +\class(1,0) +\class(1,1) +\d2(1,0)(0,2) +\d3(1,1)(0,4) +\replaceclass(1,0) +\replaceclass(1,1) +\structline(1,0)(1,1) +\end{sseqdata} +\printpage[name = structpage example,page = 3] +\qquad +\printpage[name = structpage example,page = 4] +\end{codeexample} + +By specifying a page number, you can adjust which page the |\structline| starts on: + +\begin{codeexample}[] +\begin{sseqdata}[ name = structpage example2, title = \page, yscale = 0.5 ] +\class(0,2) +\class(0,4) +\class(1,0) +\class(1,1) +\d2(1,0)(0,2) +\d3(1,1)(0,4) +\replaceclass(1,0) +\replaceclass(1,1) +\structline[structline:page = 2](1,0)(1,1) +\end{sseqdata} +\printpage[name = structpage example2,page = 1] +\qquad +\printpage[name = structpage example2,page = 2] +\qquad +\printpage[name = structpage example2,page = 3] +\qquad +\printpage[name = structpage example2,page = 4] +\end{codeexample} + +Similarly, for |\structlineoptions| you can specify a minimum page on which to apply the options, or a range of pages. +\end{key} + +\subsection{Options for \sectionstring\circleclass} +\begin{key}{fit = \meta{coordinates or nodes}} +The |\circleclasses| command uses the \href{\pgfmanualurl#section.52}{\tikzpkg\space fitting library}. Sometimes it's desirable to make the resulting node fit extra things, for example a label. It doesn't necessarily end up looking great though. +\begin{codeexample}[] +\begin{sseqpage}[Adams grading,axes gap = 0.7cm] +\class(0,2) +\class(1,0) +% Fit in the label x and also a symmetric invisible label to maintain symmetry +\d["x"{name = x},"x"'{name = x',opacity = 0}]2(1,0) +\circleclasses[fit = (x)(x'),rounded rectangle](1,0)(0,2) +\end{sseqpage} +\end{codeexample} +\end{key} + +\begin{key}{rounded rectangle} +You can put a shape as an option and it will change the shape of the node drawn by |\circleclasses|. Any shape will do, but I think that an |ellipse| or |rounded rectangle| are the only particularly appealing options. +\end{key} + +\begin{key}{ellipse ratio = \meta{ratio} (initially 1.2)} +By default, the shape drawn by |\circleclasses| is a ``newelipse'' which is a custom defined shape that respects the option |elipse ratio| which roughly controls how long and skinny versus short and fat the ellipse is. If you find that the ellipse is too long, try a larger value of this option, and conversely if it's too fat try a smaller value. If no value is satisfactory, try out the |rounded rectangle| shape. (This is stolen from the following stack exchange answer: \url{https://tex.stackexchange.com/a/24621}.) +\end{key} + +\begin{keylist}{cc:class style,cc:permanent cycle style,cc:transient cycle style,cc:this page class style,cc:differential style,cc:struct line style} +See the \pgfmanualpdfref{class style}{corresponding entry} in the \tikzpkg\space primitives section. +\end{keylist} + +\begin{key}{cc:page = \meta{page}\opt{-{}-\meta{page max}}} +By default, the ellipse will be drawn on the same set of pages that a structline between the two classes would be drawn on. This specifies a range of pages for the ellipse to be drawn. Note that unlike with structlines, you can instruct \circleclasses\ to draw the shape even on pages where one or both of the classes that it is fitting are dead. +\end{key} + +\subsection{Options for \tikzpkg\space primitives} +\begin{key}{background} +This key instructs \sseqpages\space to put the current \tikzpkg\space primitive in the background. The way that the spectral sequence is printed is as follows: +\begin{itemize} +\item The title, axes, axes ticks, and axes labels are printed (the appropriate steps are skipped when the |no title|, |no axes|, |no ticks|, or |no labels| keys are used or if no title or axes labels are provided). + +\item The \tikzpkg\space background paths are printed. + +\item The clipping is inserted (unless the |no clip| key is used). + +\item All foreground elements (classes, differentials, structlines, and normal \tikzpkg\space paths) are printed. +\end{itemize} + +In particular, this means that foreground \tikzpkg\space paths can be clipped by the standard clipping, but background paths that are outside of the clipping expand the size of the \tikzpkg\space picture. +\begin{codeexample}[] +\begin{sseqpage}[no ticks,yscale = 0.9,math nodes = false] +\class(0,0) +\class(1,1) +\begin{scope}[background] +\draw(0.1,0.1)--(1.1,1.1); +\end{scope} +\node[background] at (0.5,-1) {not clipped}; +\node at (0.5,-0.4) {clipped}; +\end{sseqpage} +\end{codeexample} +Here is an example where \tikzpkg\ labels with the |background| key are used to add labels and a grid. Note that this styling is easier to make using the |title|, |x label|, |y label|, and |grid| options. +\begin{codeexample}[] +\begin{sseqdata}[ name = tikz background example, cohomological Serre grading, classes = fill ] +\begin{scope}[background] +\node at (\xmax/2,\ymax+1.2) {\textup{Page \page}}; +\node at (\xmax/2,-1.7) {H^*(B)}; +\node[rotate = 90] at (-1.5,\ymax/2) {H^*(F)}; +\draw[step = 1cm, gray, very thin] (\xmin-0.5,\ymin-0.5) grid (\xmax+0.4,\ymax+0.5); +\end{scope} +\class(0,0) +\class(3,0) +\class(0,2) +\class(3,2) +\d3(0,2) +\end{sseqdata} +\printpage[name = tikz background example, page = 2] +\printpage[name = tikz background example, page = 3] +\end{codeexample} + +For this particular use case, it's and probably better to use |title|, |x label|, and |y label|: +\begin{codeexample}[] +\begin{sseqdata}[ name = tikz background example2, cohomological Serre grading, classes = fill, + grid = go, title = { Page \page }, x label = { $H^*(B)$ }, y label = { $H^*(F)$ }, + x label style = { yshift = 10pt}, y label style = { xshift = 10pt } ] +\class(0,0) +\class(3,0) +\class(0,2) +\class(3,2) +\d3(0,2) +\end{sseqdata} +\printpage[name = tikz background example2, page = 2] +\printpage[name = tikz background example2, page = 3] +\end{codeexample} + +But if you need more flexible labeling, you'll likely want to use tikz primitives with |background|. See \example{KF3} for an instance where this key is useful. +\end{key} + +\begin{keylist}{page constraint = \meta{predicate}, page constraint or = \meta{predicate}} +This places a constraint on the pages in which the \tikzpkg\space primitive is printed. This predicate should look something like +\texttt{(\string\page< = 4)} |&&| \texttt{(\string\page> = 3)}. The predicate is anded together with any previous predicates, so that you can use this as an option for a \scopeenv\space and again for the individual \tikzpkg\ primitive. + +\begin{commandlist}{\isalive\pararg{coordinate},\isalive\{\pararg{coordinate 1}$\cdots$\pararg{coordinate n}\}} +This command can only be used with |page constraint|. Saying +$$|page constraint = ||{|\pars{\meta{x},\meta{y}\opt{,\meta{index}}}|}}|$$ +will print the \tikzpkg\space primitive only on pages where the specified class is alive. Saying +$$|page constraint = ||{\isalive|\pars{\meta{coordinate 1}}\,\cdots\,\pars{\meta{coordinate n}}|}|$$ +is equivalent to +$$|page constraint = ||{\isalive|\pararg{coordinate 1}| &&|\,\cdots\,|&& \isalive|\pararg{coordinate n}|}|$$ +Writing +$$|\draw[||page constraint = ||{\isalive(1,0)(2,2)}](1,0)|\texttt{-{}-}|(2,2);|$$ +is the same as |\structline(1,0)(2,2)|, except that you can't later use |\structlineoptions| on it (and it won't have the |struct lines| style applied). +\end{commandlist} +\end{keylist} + +\begin{keylist}{class style,permanent cycle style,transient cycle style,this page class style,differential style,struct line style} +These classes apply the styling of the corresponding element to your \tikzpkg\space commands. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ differentials = blue, yscale = 0.65, no axes ] +\class(0,2) +\class(1,0) +% This will be styled as if it were a differential +\draw[differential style] (1,0) -- (0,2); +\end{sseqpage} +\end{codeexample} +See |\getdtarget| for a more natural example. +\end{keylist} + + + +\section{Miscellaneous commands} +\begin{command}{\sseqset\marg{keys}} +The |\sseqset| command is for adjusting the global options for all spectral sequences in the current scope, or for applying options to the rest of the current spectral sequence. For instance, if most of the spectral sequences in the current document are going to be Adams graded, you can say |\sseqset{Adams grading}| and all future spectral sequences in the current scope will have Adams grading (unless you specify a different grading explicitly). As another example, |\sseqset{no axes}| will suppress axes from spectral sequences in the current scope. Note that defaults only apply to new \sseqdataenv\ environments or to unnamed \sseqpageenv\ environments; they won't apply to existing spectral sequences. + +You can also use |\sseqset| to create styles to be used in spectral sequences. +\begin{keylist}{ + .global sseq style = \meta{keys}, + .global sseq append style = \meta{keys}, + .sseq style = \meta{keys}, + .sseq append style = \meta{keys} +} +These handlers create reusable styles to be used in spectral sequences. If this style is a set of global options, then use the |.global sseq style| handler, whereas if it is supposed to be applied to individual features (classes, differentials, struct lines, circle classes, and tikz primitives) then use the |.sseq style| handler. +\begin{codeexample}[width=6cm] +\sseqset{ + mysseq/.style = { + Adams grading, title = Page \page, + x range = {0}{4}, y range = {0}{2}, + xscale = 0.5, yscale = 1.35 + }, + htwostruct/.sseq style = { gray, thin } +} +\begin{sseqpage}[ mysseq ] +\class(0,0) \class(0,1) \class(0,2) \class(0,3) +\class(3,1) \class(3,2) \class(3,3) +\structline(0,0)(0,1) \structline(0,1)(0,2) \structline(0,2)(0,3) +\structline(3,1)(3,2) \structline(3,2)(3,3) +\structline[htwostruct](0,0)(3,1) +\structline[htwostruct](0,1)(3,2) +\structline[htwostruct](0,2)(3,3) +\end{sseqpage} +\end{codeexample} +\end{keylist} +\end{command} + +\begin{command}{\foreach} +This command is from \tikzpkg\space and works in pretty much the same way in \sseqpages, though with slightly better variants. The |\foreach| command is very flexible and has a lot of variants. See the \href{\pgfmanualurl#section.64}{\tikzpkg\space manual} for more details. +\end{command} + +\begin{command}{\sseqerrortowarning\meta{error-name}} +Turns the error with the given name into a warning. An error message will start by saying |sseqpages error: "error-name"|. This is the name you need to put into this command. +\end{command} + +\begin{command}{\sseqnormalizemonomial} +This command simplifies a monomial by combining like variables and removing bases that are raised to the 0th power, removing exponents of 1, removing 1's, and replacing the empty monomial with 1. It outputs its result into |\processedlabel|. This command is specifically meant to be used as a value for |class label handler|, so see the example there for the actual purpose. The exponents must be integers or else it will misbehave. +\begin{codeexample}[] +\sseqnormalizemonomial{x^0y^0} $\processedlabel$, \quad +\sseqnormalizemonomial{x^3yx^{-1}z^0} $\processedlabel$, \quad +\sseqnormalizemonomial{1x_2^2x^2_2} $\processedlabel$ +\end{codeexample} +\end{command} + +\begin{commandlist}{\NewSseqCommand \texttt{\textbackslash}\meta{command}\marg{argspec}\marg{body}, + \DeclareSseqCommand\texttt{\textbackslash}\meta{command}\marg{argspec}\marg{body}} +The \xparsepkg\ package provides these very powerful commands for defining macros. They are used internally to the \sseqpages\space package to define |\class|, |\d|, etc. To help you create variants of these commands, I will record here the argument specifications for each of them. See the \href{\xparseurl}{\xparsepkg\ manual} for a better explanation and more information. + +To make a command like |\class|, you can use the argument specification |O{}r()|. The argument type \texttt{O\marg{default}} stands for a bracket delimited optional argument with default value \meta{default}. In this case, we've specified the default to be empty. |r()| stands for a ``required'' argument delimited by |(| and |)|. In the command definition, access the optional argument with |#1| and the coordinate with |#2|. +\begin{codeexample}[width = 6.5cm,vbox] +\DeclareDocumentCommand\demo{ O{} r() } + { \#1 = \textcolor{purple}{\{#1\}}; + \#2 = \textcolor{purple}{\{#2\}} } +\hbox{\demo[key = value](x,y)} +\bigskip +\hbox{\demo(1,2,3)} +\end{codeexample} +% TODO: explain what u does better +If you want to separate out the coordinates into different arguments, you can use |O{}u(u,u)|. The argument type |u| stands for ``until'' and scans up until the next instance of the given character. So in this case, |#1| is of argument type |O| which is an option list, |#2| corresponds to the |u(| which is a throw-away argument, then |#3| corresponds to |u,| and contains the $\mathtt{x}$ coordinate, and |#4| corresponds to |u)| and contains the $\mathtt{y}$ coordinate. Note however that this will not match balanced parenthetical expressions. +\begin{codeexample}[width = 6.5cm,vbox] +\DeclareDocumentCommand\demo{ O{} u( u, u)} + { \#1 = \textcolor{purple}{\{#1\}}; + \#3 = \textcolor{purple}{\{#3\}}; + \#4 = \textcolor{purple}{\{#4\}} } +\hbox{\demo[hi](x,y)} +\bigskip +\hbox{\demo(1,2)} +\bigskip +\hbox{\demo((1+1)*2,2)} +\bigskip +\hbox{\demo(1,(1+1)*2)} % uh-oh -- *2) is left off! +\end{codeexample} +You can specify an optional argument delimited by parentheses using |d()|. Use the commands |\IfNoValueTF|, |\IfNoValueT|, and |\IfNoValueF| to test whether the user provided a value. +\begin{codeexample}[width = 6.5cm,vbox] +\DeclareDocumentCommand\demo{ O{} d() } { + \#1 = \textcolor{purple}{\{#1\}}; + \#2 = \textcolor{purple}{ + \{\IfNoValueTF{#2}{no value}{#2}\} } +} +\hbox{\demo[hi](x,y)} +\bigskip +\hbox{\demo[options]} +\bigskip +\hbox{\demo(1,2)} +\bigskip +\hbox{\demo} +\end{codeexample} +An example where this is actually useful: +\begin{codeexample}[width = 6.5cm] +\DeclareSseqCommand\etaclass{ O{} d() }{ + \IfNoValueF{#2}{ \pushstack(#2) } + \class[#1] (\lastx+1, \lasty+1) + \structline (\lastclass) (\lastclass1) +} +\begin{sseqpage}[ classes = fill, yscale = 0.55 ] +\class(0,0) +\class(0,1) +\etaclass\etaclass +\etaclass[blue](0,0)\etaclass +\end{sseqpage} +\end{codeexample} + + +The |\d| command has argument specification |O{} U( r()|. The argument type |U| is special to \sseqpages, and is a variant of until that reinserts the delimiting token. This allows the |(| token to also delimit the beginning of the |r()| argument. Note that the argument type |U| is specially added by \sseqpages\ and might be removed in the future if the \LaTeX3 team yells at me or something. +\begin{codeexample}[width = 7cm,vbox] +\DeclareDocumentCommand {\demo} { O{} U( r() } + { \#1 = \textcolor{purple}{\{#1\}}; + \#2 = \textcolor{purple}{\{#2\}}; + \#3 = \textcolor{purple}{\{#3\}} } +\hbox{\demo[opts]page(x,y)} +\bigskip +\hbox{\demo5(x,y)} +\end{codeexample} + +The |\structline| and |\changeclasses| commands have argument specification |O{}r()r()|. +\begin{codeexample}[width = 7cm,vbox] +\DeclareDocumentCommand\demo{ O{} r() r() } + { \#1 = \textcolor{purple}{\{#1\}}; + \#2 = \textcolor{purple}{\{#2\}}; + \#3 = \textcolor{purple}{\{#3\}} } +\hbox{\demo[hi](x,y)(x',y')} +\bigskip +\hbox{\demo(x,y,2)(x',y',-1)} +\end{codeexample} +\end{commandlist} + +\begin{commandlist}{\NewSseqGroup\texttt{\textbackslash}\meta{command}\oarg{argspec}\marg{body}, + \DeclareSseqGroup\texttt{\textbackslash}\meta{command}\oarg{argspec}\marg{body}} +% TODO: explain me +So that calling |\mygroup(x,y)| prints the whole group shifted to start at $\mathtt{(x,y)}$ instead of $\mathtt{(0,0)}$. For instance: +\begin{codeexample}[width = 8cm] +\DeclareSseqGroup\tower {m} { + \class(0,0) + \foreach \n in {1,...,#1} { + \class(0,\n) + \structline(0,\n-1)(0,\n) + } +} +\begin{sseqpage} +\tower[orange](0,0){4} +\tower[red](1,1){2} +\end{sseqpage} +\end{codeexample} +\end{commandlist} + +\begin{command}{\getdtarget\marg{macro}\marg{page}\pars{\sourcecoord}} +Sets \meta{macro} equal to the coordinates of the target position of a length \meta{page} differential starting at \sourcecoord. This helps to make commands that draw fancy differentials. For instance, consider the following example, suggested by Catherine Ray: +\begin{codeexample}[] +% O{}u(u) is the arg-spec for \d, O{}u(u)mm looks like \d with two extra mandatory arguments +\NewSseqCommand{\twods}{ O{} U( r() m m }{ + \getdtarget\target#2{#3} % Store the target position in \target + \nameclass{source}(#3) % naming the classes gives us a speed boost + \nameclass{target1}(\target,#4) % by preventing sseqpages from reparsing the coordinate + \nameclass{target2}(\target,#5) % it also makes the code easier to read +% + \circleclasses[ cc:differential style, #1, + name path = circ, page = #2--#2 ] + (target1)(target2) % Circle the classes, use differential style +% + \d[invisible]#2(source)(target1) % don't draw anything, but record source and targets as hit. + \d[invisible]#2(source)(target2) +% + \path(target1)--(target2) + coordinate[midway](midpt);% put a coordinate in the center of the two classes + \path[name path = lin] (source) -- (midpt);% save path from start to midpoint +% + % draw line in "differential style" from start to intersection point of circ and lin + \draw[ cc:differential style, #1, page constraint= { \page == #2 }, + name intersections = { of = circ and lin } ] + (source) -- (intersection-1); +} +\begin{sseqdata}[ name = cathex, Adams grading, differentials = { blue } ] +\class(0,2) +\class(0,2) +\class(1,0)\class(1,0) + +\twods2(1,0,-1){1}{2} +\end{sseqdata} +\printpage[ name = cathex, page = 1 ] +\qquad +\printpage[ name = cathex, page = 2 ] +\qquad +\printpage[ name = cathex, page = 3 ] +\end{codeexample} +\end{command} + +\begin{command}{\nameclass\marg{name}\pararg{coordinate}} +The |\nameclass| command gives a name to a class. It's similar to saying |\doptions[name = |\meta{name}|]|, but faster. It's also similar to saying |\pushstack|\pararg{coordinate}. Giving temporary names to coordinates that you are going to use repeatedly makes the code easier to read and is faster (though this only matters in very large diagrams). See |\getdtarget| for an example. +\end{command} + +\begin{command}{\tagclass\marg{tag}\pararg{coordinate}} +The |\tagclass| command gives a tag to a class. It's similar to saying |\doptions[tag = |\meta{name}|]|, but faster. See \example{tmfmayss} for a use case for this. +\end{command} + +\begin{command}{\gettag\texttt{\textbackslash}\meta{somecontrolsequence}\pararg{coordinate}} +The |\gettag| command finds the most recent tag applied to the coordinate and stores it into the command. This is useful for connecting groups of nodes. For example, consider the following code, inspired by \example{tmfmayss}. +\begin{codeexample}[width=6cm] +\DeclareSseqCommand \tower { O{} } { + \begin{scope}[#1] + \foreach\i in {1,...,7}{ + \class(\lastx,\lasty+1) + \structline(\lastclass1)(\lastclass) + } + \end{scope} + \restorestack +} +\DeclareSseqCommand \htwotower { O{} d() } { + \IfNoValueF{#2}{ + \pushstack(#2) + } + \begin{scope}[#1] + \gettag\thetag(\lastclass) + \class(\lastx+3,\lasty+1) + \structline[gray](\lastclass)(\lastclass1) + \savestack + \foreach\i in {1,...,7}{ + \class(\lastx,\lasty+1) + \structline(\lastclass1)(\lastclass) + \structline[gray](\lastx-3,\lasty-1,\thetag)(\lastclass) + } + \restorestack + \end{scope} +} +\begin{sseqpage}[ y range = {0}{6}, x tick step = 3, + xscale=0.6, yscale=1.3 ] +\class(0,2) \class(0,3) \class(3,2) +\class[tag=h_0^i](0,0) +\tower[tag=h_0^i] +\class(0,2) \class(0,1) + +\htwotower[tag=h_2 h_0^i](0,0) +\htwotower[tag=h_2 h_0^i] +\end{sseqpage} +\end{codeexample} +\end{command} + + +\subsection{The Class Stack} +\label{sec:class stack} +The class stack is a linked list of the classes in the order that they are produced that \sseqpages\space maintains. I've only recently implemented this feature, so it is more liable to change in the future than other things. Whenever you use the |\class| function, the class you added is pushed onto the stack. Here's an example that demonstrates basic usage: + + +The following commands are used to access the stack: + +\begin{commandlist}{\lastx\opt{\meta{n}},\lasty\opt{\meta{n}},\lastclass\opt{\meta{n}}} +The commands |\lastx| and |\lasty| evaluate to the |x| and |y| position, respectively, of the $n$th class on the stack. If $n = 0$ you can leave it off. +The command |\lastclass| evaluates to the coordinate of +\end{commandlist} + + +\begin{command}{\pushstack\pararg{coordinate}} +This adds a class to the top of the stack. The coordinate is specified using the same syntax as a coordinate for |\structline| or |\replaceclass|. +\end{command} + +\begin{commandlist}{\savestack,\restorestack} +This saves and reverts the stack. Saves nest. Most frequently, you will want to use these at the start and end of a command. +\end{commandlist} + + +\section{Styles} +The \sseqpages\space package has a large number of styles which control the appearance of specific components (e.g., classes, differentials, or structlines) of a spectral sequence. Each style has two corresponding keys: |classes| and |change classes|. Saying |classes = |\marg{keys} adds the keys to the list of options used to style every future class, whereas |change classes = |\marg{keys} only makes sense in a \sseqpageenv\space environment, and temporarily overwrites the list of options. Note that |change classes| only applies to classes that existed before the current page, and that even with the |keep changes| option, the |change classes| options are local to the current page. Compare: +\begin{codeexample}[width = 8cm] +\begin{sseqdata}[ name = stylesex ] +\class(0,0)\class(1,1) +\end{sseqdata} +\begin{sseqpage}[ name = stylesex, + classes = { fill, blue }, + title = change new classes ] +\class(0,1)\class(1,0) +\end{sseqpage} +\quad +\begin{sseqpage}[ name = stylesex, + change classes = { fill, blue }, + title = change old classes ] +\class(0,1)\class(1,0) +\end{sseqpage} +\end{codeexample} + +You can modify these styles outside of a spectral sequence or inside it using |\sseqset|, you can modify them as options to the \sseqdataenv\space and \sseqpageenv\space environments, or you can modify them as arguments to the \scopeenv\space environment. + +In cases where the same drawing feature is affected by multiple of these styles, the more specific style takes precedence. For instance, for a class that is the source or target of a differential on the current page, the precedence order from lowest to highest goes: |sseq style|, |class style|, |transient cycle style|, |this page cycle style|, and then any options from scopes in the order they appear, and any local options (the options that come right with the class, e.g., |\class[local options](x,y)|). If you don't want the options to your scopes to override more specific styles, use |sseq|: +\begin{codeexample}[width = 7cm] +\begin{sseqpage}[ classes = { blue, fill }, + title style = { align = center, text width = 2.4cm }, + title = { everything is orange } ] +\begin{scope}[orange] +\class(0,0) \class(0,1) +\structline(0,0)(0,1) +\end{scope} +\end{sseqpage} + +\begin{sseqpage}[ classes = { blue, fill }, + title style = { align = center, text width = 2.4cm }, + title = { only structline is orange } ] +\begin{scope}[ sseq = orange ] +\class(0,0) \class(0,1) +\structline(0,0)(0,1) +\end{scope} +\end{sseqpage} +\end{codeexample} + + +Throughout, ``class'' and ``cycle'' are synonyms. +\begin{stylekeylist}{sseqs, change sseqs,sseq,change sseq} +This passes options to all features in all future spectral sequences in the current scope. Note that for many global options you can set a default directly by saying |\sseqset{key = \marg{value}}| and this is in some cases preferable. + +\begin{codeexample}[width = 7cm] +% Applies to both of the following sseqs: +\sseqset{ sseqs = { blue, scale = 0.5 } }% +\begin{sseqpage} +\foreach \x in {0,1} +\foreach \y in {0,1,2} { + \class(\x,\y) +} +\end{sseqpage} +\begin{sseqpage}[ Adams grading, classes = fill ] +\foreach \x in {0,1,2} +\foreach \y in {0,1,2} { + \class(\x,\y) +} +\d2(1,0) +\d2(2,0) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + +\begin{stylekeylist}{classes, cycles,change classes,change cycles} +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ classes = { blue, fill, minimum width = 0.5em }, + scale = 0.5, x tick step = 2, y tick step = 2 ] +\class(0,0) +\class(2,2) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + + +\begin{stylekeylist}{permanent classes, permanent cycles, change permanent classes, change permanent cycles} +These options change the appearance of all permanent cycles (e.g., those classes which never support or are hit by a differential). For instance, we can circle the permanent cycles automatically. In the following example, note that because |permanent cycles| is more specific than |classes|, the |permanent cycles = {draw}| command takes precedence over the |classes = {draw = none}| command and the permanent cycle nodes are drawn. +\begin{codeexample}[width = 6.5cm] +\begin{sseqpage}[ cohomological Serre grading, + classes = { draw = none }, + permanent cycles = {draw} ] +\foreach \x in {0,2} \foreach \y in {0,1} { + \class["\mathbb{Z}"](\x,\y) +} +\d2(0,1) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + +\begin{stylekeylist}{transient classes, transient cycles,change transient classes,change transient cycles} +These options change the appearance of all transient cycles (e.g., those classes which eventually support or are hit by a differential). Again, this takes precedence over the |classes| option. +\begin{codeexample}[width = 6.5cm] +\begin{sseqpage}[ cohomological Serre grading, + classes = { draw = none }, + transient cycles = red ] +\foreach \x in {0,2} \foreach \y in {0,1} { + \class["\mathbb{Z}"](\x,\y) +} +\d2(0,1) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + +\begin{stylekeylist}{this page classes, this page cycles, change this page classes,change this page cycles} +These options change the appearance of all cycles which support or are hit by a differential on this page. Any class that is hit on the current page is also a transient cycle, and so |this page classes| takes precedence over |transient cycles| +\begin{codeexample}[width = 6cm] +\begin{sseqdata}[ name = this page cycles example, Adams grading, + transient cycles = { red, fill }, this page cycles = { blue } ] +\class(0,0) +\class(0,2) \class(1,0) +\class(1,3) \class(2,0) +\d2(1,0) \d3(2,0) +\end{sseqdata} +\printpage[ name = this page cycles example, page = 2 ] +\hskip1cm +\printpage[ name = this page cycles example, page = 3 ] +\end{codeexample} +\end{stylekeylist} + +\begin{stylekeylist}{edges,differentials,struct lines, change edges, change differentials, change struct lines} +The |edges| key applies to both differentials and structure lines. The |differentials| and |struct lines| keys both take precedence over |edges|. +\end{stylekeylist} + +\begin{stylekeylist}{this page struct lines, change this page struct lines} +This style applies to structure lines whose source or target is hit on the current page. It takes precedence over |struct lines|. +\end{stylekeylist} + +\begin{stylekeylist}{tikz primitives,change tikz primitives} +Applies to all \tikzpkg\space primitives. +\end{stylekeylist} + + +\begin{stylekeylist}{labels,change labels} +This style applies to labels on classes, differentials, and structlines. All the more specific label styles take precedence over it. +\end{stylekeylist} + +\begin{stylekeylist}{class labels,inner class labels,outer class labels, + change class labels,change inner class labels,change outer class labels} +Inner class labels specifically applies to class labels that are inside the node, outer class labels specifically applies to ones outside it: +\begin{codeexample}[] +\begin{sseqpage}[ no axes, classes = { inner sep = 0.1cm }, + outer class labels = { red }, + inner class labels = { blue } ] +\class["a", "b" above](0,0) +\class["a", "c" right](1,0) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + +\begin{stylekeylist}{edge labels,differential labels,struct line labels, + change edge labels,change differential labels,change struct line labels} + +\end{stylekeylist} + + +\subsection{Style-like options} +The options are not styles, but can be modified in the same set of places (namely, anywhere): + +\begin{keylist}{label distance = \meta{dimension}} +This sets the default distance from a class to an outer label. There are also variants like |above label distance| corresponding to |above|, |below|, |left|, |right|, |above left|, |above right|, |below left|, and |below right|. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ label distance = 0.3em, + right label distance = 0em, + no axes,yscale = 1.25 ] +\class["a" above](0,0) +\class["b" above right](0,1) +\class["c" right](1,0) +\class["c" {right = 1em}](1,1) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\begin{keylist}{run off = \meta{start tip}--\meta{end tip}, + run off struct lines = \meta{start tip}--\meta{end tip} (initially {...--...}), + run off differentials = \meta{start tip}--\meta{end tip} (initially {...--...})} +Change the default behavior of run off edges for either all edges, just struct lines, or just differentials respectively. Local arrowhead options override this. + +If an edge runs off the edge of the clipping, sseqpages automatically add an arrowhead to indicate that the edge continues. This option controls which arrow head is added if the start or end of an edge runs off the page. +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ x range = {0}{2}, y range = {0}{2}, + draw orphan edges, run off = >-stealth ] +\class(0,0) +\class(3,0) \class(0,3) +\structline(0,0)(3,0) +\structline[red](0,0)(0,3) +\structline[blue](3,0)(0,3) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\begin{key}{class label handler = \meta{function}} +\declarecustomhandler{class label handler}{\codehandler} +The value of |class label handler| is a function that is applied to all labels before displaying them. It should put its output into |\processedlabel|. +This is intended to help with code reusability. Because these handlers may crash or have annoying side-effects on some input, you may want to toggle the value of this command on and off. To turn this off for the rest of the current spectral sequence you can say |\sseqset{class label handler = {}}|. You can also use the |class label handler| key in a \scopeenv. + +The main function \sseqpages\ provides for use here is |\sseqnormalizemonomial{#1}|. This makes it convenient to translate expressions with polynomial labels. You can write your own handlers if your \TeX\ programming skills are sufficient. Let me know if there are any other functions that you want here, and if you implement them yourself, please send me your implementation. +Here is an example of a function that evaluates an arithmetic expression: +\begin{codeexample}[width=6cm] +\begin{sseqpage}[ + class label handler = { \edef\processedlabel{\the\numexpr#1} } +] +\class["1+1"](0,0) +\class["1+2*(1+3*(4-1))"](1,1) +\end{sseqpage} +\end{codeexample} +Here's an example using |\sseqnormalizepolynomial|: +\begin{codeexample}[width = 6cm] +\NewSseqGroup \test {m} { + \class["1#1"](0,0) + \class["\alpha#1"](0,1) + \class["y#1"](1,0) + \class["\alpha y#1"](1,1) +} +\begin{sseqpage}[ + class label handler = { \sseqnormalizemonomial{#1} }, + classes = { draw = none }, class labels = { font = \small } ] +\test{} +\test[red](2,0){y^2} +\test[orange](2,2){\alpha^2y^2} +\test[blue](0,2){\alpha^2} +\end{sseqpage} +\end{codeexample} + +Here is another example which demonstrates a useful idiom for drawing Serre spectral sequences. For a more complete example, see \example{KF3n}. Note the use of braces in |{Sq^1\iota_2}|. Without braces, |\sseqnormalizemonomial| will simplify |Sq^1xSq^2x| into $S^2q^3x^2$, which is obviously undesirable, so the correct way to input this is |{Sq^1x}{Sq^2x}|. Unfortunately, |\foreach| strips a pair of braces from its arguments, so you need to put two pairs of braces. +\begin{codeexample}[width=8cm] +\begin{sseqpage}[ + xscale = 1.4, + classes = { draw = none }, + class label handler = {\sseqnormalizemonomial{#1}} ] + +\foreach \x/\xlabel in + { 0/1, 2/\iota_2, 3/{{Sq^1\iota_2}}, 4/\iota_2^2 } +\foreach \y/\ylabel in + { 0/1, 1/\alpha, 2/x, 3/\alpha x, 4/x^2 } +{ + \class["\ylabel\xlabel"] (\x,\y) +} +\end{sseqpage} +\end{codeexample} +\end{key} + + +\section{Global options} +These options can only be set at the beginning of a \sseqdataenv\space or \sseqpageenv\space environment. When it makes sense, you can also set a default value using |\sseqset|. Generally, these options either modify the plot style or the logic for the spectral sequence. +\begin{key}{name = \meta{sseq name}} +This option must be used with the \sseqdataenv\space environment where it indicates the name of the spectral sequence, which will be used with the \sseqpageenv\space environment or |\printpage| command to draw the spectral sequence. The name used in a \sseqdataenv\space environment must be new unless the environment is used with the |update existing| key in which case the \sseqdataenv\space environment will add to the existing spectral sequence. It is optional when used with \sseqpageenv\space, and if included the name given must be the name of an existing spectral sequence. +\end{key} + +\begin{key}{page = \meta{page number} (initially 0)} +This key is for \sseqpageenv\space and |\printpage|. It specifies which page of the spectral sequence is to be printed. On page r, all |\class|es that are not hit by differentials on pages less than r will be printed, as well as all |\structline|s whose source and target classes are both printed on page r, and all differentials of length exactly r. The special value |page = 0| prints all classes, differentials, and structure lines. +\end{key} + +\begin{keylist}{degree = \marg{x degree}\marg{y degree},cohomological Serre grading, homological Serre grading, Adams grading} +Specifies the degree of differentials. The \meta{x degree} and \meta{y degree} should both be mathematical expressions in one variable |#1| that evaluate to integers on any input. They specify the $\mathtt{x}$ and $\mathtt{y}$ displacement of a page $\mathtt{\#1}$ differential. In practice, they will be linear expressions with |#1| coefficient 1, -1, or 0. + +The |degree| option must be given before placing any differentials. It can be specified at the beginning of the \sseqdataenv\space environment, at the beginning of the \sseqpageenv\space environment if it is being used as a standalone page, or as a default by saying |\sseqset{degree = \marg{x degree}\marg{y degree}}| or |\sseqset{Adams grading}| outside of the \sseqdataenv\space and \sseqpages\space environments. + +You can make a named grading convention by saying \codeverb|\sseqset{my grading/.sseq grading = \marg{x degree}\marg{y degree}}|. Then later passing |my grading| to a spectral sequence is equivalent to saying |degree = \marg{x degree}\marg{y degree}|. The following grading conventions exist by default: +\begin{codeexample}[width = 6cm] +% equivalent to degree = {#1}{1-#1}: +\begin{sseqpage}[ cohomological Serre grading ] +\class(0,1) +\class(2,0) +\d2(0,1) +\end{sseqpage} +\end{codeexample} +\begin{codeexample}[width = 6cm] +% equivalent to degree = {-#1}{#1-1}: +\begin{sseqpage}[ homological Serre grading ] +\class(0,1) +\class(2,0) +\d2(2,0) +\end{sseqpage} +\end{codeexample} +\begin{codeexample}[width = 6cm] +% equivalent to degree = {-1}{#1-1}: +\begin{sseqpage}[ Adams grading ] +\class(0,2) +\class(1,0) +\d2(1,0) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\begin{keylist}{strict degree, lax degree} +If the degree is strict, then latex will throw an error if you try to specify a differential that doesn't have the proper grading. The degree is strict by default. +\begin{codeexample}[code only] +\begin{sseqdata}[ name = laxdegree, Adams grading ] +\class(0,2) +\class(1,0) +\d3(1,0)(0,2) % Error: differential does not respect grading. + % Target should be in position (0,3) but instead it is (0,2)... +\end{sseqdata} +\end{codeexample} + +\begin{codeexample}[] +\begin{sseqdata}[ name = laxdegree, Adams grading, lax degree, yscale = 0.6 ] +\class(0,2) +\class(1,0) +\d3(1,0)(0,2) % No error because degree checking is off +\end{sseqdata} +\printpage[ name = laxdegree, page = 3 ] +\end{codeexample} +\end{keylist} + +\begin{key}{update existing} +This key is only for the \sseqdataenv\space environment. It specifies that the current \sseqdataenv\space environment is adding data to an existing spectral sequence. If you don't pass this key, then giving a \sseqdataenv\space environment the same |name| as a different \sseqdataenv\space environment will cause an error. This is intended to help you avoid accidentally reusing the same name. +\end{key} + + +\begin{key}{keep changes =\meta{boolean} (default true)(initially false)} +This option is only for the \sseqpageenv\space environment, and only works when a |name| is provided. +This option specifies that all of the commands in the current \sseqpageenv\space environment should be carried forward to future pages of the same named spectral sequence. For example: +\begin{codeexample}[] +\begin{sseqdata}[ name = keep changes example, Adams grading, y range = {0}{3} ] +\class(0,0) +\class(1,0) +\end{sseqdata} + +\begin{sseqpage}[ name = keep changes example, sseq = orange ] +\class(0,2) +\class(1,2) +\classoptions[orange](1,0) +\d2(1,0) +\end{sseqpage} \qquad + +\printpage[ name = keep changes example, page = 2 ] \qquad + +\begin{sseqpage}[ name = keep changes example, sseq = blue, keep changes ] +\class(0,3) +\class(1,3) +\classoptions[blue](1,0) +\d3(1,0) +\end{sseqpage} \qquad + +\printpage[ name = keep changes example, page = 3 ] +\end{codeexample} +Note that the orange classes and differential do not persist because the |keep changes| option is not set in the first \sseqpageenv\space environment, but the blue classes and differential do, since the |keep changes| option is set in the second \sseqpageenv\space environment. +\end{key} + + +\begin{keylist}{no differentials,draw differentials} +The option |no differentials| suppresses all of the differentials on the current page, whereas |draw differentials| causes the page appropriate differentials to be drawn. This is useful for explaining how the computation of a spectral sequence goes, or if you want to display one of the edges of the spectral sequence, like in \example{KF3n}. +%\begin{codeexample}[] +%TODO: build example +%\end{codeexample} +\end{keylist} + +\begin{keylist}{no struct lines,draw struct lines} +The option |no struct lines| suppresses all of the structure lines on the current page, whereas the option |draw struct lines| causes the page appropriate structure lines to be drawn. +\end{keylist} + +\begin{keylist}{no orphan edges,draw orphan edges} +An edge is an ``orphan'' if both its source and target lie off the page. By default these are drawn, but with the option |no orphan edges| they are not. If the option |no orphan edges| has been set, |draw orphan edges| undoes it. +\begin{codeexample}[width = 9cm] +\begin{sseqdata}[ + name = orphan edges example, + cohomological Serre grading, + x range = {0}{2}, y range = {0}{2} ] +\class(0,3) \class(3,1) +\d3(0,3) +\class(2,1) \class(4,0) +\d2(2,1) +\end{sseqdata} +\printpage[ name = orphan edges example ] +\quad +\printpage[ name = orphan edges example, + no orphan edges ] +\end{codeexample} +\end{keylist} + + +\begin{key}{class pattern = \meta{class pattern name} (initially standard)} +This key specifies the arrangement of multiple classes at the same coordinate. The default value is |standard|. +\begin{codeexample}[width = 5cm] +\begin{sseqdata}[ name = class pattern example, no axes, ymirror ] +\class(0,0) +\class(1,0) \class(1,0) +\class(0,1) \class(0,1) \class(0,1) +\class(1,1) \class(1,1) \class(1,1) \class(1,1) +\class(0,2) \class(0,2) \class(0,2) \class(0,2) \class(0,2) +\class(1,2) \class(1,2) \class(1,2) \class(1,2) \class(1,2) \class(1,2) +\end{sseqdata} + +\printpage[ name = class pattern example, class pattern = standard ] +\printpage[ name = class pattern example, change classes = blue, + class pattern = linear, class placement transform = { rotate = 45 } ] +\end{codeexample} + +You can add new class patterns using |\sseqnewclasspattern|: +\begin{command}{\sseqnewclasspattern\marg{class pattern name}\marg{offsets}} +Creates a new class pattern. For example, the |linear| class pattern is created using the command: +\begin{codeexample}[code only] +\sseqnewclasspattern{linear}{ + (0,0); + (-0.13,0)(0.13,0); + (-0.2,0)(0,0)(0.2,0); + (-0.3,0)(-0.1,0)(0.1,0)(0.3,0); + (-0.4,0)(-0.2,0)(0,0)(0.2,0)(0.4,0); + (-0.5,0)(-0.3,0)(-0.1,0)(0.1,0)(0.3,0)(0.5,0); +} +\end{codeexample} +For instance the third row indicates that if there are three classes at the position |(x,y)| they should be printed at |(x-0.2,y)|, |(x,y)|, and |(x+0.2,y)|. You can give as many rows as you like; \sseqpages\space will throw an error if there are more classes in any position than the maximum number that your class pattern can handle -- for instance, the |linear| class pattern can handle up to six classes based on this definition. +\end{command} +\end{key} + + +\begin{key}{class placement transform = \marg{transform keys}, add class placement transform = \marg{transform keys} } +\declareasstyle{class placement transform}\declareasstyle{add class placement transform} +The option |class placement transform| allows the user to specify a \tikzpkg\space coordinate transform to adjust the relative position of multiple nodes in the same $\mathtt{(x,y)}$ position. The |class placement transform| key overrides the previous value of transformations, the |add class placement transform| just adds the new transformation to the end of the list. This coordinate transform can only involve rotation and scaling, no translation. Specifying a scaling factor helps if the nodes are too large and overlap. In some cases a rotation makes it easier to see which class is the target of a differential. +\begin{codeexample}[width = 5cm] +\begin{sseqpage}[ class placement transform = { xscale = 3 }, + class pattern = linear, + classes = { draw = none }, + xscale = 2, x axis extend end = 0.7cm ] +\class["\mathbb{Z}"](0,0) +\class["\mathbb{Z}/2"](1,1) +\class["\mathbb{Z}/3"](1,1) +\end{sseqpage} +\end{codeexample} +\begin{codeexample}[width = 5cm] +\begin{sseqpage}[ class placement transform = { rotate = 40 }, + cohomological Serre grading, scale = 0.65, + classes = fill, differentials = blue ] +\class(0,0) +\class(0,2)\class(0,2) +\class[red](3,0)\class[green](3,0)\class[blue](3,0) + +\d3(0,2,1,2) +\d3(0,2,-1,-1) +\draw[->,red](3,0,1)--(0,0); +\end{sseqpage} +\end{codeexample} +With multiple large class names, the best option is to arrange the classes vertically: +\begin{codeexample}[width = 5.5cm] +\begin{sseqpage}[ classes = {draw = none }, xscale = 2, yscale=1.55, + class pattern = linear, + class placement transform = { scale = 3, rotate = 90 }, + right clip padding = 20pt, top clip padding = 20pt, + x axis gap = 30pt, y axis gap = 20pt ] +\class["\iota_3\beta\iota_3"](7,0) +\class["P^1\iota_3"](7,0) + +\class["\iota_2\iota_3\beta\iota_3"](7,2) +\class["\iota_2P^1\iota_3"](7,2) + +\class["(\beta\iota_3)^2"](8,0) +\class["P^1\beta\iota_3"](8,0) +\class["\beta P^1\iota_3"](8,0) + +\class["\iota_2(\beta\iota_3)^2"](8,2) +\class["\iota_2P^1\beta\iota_3"](8,2) +\class["\iota_2\beta P^1\iota_3"](8,2) +\end{sseqpage} +\end{codeexample} +\end{key} + +\begin{key}{math nodes = \meta{boolean} (default true)(initially true)} +This key instructs \sseqpages\space to put all labels in math mode automatically. +\end{key} + + + +\subsection{Global Coordinate Transformations} +Of the normal \tikzpkg\ coordinate transformations, only the following can be applied to a sseq diagram: +\begin{keylist}{scale = \meta{factor},xscale = \meta{factor}, yscale = \meta{factor}, xmirror, ymirror} +Scale the diagram by \meta{factor}. Under normal circumstances, you can tell \tikzpkg\ to mirror a diagram by saying, for instance, |xscale = -1|, but \sseqpages\space needs to be aware that the diagram has been mirrored in order to draw the axes correctly. Thus, if you want to mirror a spectral sequence, use the |xmirror| and |ymirror| options as appropriate. +\end{keylist} + +\begin{key}{rotate = \meta{angle}} +It probably won't look great if you pick an angle that isn't a multiple of 90 degrees. +\end{key} + +\subsection{Plot Options and Axes Style} +\begin{keylist}{x range = \marg{x min}\marg{x max},y range = \marg{y min}\marg{y max}} +These options force the x and y range to be a specific interval. By default, if no range is specified then the range is chosen to fit all the classes. If an x range is specified but no y range, then the y range is chosen to fit all the classes that lie inside the specified x range, and vice versa. +\end{keylist} + +\begin{key}{grid = \marg{grid style}} +Makes \sseqpages\space draw a grid. The grid styles and a significant part of the code that produces them were stolen from the \sseqpkg\ package. +\begin{codeexample}[vbox] +\begin{sseqdata}[ name = grid example, scale = 0.8 ] +\class(0,0) +\class(3,0) +\class(2,1)\class(2,1) +\class(1,2)\class(1,2)\class(1,2) +\class(0,3) +\class(3,3) +\end{sseqdata} +\hbox{ +\printpage[ name = grid example, grid = chess ] +\qquad +\printpage[ name = grid example, grid = crossword ] +\qquad +\printpage[ name = grid example, grid = dots ] +} +\vskip20pt +\hbox{ +\printpage[ name = grid example, grid = go ] +\qquad +\printpage[ name = grid example, grid = none ] +} +\end{codeexample} +It is possible to make your own grid style by defining the command |\sseq@grid@yourgridname| to draw a grid. +\end{key} + +\begin{keylist}{title = \meta{text}, title style = \meta{keys}, x label = \meta{text}, y label = \meta{text},x label style = \meta{keys}, y label style = \meta{keys}, label style = \meta{keys}} +\declareasstyle{title style} +\declareasstyle{x label style} +\declareasstyle{y label style} +\declareasstyle{label style} +\begin{codeexample}[width = 6cm] +\begin{sseqpage}[ title = { An example }, yscale = 0.5, + x label = { x axis label }, + y label = { y axis label }, + label style = { blue, font = \small }, + x label style = { yshift = 5pt }, + ] +\class(0,0) +\class(2,2) +\end{sseqpage} +\end{codeexample} +\end{keylist} + + +\begin{keylist}{no title, draw title, no x label, no y label, no labels, draw x label, draw y label, draw labels} +Suppress or unsuppress the title, x label, y label, or both x and y labels, respectively. +\end{keylist} + +\begin{keylist}{no x axis, no y axis, no axes, draw x axis, draw y axis, draw axes} +Suppress the axis. Also suppresses axes ticks. If there is a title or axes labels they will still be drawn. You can draw your own axes using \tikzpkg\space inside a \scopeenv\space environment with the |background| key. +\end{keylist} + +\begin{keylist}{no x ticks, no y ticks, no ticks, draw x ticks, draw y ticks, draw ticks} +Suppress axes ticks (the numbers next to the axes). Only matters if axes are drawn. You can make your own ticks using \tikzpkg\space inside a \scopeenv\space environment with the |background| key. For instance, you might want to label the axes as 0, $n$, $2n$, \ldots You can achieve this as follows: (you can also use |x tick handler|). +\begin{codeexample}[width = 5.7cm] +\begin{sseqpage}[ no x ticks, x range = {0}{3} ] +\begin{scope}[ background ] + \node at (0,\ymin - 1) {0}; + % \vphantom is fragile so we have to throw in an extra \protect + \node at (1,\ymin - 1) {\protect\vphantom{2}n}; +\foreach \n in {2,..., \xmax}{ + \node at (\n,\ymin - 1) {\n n}; +} +\end{scope} +\class(0,0) +\class(3,2) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\begin{keylist}{x tick step = \meta{positive integer} (initially 1),y tick step = \meta{positive integer} (initially 1),tick step = \meta{positive integer} (initially 1)} +Sets the interval between labels. +\end{keylist} + +\begin{stylekeylist}{x tick style,y tick style,tick style} +Change the tick style: +\begin{codeexample}[width = 7cm] +\begin{sseqpage}[ tick style = { blue, font = \tiny } ] +\class(0,0) \class(2,1) +\end{sseqpage} +\end{codeexample} +\end{stylekeylist} + +\begin{keylist}{x tick handler = \meta{function} (initially \#1), y tick handler = \meta{function} (initially \#1), tick handler = \meta{function} (initially \#1)} +\declarecustomhandler{x tick handler}{\codehandler} +\declarecustomhandler{y tick handler}{\codehandler} +\declarecustomhandler{tick handler}{\codehandler} +The value for |x tick handler| should be a function that takes in the current $\mathtt{x}$ value and outputs the appropriate tick. Correspondingly with |y tick handler|. The |tick handler| key sets both. +\begin{codeexample}[width = 7cm] +\begin{sseqpage}[ x range = {0}{4}, yscale = 1.78, + x tick handler = { + \ifnum#1 = 0\relax + 0 + \else + \ifnum#1 = 1\relax + % \vphantom is fragile so we \protect it + \protect\vphantom{2}n + \else + #1n + \fi + \fi + } +] +\class(0,0) +\class(4,2) +\end{sseqpage} +\end{codeexample} +\end{keylist} + +\needspace{5\baselineskip} +\subsection{Layout} +\begin{keylist}{x axis style = \meta{style} (initially border), y axis style = \meta{style} (initially border),axes style = \meta{style} (initially border)} +The \meta{style} is either |border| or |center|. The |border| option puts the axes on the bottom and left of the picture; the center option by default places the axes at $\mathtt{x = y = 0}$. This option is only worth using for multi-quadrant spectral sequences. See \example{KRAHSS} and \example{KUHFPSS} for examples where this is used. +%TODO: example? +\end{keylist} + +\parskip=0pt +\begin{keylist}{x axis origin = \meta{x value} (initially 0), y axis origin = \meta{y value} (initially 0)} +If you use |axes style = center|, these keys change the position of the axes. Otherwise, they are ignored. +\end{keylist} +% +% +\begin{keylist}{x axis gap = \meta{dimension} (initially 0.5cm),y axis gap = \meta{dimension} (initially 0.5cm), axes gap = \meta{dimension} (initially 0.5cm)} +% +\end{keylist} +% +% +\begin{keylist}{x tick gap = \meta{dimension} (initially 0.5cm),y tick gap = \meta{dimension} (initially 0.5cm)} +% +\end{keylist} +% +\begin{keylist}{x axis start extend = \meta{dimension} (initially 0.5cm), y axis start extend = \meta{dimension} (initially 0.5cm), + x axis end extend = \meta{dimension} (initially 0.9cm), y axis end extend = \meta{dimension} (initially 0.9cm)} +\end{keylist} +% +\begin{keylist}{x axis clip padding = \meta{dimension} (initially 0.1cm), y axis clip padding = \meta{dimension} (initially 0.1cm)} +\end{keylist} +% +\begin{keylist}{right clip padding = \meta{dimension} (initially 0.1cm), left clip padding = \meta{dimension} (initially 0.4cm), + top clip padding = \meta{dimension} (initially 0.1cm), bottom clip padding = \meta{dimension} (initially 0.4cm)} +\end{keylist} + +\begin{center} +\pgfkeys{/sseqpages/tikz primitives/distance label/.style = {orange,{<[width = 4pt]}-}, /sseqpages/tikz primitives/description/.style = {black,/tikz/align = center}} +\begin{sseqpage}[ grid = chess, + x range = {0}{5}, y range = {0}{5}, math nodes = false, + x axis clip padding = 0.15cm, y axis clip padding = 0.15cm, + right clip padding = 0.2cm, top clip padding = 0.2cm, axes gap = 25pt] +\begin{scope}[background,red] +\sseq@savedpaths@add{\pgfsetpath\sseq@theclippath\pgfusepath{draw}} +\end{scope} +\catcode`\| = 12 +\begin{scope}[background,|-|,blue] +% clip gap +\draw[shift = {(\sseq@xmax+0.8,-\sseq@xaxisgap)}] (0,0)--(0,\sseq@xclip@axisgap); +\draw[shift = {(-\sseq@yaxisgap,\sseq@ymax+0.8)}] (0,0)--(\sseq@yclip@axisgap,0); +\draw[distance label,shift = {(\sseq@xmax+0.8,-\sseq@xaxisgap+\sseq@xclip@axisgap/2)}] (0,0) -- (2,0) +node[description, right] {x axis\\ clip gap}; +\draw[distance label,shift = {(-\sseq@yaxisgap+\sseq@yclip@axisgap/2,\sseq@ymax+0.8)}] (0,0) .. controls (0,0.5) .. (-0.5,0.5) +node[description, left] {y axis\\ clip gap}; + + +% border clip padding +\draw[shift = {(\sseq@xmax cm + \sseq@xaxis@end@extend,\sseq@ymin cm-\sseq@xaxisgap-0.3cm)}] (0,0)--(\sseq@clip@padding@right,0); +\draw[shift = {(\sseq@xmin cm -\sseq@yaxisgap-0.3cm,\sseq@ymax cm+\sseq@yaxis@end@extend)}] (0,0)--(0,\sseq@clip@padding@top); +\draw[distance label, shift = {(\sseq@xmax cm + \sseq@xaxis@end@extend+\sseq@clip@padding@right/2,\sseq@ymin cm-\sseq@xaxisgap-0.3cm)}] (0,0) .. controls (0,-0.7) ..(1.5,-0.7) +node[description, right] {right clip\\ padding}; +\draw[distance label, shift = {(\sseq@xmin cm -\sseq@yaxisgap-0.3cm,\sseq@ymax cm+\sseq@yaxis@end@extend+\sseq@clip@padding@top/2)}] (0,0) -- (-2,0) +node[description, left] {top clip\\ padding}; + +% extend start axis +\draw[shift = {(\sseq@xmin-\sseq@yaxisgap-0.02cm,\sseq@ymin-\sseq@xaxisgap+0.1cm)}] (0,0) -- (-\sseq@xaxis@start@extend, 0); +\draw[shift = {(\sseq@xmin-\sseq@yaxisgap+0.1cm,\sseq@ymin-\sseq@xaxisgap-0.02cm)}] (0,0) -- (0, -\sseq@yaxis@start@extend); +\draw[distance label,shift = {(\sseq@xmin-\sseq@yaxisgap-0.02cm-\sseq@xaxis@start@extend/2,\sseq@ymin-\sseq@xaxisgap+0.1cm)}] (0,0) .. controls (0,0.5) .. (-1,0.5) +node[description, left]{x axis\\ extend start}; +\draw[distance label,shift = {(\sseq@xmin-\sseq@yaxisgap+0.1cm,\sseq@ymin-\sseq@xaxisgap-0.02cm-\sseq@yaxis@start@extend/2)}] (0,0) .. controls (0.5,0) .. (0.5,-1) +node[description, below]{y axis\\ extend start}; + +% extend end axis +\draw[shift = {(\sseq@xmax,\sseq@ymin-\sseq@xaxisgap-0.1cm)}] (0,0)--(\sseq@xaxis@end@extend,0); +\draw[shift = {(\sseq@xmin cm-\sseq@yaxisgap-0.1cm,\sseq@ymax)}] (0,0)--(0,\sseq@yaxis@end@extend); +\draw[distance label,shift = {(\sseq@xmax cm+\sseq@xaxis@end@extend/2,\sseq@ymin-\sseq@xaxisgap-0.1cm)}] (0,0) -- (0,-1.5) + node[description, below] {x axis\\ extend end}; +\draw[distance label,shift = {(\sseq@xmin cm- \sseq@yaxisgap-0.1cm,\sseq@ymax cm+\sseq@yaxis@end@extend/2)}] (0,0) .. controls (-2,0) .. (-2,-1) +node[description, below] {y axis\\ extend end}; + + + +% tick gap +\draw[shift = {(\sseq@xmin+\sseq@xmax/2+0.2,-0.5-\sseq@xaxisgap)}] (0,0)--(0,-\sseq@xlabelgap); +\draw[shift = {(-0.5-\sseq@yaxisgap,\sseq@ymin+\sseq@ymax/2+0.2)}] (0,0)--(-\sseq@ylabelgap,0); +\draw[distance label,shift = {(\sseq@xmin+\sseq@xmax/2+0.2,-\sseq@xlabelgap/2-\sseq@xaxisgap)}] (0,0) .. controls (0.5 ,0) .. (0.5,-0.8) + node[below,black]{x tick gap}; +\draw[distance label,shift = {(-\sseq@yaxisgap -\sseq@ylabelgap/2,\sseq@ymin+\sseq@ymax/2+0.2)}] (0,0) .. controls (0, -0.3) .. (-0.5,-0.7) +node[left,black]{y tick gap}; + +% axis gap +\draw[shift = {(\sseq@xmax cm+0.17cm,\sseq@ymin cm-\sseq@xaxisgap+0.02cm)}] (0,0) -- (0, \sseq@xaxisgap); +\draw[shift = {(\sseq@xmin cm-\sseq@yaxisgap+0.02cm,\sseq@ymax cm+0.17cm)}] (0,0) -- (\sseq@yaxisgap,0); +\draw[distance label,shift = {(\sseq@xmax cm+0.17cm,\sseq@ymin cm-\sseq@xaxisgap/2+0.02cm)}](0,0) .. controls (2,0) .. (2,0.5) +node[above,description]{x axis gap}; +\draw[distance label,shift = {(\sseq@xmin cm-\sseq@yaxisgap/2+0.02cm,\sseq@ymax cm+0.17cm)}](0,0)--(0,2) %.. controls (0,1) .. (0.5,1); +node[above,description]{y axis gap}; +\end{scope} + +\class(0,0) +\class(10,10) +\draw (0,0) -- (11,11); +\class(5,0) +\class(0,5) +\end{sseqpage} +\end{center} + +\parskip=10pt +\begin{key}{custom clip = \meta{clip path}} +Give a custom clipping. The clipping specified must be in the form of a valid \tikzpkg\space path, for instance |\clip (0,0) rectangle (10,10);|. This clipping is also applied to any grid and is used to draw ellipses on appropriate differentials or struct lines that go out of bounds and to determine whether a differential or struct line is an ``orphan''. It is not applied to any background elements, which is important because these are often used for axes labels and such that should lie outside of the clipping region. Weird things can happen with out of range edges if use this option with an oddly shaped path. +\end{key} + +\begin{key}{clip = \meta{boolean} (default true)(initially true)} +If this is false the spectral sequence won't be clipped. I'm not really sure why you would want that, but there might be some use case. Setting this to be false is not fully supported, and it's possible that weird things will happen with some of the edges that go out of range. +\end{key} + + +\begin{key}{rotate labels = \meta{boolean} (default true)(initially false)} +If you use |rotate = 90| but also want the labels rotated (so that the whole diagram is sideways) use this key. +\end{key} +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex new file mode 100644 index 00000000000..f2897deb03a --- /dev/null +++ b/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex @@ -0,0 +1,505 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: spectralsequencesmanualpreamble.tex +%% +%% Manual preamble +%% + +% TODO: someday I should comment this -- it's a bit of a mess + +\documentclass{ltxdoc} +\usepackage[a4paper,left=2.25cm,right=2.25cm,top=2.5cm,bottom=2.5cm,nohead]{geometry} +\usepackage{spectralsequences} +\usetikzlibrary{shapes.geometric} +\usepackage{amssymb} +\usepackage[notmath]{sansmathfonts} +\usepackage{verbatim} +\usepackage{needspace} +\usepackage[documentation]{tcolorbox} +\usepackage[T1]{fontenc} +\usepackage{hyperref} + +\hypersetup{% + colorlinks=true, + linkcolor=blue, + filecolor=blue, + urlcolor=thered, + citecolor=blue, + pdfborder=0 0 0, +} +\usepackage{hyperxmp} +\makeatletter +\def\displaycommand#1{\displaycommand@#1\@nil} +\def\displaycommand@#1#2\@nil{\texttt{\string#1}#2} + +% From Christian Feuersänger https://tex.stackexchange.com/a/73103 +\makeatletter % !!!! +\input{pgfmanual.code} % This must be exectuted when catcode of @ is letter +\makeatother % !!!! + +\usepackage{calc} % +\include{pgfmanual-en-macros} % This must be executed when catcode of @ is other + +\makeatletter + +\parskip=10pt +\parindent=0pt +\MakeShortVerb{\|} + +\def\sectionstring{\textbackslash\@xp\@gobble\string} + +\def\@gobbletocln#1:{} +\def\eatclnifpresent#1{% + \eatclnifpresent@#1:\nil +} +\def\eatclnifpresent@#1:#2\nil{% + \ifx$#2$% + #1% + \else + \removecln#2\nil + \fi +} +\def\removecln#1:\nil{#1} + +\def\removenil#1\nil{#1} + +\def\pgfmanual@pretty@singlequote{'} + + + +\def\pulloffstartspaces{\@xp\pulloffstartspaces@\thekey\@nil} +\def\pulloffstartspaces@#1{% + \def\test{#1}% + \ifx\test\pgfmanual@pretty@activespace + \@xp\def\@xp\leadingtoks\@xp{\leadingtoks\pgfmanual@pretty@space}% + \@xp\pulloffstartspaces@ + \else + \ifx#1\@nil + \def\thekey{}% + \else + \@xp\@xp\@xp\pulloffstartspaces@@\@xp\@xp\@xp#1% + \fi + \fi +} +\def\pulloffstartspaces@@#1\@nil{\def\thekey{#1}} + +\def\pulloffstartbrace{\@xp\pullofflbrace\thekey\nil\@nil} +\def\pullofflbrace#1#2\@nil{% + \ifx\test\pgfmanual@pretty@lbrace + \@xp\def\@xp\leadingtoks\@xp{\leadingtoks\pgfmanual@pretty@lbrace}% + \@xp\def\@xp\thekey\@xp{\removenil#2}% + \else + \@xp\def\@xp\thekey\@xp{\removenil#1#2}% + \fi +} + + +\def\pulloffsinglequote{\@xp\pulloffsinglequote@\thekey\nil\@nil} +\def\pulloffsinglequote@#1#2\@nil{% + \def\test{#1}% + \ifx\test\pgfmanual@pretty@singlequote + \@xp\def\@xp\leadingtoks\@xp{\leadingtoks\pgfmanual@pretty@singlequote}% + \@xp\def\@xp\thekey\@xp{\removenil#2}% + \else + \def\possiblesinglequote{}% + \@xp\def\@xp\thekey\@xp{\removenil#1#2}% + \fi +} + + + + +% deletes everything except trailing spaces. For making link underline not include trailing spaces (have to reinsert spaces) +\def\onlytrailingspaces#1{% + \pgfkeys@spdef\temp{#1}% + \@xp\def\@xp\temp\@xp##\@xp1\temp{}% + \temp#1% +} + +% remove trailing spaces, for making link underline not include trailing spaces +\def\removetrailingspaces{\@xp\removetrailingspaces@\@xp{\thekey}} +\def\removetrailingspaces@#1{% + \removetrailingspace{#1}% + \ifx\possibletrailingspace\empty\else + \edef\trailingtoks{\unexpanded\@xp{\possibletrailingspace}\unexpanded\@xp{\trailingtoks}}% + \@xp\removetrailingspaces@\@xp{\thekey}% + \fi +} + +\bgroup +\catcode`\Q=3\lccode`\)=`\}\lccode`\~=`\ \lowercase{ + \gdef\removetrailingspace#1{\removetrailingspace@#1QQ~Q} + \gdef\removetrailingspace@#1~Q{\removetrailingspace@@#1} + \gdef\removetrailingspace@@#1Q#2Q{\def\thekey{#1}\def\possibletrailingspace{#2}} + + % Remove trailing brace -- so close brace can be colored / styled differently + \gdef\removetrailingbrace{\@xp\removetrailingbrace@\thekey QQ)Q} + \gdef\removetrailingbrace@#1)Q{\removetrailingbrace@@#1} + \gdef\removetrailingbrace@@#1Q#2Q{\def\thekey{#1}\edef\trailingtoks{\unexpanded{#2}\unexpanded\@xp{\trailingtoks}}} +} + +\catcode`\^^M=\active + % remove trailing new line -- so we can properly test whether the last nonwhitespace character is a brace + \gdef\removetrailingnewline{\@xp\removetrailingnewline@\thekey \nil\nil^^M\nil}% + \gdef\removetrailingnewline@#1^^M\nil{\removetrailingnewline@@#1}% + \gdef\removetrailingnewline@@#1\nil#2\nil{\def\thekey{#1}\edef\trailingtoks{\unexpanded{#2}\unexpanded\@xp{\trailingtoks}}}% +\egroup + + + +% Redefine decompose not to do all that fancy crap -- just print as is. Maybe we should get rid of surrounding spaces here and where we do the ref? +\def\decompose#1/\nil{% + \index{#1@\protect\texttt{#1} key}% + \index{\mypath#1@\protect\texttt{#1}}% + \pgfmanualpdflabel{#1}{}% +} +\let\olddeclare\declare +\ExplSyntaxOn +% Get rid of colon so that we can have context based linking -- "page" links to global page, "class:page" prints page and links to the page key in the class section, etc. +\def\declare#1{% + \exp_args:Nf\olddeclare{% + \eatclnifpresent{#1}% + }% +} +\ExplSyntaxOff + +%\patchcmd\pgfmanualpdfref{#2}{#2} % If I want it to behave differently for things that aren't links +\patchcmd\pgfmanualpdfref{\expandafter\pgfmanualpdfref@\expandafter{\pgfmanualpdflabel@@}{#2}} % Fix it so that being a link doesn't change the color + {\colorlet{temp}{.}\expandafter\pgfmanualpdfref@\expandafter{\pgfmanualpdflabel@@}{\textcolor{temp}{#2}}}{}{}% + +\newenvironment{manualentry}[1]{% + \begin{pgfmanualentry}% + \pgfmanualentryheadline{#1}% + \pgfmanualbody +}{% + \end{pgfmanualentry}% +} + + + +\def\removespace#1\space\nil{#1} +\newenvironment{stylekeylist}[2][]{% + \begin{pgfmanualentry} + \def\extrakeytext{}% + \foreach \xx in {#2} {% + \expandafter\extractkey\xx\space= \marg{keys}\@nil% + \declareasstyle{\@xp\removespace\mykey\nil}% tells latex not to italicize body + }% + \pgfmanualbody +}{% + \end{pgfmanualentry} +}% + +% Custom handler for value of key -- instead of italicizing, do what? +\def\ifcustomhandler#1{% + \@xp\pgfkeys@spdef\@xp\test\@xp{#1}% + \expandafter\ifx\csname\test @ custom handler\endcsname\relax\@xp\@secondoftwo\else\@xp\@firstoftwo\fi +} +\def\customhandler#1{% + \@xp\pgfkeys@spdef\@xp\test\@xp{#1}% + \csname\test @ custom handler\endcsname{#1}% +} + +\def\declarecustomhandler#1#2{% + \immediate\write\@auxout{\@nx\expandafter\gdef\@nx\csname#1@ custom handler\endcsname{\@nx#2}}% + \@xp\gdef\csname#1@ custom handler\endcsname{#2}% +} + +\def\declareasstyle#1{\declarecustomhandler{#1}\stylehandler} +\def\stylehandler#1#2{% + \bgroup + \let\pgfmanualwordstartup\relax + \def\thekey{#2}% + \let\leadingtoks\empty + \pulloffstartspaces\pulloffstartbrace + \textcolor{keycolor}{\leadingtoks}% + \@xp\pgfmanualprettyprintpgfkeys\@xp{\thekey}% + \egroup +} +\def\codehandler#1#2{% + \bgroup + \def\thekey{#2}% + \let\leadingtoks\empty + \let\trailingtoks\empty + \pulloffstartspaces\pulloffstartbrace + \removetrailingspaces\removetrailingnewline + \removetrailingspaces\removetrailingbrace + \textcolor{keycolor}{\leadingtoks}% + \@xp\pgfmanualprettyprintcode\@xp{\thekey}% + \textcolor{keycolor}{\trailingtoks}% + \egroup +} + +\declarecustomhandler{font}{\codehandler} +\declarecustomhandler{page constraint}{\codehandler} +\declarecustomhandler{page constraint}{\codehandler} + +\let\pgfmanualpdflabel@opt@old\pgfmanualpdflabel@opt +\def\pgfmanualpdflabel@opt[#1]#2#3{% + \pgfkeys@spdef\temp{#2}% + \sseq@eval{\unexpanded{\pgfmanualpdflabel@opt@old[#1]}\unexpanded\@xp{\@xp{\temp}{#3}}}% +} + +\patchcmd\extractkey{\hfill(\extrakeytext no value)}{}{}{\error} +\patchcmd\extractkey{\def\mykey}{\gdef\mykey}{}{\error} +\patchcmd\extractkeyequal{\hfill(\extrakeytext no default)}{}{}{\error} +\patchcmd\extractkeyequal{\def\mykey}{\gdef\mykey}{}{\error} +\patchcmd\extractinitial{no default, }{}{}{\error} +\patchcmd\extractinitial{\def\mykey}{\gdef\mykey}{}{\error} +\patchcmd\extractdefault{\def\mykey}{\gdef\mykey}{}{\error} +\patchcmd\extractdefault{#2}{{\hskip2pt}#2}{}{\error} +\patchcmd\extractequalinitial{\def\mykey}{\gdef\mykey}{}{\error} +\let\extractkey@\extractkey +\apptocmd\extractkey@{\egroup}{}{\error} +\def\extractkey{\bgroup\@ifnextchar*{\def\decompose####1\nil{}\relax\extractkey@\@gobble}{\extractkey@}} + +\def\pgfmanual@pretty@quote{"} +\let\pgfmanual@pretty@pgfkeys@loop@\pgfmanual@pretty@pgfkeys@loop +\def\pgfmanual@pretty@pgfkeys@loop#1{% + \def\pgfmanual@loc@TMPa{#1}% + \def\pgfmanual@pretty@pgfkeys@loop@NEXT{\pgfmanual@pretty@pgfkeys@loop@{#1}}% + \ifx\pgfmanual@loc@TMPa\pgfmanual@pretty@quote% + \let\pgfmanual@pretty@pgfkeys@loop@NEXT\pgfmanual@pretty@collectquote + \fi + \pgfmanual@pretty@pgfkeys@loop@NEXT +} +\def\pgfmanual@pretty@collectquote{% + \let\pgfmanualprettyprinterhandlecollectedargs=\pgfmanual@pretty@collectargs@finish@collectquote + \pgfmanualprettyprintercollectupto" + {\pgfmanual@pretty@collectquote@b}% +} +\def\pgfmanual@pretty@collectquote@b{% + \let\pgfmanualprettyprinterhandlecollectedargs=\pgfmanual@pretty@collectargs@finish@collectquote@b + \pgfmanualprettyprintercollectupto,{% + \@xp\afterpgfmanual@pretty@collectquote\temp + }% +} + +\def\afterpgfmanual@pretty@collectquotenocomma,{\pgfmanual@pretty@pgfkeys@loop} +\def\afterpgfmanual@pretty@collectquote{\pgfmanual@pretty@pgfkeys@loop} +\def\pgfmanual@pretty@collectargs@finish@collectquote#1{\textcolor{keycolor}{\pgfmanualpdfref{""quotes}{"#1"}}} +\def\pgfmanual@pretty@collectargs@finish@collectquote@b#1{% + \edef\temp{\ifpgfmanualprettyprinterfoundterminator,\fi}% + \pgfkeys{/codeexample/prettyprint/key name/.code={\textcolor{keycolor}{##1}}}% + \def\thekey{#1}% + \def\leadingtoks{}\def\trailingtoks{}% + \pulloffstartspaces\pulloffsinglequote\pulloffstartspaces\pulloffstartbrace + \removetrailingspaces\removetrailingbrace + \textcolor{keycolor}{{}\leadingtoks}% {} here to prevent \textcolor from eating initial space + \@xp\pgfmanual@pretty@pgfkeys@loop\thekey\pgfmanual@EOI + \textcolor{keycolor}{{}\trailingtoks}% +} + +% Don't allow braces in key names +\patchcmd\pgfmanual@pretty@pgfkeys@collectkey{% + \def\pgfmanual@pretty@pgfkeys@collectkey@next{% + \pgfmanualprettyprintercollectargcount{1}{\pgfmanual@pretty@pgfkeys@collectkey}% + #1% + }% +}{% + \expandafter\pgfmanual@pretty@pgfkeys@processkey\expandafter{\the\toks0 }% + #1% + \def\pgfmanual@pretty@pgfkeys@collectkey@next{\pgfmanual@pretty@pgfkeys@loop}% +}{}{\error} + +% Redefine point collection to correctly balance the parens +% Has unfortunate side effect that it now throws an error if parens don't balance. +\let\pgfmanual@pretty@collectpoint@old\pgfmanual@pretty@collectpoint +\def\pgfmanual@pretty@collectpoint{\pgfmanual@pretty@collectpoint@(} %) +\DeclareDocumentCommand\pgfmanual@pretty@collectpoint@{r()}{% + \pgfmanualprettyprinterfoundterminatortrue + \pgfmanual@pretty@collectargs@finish@collectpoint{#1}% + \afterpgfmanual@pretty@collectpoint +} + + +\pgfqkeys{/codeexample/prettyprint}{ + cs arguments/meta/.initial=1, % Make \meta work correctly in codeexample + cs/meta/.code={\textcolor{black}{\meta{\@gobble#1}}}, +% + cs arguments/opt/.initial=1, + cs/opt/.code={\opt{\@gobble#1}}, + % + cs arguments/oarg/.initial=1, + cs/oarg/.code={\oarg{\@gobble#1}}, +% + cs arguments/marg/.initial=1, + cs/marg/.code={\marg{\@gobble#1}}, +% + cs arguments/pars/.initial=1, + cs/pars/.code={\@xp\pars\@xp{\@xp\pgfmanualprettyprintpgfkeys\@xp{\@gobble#1}}}, + cs arguments/pararg/.initial=1, + cs/pararg/.code={\pararg{\@gobble#1}}, + cs arguments/parargtwo/.initial=2, + cs/parargtwo/.code 2 args={\parargtwo{\@gobble#1}{\@gobble#2}}, +% + cs arguments/cscolor/.initial=1, + cs/cscolor/.code={\textcolor{cscolor}{\@gobble#1}}, + cs arguments/pointcolor/.initial=1, + cs/pointcolor/.code={\textcolor{pointcolor}{\@gobble#1}}, + %point/.code={\def\temp{#1}\show\temp}, +% + cs arguments/sseqset/.initial=1, + cs/sseqset/.code 2 args={\textcolor{cscolor}{\string\sseqset}\{\pgfmanualprettyprintpgfkeys{#2}\}}, +% + cs arguments/DeclareDocumentCommand/.initial=2, + cs/DeclareDocumentCommand/.code={\handlexparsestylecmd#1}, + cs arguments/NewSseqCommand/.initial=2, + cs/NewSseqCommand/.code={\handlexparsestylecmd#1}, +% + /pdflinks/internal link prefix=pgf, + key value with style detection/.code 2 args={\pgfkeysalso{/codeexample/prettyprint/key value display only={#2}}}, % get rid of bothersome special style handling + % handle spaces and colons + key name/.code={% + \pgfkeys@spdef\temp{#1}% + \let\pgfmanual@pretty@pgfkeys@collectkey@keyname\temp + \textcolor{keycolor}{% + \pgfmanualpdfref{\temp}{% + \noligs{\@xp\eatclnifpresent\@xp{\temp}}% + }% + }% + \onlytrailingspaces{#1}% + }, + key value display only/.code={% + \sseq@eval{\@nx\pgfutil@in@{/.style}{\pgfmanual@pretty@pgfkeys@collectkey@keyname}}% + \ifpgfutil@in@\else + \sseq@eval{\@nx\pgfutil@in@{/.sseq style}{\pgfmanual@pretty@pgfkeys@collectkey@keyname}}% + \fi + \ifpgfutil@in@ + \def\thekey{#1}% + \def\trailingtoks{}% + \removetrailingspaces\removetrailingbrace + \@xp\stylehandler\@xp{\@xp}\@xp{\thekey}% + \textcolor{keycolor}{% + \trailingtoks + }% + \else + \ifcustomhandler{\pgfmanual@pretty@pgfkeys@collectkey@keyname}{% + \def\thekey{#1}% + \def\trailingtoks{}% + \removetrailingspaces\removetrailingbrace + \@xp\customhandler\@xp{\@xp\pgfmanual@pretty@pgfkeys@collectkey@keyname\@xp}\@xp{\thekey}% + \textcolor{keycolor}{% + \trailingtoks + }% + }{% + \textcolor{keycolor}{{\itshape{\let\pgfmanualwordstartup\relax\pgfmanualprettyprintpgfkeys{#1}}}}% + }% + \fi + }, + point/.code={\pgfutil@in@){#1}\ifpgfutil@in@\prettyprintprocesspoint#1\else \textcolor{pointcolor}{\noligs{#1}}\fi}, + %/cs/.code={\pgfmanualpdfref{#1}{\textcolor{blue}{#1}}}, +% /cs with args/.code 2 args={\pgfmanualpdfref{#1}{\textcolor{blue}{#1}}\{\pgfmanualprettyprintcode{#2}\pgfmanualclosebrace}, + %/colored +} + +\def\handlexparsestylecmd#1#2#3{\pgfkeysvalueof{/codeexample/prettyprint/cs/.@cmd}#1\pgfeov\textcolor{cscolor}{#2}\typesetargspec{#3}} +\def\typesetargspec#1{\{\textcolor{purple}{#1}\}} + +\let\oldtextcolor\textcolor +\def\textcolorpoint#1{\oldtextcolor{pointcolor}} + + +% Normally the verbatim processes stuff using +\let\pgfmanual@verb@collect@code\pgfmanual@verb@collect +\patchcmd\pgfmanual@verb@collect@code{\pgfmanualprettyprintpgfkeys}{\pgfmanualprettyprintcode}{}{\error} +\let\pgfmanual@verb@code\pgfmanual@verb +\patchcmd\pgfmanual@verb@code{\begingroup}{\begingroup\let\pgfmanual@verb@collect\pgfmanual@verb@collect@code}{}{\error} +\def\codeverb|{\pgfmanual@verb@code} + +% balance the braces +\NewDocumentCommand\prettyprintprocesspoint { r() } {% + \textcolor{pointcolor}{% + \bgroup + \let\pgfmanual@pretty@collectpoint\pgfmanual@pretty@collectpoint@old + \let\textcolor\textcolorpoint + \noligs{(\pgfmanualprettyprintcode{#1})}% + \egroup + }% +} +%\pgfqkeys{/codeexample}{every codeexample/.style={width=6cm}} + + +\pgfqkeys{/sseqpages}{ + class/class:name/.forward to=/sseqpages/class/name, + class/class:page/.forward to=/sseqpages/class/page, + struct line/structline:page/.forward to=/sseqpages/struct line/page, + fit/cc:differential style/.forward to=/sseqpages/fit/differential style, + tikz primitives/cc:differential style/.forward to=/sseqpages/tikz primitives/differential style +} + + +\def\ooptions{\oarg{options}} +\def\moptions{|[|\meta{options}|]|} +\def\sourcecoord{\meta{source coordinate}} +\def\targetcoord{\meta{target coordinate}} +\def\sourcen{\meta{source n}} +\def\targetn{\meta{target n}} +\def\sourcename{\meta{source name}} + +\def\version{version 1.0} +\def\today{\the\year/\the\month/\the\day} +\def\pgfmanualurl{http://math.mit.edu/~hood/pgfmanual_v3.0.1a.pdf} +\def\xparseurl{http://mirror.ctan.org/macros/latex2e/contrib/l3packages/xparse.pdf} +\def\colormanualurl{http://mirror.ctan.org/macros/latex/required/graphics/color.pdf} + +\def\pkg#1{\textsf{\textmd{#1}}} +\def\sseqpages{\textsc{\pkg{spectralsequences}}} +\def\sseqpkg{\pkg{sseq}} +\let\tikzpkg\tikzname +\def\pgfpkg{\pkg{\textmd{PGF}}} +\def\tikzcdpkg{\pkg{tikzcd}} +\def\pgfplotspkg{\textsc{\pkg{pgfplots}}} +\def\xparsepkg{\pkg{xparse}} +\def\colorpkg{\pkg{color}} + +\bgroup\lccode`\(=`\{\lccode`\)=`\}\lowercase{\egroup + \def\sseqpageenv{\pgfmanualpdfref{sseqpage}{\texttt{(sseqpage)}}} + \def\sseqdataenv{\pgfmanualpdfref{sseqdata}{\texttt{(sseqdata)}}} + \def\tikzpictureenv{\texttt{(tikzpicture)}} + \def\scopeenv{\texttt{(scope)}} +} + + +\hypersetup{ + pdftitle={The Sseqpages Package}, + pdfauthor={Hood Chatham}, + pdfsubject={A spectral sequence drawing package build on tikz}, + pdfkeywords={spectral sequences,algebraic topology,homotopy theory,math,tikz,sseq}, + pdflicenseurl={http://www.latex-project.org/lppl/} +} + +\def\pars#1{|(|#1|)|} +\def\pararg#1{\pars{\meta{#1}}} +\def\parargtwo#1#2{|(\meta{#1},\meta{#2})|} +\def\parargthree#1#2#3{|(\meta{#1},\meta{#2},\meta{#3})|} +\def\parargthreeopt#1#2#3{|(\meta{#1},\meta{#2}|\opt{|,\meta{#3}|}|)|} +\def\parargthreevar#1#2#3{|(\meta{#1},\meta{#2}#3)|} + + +\def\example#1{\path{example_#1.tex}} + + +% xparse modifications: +\ExplSyntaxOn +\cs_set_eq:NN \__xparse_grab_U:w \sseq__xparse_grab_U:w +\cs_set_eq:NN \__xparse_add_type_U:w \sseq__xparse_add_type_U:w +\ExplSyntaxOff + +\def\@maketitle{% + \null\vskip 2em + \begin{center}\let\footnote\thanks\sffamily + {\huge \@title\par}\vskip 1.5em + {\large \parbox{.33\textwidth}{\centering\@author}% + \parbox{.33\textwidth}{\centering\@date}}% + \vskip2.5em\rule{\textwidth}{.4pt}% + \end{center}\par\vskip1.5em} +\def\abstractname{} +\def\mailtoHC{\href % some PDF viewers don't like spaces: + {mailto:<hood@mit.edu>\%20Hood\%20Chatham?subject=[sseqpages]} + {\texttt{hood@mit.edu}}}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty b/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty new file mode 100644 index 00000000000..62ff3e40a4f --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty @@ -0,0 +1,279 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% A package for drawing spectral sequences +%% + + +% TODO: +% label handler key, \sseqnormalizepolynomial +% speed up off page edges (uses 10% of the draw time for page 0 of tmfass) +% speed up label nodes +% try to restrict fragility issues to tooltips and tikz primitives... annoying +% error messages that should be warnings by default? +% improve axes options? allow axis to be centered on coordinate or centered between coordinates +% recover from failing to patch pgfkeys + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{spectralsequences}[2017/06/04 v1.0] + +\RequirePackage{tikz} +\RequirePackage{etoolbox} +\RequirePackage{xparse} +\RequirePackage{verbatim} +\RequirePackage{pdfcomment} + +\usetikzlibrary{quotes} +\usetikzlibrary{fit} +\usetikzlibrary{positioning} +\usetikzlibrary{intersections} +\usetikzlibrary{backgrounds} +\usepgflibrary{arrows.meta} +\usetikzlibrary{shapes} +%\usetikzlibrary{profiler} + +\newif\ifsseq@draftmode +\DeclareOption{draft}{\sseq@draftmodetrue} +\ProcessOptions\relax + +\def\sseq@authorname{Hood Chatham} +\def\sseq@authoremail{hood@mit.edu} + + +%\sseq@draftmodetrue + +%%%%%% %%%%%% +%% %% +%% Declarations and preliminaries %% +%% %% +%%%%%% %%%%%% +\newif\ifsseq@inprogress + +\newif\ifsseq@hasname +\newif\ifsseq@updateexisting +\newif\ifsseq@ispageenv +\newif\ifsseq@keepchanges +\newif\ifsseq@keepglobaloptions +\newif\ifsseq@globaldetone + +\newif\ifsseq@needstikz +\newif\ifsseq@thispage +\newif\ifsseq@outofrange +\newif\ifsseq@classlabel +\newif\ifsseq@draworphanedges +\newif\ifsseq@drawedge +\newif\ifsseq@tikzprims@integershift +\newif\ifsseq@anchor +\sseq@drawedgetrue +\sseq@tikzprims@integershifttrue + +\newif\ifsseq@patchforeach +\newif\ifsseq@patchfit + +\newif\ifsseq@tempif +\newif\ifsseq@gtempif +\newif\ifsseq@error + +\newtoks\sseq@temptoks +\newtoks\sseq@temptoksii +\newtoks\sseq@scope@toks + +\newcount\sseq@thepagecount +\newcount\sseq@anonsseqcount +\newcount\sseq@x +\newcount\sseq@y +\newcount\sseq@tempcount +\newcount\sseq@tempcountb +\newcount\sseq@tempx +\newcount\sseq@tempy +\newcount\sseq@tempxb +\newcount\sseq@tempyb + +\newcount\sseq@stackdepth + +\newdimen\sseq@tooltip@height +\newdimen\sseq@tooltip@width +\newdimen\sseq@gridstrokethickness +\sseq@gridstrokethickness=.1pt + +% Ensure \@xp and \@nx have the correct values in case that amsmath isn't loaded +\let\@xp\expandafter +\let\@nx\noexpand +\def\@xptwo{\@xp\@xp\@xp} +\def\@xpthree{\@xp\@xp\@xp\@xp\@xp\@xp\@xp} +\def\sseq@nil{\sseq@thisshouldnthappen@nil unique expansion} % This expansion text should be unique so that \ifx\sseq@nil\othercommand is false. +\def\sseq@infinity{10000} % Larger than any coordinate anyone will ever use. +\newcount\sseq@infinitycount +\sseq@infinitycount=\sseq@infinity\relax +\def\sseq@macroname{\@xp\@gobble\string} +\def\sseq@gobble@to@nil#1\sseq@nil{} +\def\sseq@macrogobble#1->{} + +% These are only used by defertikzcommand now +\def\sseq@callas#1{\def\sseq@callcmd{#1}} +\def\sseq@call#1{\bgroup\@xp\let\sseq@callcmd#1\@xptwo\egroup\sseq@callcmd} + +\def\sseq@getfirstchar#1#2\sseq@nil{#1} % used in shift/checkshift transform +\def\sseq@smuggle@macro#1#2\egroup{\@xp\egroup\@xp\def\@xp#1\@xp{#1}} + + +\def\sseq@protected@edef{\let\sseq@store@slsl\\\def\\{\protect\\}\let\@@protect \protect \let \protect \@unexpandable@protect \afterassignment \sseq@restore@protect \edef} +\def\sseq@protected@xdef{\let\sseq@store@slsl\\\def\\{\protect\\}\let\@@protect \protect \let \protect \@unexpandable@protect \afterassignment \sseq@restore@protect \xdef} +\def\sseq@restore@protect{\let\protect\@@protect\let\\\sseq@store@slsl} + +\def\sseq@eval#1{\bgroup\edef\sseq@temp{#1}\@xp\egroup\sseq@temp}% I got this from sseq.sty +\def\sseq@protectedeval#1{\bgroup\sseq@protected@edef\sseq@temp{#1}\@xp\egroup\sseq@temp} +\def\sseq@eval@show#1{\bgroup\edef\sseq@temp{#1}\show\sseq@temp\@xp\egroup\sseq@temp} +\def\sseq@profilenew#1#2{\pgfprofilenew{#1}\pretocmd#2{\pgfprofilestart{#1}}{}{\error}\apptocmd#2{\pgfprofileend{#1}}{}{\error}} + +%%%% add to macro commands +\def\sseq@d@addto@macro#1#2{\@xp\def\@xp#1\@xp{#1#2}} +\def\sseq@e@addto@macro#1#2{\edef#1{\unexpanded\@xp{#1}#2}} % let #2 be expanded +\def\sseq@eo@addto@macro#1#2{\edef#1{\unexpanded\@xp{#1}\unexpanded\@xp{#2}}} % let #2 be expanded once +\def\sseq@g@addto@macro#1#2{\@xp\gdef\@xp#1\@xp{#1#2}} +\def\sseq@x@addto@macro#1#2{\xdef#1{\unexpanded\@xp{#1}#2}} % let #2 be expanded +\def\sseq@xprotected@addto@macro#1#2{\sseq@protected@xdef#1{\unexpanded\@xp{#1}#2}} + +\def\sseq@d@addto@toks#1#2{#1\@xp{\the#1#2}} +\def\sseq@e@addto@toks#1#2{\sseq@eval{#1{\the#1#2}}} + +\def\sseq@d@addto@temptoks{\sseq@d@addto@toks\sseq@temptoks} +\def\sseq@e@addto@temptoks{\sseq@e@addto@toks\sseq@temptoks} + + +% Used in sseqkeys to delete spaces from style commands. +\def\sseq@setmacronospaces#1#2{% + \bgroup\catcode`\ =9\relax + \scantokens{\@xp\egroup\@xp\def\@xp#1\@xp{\csname #2\endcsname}}% +} + + +\def\sseq@removeparens{\@xp\sseq@removeparens@} +\def\sseq@removeparens@(#1){#1} + +% Stolen from trimspaces.sty +\bgroup +\catcode`\Q=3 +\gdef\sseq@trimspaces#1{% + \romannumeral-`\q\sseq@trim@trim@\noexpand#1Q Q% +} +\long\gdef\sseq@trim@trim@#1 Q{\sseq@trim@trim@@#1Q} +\long\gdef\sseq@trim@trim@@#1Q#2{#1} +\egroup +\def\sseq@trimleadingspaces{\romannumeral-`q} + +\def\sseq@ifempty#1{% + \@xp\ifx\@xp\sseq@nil\detokenize{#1}\sseq@nil + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi +} + +\def\sseq@ifnil#1{ + \ifx\sseq@nil#1 + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi +} + +\let\sseq@breakpoint\relax +\def\sseq@break#1\sseq@breakpoint{} +\def\sseq@break@withcleanup#1\sseq@breakpoint#2{} + +\def\sseq@breakfi{\fi\sseq@break} +\def\sseq@breakfifi{\fi\fi\sseq@break} +\def\sseq@breakfififi{\fi\fi\fi\sseq@break} +\long\def\sseq@breakdataenv#1\end#2{ + \def\sseq@tempa{sseqdata}\def\sseq@tempb{#2}\ifx\sseqtempa\sseqtempb + \@xp\sseq@breakdataenv@ + \else + \@xp\sseq@breakdataenv + \fi +} +\def\sseq@breakdataenv@{\let\endsseqdata\sseq@breakendsseqdata\end{sseqdata}} + +\long\def\sseq@breakpageenv#1\end#2{ + \def\sseq@tempa{sseqpage}\def\sseq@tempb{#2}\ifx\sseqtempa\sseqtempb + \@xp\sseq@breakpageenv@ + \else + \@xp\sseq@breakpageenv + \fi +} +\def\sseq@breakpageenv@{\let\endsseqpage\sseq@breakendsseqpage\end{sseqpage}} +\def\sseq@breakendsseqdata{} +\def\sseq@breakendsseqpage{} + +\def\sseq@seteverythingtonoops{% + \let\sseqdata\comment + \let\sseqpage\comment + \let\sseqkeys\@gobble + \let\sseqnewgroup\@gobblethree +} + +% Commands we are going to expose just inside of environments +\def\sseq@macrolist{% + % These are defined in sseqmain: + \class\replaceclass\d\structline\classoptions\doptions\structlineoptions\circleclasses + % The following are defined in sseqparsers: + \pgfmathparse\isalive\lastx\lasty\lastclass\savestack\restorestack\pushstack\nameclass\tagclass + \parsecoordinate\parsedifferential\getdtarget\gettag + \xcoord\ycoord\page %\xmin\xmax\ymin\ymax % these just get protected +} + +% All the tikz commands. We replace these in our environment too. Replacements defined in sseqparsers. +\def\sseq@tikzcommands{% + \clip\coordinate\draw\fill\filldraw + \graph\matrix\node\path\pattern + \shade\shadedraw\useasboundingbox +} + + +\input sseqmessages.code.tex % Exposes directly: \sseqerrortowarning +\input sseqcheckdefinitions.code.tex + +%\sseq@patchforeachfalse + +\ifsseq@tempif\else % Set to false in checkdefinitions if it failed to patch the key-value system. + \sseq@seteverythingtonoops + \sseq@pgfkeyspatchfailed +\fi + +\input sseqloadstore.code.tex % Responsible for installing environment-only macros +\input sseqmacromakers.code.tex % Exposes directly: \DeclareSseqCommand, \NewSseqCommand, \DeclareSseqGroup, \NewSseqGroup + +\input sseqparsers.code.tex % Responsible for making tikz modifications, exposes directly \sseqnormalizemonomial + + +\ifsseq@patchforeach + \input sseqforeach.code.tex +\else + \def\sseq@patchfor{} +\fi + +\input sseqkeys.code.tex % Exposes directly: \sseqset +\input sseqmain.code.tex % Defines all the main commands. Exposes directly: the environments, \xmin, \xmax, etc. +\input sseqdrawing.code.tex + + +%%% Some default key settings +\sseqset{ + edge labels={auto=right}, + classes={draw,circle,inner sep=0pt,minimum size=0.35em}, + circle classes={newellipse, ellipse ratio=1.2,draw, inner sep=2pt}, + edges=draw, + math nodes, + differentials=-> +} + +% Extra commands to expose: +\let\sseqifempty\sseq@ifempty + +\def\sseqpower#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{1}} +\def\sseqpowerempty#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{}} +\def\sseqtypesetpower@#1#2#3{\ifnum#1=\z@#3\else\ifnum#1=\@ne#2\else#2^{#1}\fi\fi} diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex new file mode 100644 index 00000000000..bdbc68f51b5 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex @@ -0,0 +1,170 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqcheckdefinitions.code.tex +%% +%% A few tikz commands are modified in sseqpages. This file checks the definitions of all commands modified. Of course, this is insufficient to ensure that +%% the behavior isn't completely wrong, but at least it's a sanity check. +%% + +% TODO: we could recover from failing to patch keys. + +\sseq@tempiftrue +\begingroup + +\def\sseq@checkdef#1{\def\sseq@temp{\sseq@checkdef@{#1}}\afterassignment\sseq@temp\@xp\def\csname sseq@check@\sseq@macroname#1\endcsname} +\def\sseq@checkdef@#1{\@xp\ifx\csname sseq@check@\sseq@macroname#1\endcsname#1\else + \sseq@tempiffalse +\fi} + +%% +%% sseqkeys.code.tex +%% + + +\sseq@checkdef\pgfkeys@case@one{% + \pgfkeysifdefined{\pgfkeyscurrentkey/.@cmd}% + {\pgfkeysgetvalue{\pgfkeyscurrentkey/.@cmd}{\pgfkeys@code}% + \expandafter\pgfkeys@code\pgfkeyscurrentvalue\pgfeov} + {\pgfkeys@case@two}% +} + +\sseq@checkdef\pgfkeys@case@two@extern{% + \ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text% + \pgfkeysvalueof{\pgfkeyscurrentkey}% + \else% + \pgfkeyslet{\pgfkeyscurrentkey}\pgfkeyscurrentvalue% + \fi% +} + + +\ifsseq@tempif\else + \endgroup + \sseq@tempiffalse % We'll throw a critical error in spectralsequences.sty to end input + \endinput +\fi +%% +%% sseqdrawing.code.tex +%% + +%from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 +\sseq@checkdef\tikz@lib@fit@scan@handle#1{% + \iftikz@shapeborder% + % Ok, fit all four external anchors, if they exist + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{west}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{east}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{north}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{south}}% + \else% + \tikz@lib@fit@adjust{#1}% + \fi% + \tikz@lib@fit@scan% +} + +% from \pgf\frontendlayer\tikz\tikz.code.tex line 5164 +\sseq@checkdef\tikz@calc@anchor#1.#2\tikz@stop{% + \pgfpointanchor{\tikz@pp@name{#1}}{#2}% +} + +\ifsseq@tempif + \global\sseq@patchfittrue +\else + \sseq@warning{fit-patch-failed} + \global\sseq@patchfitfalse +\fi + +\sseq@tempiftrue + + +%% +%% sseqforeach.code.tex +%% +\sseq@checkdef\pgffor@@vars@opt[#1]{\pgfkeys{/pgf/foreach/.cd,#1}\pgffor@vars} + +\sseq@checkdef\pgffor@doloop{% + \pgffor@begingroup + \edef\pgffor@temp{\expandafter\Pgffor@geT\the\pgffor@iter}% + \edef\pgffor@incheck{{.0/}{\pgffor@temp/}}% + \expandafter\pgfutil@in@\pgffor@incheck% + \ifpgfutil@in@% + \expandafter\pgffor@strip\pgffor@temp% + \fi% + \expandafter\pgfutil@in@\expandafter/\expandafter{\pgffor@var}% + \ifpgfutil@in@% + \expandafter\def\expandafter\pgffor@valuerest\expandafter{\pgffor@temp//\relax}% + \expandafter\pgffor@multiassign\pgffor@var/\pgffor@stop/\pgffor@stop/\relax% + \else% + % Convert to alphabetic sequence, if necessary. + \ifpgffor@alphabeticsequence% + \pgffor@makealphabetic\pgffor@temp% + \expandafter\let\pgffor@var=\pgffor@temp% + \else% + \expandafter\expandafter\expandafter\def\expandafter\pgffor@var\expandafter{\pgffor@temp}% + \fi% + \fi% + % Insert any context, if any. + \ifpgffor@context% + \let\pgffor@temp=\pgffor@dots@pre% + \expandafter\pgfutil@append@macrotomacro\expandafter% + {\expandafter\pgffor@temp\expandafter}\expandafter{\pgffor@var}% + \expandafter\pgfutil@append@macrotomacro\expandafter% + {\expandafter\pgffor@temp\expandafter}\expandafter{\pgffor@dots@post}% + \expandafter\let\pgffor@var=\pgffor@temp% + \fi% + % Perform assignments before loop body. + \ifx\pgffor@assign@before@code\pgfutil@empty% + \else% + \pgffor@assign@before@code% + \fi% + % + \expandafter\expandafter\expandafter\pgffor@reset@hooks\expandafter\pgffor@beginhook\expandafter\pgffor@body\pgffor@endhook% + % + % Perform assignments after loop body. + \ifx\pgffor@assign@after@code\pgfutil@empty% + \else% + \pgffor@assign@after@code% + \fi% + \pgffor@endgroup% + \pgffor@loop% +} + +\sseq@checkdef\pgffor@invokebody{% + \pgffor@begingroup% + \expandafter\pgfutil@in@\expandafter/\expandafter{\pgffor@var}% + \ifpgfutil@in@% + \expandafter\def\expandafter\pgffor@valuerest\expandafter{\pgffor@value//\relax}% + \expandafter\pgffor@multiassign\pgffor@var/\pgffor@stop/\pgffor@stop/\relax% + \else% + \expandafter\expandafter\expandafter\def\expandafter\pgffor@var\expandafter{\pgffor@value}% + \fi% + % Execute assign once code. + \ifx\pgffor@assign@once@code\pgfutil@empty% + \else\pgffor@assign@once@code% + \fi% + % Execute assign before code. + \ifx\pgffor@assign@before@code\pgfutil@empty% + \else\pgffor@assign@before@code% + \fi% + % + \expandafter\expandafter\expandafter\pgffor@reset@hooks\expandafter\pgffor@beginhook\expandafter\pgffor@body\pgffor@endhook% + % Execute assign after code. + \ifx\pgffor@assign@after@code\pgfutil@empty% + \else% + \pgffor@assign@after@code% + \fi% + % + \pgffor@endgroup% +} + +\ifsseq@tempif + \global\sseq@patchforeachtrue +\else + \sseq@warning{foreach-patch-failed} + \global\sseq@patchforeachfalse +\fi + +\endgroup
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex new file mode 100644 index 00000000000..098e73f9110 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex @@ -0,0 +1,990 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqdrawing.code.tex +%% +%% Defines the macros that draw the features of the spectral sequence (at least, those that aren't drawn by tikz). +%% Everything here has to be super optimized, because like 90% of the execution time is in these functions. +%% In particular, tikz is a horrible performance hole that must be avoided at all costs. For example, the code +%% the code to produce the axis ticks used to use the tikz \node command, and in the file example_KF3n.tex drawing +%% the axes ticks was taking about 1/3 of the compile time (a little under 1s out of a 3.2) +%% + + + +%%% +%%% Draw axes and clip +%%% +\def\sseq@handlexaxis{ + \ifsseq@drawxaxis + \bgroup + \ifsseq@borderxaxis\else + \let\sseq@ymin\sseq@yaxisorigin % Warning: this is a stupid, lazy hack. + \fi + \sseq@drawxaxis + \ifsseq@drawxaxisticks + \sseq@drawxticks + \fi + \egroup + \fi +} +\def\sseq@handleyaxis{ + \ifsseq@drawyaxis + \bgroup + \ifsseq@borderyaxis\else + \let\sseq@xmin\sseq@xaxisorigin % Warning: this is a stupid, lazy hack. + \fi + \sseq@drawyaxis + \ifsseq@drawyaxisticks + \sseq@drawyticks + \fi + \egroup + \fi +} +\def\sseq@drawxaxis{ + \bgroup + \pgftransformreset + \sseq@globaldetonetransform + % + \bgroup + \pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformyshift{-\sseq@xaxisgap} + \sseq@globalscaletransform + \pgfpathmoveto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}} + \egroup + \bgroup + \pgftransformxshift{-\sseq@yaxisgap} + %\pgftransformxshift{-\sseq@ylabelgap} + \pgftransformxshift{-\sseq@xaxis@start@extend} + \pgftransformyshift{-\sseq@xaxisgap} + \sseq@globalscaletransform + \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}} + \egroup + \egroup + \pgfusepath{stroke} +} +\def\sseq@drawyaxis{ + \bgroup + \pgftransformreset + \sseq@globaldetonetransform + \bgroup + \pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformxshift{-\sseq@yaxisgap} + \sseq@globalscaletransform + \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}} + \egroup + \bgroup + \pgftransformyshift{-\sseq@xaxisgap} + %\pgftransformyshift{-\sseq@xlabelgap} + \pgftransformyshift{-\sseq@yaxis@start@extend} + \pgftransformxshift{-\sseq@yaxisgap} + \sseq@globalscaletransform + \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}} + \egroup + \egroup + \pgfusepath{stroke}% +} +\def\sseq@drawxticks{ + \sseq@tempy=\sseq@ymin\relax + \sseq@tempx=\sseq@xmax\relax + \advance\sseq@tempx\@ne\relax + \edef\sseq@temp{\the\sseq@tempx}% + \sseq@tempx=\sseq@xmin\relax + \loop + \bgroup + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}} + \pgftransformresetnontranslations + \sseq@globaldetonetransform + \pgftransformyshift{-\sseq@xlabelgap}\pgftransformyshift{-\sseq@xaxisgap} + \pgftransformresetnontranslations + \ifsseq@rotatelabels\sseq@globalrotatetransform\fi + \sseq@xtickstyle + \tikz@options + \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}} + \egroup + \advance\sseq@tempx\sseq@xtickstep\relax + \ifnum\sseq@tempx<\sseq@temp\repeat +} +\def\sseq@drawyticks{ + \sseq@tempx=\sseq@xmin\relax + \sseq@tempy=\sseq@ymax\relax + \advance\sseq@tempy\@ne\relax + \edef\sseq@tempmax{\the\sseq@tempy} + \sseq@tempy=\sseq@ymin\relax + \loop + \bgroup + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}} + \pgftransformresetnontranslations + \sseq@globaldetonetransform + \pgftransformxshift{-\sseq@ylabelgap}\pgftransformxshift{-\sseq@yaxisgap} + \pgftransformresetnontranslations + \ifsseq@rotatelabels\sseq@globalrotatetransform\fi + \sseq@ytickstyle + \tikz@options + \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempy}$}} + \egroup + \advance\sseq@tempy\sseq@ytickstep\relax + \ifnum\sseq@tempy<\sseq@tempmax\repeat +} +\def\sseq@setupclip{ + %\clip(\sseq@xmin-0.4,\sseq@ymin-0.4) rectangle (\sseq@xmax+0.5,\sseq@ymax+0.5);% + \ifsseq@clip + \ifx\sseq@customclip\pgfutil@empty + \bgroup + \pgftransformreset + \sseq@globaldetonetransform + \ifsseq@borderyaxis + \def\xmin{\pgftransformxshift{-\sseq@yaxisgap}\pgftransformxshift{\sseq@yclip@axisgap}} + \else + \def\xmin{\pgftransformxshift{-\sseq@xaxis@start@extend}\pgftransformxshift{-\sseq@clip@padding@left}} + \fi + \ifsseq@borderxaxis + \def\ymin{\pgftransformyshift{-\sseq@xaxisgap}\pgftransformyshift{\sseq@xclip@axisgap}} + \else + \def\ymin{\pgftransformyshift{-\sseq@yaxis@start@extend}\pgftransformyshift{-\sseq@clip@padding@bottom}} + \fi + \def\xmax{\pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformxshift{\sseq@clip@padding@right}} + \def\ymax{\pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformyshift{\sseq@clip@padding@top}} + \bgroup + \xmin\ymin\sseq@globalscaletransform + \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}} + \egroup + \bgroup + \xmin\ymax\sseq@globalscaletransform + \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}} + \egroup + \bgroup + \xmax\ymax\sseq@globalscaletransform + \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}} + \egroup + \bgroup + \xmax\ymin\sseq@globalscaletransform + \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}} + \egroup + \egroup + \pgfpathclose + \pgfgetpath\sseq@theclippath % This stores the clipping so I can find intersections later + \pgfusepath{discard}% This has to be after the egroup or else the clipping gets screwed up + \bgroup + %\sseq@globalscaletransform + \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}} + \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}} + \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}} + \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}} + \pgfpathclose + \egroup + \pgfgetpath\sseq@therangepath % Only for deciding whether to draw "tricky edges" + \pgfusepath{discard} + \else + \def\sseq@temp{\path[name path=temp]} + \@xptwo\sseq@temp\@xp\@gobble\sseq@customclip + \pgfgetpath\sseq@theclippath + \let\sseq@theclippath\tikz@intersect@path@name@temp + \fi + \else + \let\sseq@theclippath\relax + \fi +} +\def\sseq@useclip{\ifx\sseq@theclippath\relax\else\pgfsetpath\sseq@theclippath\pgfusepath{clip}\fi} +\def\sseq@grid@chess{ + \bgroup + \pgfscope + \sseq@useclip + \pgflowlevelsynccm + \pgfsetlinewidth{1cm} + \pgfsetdash{{1cm}{1cm}}{1cm} + \pgfsetcolor{lightgray} + \pgfpathgrid[stepx=2cm,stepy=2cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\sseq@xmax cm+0.499cm}{\sseq@ymax cm+0.499cm}} + \pgfusepath{stroke} + \endpgfscope + \egroup +} +\def\sseq@grid@crossword{ + \bgroup + \pgfscope + \pgfsetlinewidth{\the\sseq@gridstrokethickness} + \sseq@useclip + \pgftransformxshift{-0.5cm} + \pgftransformyshift{-0.5cm} + \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.99cm}{\ymax cm+0.99cm}} + \pgfusepath{stroke} + \endpgfscope + \egroup +} +\def\sseq@grid@go{ + \bgroup + \pgfscope + \sseq@useclip + \pgfsetlinewidth{\the\sseq@gridstrokethickness} + \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.5cm}{\ymax cm+0.5cm}} + \pgfusepath{stroke} + \endpgfscope + \egroup +} +\def\sseq@grid@none{} +\def\sseq@grid@dots{ + \bgroup + \pgfscope + \pgfgettransform\sseq@savetransform + \pgftransformreset + \sseq@globalscaletransform + \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v} + \pgfsettransform\sseq@savetransform + \sseq@useclip + \pgftransformxshift{-1.5cm} + \pgftransformyshift{-0.5cm} + \pgfsetdash{{1pt}{\sseq@a*1cm-1pt}}{0.5cm+.5pt} + \pgfsetlinewidth{1pt} + \sseq@tempy=\sseq@ymin\relax + \advance\sseq@tempy\m@ne + \loop + \advance\sseq@tempy\@ne + \pgfpathmoveto{\pgfpoint{\sseq@xmin cm+0.5cm/\sseq@a}{\the\sseq@tempy cm}} + \pgfpathlineto{\pgfpoint{\sseq@xmax cm+1.01cm }{\the\sseq@tempy cm}} + \ifnum\sseq@tempy<\sseq@ymax\repeat + %\pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\xmax cm-0.5cm}{\ymax cm-0.5cm}} + \pgfusepath{stroke} + \endpgfscope + \egroup +} +%%% +%%% Draw Classes +%%% +%%% Class offsets +\sseqnewclasspattern{standard}{ + (0,0); + (-0.13,0)(0.13,0); + (-0.2,0)(0,0)(0.2,0); + (-0.13,-0.13)(0.13,-0.13)(-0.13,0.13)(0.13,0.13); + (-0.16,-0.16)(0.16,-0.16)(-0.16,0.16)(0.16,0.16)(0,0); + (-0.13,-0.2)(-0.13,0)(-0.13,0.2)(0.13,-0.2)(0.13,0)(0.13,0.2); +} +\sseqnewclasspattern{linear}{ + (0,0); + (-0.13,0)(0.13,0); + (-0.2,0)(0,0)(0.2,0); + (-0.3,0)(-0.1,0)(0.1,0)(0.3,0); + (-0.4,0)(-0.2,0)(0,0)(0.2,0)(0.4,0); + (-0.5,0)(-0.3,0)(-0.1,0)(0.1,0)(0.3,0)(0.5,0); +} +\def\sseq@offset#1#2{ + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{0\csname sseq@\sseq@classpattern xoffset#1/#2\endcsname cm}{0\csname sseq@\sseq@classpattern yoffset#1/#2\endcsname cm}}} +} +\def\sseq@class@getparts#1(#2,#3,#4)[#5].{ + \sseq@seterrorannotation@drawing{#1}{#2}{#3}{#4}{#5} + \def\sseq@thisclassname{class.(#2,#3,#4)} + \def\sseq@thisnodename{sseq{#2,#3,#4}} + \def\sseq@thispos{(#2,#3)} + \def\sseq@thisposnum{#4} + \def\sseq@thisclassnum{#5} +} + +\def\sseqtooltip#1#2{% + \edef\temp{\detokenize\@xpthree{#2}}% + \edef\temp{\@xp\sseqtooltip@replaceslashes\@xp{\temp}}% + \sseq@eval{\@nx\pdftooltip{\unexpanded{#1}}{\temp}}% +} +\bgroup\lccode`\!=`\\\lowercase{\egroup +\def\sseqtooltip@replaceslashes#1{\sseqtooltip@replaceslashes@#1!\sseq@nil} +\def\sseqtooltip@replaceslashes@#1!#2{% + #1% + \ifx\sseq@nil#2\@xp\@gobble\else + \@nx\@nx\@nx\textbackslash + \@xp\sseqtooltip@replaceslashes@ + \fi#2% +} +} + +% #1 -- the name of the node object +\def\sseq@class@drawnode#1{% + \begingroup + \sseq@class@getparts#1. + \sseq@tempx=\sseq@obj{\sseq@thisclassname.x}\relax + \sseq@tempy=\sseq@obj{\sseq@thisclassname.y}\relax + \sseq@needstikzfalse + \sseq@options@firstpassmode + \sseq@thesseqstyle + \sseq@theclassstyle + \ifnum\sseq@obj{#1.page}=\sseq@infinitycount + \sseq@thepermanentcyclestyle + \else + \sseq@thetransientcyclestyle + \ifsseq@thispage + \sseq@thethispagecyclestyle + \fi + \fi + \the\sseq@scope@toks + \sseq@obj{#1.needstikz} +% + \sseq@outofrangetrue + \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax + \sseq@outofrangefalse + \pgfscope + \let\tikz@options\pgfutil@empty + \let\tikz@alias=\pgfutil@empty + \def\pgfkeysdefaultpath{/sseqpages/class/} + \sseq@options@secondpassmode + \sseq@thesseqstyle + \sseq@theclassstyle + \ifnum\sseq@obj{#1.page}=\sseq@infinitycount + \sseq@thepermanentcyclestyle + \else + \sseq@thetransientcyclestyle + \ifsseq@thispage + \sseq@thethispagecyclestyle + \fi + \fi + \the\sseq@scope@toks + \sseq@obj{#1.options}% + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}} + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}} + \iftikz@fullytransformed\pgfgettransform{\savetransform}\fi + \pgftransformresetnontranslations + \sseq@globalrotatetransform + \sseq@classplacementtransform + \sseq@obj@ifdef{#1.offset}{\sseq@obj{#1.offset}}{% + \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}}% + }% + \iftikz@fullytransformed\pgfsettransform{\savetransform}\else\pgftransformresetnontranslations\ifsseq@rotatelabels\sseq@globalrotatetransform\fi\fi + \tikz@options + \ifsseq@needstikz + \let\sseq@mode\tikz@mode + \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj{#1.nodetext.options}}}% + \sseq@eval{% + \@nx\node[/utils/exec={\let\@nx\tikz@mode\@nx\sseq@mode}, + /handlers/first char syntax/the character "/.initial=\@nx\sseq@handlequote + ] (\sseq@thisnodename) {\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}} + [every text node part/.code={}] + \@nx\sseq@obj{#1.labelnodes}; + }% + \else + \tikz@node@textfont + \edef\sseq@classnodetextoptions{\@xptwo\@nx\sseq@obj{#1.nodetext.options}} + \edef\sseq@classnodetext{\@xptwo\@nx\sseq@obj{#1.nodetext}} + \sseq@setnodetext + \let\tikz@fig@name\sseq@thisnodename + \pgfmultipartnode{\tikz@shape}{\tikz@anchor}{\tikz@fig@name}{\sseq@drawnode}% + \tikz@alias + \sseq@obj{#1.labelnodes} + \fi + \sseq@obj@ifdef{#1.tooltip}{ + \pgfpointanchor{\sseq@thisnodename}{west} + \pgf@xa=\pgf@x + \pgfpointanchor{\sseq@thisnodename}{south} + \pgf@ya=\pgf@y +% + \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{west}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{east}}}} + \pgf@xb=\pgf@x + \pgf@process{\pgfpointdiff{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{south}}}{\pgfpointtransformed{\pgfpointanchor{\sseq@thisnodename}{north}}}} + \pgf@yb=\pgf@y +% + \setbox\tikz@tempbox=\hbox{ + \pgfinterruptpicture + \sseqtooltip{\rule{\pgf@xb}{0pt}\rule{0pt}{\pgf@yb}}{\sseq@obj{#1.tooltip}} + \endpgfinterruptpicture + } + {% + \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}% + \pgfapproximatenonlineartransformation% + \pgfqboxsynced{\tikz@tempbox}% + }% + }{} + \endpgfscope + \fi\fi\fi\fi + \ifsseq@outofrange + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}% + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}} + \pgftransformresetnontranslations + \sseq@globalrotatetransform + \sseq@classplacementtransform + \sseq@offset{\sseq@thisposnum}{\sseq@obj{partcoord.\sseq@thispos.numnodes}} + \pgfcoordinate{\sseq@thisnodename}{\pgfpointorigin}% + \fi + \endgroup +} +\def\sseq@setnodetext{% + \setbox\pgfnodeparttextbox=\hbox{% + \pgfscope% + \tikzset{every text node part/.try}% + \sseq@classnodetextoptions + \ifx\tikz@textopacity\pgfutil@empty% + \else% + \pgfsetfillopacity{\tikz@textopacity}% + \pgfsetstrokeopacity{\tikz@textopacity}% + \fi% + \pgfinterruptpicture + \ifx\tikz@text@width\pgfutil@empty% + \tikz@textfont% + \else% + \begingroup% + \pgfmathsetlength{\pgf@x}{\tikz@text@width}% + \pgfutil@minipage[t]{\pgf@x}\leavevmode\hbox{}% + \tikz@textfont% + \tikz@text@action% + \fi% + \ifx\tikz@textcolor\pgfutil@empty% + \else% + \pgfutil@colorlet{.}{\tikz@textcolor}% + \fi% + \pgfsetcolor{.}% + \tikz@atbegin@node% + \sseq@classnodetext% + \tikz@atend@node% + \ifx\tikz@text@width\pgfutil@empty% + \else% + \pgfutil@endminipage% + \endgroup% + \fi% + \endpgfinterruptpicture + \endpgfscope% + }% + \ifx\tikz@text@width\pgfutil@empty% + \else% + \pgfmathsetlength{\pgf@x}{\tikz@text@width}% + \wd\pgfnodeparttextbox=\pgf@x% + \fi% + \ifx\tikz@text@height\pgfutil@empty% + \else% + \pgfmathsetlength{\pgf@x}{\tikz@text@height}% + \ht\pgfnodeparttextbox=\pgf@x% + \fi% + \ifx\tikz@text@depth\pgfutil@empty% + \else% + \pgfmathsetlength{\pgf@x}{\tikz@text@depth}% + \dp\pgfnodeparttextbox=\pgf@x% + \fi% +} +\def\sseq@drawnode{% + \pgfutil@tempdima=\pgflinewidth% + {% + \tikz@mode% + %\iftikz@mode@clip \sseq@error@internal{Clip shouldn't happen here, but this error should be caught earlier}{}\fi % + \iftikz@mode@draw% + \iftikz@mode@double% + % Change line width + \begingroup% + \pgfsys@beginscope% + \tikz@double@setup% + \fi% + \fi% + % + % Step 10: Do stroke/fill as needed + % + \sseq@eval{\noexpand\pgfusepath{% + \iftikz@mode@fill fill,\fi% + \iftikz@mode@draw draw,\fi% + }}% + % + % Step 11: Double stroke, if necessary + % + \iftikz@mode@draw% + \iftikz@mode@double% + \pgfsys@endscope% + \endgroup% + \fi% + \fi + }% + \global\pgflinewidth=\pgfutil@tempdima% +} + +%%% +%%% Drawing edges +%%% +\def\sseq@ifinrange(#1){\sseq@ifinrange@#1,\sseq@nil} +\def\sseq@ifinrange@#1,#2,#3\sseq@nil{% + \sseq@tempx=#1\relax\sseq@tempy=#2\relax + \sseq@outofrangetrue + \ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax + \sseq@outofrangefalse + \fi\fi\fi\fi + \ifsseq@outofrange + \@xp\pgfutil@secondoftwo + \else + \@xp\pgfutil@firstoftwo + \fi +} + +\def\sseq@fullcoord@to@partialcoord(#1){\sseq@fullcoord@to@partialcoord@#1,\@nil} +\def\sseq@fullcoord@to@partialcoord@#1,#2,#3\@nil{{#1cm}{#2cm}} +% #1 -- source (full) +% #2 -- target (full) +% #3 -- which type of edge (either "structline" or "differential") +% #4 -- options +\def\sseq@drawedge(#1)(#2)#3#4{% + \begingroup\pgfscope + \def\sseq@edgetype{#3} + \let\sseq@edgesourceanchor\pgfutil@empty + \let\sseq@edgetargetanchor\pgfutil@empty +% + \sseq@needstikzfalse + \def\pgfkeysdefaultpath{/sseqpages/#3/}% + \sseq@options@bothpassmode + \sseq@thesseqstyle + \sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks + #4% + \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}% + % First calculate actual start and end of the edge + \let\tempaf\pgfutil@empty + \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor + \def\tempa{\pgfpointanchor{sseq{#1}}{center}}% if so, start by taking the center of that coordinate + \else + \edef\tempa{\@nx\pgfpointanchor{sseq{#1}}{\sseq@edgesourceanchor}} % If it has an anchor, use that + \let\tempaf\tempa + \fi + \ifx\sseq@edgetargetanchor\pgfutil@empty % check that the target doesn't have a specified anchor + \def\tempb{\pgfpointshapeborder{sseq{#2}}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate + \else + \edef\tempb{\@nx\pgfpointanchor{sseq{#2}}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that + \fi + \let\tempbf\tempb + \ifx\tempaf\pgfutil@empty% + \def\tempaf{\pgfpointshapeborder{sseq{#1}}{\tempb}}% + \fi +% + \tikz@options + \tikz@mode + \def\temparrowstartspec{}% + \def\temparrowendspec{}% + \pgfcoordinate{tempa}{\tempaf}% + \pgfcoordinate{tempb}{\tempbf}% + \pgftransformreset + \sseq@ifinrange(#1){\sseq@ifinrange(#2){\sseq@outofrangefalse}{\sseq@outofrangetrue}}{\sseq@outofrangetrue}% + \ifsseq@outofrange + \sseq@handleoffpageedge{#1}{#2}{#3}% + \fi + \ifsseq@drawedge + % TODO: should some sort of transformation manipulation be here? Maybe allow user to specify preference? + % Don't draw dots on very short segments + \pgfpointdiff{\tempbf}{\tempaf} + \pgfmathveclen{\pgf@x}{\pgf@y}% + \@xp\pgfmathint\@xp{\pgfmathresult}% + \ifnum\pgfmathresult<10\relax%%17? % TODO: Fix this predicate + \tikzset{every text node part/.append code={\pgfsetcolor{white}}}% I wonder why this is here... + \ifx\temparrowstartspec\pgfutil@empty + \else + \def\temparrowstartspec{\pgfsetarrowsstart{}}% + \fi + \ifx\temparrowendspec\pgfutil@empty + \else + \def\temparrowendspec{\pgfsetarrowsend{}}% + \fi + \fi + \ifsseq@needstikz + \draw[/sseqpages, + /utils/exec={\sseq@thesseqstyle\sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks + \temparrowstartspec\temparrowendspec #4}% + ] (tempa) to (tempb);% + \else + \temparrowstartspec + \temparrowendspec + \pgfpathmoveto{\pgfpointanchor{tempa}{center}}% + \pgfpathlineto{\pgfpointanchor{tempb}{center}}% + \sseq@eval{\noexpand\pgfusepath{% + \iftikz@mode@fill fill,\fi + \iftikz@mode@draw draw,\fi + }}% + \fi + \fi + \sseq@breakpoint + \endpgfscope\endgroup +} + +% TODO: this macro is super expensive. Make it faster (avoid +\def\sseq@handleoffpageedge#1#2#3{ + \pgfpathmoveto{\tempaf}% + \pgfpathlineto{\tempbf}% + \pgfgetpath\thispath + \pgfusepath{discard}% + \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}% + \ifcase\pgfintersectionsolutions\relax + % No intersections, but one or both endpoints may be out of range but still in clipping region due to scaling. Add ellipses as appropriate. + \sseq@ifinrange(#1){% If the first endpoint is in range, the second must be out of range b/c sseq@outofrange is true. + %\edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}} + }{% + \sseq@ifinrange(#2){% + \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}} + }{\sseq@drawedge@handletrickyedge}% uh-oh, both ends are out of range + }% + \or + \sseq@ifinrange(#1){% If the startpoint is in range, the intersection must be the end. + \def\tempbf{\pgfpointintersectionsolution{1}} + \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}} + \pgfcoordinate{tempb}{\tempbf} + }{% + \sseq@ifinrange(#2){% If the startpoint is out of range and the endpoint is in range, the intersection must be the start + \def\tempaf{\pgfpointintersectionsolution{1}}% + \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}% + \pgfcoordinate{tempa}{\tempaf}% + }{\sseq@drawedge@handletrickyedge}% Uh-oh, both ends are out of range. + } + \or% an orphan + \ifsseq@draworphanedges + \sseq@drawedge@handleorphan + \else + \sseq@drawedgefalse % Don't draw "orphaned edges" + \fi + \else + \sseq@error{clip-not-convex}% + \sseq@breakfifi + \fi +} + +\def\sseq@drawedge@handletrickyedge{% + \ifsseq@draworphanedges + \pgfintersectionofpaths{\pgfsetpath\sseq@therangepath}{\pgfsetpath\thispath}% + \ifnum\pgfintersectionsolutions=\z@ + \sseq@drawedgefalse % don't draw orphan edges that never intersect actual range + \else% Now we have to make a line through tempa and tempb long enough so that it intersects the original clip area twice. + \pgfmathanglebetweenpoints{\pgfpointanchor{tempa}{center}}{\pgfpointanchor{tempb}{center}}% + \edef\tempangle{\pgfmathresult} + \pgfpathmoveto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{100cm}}}% a really long line + \pgfpathlineto{\pgfpointadd{\pgfpointanchor{tempa}{center}}{\pgfpointpolar{\tempangle}{-100cm}}}% + \pgfgetpath\thispath + \pgfusepath{discard} + \pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath} + \sseq@drawedge@handleorphan + \fi + \else + \sseq@drawedgefalse + \fi +} + + +\def\sseq@drawedge@handleorphan{% + \def\tempaf{\pgfpointintersectionsolution{1}}% + \def\tempbf{\pgfpointintersectionsolution{2}}% + \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@\sseq@edgetype @spec\endcsname}}% + \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@\sseq@edgetype @spec\endcsname}}% + \pgfcoordinate{tempa}{\tempaf}% + \pgfcoordinate{tempb}{\tempbf}% +} + + +% +% #1 -- first coordinate +% #2 -- second coordinate +% #3 -- uid +\def\sseq@circleclass@draw#1#2#3{ + \begingroup + \pgfmathanglebetweenpoints{\pgfpointanchor{sseq{#2}}{center}}{\pgfpointanchor{sseq{#3}}{center}} + \let\tempangle\pgfmathresult + \let\tikz@lib@fit@scan@handle\sseq@fit@tikz@lib@fit@scan@handle % install fit modifications. + \let\tikz@calc@anchor\sseq@fit@tikz@calc@anchor + \sseq@tempiftrue + \node[ + rotate fit=\tempangle, + /utils/exec={\sseq@thesseqstyle\sseq@thecircleclassstyle\the\sseq@scope@toks\sseq@savedoptioncode + \sseq@obj{#1.options} + \sseq@obj{#1.fitnodes} + \@xp\pgfkeysalso\@xp{\romannumeral0\sseq@obj{#1.tikzprimoptions}} + } + ] {}; + \endgroup +} +% Modifies tikz commands \tikz@lib@fit@scan@handle from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 and +% \tikz@calc@anchor from \pgf\frontendlayer\tikz\tikz.code.tex line 5164 +% make it so that fit silently ignores nodes that are not defined. +% This is copied with modification from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 +\def\sseq@fit@tikz@lib@fit@scan@handle#1{% + \ifsseq@tempif % this has been set in the following macro to be true if there is a node with the given name. If it's not true, ignore this. + \iftikz@shapeborder% + % Ok, fit all four external anchors, if they exist + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{west}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{east}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{north}}% + \tikz@lib@fit@adjust{\pgfpointanchor{\tikz@shapeborder@name}{south}}% + \else% + \tikz@lib@fit@adjust{#1}% + \fi% + \fi + \sseq@tempiftrue + \tikz@lib@fit@scan% +} + +% This is copied with modification from \pgf\frontendlayer\tikz\tikz.code.tex line 5164 +\def\sseq@fit@tikz@calc@anchor#1.#2\tikz@stop{% + \pgfutil@ifundefined{pgf@sh@ns@#1}{\sseq@tempiffalse}{%If the node doesn't exist, don't throw an error but record that we should skip it + \pgfpointanchor{\tikz@pp@name{#1}}{#2}% + }%s +} + + +%% New shapes and arrows +%% These use lots of keys with spaces so it's convenient to turn off ExplSyntax. + +% Stolen from: https://tex.stackexchange.com/a/24621 +\pgfqkeys{/pgf}{ + ellipse ratio/.code={\pgfkeyssetvalue{/pgf/ellipse ratio}{#1}}, + ellipse ratio/.initial=1 +} +\pgfdeclareshape{newellipse} +{ + \inheritsavedanchors[from=ellipse] + \inheritanchorborder[from=ellipse] + \savedanchor\radius{% + % + % Caculate ``height radius'' + % + \pgf@y=.5\ht\pgfnodeparttextbox% + \advance\pgf@y by.5\dp\pgfnodeparttextbox% + \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}% + \advance\pgf@y by\pgf@yb% + % + % Caculate ``width radius'' + % + \pgf@x=.5\wd\pgfnodeparttextbox% + \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}% + \advance\pgf@x by\pgf@xb% + % + % Adjust + % + \pgfkeysgetvalue{/pgf/ellipse ratio}{\ratioscale} + \pgfmathsetmacro\widthfactor{sqrt(\ratioscale^2+1)/\ratioscale} + \pgfmathsetmacro\heightfactor{sqrt(\ratioscale^2+1)} + \pgf@x=\widthfactor\pgf@x% + \pgf@y=\heightfactor\pgf@y% + % + % Adjust height, if necessary + % + \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/minimum height}}% + \ifdim\pgf@y<.5\pgf@yc% + \pgf@y=.5\pgf@yc% + \fi% + % + % Adjust width, if necessary + % + \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/minimum width}}% + \ifdim\pgf@x<.5\pgf@xc% + \pgf@x=.5\pgf@xc% + \fi% + % + % Add outer sep + % + \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}% + \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}% + \advance\pgf@x by\pgf@xb% + \advance\pgf@y by\pgf@yb% + } + + \inheritanchor[from=ellipse]{center} + \inheritanchor[from=ellipse]{mid} + \inheritanchor[from=ellipse]{base} + \inheritanchor[from=ellipse]{north} + \inheritanchor[from=ellipse]{south} + \inheritanchor[from=ellipse]{west} + \inheritanchor[from=ellipse]{mid west} + \inheritanchor[from=ellipse]{base west} + \inheritanchor[from=ellipse]{north west} + \inheritanchor[from=ellipse]{south west} + \inheritanchor[from=ellipse]{east} + \inheritanchor[from=ellipse]{mid east} + \inheritanchor[from=ellipse]{base east} + \inheritanchor[from=ellipse]{north east} + \inheritanchor[from=ellipse]{south east} + + \inheritbackgroundpath[from=ellipse] +} + +%% +%% +%% n concentric circles +%% + +\tikzset{circlen/.code={\def\circlen@n{#1}\pgfkeysalso{shape=circlen@shape}}} +\pgfdeclareshape{circlen@shape} +{ + \savedanchor\centerpoint{% + \pgf@x=.5\wd\pgfnodeparttextbox% + \pgf@y=.5\ht\pgfnodeparttextbox% + \advance\pgf@y by-.5\dp\pgfnodeparttextbox% + } + + \saveddimen\radius{% + % + % Caculate ``height radius'' + % + \pgf@ya=.5\ht\pgfnodeparttextbox% + \advance\pgf@ya by.5\dp\pgfnodeparttextbox% + \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/inner ysep}}% + \advance\pgf@ya by\pgf@yb% + % + % Caculate ``width radius'' + % + \pgf@xa=.5\wd\pgfnodeparttextbox% + \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/inner xsep}}% + \advance\pgf@xa by\pgf@xb% + % + % Calculate length of radius vector: + % + \pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}% + \ifdim\pgf@x>\pgf@y% + \c@pgf@counta=\pgf@x% + \ifnum\c@pgf@counta=\z@% + \else% + \divide\c@pgf@counta by 255\relax% + \pgf@xa=16\pgf@xa\relax% + \divide\pgf@xa by\c@pgf@counta% + \pgf@xa=16\pgf@xa\relax% + \fi% + \else% + \c@pgf@counta=\pgf@y% + \ifnum\c@pgf@counta=\z@% + \else% + \divide\c@pgf@counta by 255\relax% + \pgf@ya=16\pgf@ya\relax% + \divide\pgf@ya by\c@pgf@counta% + \pgf@xa=16\pgf@ya\relax% + \fi% + \fi% + \pgf@x=\pgf@xa% + % + % If necessary, adjust radius so that the size requirements are + % met: + % + \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/minimum width}}% + \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/minimum height}}% + \ifdim\pgf@x<.5\pgf@xb% + \pgf@x=.5\pgf@xb% + \fi% + \ifdim\pgf@x<.5\pgf@yb% + \pgf@x=.5\pgf@yb% + \fi% + % + % Now, add larger of outer sepearations. + % + \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}% + \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}% + \ifdim\pgf@xb<\pgf@yb% + \advance\pgf@x by\pgf@yb% + \else% + \advance\pgf@x by\pgf@xb% + \fi% + \pgf@xb=2pt + \multiply\pgf@xb\circlen@n + \advance\pgf@x\pgf@xb + \advance\pgf@x-2pt\relax + } + + % + % Anchors + % + \anchor{center}{\centerpoint} + \anchor{mid}{\centerpoint\pgfmathsetlength\pgf@y{.5ex}} + \anchor{base}{\centerpoint\pgf@y=0pt} + \anchor{north}{\centerpoint\advance\pgf@y by\radius} + \anchor{south}{\centerpoint\advance\pgf@y by-\radius} + \anchor{west}{\centerpoint\advance\pgf@x by-\radius} + \anchor{east}{\centerpoint\advance\pgf@x by\radius} + \anchor{mid west}{\centerpoint\advance\pgf@x by-\radius\pgfmathsetlength\pgf@y{.5ex}} + \anchor{mid east}{\centerpoint\advance\pgf@x by\radius\pgfmathsetlength\pgf@y{.5ex}} + \anchor{base west}{\centerpoint\advance\pgf@x by-\radius\pgf@y=0pt} + \anchor{base east}{\centerpoint\advance\pgf@x by\radius\pgf@y=0pt} + \anchor{north west}{ + \centerpoint + \pgf@xa=\radius + \advance\pgf@x by-0.707107\pgf@xa + \advance\pgf@y by0.707107\pgf@xa + } + \anchor{south west}{ + \centerpoint + \pgf@xa=\radius + \advance\pgf@x by-0.707107\pgf@xa + \advance\pgf@y by-0.707107\pgf@xa + } + \anchor{north east}{ + \centerpoint + \pgf@xa=\radius + \advance\pgf@x by0.707107\pgf@xa + \advance\pgf@y by0.707107\pgf@xa + } + \anchor{south east}{ + \centerpoint + \pgf@xa=\radius + \advance\pgf@x by0.707107\pgf@xa + \advance\pgf@y by-0.707107\pgf@xa + } + \anchorborder{ + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \edef\pgf@marshal{% + \noexpand\pgfpointborderellipse + {\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}} + {\noexpand\pgfqpoint{\radius}{\radius}}% + }% + \pgf@marshal% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \centerpoint% + \advance\pgf@x by\pgf@xa% + \advance\pgf@y by\pgf@ya% + } + + % + % Background path + % + \behindbackgroundpath{ + \pgfutil@tempdima=\radius% + \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}% + \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}% + \ifdim\pgf@xb<\pgf@yb% + \advance\pgfutil@tempdima by-\pgf@yb% + \else% + \advance\pgfutil@tempdima by-\pgf@xb% + \fi% + \sseq@tempcount=\@ne + \loop + \pgfpathcircle{\centerpoint}{\pgfutil@tempdima}% + \advance\pgfutil@tempdima-2pt\relax + \advance\sseq@tempcount\@ne + \ifnum\sseq@tempcount<\circlen@n \repeat + \tikz@mode + \sseq@eval{\noexpand\pgfusepath{ + \iftikz@mode@draw draw,\fi + }} + } + \backgroundpath{% + \pgfutil@tempdima=\radius% + \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}% + \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}% + \ifdim\pgf@xb<\pgf@yb% + \advance\pgfutil@tempdima by-\pgf@yb% + \else% + \advance\pgfutil@tempdima by-\pgf@xb% + \fi% + \advance\pgfutil@tempdima2pt\relax + \pgfutil@tempdimb=-2pt\relax + \multiply\pgfutil@tempdimb\circlen@n + \advance\pgfutil@tempdima\pgfutil@tempdimb\relax + \pgfpathcircle{\centerpoint}{\pgfutil@tempdima} + } +} + + + +% For out of bounds edges: + +\pgfdeclarearrow{ + name = ..., + parameters = { \the\pgfarrowlength\the\pgflinewidth}, + setup code = { + % The different end values: + \pgfarrowssetlineend{-\pgfarrowlength} + \pgfarrowssetbackend{-0.6\pgfarrowlength} + % The hull + \pgfarrowshullpoint{-\pgfarrowlength}{0pt} + \pgfarrowshullpoint{\pgfarrowlength}{0pt} + % Saves: Only the length: + \pgfarrowssavethe\pgfarrowlength + \pgfarrowssavethe\pgflinewidth + }, + drawing code = { + \pgfpathcircle{\pgfpoint{-0.7\pgfarrowlength}{0pt}}{1.5\pgflinewidth} + \pgfpathcircle{\pgfpoint{-0.4\pgfarrowlength}{0pt}}{1.5\pgflinewidth} + \pgfpathcircle{\pgfpoint{-0.1\pgfarrowlength}{0pt}}{1.5\pgflinewidth} + \pgfpathclose + \pgfusepathqfill + }, + defaults = { length = 0.3cm } +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex new file mode 100644 index 00000000000..0d4c4758215 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex @@ -0,0 +1,88 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqforeach.code.tex +%% +%% Patches the \foreach command to obtain better error reporting +%% + + +% All of this \foreach stuff is defined by tikz in the file /pgf/utilities/pgffor.code.tex + +\def\sseq@for@nopatch{\sseq@error{foreach-patch-failed}\def\sseq@patchfor{}\endinput} + +\newtoks\sseq@foreachcall + +\def\sseq@for@vars{} +\def\sseq@for@savemacro#1{\sseq@d@addto@macro\sseq@for@vars{\sseq@for@vars@do#1}} +\def\sseq@for@vars@do#1{; \string#1 = #1} +\def\sseq@for@vars@donx#1{; \string#1= #1} +\ExplSyntaxOn +\def\sseq@for@printvars{\ifx\sseq@for@vars\pgfutil@empty\else\exp_last_unbraced:Nf\@gobble\sseq@for@vars\fi} +\ExplSyntaxOff + + +\def\sseq@patchfor{% + \let\pgffor@atbeginforeach\sseq@pgffor@atbeginforeach + \let\pgffor@@vars@opt\sseq@pgffor@@vars@opt +} +\def\sseq@pgffor@modify#1{% + \@xp\let\csname sseq@\sseq@macroname#1\endcsname #1% + \eappto\sseq@patchfor{\let\@nx#1 \@xp\@nx\csname sseq@\sseq@macroname#1\endcsname}% +} + + + +\def\sseq@pgffor@recordarg#1#2{ + \sseq@pgffor@modify#1 + \@xp\pretocmd\csname sseq@\sseq@macroname#1\endcsname{\sseq@foreachcall\@xp{\the\sseq@foreachcall#2}}{}{\sseq@for@nopatch} +} +\def\sseq@pgffor@erecordarg#1#2{ + \sseq@pgffor@modify#1 + \@xp\pretocmd\csname sseq@\sseq@macroname#1\endcsname{\sseq@eval{\sseq@foreachcall{\the\sseq@foreachcall#2}}}{}{\sseq@for@nopatch} +} + + + +\bgroup\lccode`\*=`\#\lowercase{\egroup + + +\def\sseq@pgffor@atbeginforeach{% + \begingroup % + \sseq@atbeginforeach@msgsetup + % \pgffor@macro@list calls \pgffor@normal@list, so we need to mark that the list has already been added to foreachcall. + \sseq@tempiftrue +} + +% Modify the foreach argument parser commands to put the call into \sseq@foreachcall and to tell us what the variables are +\def\sseq@pgffor@@vars@opt[#1]{\sseq@foreachcall\@xp{\the\sseq@foreachcall#1}\pgfkeys{/sseqpages/foreach/.cd,#1}\pgffor@vars} + +\sseq@pgffor@recordarg\pgffor@@vars{*1} +\pretocmd\sseq@pgffor@@vars{\sseq@for@savemacro*1}{}{\sseq@for@nopatch} + +\sseq@pgffor@recordarg\pgffor@@vars@slash@gobble{/} +\sseq@pgffor@recordarg\pgffor@macro@list{in *1} +\pretocmd\sseq@pgffor@macro@list{\sseq@tempiffalse}{}{\sseq@for@nopatch}% Don't add this again in \pgffor@normal@lis + +\sseq@pgffor@modify\pgffor@normal@list +% Add list to argument if it wasn't a macro +\pretocmd\sseq@pgffor@normal@list{\ifsseq@tempif\sseq@foreachcall\@xp{\the\sseq@foreachcall in {*1}}\fi\sseq@tempiftrue}{}{\sseq@for@nopatch} + +\sseq@pgffor@recordarg\pgffor@collectforeach@macro{\foreach} +\sseq@pgffor@recordarg\pgffor@collectforeach@normal{\foreach} + +\sseq@pgffor@modify\pgffor@iterate +\pretocmd\sseq@pgffor@iterate{\sseq@opushstacktrace{\the\sseq@foreachcall}\sseq@thiscalltoks\@xp{\the\sseq@foreachcall}}{}{\sseq@for@nopatch} + +\sseq@pgffor@modify\pgffor@doloop +\sseq@pgffor@modify\pgffor@invokebody +\patchcmd\sseq@pgffor@doloop{\pgffor@begingroup}{\pgffor@begingroup\sseq@xsetlastcall{\the\sseq@foreachcall}}{}{\sseq@for@nopatch} +\patchcmd\sseq@pgffor@invokebody{\pgffor@begingroup}{\pgffor@begingroup\sseq@xsetlastcall{\the\sseq@foreachcall}}{}{\sseq@for@nopatch} +} + +%TODO: also hook \pgffor@assign@parse, \pgffor@remember@parse, \pgffor@count@parse. + 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}} +} diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex new file mode 100644 index 00000000000..e86a1baf071 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex @@ -0,0 +1,175 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqloadstore.code.tex +%% +%% Defines commands for maintaining separate namespaces between distinct spectral sequences and saving information. +%% + + +% These are attributes that come with a given spectral sequence (by name) +% All of these values are loaded at the beginning of sseqpage (and of sseqdata if an existing sseq is being modified). +% They are then stored together at the end of sseqdata (and of sseqpage if "keep changes" option is present). +\def\sseq@storelist{} +\def\sseq@storelist@setdefaults{} +\def\sseq@addtostorelist#1#2{% + \sseq@g@addto@macro\sseq@storelist{\\#1}% + \sseq@x@addto@macro\sseq@storelist@setdefaults{\global\let\@nx#1\@xp\@nx\csname \sseq@macroname#1@default\endcsname}% + \@xp\gdef\csname\sseq@macroname#1@default\endcsname{#2}% +} +\def\sseq@addtostorelistlet#1#2{% + \sseq@g@addto@macro\sseq@storelist{\\#1}% + \sseq@x@addto@macro\sseq@storelist@setdefaults{\global\let\@nx#1\@xp\@nx\csname \sseq@macroname#1@default\endcsname}% + \global\@xp\let\csname\sseq@macroname#1@default\endcsname#2% +} + +\def\sseq@addiftostorelist#1{\sseq@addiftostorelistopt{#1}{false}} +\def\sseq@addiftostorelist@truedefault#1{\sseq@addiftostorelistopt{#1}{true}} +\def\sseq@addiftostorelistopt#1#2{% + \@xp\newif\csname ifsseq@#1\endcsname + \sseq@g@addto@macro\sseq@storelist{\sseq@storelistif{#1}}% + \sseq@x@addto@macro\sseq@storelist@setdefaults{\@xp\@nx\csname sseq@#1@default\endcsname}% + \@xp\xdef\csname sseq@#1@default\endcsname{\global\@xp\@nx\csname sseq@#1#2\endcsname}% +} +\def\sseq@addkeytostorelist#1#2{ + \sseq@g@addto@macro\sseq@storelist{\sseq@storelistkey{#1}}% + \sseq@x@addto@macro\sseq@storelist@setdefaults{ + \global\let\@xp\@nx\csname pgfk@#1/.@cmd\endcsname\@xp\@nx\csname pgfk@#1/.@cmd@default\endcsname + \global\let\@xp\@nx\csname pgfk@#1/.@body\endcsname\@xp\@nx\csname pgfk@#1/.@body@default\endcsname + }% + \pgfkeysdef{#1}{#2}% + \global\@xp\let\csname pgfk@#1/.@cmd@default\@xp\endcsname\csname pgfk@#1/.@cmd\endcsname + \global\@xp\let\csname pgfk@#1/.@body@default\@xp\endcsname\csname pgfk@#1/.@body\endcsname +} + +% transfer data about the current spectral sequence between \<command> and \<command><sseqname> +\def\sseq@storelist@store#1{\global\@xp\let\csname\sseq@macroname#1@@@\sseq@thename\endcsname#1} +\def\sseq@storelist@get#1{\global\@xp\let\@xp#1\csname\sseq@macroname#1@@@\sseq@thename\endcsname} + +\def\sseq@storelistif@store#1{% + \@xp\edef\csname sseq@storeif@#1\endcsname{\csname ifsseq@#1\endcsname \@xp\@nx\csname sseq@#1true\endcsname\else\@xp\@nx\csname sseq@#1false\endcsname\fi}% + \@xp\sseq@storelist@store\csname sseq@storeif@#1\endcsname +} +\def\sseq@storelistif@get#1{ + \@xp\sseq@storelist@get\csname sseq@storeif@#1\endcsname + \csname sseq@storeif@#1\endcsname +} + +\def\sseq@storelistkey@store#1{ + \global\@xp\let\csname pgfk@#1/.@cmd@@@\sseq@thename\@xp\endcsname\csname pgfk@#1/.@cmd\endcsname + \global\@xp\let\csname pgfk@#1/.@body@@@\sseq@thename\@xp\endcsname\csname pgfk@#1/.@body\endcsname +} +\def\sseq@storelistkey@get#1{ + \global\@xp\let\csname pgfk@#1/.@cmd\@xp\endcsname\csname pgfk@#1/.@cmd@@@\sseq@thename\endcsname + \global\@xp\let\csname pgfk@#1/.@body\@xp\endcsname\csname pgfk@#1/.@body@@@\sseq@thename\endcsname +} + + +\def\sseq@storecmds{\let\\\sseq@storelist@store\let\sseq@storelistif\sseq@storelistif@store\let\sseq@storelistkey\sseq@storelistkey@store\sseq@storelist} +\def\sseq@getcmds{\let\\\sseq@storelist@get\let\sseq@storelistif\sseq@storelistif@get\let\sseq@storelistkey\sseq@storelistkey@get\sseq@storelist} + +%%%% New "poor man's OOP" Load/Store +% Directly stores things into commands that are annotated with the name of the spectral sequence. +% I use this primarily for commands that won't necessarily exist for every spectral sequence +% for instance because it has the description of a particular class or differential as part of its name +\def\sseq@obj@fullname#1{sseq.\sseq@thename.#1} +\def\sseq@obj#1{\csname sseq.\sseq@thename.#1\endcsname} +\def\sseq@obj@gdef#1{\@xptwo\gdef\sseq@obj{#1}} +\def\sseq@obj@xdef#1{\@xptwo\xdef\sseq@obj{#1}} +\def\sseq@obj@protectedxdef#1{\@xptwo\sseq@protected@xdef\sseq@obj{#1}} +\def\sseq@obj@xodef#1{\@xp\gdef\csname \sseq@obj@fullname{#1}\@xp\endcsname\@xp} +\def\sseq@obj@let#1{\@xptwo\let\sseq@obj{#1}} +\def\sseq@obj@gletcsname#1#2{\global\@xp\let\csname\sseq@obj@fullname{#1}\@xp\endcsname\csname#2\endcsname} +\def\sseq@obj@gletobj#1#2{\global\@xp\let\csname\sseq@obj@fullname{#1}\@xp\endcsname\csname\sseq@obj@fullname{#2}\endcsname} +\def\sseq@obj@undef#1{\@xptwo\let\sseq@obj{#1}\relax} +\def\sseq@obj@show#1{\@xptwo\show\sseq@obj{#1}} +\def\sseq@obj@ifundef#1{\@ifundefined{\sseq@obj@fullname{#1}}} +\def\sseq@obj@ifdef#1#2#3{\@ifundefined{\sseq@obj@fullname{#1}}{#3}{#2}} +\def\sseq@obj@inc#1{\bgroup\sseq@tempcount\sseq@obj{#1}\relax\advance\sseq@tempcount\@ne\sseq@obj@xdef{#1}{\the\sseq@tempcount}\egroup} +\def\sseq@obj@gaddto{\@xptwo\sseq@g@addto@macro\sseq@obj} +\def\sseq@obj@xaddto{\@xptwo\sseq@x@addto@macro\sseq@obj} +\def\sseq@obj@xaddto{\@xptwo\sseq@x@addto@macro\sseq@obj} +\def\sseq@obj@xoaddto#1{\@xp\sseq@g@addto@macro\csname \sseq@obj@fullname{#1}\@xp\endcsname\@xp} +\def\sseq@obj@map#1#2{\def\\##1{#2}\sseq@obj{#1}} + + +\def\sseq@obj@ifchanged#1#2#3{\sseq@obj@ifundef{#1.changed}{#3}{#2}} +\def\sseq@obj@changedtrue#1{\sseq@obj@gdef{#1.changed}{}} +\def\sseq@obj@changedfalse#1{\sseq@obj@undef{#1.changed}} + +\def\sseq@cleanup@obj#1{ + \ifsseq@keepchanges\else + \sseq@obj@ifchanged{#1}{}{ + \sseq@obj@changedtrue{#1} + \sseq@x@addto@macro\sseq@pagecleanup{ + \@xptwo\ifx\sseq@obj{#1}\relax + \global\@nx\sseq@obj@let{#1}\relax + \else + \@nx\sseq@obj@gdef{#1}{\unexpanded\@xpthree{\sseq@obj{#1}}} + \fi + \@nx\sseq@obj@changedfalse{#1} + } + } + \fi +} + + +%%%% Saved paths, temporary saved paths, background saved paths +% \sseq@savedpaths@whatever is redefined to be \sseq@savedpaths@whatever@standard or \sseq@savedpaths@whatever@temporary depending on context +% This simplifies the code a lot because I don't have to check again where I should put things. +\sseq@addtostorelist\sseq@savedpaths{} +\def\sseq@tempsavedpaths{} +\def\sseq@savedpaths@addclass@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@class@draw@ifpage{#1}}} +\def\sseq@savedpaths@adddifferential@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@differential@draw@ifpage{#1}}} +\def\sseq@savedpaths@addstructline@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@structline@draw@ifpage{#1}}} +\def\sseq@savedpaths@add@standard{\sseq@g@addto@macro\sseq@savedpaths} +\def\sseq@savedpaths@xadd@standard{\sseq@x@addto@macro\sseq@savedpaths} +\def\sseq@savedpaths@show@standard{\show\sseq@savedpaths} +\def\sseq@scope@savedpaths@add@standard#1{\sseq@savedpaths@add@standard{#1}\sseq@savedpaths@add@background{#1}} + +\def\sseq@savedpaths@addclass@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@class@draw@ifpage{#1}}} +\def\sseq@savedpaths@adddifferential@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@differential@draw@ifpage{#1}}} +\def\sseq@savedpaths@addstructline@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@structline@draw@ifpage{#1}}} +\def\sseq@savedpaths@add@temporary{\sseq@g@addto@macro\sseq@tempsavedpaths} +\def\sseq@savedpaths@xadd@temporary{\sseq@x@addto@macro\sseq@tempsavedpaths} +\def\sseq@savedpaths@show@temporary{\show\sseq@tempsavedpaths} +\def\sseq@scope@savedpaths@add@temporary#1{\sseq@savedpaths@add@temporary{#1}\sseq@savedpaths@add@background{#1}} + + +\def\sseq@savedpaths@addclass@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@addclass}} +\def\sseq@savedpaths@adddifferential@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@adddifferential}} +\def\sseq@savedpaths@addstructline@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@addstructline}} +\def\sseq@savedpaths@add@background{\sseq@g@addto@macro\sseq@savedbackgroundpaths} +\def\sseq@savedpaths@xadd@background{\sseq@x@addto@macro\sseq@savedbackgroundpaths} +\def\sseq@savedpaths@show@background{\show\sseq@savedbackgroundpaths} + +\def\sseq@savedpaths@addclass@ignore#1{} +\def\sseq@savedpaths@adddifferential@ignore#1{} +\def\sseq@savedpaths@addstructline@ignore#1{} +\def\sseq@savedpaths@add@ignore#1{} +\def\sseq@savedpaths@xadd@ignore#1{} +\def\sseq@savedpaths@show@ignore#1{} +\def\sseq@scope@savedpaths@add@ignore#1{} + +\def\sseq@setsavedpaths#1{% + \@xp\let\@xp\sseq@savedpaths@addclass \csname sseq@savedpaths@addclass@#1\endcsname + \@xp\let\@xp\sseq@savedpaths@adddifferential\csname sseq@savedpaths@adddifferential@#1\endcsname + \@xp\let\@xp\sseq@savedpaths@addstructline \csname sseq@savedpaths@addstructline@#1\endcsname + \@xp\let\@xp\sseq@savedpaths@add \csname sseq@savedpaths@add@#1\endcsname + \@xp\let\@xp\sseq@savedpaths@xadd \csname sseq@savedpaths@xadd@#1\endcsname + \pgfutil@ifundefined{sseq@scope@savedpaths@add@#1}{}{% + \@xp\let\@xp\sseq@savedpaths@show \csname sseq@savedpaths@show@#1\endcsname + \@xp\let\@xp\sseq@scope@savedpaths@add \csname sseq@scope@savedpaths@add@#1\endcsname + }% +} + +\def\sseq@usesavedpaths{% + \sseq@savedpaths + \sseq@clearchangestyles + \sseq@tempsavedpaths + \gdef\sseq@tempsavedpaths{}% +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex new file mode 100644 index 00000000000..1a89dc4b66a --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex @@ -0,0 +1,389 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqmacromakers.code.tex +%% Exposes: \DeclareSseqCommand, \NewSseqCommand, \DeclareSseqGroup, \NewSseqGroup +%% +%% Set up commands to define other commands, both the internal macros, and the external ones. +%% Also the internal macros \sseq@DeclareDocumentCommandAs and \sseq@DeclareDocumentCommand +%% For the user commands, sets up call stack, thiscall, etc +%% + + + +\ExplSyntaxOn + +%%% \sseq@DeclareDocumentCommand +% +% \sseq@DeclareDocumentCommand\somecommand is shorthand for \sseq@DeclareDocumentCommandAs\sseq@somecommand\somecommand +% +% so the result is that it defines \sseq@somecommand intended to be \let to \somecommand later. +%%% Install user commands +% copy commands into user namespace by removing sseq@ prefixes +% given a list of commands, \let\thiscommand\sseq@thiscommand on each one + +\def\sseq@recordmacros{\@xp\sseq@recordmacros@\sseq@macrolist\sseq@nil} +\def\sseq@recordmacros@#1{% + \ifx#1\sseq@nil\else % if so, that was the last command in the list + \@xp\def\csname sseq@builtin\sseq@macroname#1\endcsname{} + \@xp\sseq@recordmacros@ + \fi % +} + + + +\def\sseq@installmacros{\@xp\sseq@installmacros@\sseq@macrolist\sseq@nil} +\def\sseq@installmacros@#1{% + \ifx#1\sseq@nil\else % if so, that was the last command in the list + \@xp\let\@xp#1\csname sseq@\sseq@macroname#1\endcsname + \@xp\sseq@installmacros@ + \fi % +} + + +% Capital U argument type is "Until" but puts back the token when it's done. +\cs_new_protected:Npn \sseq__xparse_add_type_U:w #1 + { + \__xparse_flush_m_args: + \__xparse_add_grabber_mandatory:N U + \tl_put_right:Nn \l__xparse_signature_tl { {#1} } + \__xparse_prepare_signature:N + } + +\cs_new_protected:Npn \sseq__xparse_grab_U:w #1#2 \l__xparse_args_tl + { \sseq__xparse_grab_U_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn } + +\cs_new_protected:Npn \sseq__xparse_grab_U_aux:nnN #1#2#3 + { + \exp_after:wN #3 \l__xparse_fn_tl ##1 #1 + { + \__xparse_add_arg:n {##1} + #2\l__xparse_args_tl #1 + } + \l__xparse_fn_tl + } + +% I would like to patch the \__xparse_grab_U:w's in my commands into \sseq__xparse_grab_U:w's but I can't because of -NoValue-. +\def\sseq@install@xparse@Uarggrabber{ \cs_set_eq:NN \__xparse_grab_U:w \sseq__xparse_grab_U:w } + +%%% \sseq@DeclareDocumentCommand +% +% \sseq@DeclareDocumentCommand\somecommand is shorthand for \sseq@DeclareDocumentCommandAs\sseq@somecommand\somecommand +% +% so the result is that it defines \sseq@somecommand intended to be \let to \somecommand later. + +\cs_new_protected:Npn\sseq@DeclareDocumentCommand#1{% + \exp_args:Nc \sseq@DeclareDocumentCommandAs { sseq @ \cs_to_str:N #1 }#1 +} + +%%% \sseq@DeclareDocumentCommandAS +% +% #1 - the command to define +% #2 - the command to use in argument parsing errors +% #3 - parameters (\NewDocumentCommand style) +% #4 - code +% +% See my stack exchange question: https://tex.stackexchange.com/questions/350596/control-error-messages-made-by-commands-defined-with-newdocumentcommand + + + +\cs_new_protected:Npn\sseq@DeclareDocumentCommandAs#1#2#3#4{ + \group_begin: + \cs_set_eq:NN \__xparse_add_type_U:w \sseq__xparse_add_type_U:w + \cs_set_eq:cN { tempsave_ \cs_to_str:N #2 } #2 % Store the original value of #2 + \cs_set_eq:cc { tempsave_ \cs_to_str:N #2 \c_space_tl code } { \cs_to_str:N #2 \c_space_tl code } % Store the original value of #2 + \sseq@installmsghooks + \def\sseq@error@setup{} + \def\sseq@error@cleanup{\sseq@errortrue} + \let\sseq@error@annotation\empty + \DeclareDocumentCommand #2 { #3 } { #4 } + \ifsseq@error + \group_end: + \sseq@errortrue % This only happens if it came from user code, so don't set error to be false so it can break out too. + \@xp\sseq@break + \fi + \cs_if_exist:cTF{ \cs_to_str:N #2 \c_space_tl code }{ + \cs_gset:Npx #1{ + \begingroup + \exp_not:N \cs_set_eq:NN + \exp_not:c { \cs_to_str:N #2 \c_space_tl code } + \exp_not:c { \cs_to_str:N #1 \c_space_tl code } + \exp_not:c { \cs_to_str:N #1 \c_space_tl inner } + } + \pretocmd:cnnn { \cs_to_str:N #2 \c_space_tl code } { \endgroup } { } { \sseq@error@x { macro-patch-failed } { \string#1 } } + \cs_gset_eq:cN { \cs_to_str:N #1 \c_space_tl inner } #2 + \cs_gset_eq:cc { \cs_to_str:N #1 \c_space_tl code } { \cs_to_str:N #2 \c_space_tl code } + \cs_gset_eq:Nc #2 { tempsave _ \cs_to_str:N #2 } + \cs_gset_eq:cc { \cs_to_str:N #2 \c_space_tl code } { tempsave_ \cs_to_str:N #2 \c_space_tl code } + }{ + \cs_gset_eq:NN #1 #2 + } + \group_end: % In this case, I want to pass \sseq@errortrue out of the block, so I close the group before I break. + \sseq@breakpoint % So this breakpoint definitely should be after the \endgroup. +} + +\cs_set_eq:NN \patchcmd:Nnnnn \patchcmd +\cs_set_eq:NN \pretocmd:Nnnn \pretocmd +\cs_generate_variant:Nn \patchcmd:Nnnnn {cnfnn} +\cs_generate_variant:Nn \pretocmd:Nnnn {cfnn} +\cs_generate_variant:Nn \pretocmd:Nnnn {cnnn} + +\cs_new_protected:Npn\NewSseqCommand#1{% + \cs_if_free:cTF { sseq @ usermacro @ \cs_to_str:N #1 } { \DeclareSseqCommand#1 } { \sseq@error@x{usermacro-not-free}{\string#1} \use_none:nn } +} + +\cs_new_protected:Npn\DeclareSseqCommand#1#2#3{% + \cs_if_exist:cTF { sseq @ builtin @ \cs_to_str:N #1 } {\sseq@error@x{wont-override-system-macro}{\string#1}\sseq@break} {} + \cs_if_free:cT { sseq @ usermacro @ \cs_to_str:N #1 } { + \sseq@x@addto@macro { \sseq@installmacros } { \let \exp_not:N #1 \exp_not:c { sseq @ usermacro @ \cs_to_str:N #1 } } + } + % Make sure \cs_if_exist doesn't pass because there was a previously defined user macro with same name + \cs_undefine:c { sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code } + \exp_args:Nc \sseq@DeclareDocumentCommandAs { sseq @ usermacro @ \cs_to_str:N #1 } #1 { #2 } { + #3 + \endgroup + }% + \ifsseq@error + \global\sseq@errorfalse + \@xp\sseq@break + \fi + \sseq@parseargspec{#1}{#2}% + % You might think we could skip this patching, and it's probably possible. + % However, this is responsible for turning the #'s of catcode other into #'s of catcode arg. I don't have as good of a way to do that. + % Also, this allows me to use \sseq@parseargspec after defining the command, so I don't have to run any error checking inside of it + % because if the argspec is invalid, \DeclareDocumentCommand will let me know. + \cs_if_exist:cTF{ sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code }{ + \patchcmd:cnfnn{ sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code }{\endgroup}{ + \@xp\endgroup + \@xp\begingroup + \the\sseq@temptoks + \sseq@atbeginusermacro@msgsetup + }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}} + }{ + \pretocmd:cfnn{ sseq @ usermacro @ \cs_to_str:N #1 }{ + \@xp\begingroup + \the\sseq@temptoks + \sseq@atbeginusermacro@msgsetup + }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}} + } + \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #1 } { sseq @ usermacro @ \cs_to_str:N #1 } + \ifsseq@inprogress + \cs_set_eq:Nc #1 { sseq @ usermacro @ \cs_to_str:N #1 } + \fi + \sseq@breakpoint +} + +%%% Commands to help the user define "groups" of commands to be reused +\def\sseqnewgroup@splitcoord#1,#2\sseq@nil{% + \sseq@eval{ + \@nx\begin{scope}[xshift=#1,yshift=#2,\unexpanded\@xp{\sseq@options}] + } +} + +% #1 -- command +% #2 -- argspec +% #3 -- body of function (long) +\NewDocumentCommand\NewSseqGroup{mm+m}{\DeclareSseqGroup@\NewSseqCommand{#1}{#2}{#3}} +\NewDocumentCommand\DeclareSseqGroup{mm+m}{\DeclareSseqGroup@\DeclareSseqCommand{#1}{#2}{#3}} + +% #1 -- \NewSseqCommand or \DeclareSseqCommand +% #2 -- command +% #3 -- argspec +% #4 -- body of function (long) +\long\def\DeclareSseqGroup@#1#2#3#4{% + \group_begin: + \let\sseq@parseargspec\@gobbletwo % Get rid of argparse so we can change what gets added for setting up thiscall + \sseq@temptoks\@xp{\sseq@SseqGroup@argspec} % This gets added to the outer command by DeclareSseqCommand +% + \sseq@installmsghooks + \def\sseq@error@setup{} + \def\sseq@error@cleanup{\sseq@errortrue} + \let\sseq@error@annotation\empty +% +% undefine so we can tell whether we need to patch \command<space>code or \command + \cs_undefine:c { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } + \exp_args:Nc \DeclareDocumentCommand { sseq @ usermacro @ \cs_to_str:N #2 @ helper } { #3 } { + #4 + \end{scope} + }% + \ifsseq@error + \@xp\sseq@break + \fi + #1#2{od()}{% + \IfNoValueTF{##1}{\def\sseq@options{}}{\def\sseq@options{##1}}% + \IfNoValueTF{##2}{% + \sseq@eval{ + \@nx\begin{scope}[\unexpanded\@xp{\sseq@options}] + }% + }{% + \sseqnewgroup@splitcoord##2\sseq@nil + }% + \csname sseq @ usermacro @ \sseq@macroname #2 @ helper \@xp\endcsname \@gobble % This gobble eats the endgroup added by sseqDeclareDocumentCommand + }% + + \sseq@parseargspec@newgroup{#2}{#3}% + % You might think we could skip this patching, and it's probably possible. + % However, this is responsible for turning the #'s of catcode other into #'s of catcode arg. I don't have as good of a way to do that. + \cs_if_exist:cTF{ sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }{ + \pretocmd:cfnn { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }{ + \the\sseq@temptoks + \sseq@atbeginusermacro@msgsetup + }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}} + \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } % globalize definition + }{ + \pretocmd:cfnn { sseq @ usermacro @ \cs_to_str:N #2 @ helper }{ + \the\sseq@temptoks + \sseq@atbeginusermacro@msgsetup + }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}} + } + \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #2 @ helper } { sseq @ usermacro @ \cs_to_str:N #2 @ helper } % globalize definition + \let\sseq@parseargspec\sseq@parseargspec@normal + \sseq@breakpoint + \group_end: +} +\let\sseqnewgroup\NewSseqGroup + + +\bgroup\catcode`\#=12\relax + \gdef\sseq@SseqGroup@argspec{\sseq@eval{\sseq@temptoks{\IfNoValueF{#1}{\unexpanded{[#1]}}\IfNoValueF{#2}{\unexpanded{(#2)}}}}\@gobble} + \gdef\sseq@thearg{#\the\sseq@tempcount} +\egroup + + +% When there are arguments with default values (O, D, R, G), we need to put them into temporary macros to compare them and see if they are the default value +% that's what temptoksii is for. +\def\sseq@parseargspec#1#2{% + \sseq@tempcount=\z@ + \sseq@temptoks{\@nx#1}% Holds the stuff that goes in \esetthiscall (so most stuff) + \sseq@temptoksii{} + \sseq@parseargspec@#2\sseq@nil + \sseq@eval{\sseq@temptoks{\the\sseq@temptoksii\@nx\sseq@usermacro@esetthiscall{\the\sseq@temptoks}}} +} + +% For NewGroup: +\let\sseq@parseargspec@normal\sseq@parseargspec +\def\sseq@parseargspec@newgroup#1#2{% + \sseq@tempcount=\z@ + \sseq@temptoks{} + \sseq@temptoksii{}% + \sseq@parseargspec@#2\sseq@nil + \sseq@eval{\sseq@temptoks{\the\sseq@temptoksii\@nx\sseq@usermacro@esetthiscall{\@nx\@nx\@nx#1\@nx\the\sseq@temptoks\the\sseq@temptoks}}} +} + + +\def\sseq@parseargspec@#1{ + \advance\sseq@tempcount\@ne + \ifx#1\sseq@nil\else + \@xp\ifx\csname sseq@parseargspec@#1\@xp\endcsname\relax + \sseq@error@n{usermacro-unsupported-argument-type}{#1} + \else + \csname sseq@parseargspec@#1\@xptwo\endcsname + \fi + \fi +} + + +% Have to use \@alph to convert the number to a letter. Using a number here doesn't work because the control sequence gets retokenized +% so we can only use letters in control sequences (another option would be to not expand the \csnames till later, but that would be harder). +\def\sseq@parseargspec@ifargisnotdefault{% + \@nx\ifx + \@xp\@nx\csname sseq@parseargspec@temparg\@alph\sseq@tempcount\endcsname + \@xp\@nx\csname sseq@parseargspec@tempdefault\@alph\sseq@tempcount\endcsname + \unexpanded{% + \@xp\@gobble + \else + \@xp\@firstofone + \fi + }% +} + +\def\sseq@parseargspec@setargdefault#1{% + \sseq@e@addto@toks\sseq@temptoksii{% + \def\@xp\@nx\csname sseq@parseargspec@temparg\@alph\sseq@tempcount\endcsname{\sseq@thearg}% + \def\@xp\@nx\csname sseq@parseargspec@tempdefault\@alph\sseq@tempcount\endcsname{\unexpanded{#1}}% + } +} + +% Mandatory +\def\sseq@parseargspec@m{% + \sseq@e@addto@temptoks{{\@nx\unexpanded{\sseq@thearg}}} + \sseq@parseargspec@ +} +\def\sseq@parseargspec@l{% + \sseq@e@addto@temptoks{\@nx\unexpanded{\sseq@thearg}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@u#1{% + \sseq@e@addto@temptoks{\@nx\unexpanded{\sseq@thearg}\unexpanded{\unexpanded{#1}}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@U#1{% + \sseq@e@addto@temptoks{\@nx\unexpanded{\sseq@thearg}} + \sseq@parseargspec@ +} + +% Optional no default +\def\sseq@parseargspec@o{% + \sseq@e@addto@temptoks{\@nx\IfNoValueF{\sseq@thearg}{[\@nx\unexpanded{\sseq@thearg}]}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@d#1#2{% + \sseq@e@addto@temptoks{\@nx\IfNoValueF{\sseq@thearg}{\@nx\unexpanded{#1\sseq@thearg#2}}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@r#1#2{ % technically required, but behaves like optional + \sseq@e@addto@temptoks{#1\@nx\unexpanded{\sseq@thearg}#2} + \sseq@parseargspec@ +} + + +\def\sseq@parseargspec@g{% + \sseq@e@addto@temptoks{\@nx\IfNoValueF{\sseq@thearg}{\@nx\unexpanded{{\sseq@thearg}}}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@s{% + \sseq@e@addto@temptoks{\@nx\IfBooleanT{\sseq@thearg}{*}} + \sseq@parseargspec@ +} + +\def\sseq@parseargspec@t#1{% + \sseq@e@addto@temptoks{\@nx\IfBooleanT{\sseq@thearg}{#1}} + \sseq@parseargspec@ +} + + + +\def\sseq@parseargspec@O#1{ + \sseq@parseargspec@setargdefault{#1}% + \sseq@e@addto@temptoks{\sseq@parseargspec@ifargisnotdefault{\@nx\unexpanded{[\sseq@thearg]}}}% + \sseq@parseargspec@ +} +\def\sseq@parseargspec@D#1#2#3{% + \sseq@parseargspec@setargdefault{#3}% + \sseq@e@addto@temptoks{\sseq@parseargspec@ifargisnotdefault{\@nx\unexpanded{#1\sseq@thearg#2}}}% + \sseq@parseargspec@ +} +\def\sseq@parseargspec@R#1#2#3{% + \sseq@parseargspec@setargdefault{#3}% + \sseq@e@addto@temptoks{\sseq@parseargspec@ifargisnotdefault{\@nx\unexpanded{#1\sseq@thearg#2}}}% + \sseq@parseargspec@ +} +\def\sseq@parseargspec@G#1{% + \sseq@parseargspec@setargdefault{#1}% + \sseq@e@addto@temptoks{\sseq@parseargspec@ifargisnotdefault{\@nx\unexpanded{{\sseq@thearg}}}}% + \sseq@parseargspec@ +} + + +\ExplSyntaxOff + +% diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex new file mode 100644 index 00000000000..edc87c5d2b0 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex @@ -0,0 +1,1123 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqmain.code.tex +%% +%% Defines the main environments and commands +%% + + +%%%%%%% +%%% +%%% Environment definitions +%%% +%%%%%%% + +\sseq@addtostorelist\sseq@savedbackgroundpaths{} +\sseq@addtostorelist\sseq@restorestyles{} + +\def\sseqdata{\@ifnextchar[{\sseqdata@}{\sseqdata@[]}}%} + +\def\sseq@page{\protect\sseq@thepage} + +\def\sseqdata@[#1]{% + \edef\sseq@restorefont{\font@name} + \selectfont\nullfont % Avoid space hazards! + + \def\par{} +% + \ifx\pgfpictureid\@undefined\else %Uh-oh, we're inside tikz. + \sseq@error@n{env-inside-tikz}{sseqdata}\@xp\sseq@breakdataenv + \fi + \ifsseq@inprogress % Uh-oh, we're already in a sseq environment. This is not good. + \sseq@error@n{env-inside-sseq}{sseqdata}\@xp\sseq@breakdataenv + \fi + \sseq@inprogresstrue + \def\sseq@sseqsetdirectory{/sseqpages} + \sseq@keepchangestrue + \sseq@storelist@setdefaults + \let\sseq@xtickfn\@firstofone\let\sseq@ytickfn\@firstofone % These are default functions, which addtostorelist can't handle. +% + \ifx\sseq@xmin@default\sseq@infinity + \let\sseq@xminmax\sseq@xminmax@active + \fi + \ifx\sseq@ymin@default\sseq@infinity + \let\sseq@yminmax\sseq@yminmax@active + \fi + \ifsseq@mathnodes + \let\sseq@maybemathswitch=$\@gobble$ + \fi +% + % copy commands into the user namespace. + \sseq@installmacros + \sseq@installmsghooks + \sseq@install@xparse@Uarggrabber + \def\xmin{\protect\sseq@xmin}\def\xmax{\protect\sseq@xmax} + \def\ymin{\protect\sseq@ymin}\def\ymax{\protect\sseq@ymax} +% + \sseq@modtikzcommands % Defer evaluation of tikz primitives + \sseq@patchfor % patch \foreach to work with deferred macros + \pgfkeys{/handlers/first char syntax/the character "/.initial=\sseq@handlequote} % install quotes parsing +% +% + \pgfqkeys{/sseqpages/global/name only}{#1} + \@ifundefined{sseq@thename}{\sseq@error{env-data-no-name}\sseq@breakdataenv}{} + \sseq@obj@ifundef{exists}{ + \sseq@obj@gdef{exists}{} + \pgfqkeys{/sseqpages/global}{{\sseq@thename} options/.code={}} + }{ + \ifsseq@updateexisting\else + \sseq@error@x{env-data-already-exist}{\sseq@thename}% this could be a warning + \fi + \sseq@restorestyles + \sseq@getcmds + + } + \sseq@setsavedpaths{standard} +% + % the default option handler for /sseqpages/global adds to \sseq@currentoptionpath options + \let\sseq@currentoptionpath\sseq@thename + \pgfqkeys{/sseqpages/global}{#1} + \ifx\sseq@targetx\pgfutil@empty\else + \sseq@hasdegreetrue + \fi + \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 + } + \sseq@savedpaths@xadd{\sseq@stylelist} + \sseq@savedpaths@add{\begingroup} % prevent some of the two-pass user macros horrors +} + +% Just store all the settings +\def\endsseqdata{ + \sseq@savedpaths@add{\endgroup} % prevent some of the two-pass user macros horrors + \xdef\sseq@restorestyles{\sseq@stylelist} + \sseq@storecmds + \ignorespacesafterend +} + +\def\sseqpage{\@ifnextchar[{\sseqpage@}{\sseqpage@[]}} %] + +\def\sseqpage@[#1]{% + \edef\sseq@restorefont{\font@name} + \selectfont\nullfont % Avoid space hazards! + \def\par{} +% + \ifx\pgfpictureid\@undefined\else %Uh-oh, we're inside tikz. + \sseq@error@n{env-inside-tikz}{sseqpage}\@xp\sseq@breakpageenv + \fi + \ifsseq@inprogress % Uh-oh, we're already in a sseq environment. This is not good. + \sseq@error@n{env-inside-sseq}{sseqpage}\@xp\sseq@breakpageenv + \fi + \sseq@inprogresstrue + \sseq@ispageenvtrue + \def\sseq@sseqsetdirectory{/sseqpages} +% + \let\sseq@xminmax\sseq@xminmax@active + \let\sseq@yminmax\sseq@yminmax@active + \ifsseq@mathnodes + \let\sseq@maybemathswitch=$\@gobble$ + \fi +% + % Copy commands into user namespace + \sseq@installmacros + \sseq@installmsghooks + \sseq@install@xparse@Uarggrabber + \def\xmin{\protect\sseq@xmin}\def\xmax{\protect\sseq@xmax} + \def\ymin{\protect\sseq@ymin}\def\ymax{\protect\sseq@ymax} + \sseq@modtikzcommands % Redefine tikz primitives to store themselves in the appropriate place + \sseq@patchfor % Change foreach to record it's variable values in the appropriate places + \pgfkeys{/handlers/first char syntax/the character "/.initial=\sseq@handlequote}% install quotes parsing +% + \gdef\sseq@pagecleanup{}% For undoing local option settings +% + \def\sseq@thepage{0}% page defaults to 0 + \sseq@thepagecount=\z@ + \pgfqkeys{/sseqpages/global/name only}{#1}% Get the name + \sseq@tempiftrue + \ifsseq@hasname + \sseq@obj@ifundef{exists}{ + \sseq@error@x{env-page-not-exist}{\sseq@thename} % This could be a warning + \sseq@obj@gdef{exists}{} + \let\sseq@currentoptionpath\sseq@thename + \pgfqkeys{/sseqpages/global}{{\sseq@thename} options/.code={}} + \sseq@keepchangestrue + \sseq@keepglobaloptionstrue + \sseq@setsavedpaths{standard} + }{ + \sseq@restorestyles + \sseq@getcmds + \ifsseq@keepchanges + \sseq@setsavedpaths{standard} + \else + \sseq@setsavedpaths{temporary} + \fi + \sseq@tempiffalse + \def\sseq@currentoptionpath{this page} + \pgfqkeys{/sseqpages/global}{{this page} options/.code={},#1} + } + \else + \edef\sseq@thename{temp@sseq@number@\the\sseq@anonsseqcount} + \global\advance\sseq@anonsseqcount1 + \sseq@setsavedpaths{temporary} + \fi + \ifsseq@tempif % Either the spectral sequence has no name, or it has a name but no such existed. + \sseq@storelist@setdefaults + \sseq@savedpaths@xadd{\sseq@stylelist} + \let\sseq@currentoptionpath\sseq@thename + \pgfqkeys{/sseqpages/global}{{\sseq@thename} options/.code={},{this page} options/.code={},#1} + \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 + \sseq@savedpaths@xadd{\sseq@stylelist} + \sseq@savedpaths@add{\begingroup} % prevent some of the two-pass user macros horrors + \ifx\sseq@targetx\pgfutil@empty\else + \sseq@hasdegreetrue + \fi +} + +% Here we do all of the work to actually print the page +\def\endsseqpage{ + \sseq@savedpaths@add{\endgroup} % prevent some of the two-pass user macros horrors + \ifx\sseq@xmin\sseq@infinity\sseq@error{no-range}\def\sseq@xmin{0}\def\sseq@xmax{0}\@xp\sseq@break\fi % could be warning + \ifx\sseq@ymin\sseq@infinity\sseq@error{no-range}\def\sseq@ymin{0}\def\sseq@ymax{0}\@xp\sseq@break\fi +% + \tikzset{ + z=0pt, + every path/.style={}, + every node/.style={} + } + \let\errmessage\sseq@errmessage@std + \begin{tikzpicture}[/sseqpages/global/{default} options,\ifsseq@hasname/sseqpages/global/{\sseq@thename} options\fi,/sseqpages/global/{this page} options]% + \sseq@sseqstyle@globalpart + \pgftransformreset + \sseq@globaldetonetransform + \sseq@globalscaletransform +% + \let\sseq@transform\sseq@error@illegaltransform % Disallow most coordinate transforms + \let\sseq@shifttransform\sseq@checkshifttransform % Allow shifts as long as they are by integers and have no units. +% + \sseq@setupclip + \pgfonlayer{background}% + % Axes labels only occur once per page, so the cost of typesetting them with tikz doesn't matter ... THANK GOD + \ifx\sseq@title\pgfutil@empty\else + \ifsseq@drawtitle + \sseq@eval{\unexpanded{\path (0.5*\xmin+0.5*\xmax,\ymax) node[ + /sseqpages/global/every title, + above=\sseq@clip@padding@top+\sseq@yaxis@end@extend+10pt + ]} {\unexpanded\expandafter{\sseq@title}};} + \fi + \fi + % Don't touch the shifts -- they are very persnickety. + \ifx\sseq@xaxislabel\pgfutil@empty\else\ifsseq@drawxaxislabel + \sseq@eval{\noexpand\node[/sseqpages/global/every x axis label, yshift=-\sseq@xaxisgap-\sseq@yaxis@start@extend-10pt] {\unexpanded\expandafter{\sseq@xaxislabel}};} + \fi\fi + \ifx\sseq@yaxislabel\pgfutil@empty\else\ifsseq@drawyaxislabel + \sseq@eval{\noexpand\node[/sseqpages/global/every y axis label,rotate=90,yshift=\sseq@yaxisgap+\sseq@xaxis@start@extend+10pt] {\unexpanded\expandafter{\sseq@yaxislabel}};} + \fi\fi + \sseq@handlexaxis % Draw the axis with pgf primitives. These are defined in sseqdrawing.code.tex + \sseq@handleyaxis + \sseq@grid + \endpgfonlayer +% + \ifsseq@mathnodes + \tikzset{execute at begin node=$,execute at end node=$}% + \fi + %\let\sseq@error@setup\sseq@error@setup@withinfo + \begingroup + \sseq@savedbackgroundpaths + \endgroup +% + \sseq@useclip +% + \ifsseq@drawdifferentials\else + \let\sseq@differential@draw@ifpage\@gobble + \fi + \ifsseq@drawstructlines\else + \let\sseq@structline@draw@ifpage\@gobble + \fi +% + \sseq@usesavedpaths +% + \ifsseq@keepchanges + \xdef\sseq@restorestyles{\sseq@stylelist} + \fi + \end{tikzpicture}% + \ifsseq@keepchanges + \sseq@storecmds % store changes + \else + \sseq@pagecleanup % undo any changes specific to this page + \fi + \sseq@breakpoint + \ignorespacesafterend +} + +% Shorthand for sseqpage with empty body +\def\printpage[#1]{% + \begin{sseqpage}[#1] + \end{sseqpage}% +} + +%%% Scope +\newcount\sseq@scope@savestackid +\def\sseq@scope{\@ifnextchar[{\sseq@scope@}{\sseq@scope@[]}}%] +\def\sseq@scope@[#1]{% + \sseq@scope@savedpaths@add{\begin{scope}}% + \sseq@processoptions{scope}{#1}% outputs into \sseq@savedoptioncode + \sseq@eval{\@nx\sseq@scope@savedpaths@add{\sseq@scope@toks{\unexpanded\@xp{\sseq@savedoptioncode\tikz@options}}}}% + %\advance\sseq@scope@savestackid\@ne + %\sseq@savestack@name{scope@save\the\sseq@scope@savestackid} +} +\def\sseq@endscope{% + \sseq@scope@savedpaths@add{\end{scope}} + %\sseq@restorestack@name{scope@save\the\sseq@scope@savestackid +} + + + + +\ifsseq@draftmode % Okay, have to dummy out all the main commands. + \sseq@setsavedpaths{ignore} % Don't add stuff to paths + \let\sseq@setsavedpaths\@gobble % and dummy out the normal mechanism that would change this + + % We don't really want to add anything to the saved paths, but the whole tikz parser is already loaded in parsers and we want to dummy a bit of it out. + % It's good to have the parser itself though, because it is responsible for sanity checking the structure of the input. Just get rid of the hard tasks + % the parser does once it's parsed the stuff. + \def\sseq@defer@tikzcommand@option[#1]{% + \sseq@g@addto@macro\sseq@whattheusersaid{[#1]}% + \sseq@defer@tikzcommand@ + } % These are the two expensive handlers, redefine them to do nothing. + \def\sseq@defer@tikzcommand@coord(#1){% + \sseq@g@addto@macro\sseq@whattheusersaid{(#1)}% + \sseq@defer@tikzcommand@ + } + + + % All we want to do here is record the range. Have to process options in order to figure out where it is. + \sseq@DeclareDocumentCommand\class{or()}{% + \begingroup + \IfNoValueT{#2}{\sseq@break}% + \sseq@xsetthiscall{\string\class\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}% + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@classstyle + \sseq@options@normalmode + \IfNoValueF{#1}{% + \sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode + }% + \sseq@cparsecoord{#2}{}% + \sseq@xminmax{\xcoord}{\ycoord}% + \sseq@yminmax{\xcoord}{\ycoord}% + \sseq@pushstack@\coord % also need the class stack to calculate other \class commands. + \sseq@cleanup@obj{partcoord.(\partialcoord).numnodes}% + \sseq@cleanup@obj{partcoord.(\partialcoord).numnodespp}% + \ifnum\nodenum=\@ne + \sseq@obj@gdef{partcoord.(\partialcoord).numnodes}{0}% + \sseq@obj@gdef{partcoord.(\partialcoord).numnodespp}{1}% + \fi + \sseq@obj@xdef{partcoord.(\partialcoord).numnodes}{\nodenum}% + \sseq@obj@xdef{partcoord.(\partialcoord).numnodespp}{\the\numexpr\nodenum+1}% + \edef\classname{class.\coord[0]}% + \ifx\sseq@class@tag\pgfutil@empty\else + \sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{% + \sseq@error@xx{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{(\partialcoord)}% could be warning + }{}% + \sseq@cleanup@obj{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}% + \sseq@obj@xdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\nodenum}% + \fi + \ifx\sseq@class@name\pgfutil@empty\else + \sseq@cleanup@obj{class.\classname.name} + \sseq@cleanup@obj{class.namedclass.\sseq@class@name} + \sseq@namehandler + \sseq@obj@xdef{class.\classname.name}{\sseq@class@name} + \sseq@obj@xdef{class.namedclass.\sseq@class@name}{\coordnopar} + \fi + \sseq@breakpoint + \endgroup + } + + % Now the rest of these can be no-ops + \sseq@DeclareDocumentCommand\classoptions{or()}{} + \sseq@DeclareDocumentCommand\replaceclass{or()}{} + \sseq@DeclareDocumentCommand\d{oU(r()d()}{} + \sseq@DeclareDocumentCommand\doptions{oU(r()d()}{} + \sseq@DeclareDocumentCommand\structline{or()r()}{} + \sseq@DeclareDocumentCommand\structlineoptions{or()r()}{} + \sseq@DeclareDocumentCommand\circleclasses{or()r()}{} + \endinput +\fi + + +\protected\def\sseq@xcoord{}\protected\def\sseq@ycoord{} + +%%%%% +%% +%% The main commands +%% +%%%%% +%%% \class, \classoptions, \replaceclass +\sseq@DeclareDocumentCommand\class{or()}{% + \begingroup + \IfNoValueT{#2}{\sseq@break} + \sseq@xsetthiscall{\string\class\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}% + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@classstyle + \the\sseq@scope@toks + \sseq@options@normalmode + \IfNoValueF{#1}{% + \sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode + }% +% + \@ifundefined{sseq@class@page}{}{\sseq@error@xxx{cmdoptions-only}{page} {\string\class}{\string\classoptions}}% could be warnings + \@ifundefined{sseq@gen} {}{\sseq@error@xxx{cmdoptions-only}{generation}{\string\class}{\string\classoptions}} +% + \sseq@cparsecoord{#2}{}% + \ifnum\csname sseq@\sseq@classpattern @maxclasses\endcsname<\nodenum\relax + \sseq@error@xxxx{classpattern-too-many-classes}{(\partialcoord)}{\nodenum}{\sseq@classpattern}{\@xp\the\csname sseq@\sseq@classpattern @maxclasses\endcsname} + \sseq@breakfi + \fi + \sseq@processlabels +% + \sseq@xminmax{\xcoord}{\ycoord}% + \sseq@yminmax{\xcoord}{\ycoord}% + \sseq@cleanup@obj{partcoord.(\partialcoord).numnodes}% + \sseq@cleanup@obj{partcoord.(\partialcoord).numnodespp}% + \ifnum\nodenum=\@ne + \sseq@obj@gdef{partcoord.(\partialcoord).numnodes}{0}% + \sseq@obj@gdef{partcoord.(\partialcoord).numnodespp}{1}% + \fi + \sseq@obj@xdef{partcoord.(\partialcoord).numnodes}{\nodenum}% + \sseq@obj@xdef{partcoord.(\partialcoord).numnodespp}{\the\numexpr\nodenum+1}% + \edef\classname{class.\coord[0]}% + \ifx\sseq@class@tag\pgfutil@empty\else + \sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{ + \sseq@error@xx{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{(\partialcoord)}% could be warning + }{} + \sseq@cleanup@obj{class.\coord.tag} + \sseq@obj@xdef{class.\coord.tag}{\sseq@class@tagprefix\sseq@class@tag} + \sseq@cleanup@obj{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag} + \sseq@obj@xdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\nodenum}% + \fi + \ifx\sseq@class@name\pgfutil@empty\else + \sseq@cleanup@obj{class.\classname.name} + \sseq@cleanup@obj{class.namedclass.\sseq@class@name} + \sseq@namehandler + \sseq@obj@xdef{class.\classname.name}{\sseq@class@name} + \sseq@obj@xdef{class.namedclass.\sseq@class@name}{\coordnopar} + \fi + \ifcsname sseq@class@showname\endcsname + \sseq@eval{\@nx\sseq@handleclassquotes{\sseq@obj{class.\classname.name}}{\sseq@class@showname}} + \fi + \sseq@pushstack@\coord +% +% + \sseq@obj@gdef{class.\coord.num}{0}% For \replaceclass + \sseq@obj@xdef{\classname.page}{\sseq@infinity}% + \sseq@obj@xodef{\classname.options}{\sseq@savedoptioncode}% + \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext}% + \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions}% + \sseq@obj@xodef{\classname.labelnodes}{\sseq@classlabelnodes}% + \sseq@obj@xdef{class.\coord.x}{\xcoord}% + \sseq@obj@xdef{class.\coord.y}{\ycoord}% + \sseq@obj@gdef{\classname.dependencies}{}% + \sseq@obj@xdef{\classname.needstikz}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi}% + \@ifundefined{sseq@tempoffset}{}{% + \tikz@scan@one@point\sseq@setoffset\sseq@tempoffset + }% + \ifx\sseq@tooltip\pgfutil@empty\else + \sseq@obj@protectedxdef{\classname.tooltip}{\sseq@tooltip} + \fi +% + \sseq@savedpaths@addclass{class.\coord}% + \sseq@obj@gdef{class.\coord.style}{}% + \sseq@breakpoint + \endgroup +} +\def\sseq@setoffset#1{\sseq@obj@gdef{\classname.offset}{\pgftransformshift{#1}}} + +\sseq@DeclareDocumentCommand\classoptions{or()}{% + \begingroup + \sseq@xsetthiscall{\classoptions\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}% + \IfNoValueT{#1}{\sseq@error@x{cmdoptions-without-options}{\string\classoptions}\sseq@break}% could be warning + \IfNoValueT{#2}{\sseq@break}% + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@classstyle + \the\sseq@scope@toks + \sseq@options@normalmode + \let\sseq@processlabels\sseq@processlabels@default % Don't double dip on labels from the scope or classstyle + \sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode +% + \sseq@parsecoord\coord{#2}{\string\classoptions}% +% + \sseq@processlabels +% + \let\partialcoord\coord@partial + \@ifundefined{sseq@class@page}{% + \@ifundefined{sseq@gen}{ + \@ifundefined{sseq@thepage}{ + \edef\sseq@gen{\sseq@obj{class.\coord.num}} + }{ + \sseq@obj@pagetogen{class.\coord}{\sseq@thepage} % stores in \sseq@gen + } + \let\sseq@genmax\sseq@gen + }{ + \ifnum\sseq@gen<\z@ + \edef\sseq@gen{\the\numexpr\sseq@obj{class.\coord.num}+\sseq@gen+1} + \fi + \@ifundefined{sseq@genmax}{\let\sseq@genmax\sseq@gen}{ + \edef\sseq@genmax{\the\numexpr\sseq@obj{class.\coord.num}+\sseq@genmax+1} + } + } + }{ + \@ifundefined{sseq@gen}{}{\sseq@error{classoptions-page-gen}}% This could be a warning + \sseq@class@getgen{\sseq@class@page} + \@ifundefined{sseq@class@pagemax}{ + % If no max is present, apply options to all pages starting at specified minimum + \edef\sseq@genmax{\sseq@obj{class.\coord.num}}% + \let\sseq@class@pagemax\sseq@infinity % ensure if "page" is defined, "pagemax" is defined too + }{ + \let\sseq@genmin\sseq@gen + \sseq@class@getgen{\sseq@class@pagemax} + \let\sseq@genmax\sseq@gen + \let\sseq@gen\sseq@genmin + } + \edef\sseq@class@page{\the\numexpr\sseq@class@page-\@ne} + \edef\sseq@class@pagemax{\the\numexpr\sseq@class@pagemax+\@ne} + } + \ifnum\sseq@gen=\m@ne + \edef\sseq@gen{\sseq@obj{class.\coord.num}} + \fi + \edef\classname{class.\coord[\sseq@gen]} + \ifsseq@keepchanges\else + \ifnum\sseq@thepagecount>\sseq@obj{\classname.page}\relax + \sseq@error@xxx{classoptions-already-dead}{\sseq@gen}{\coordname}{\sseq@obj{\classname.page}} + \sseq@breakfifi + \fi + \ifnum\sseq@gen>\z@ + \ifnum\sseq@thepagecount>\sseq@obj{class.\coord[\the\numexpr\sseq@gen-\@ne].page}\relax\else + \sseq@error@xx{classoptions-not-yet-born}{\sseq@gen}{\coord}{\sseq@class@page}% + \sseq@breakfififi + \fi + \fi + \fi{} + \ifx\sseq@class@tag\pgfutil@empty\else + \sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{% + \sseq@error@nn{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{\sseq@partialcoord}% could be warning + }% + \sseq@cleanup@obj{class.\coord.tag}% + \sseq@obj@xdef{class.\coord.tag}{\sseq@class@tagprefix\sseq@class@tag}% + \sseq@cleanup@obj{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}% + \sseq@obj@xdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\sseq@index}% + \fi + \ifx\sseq@class@name\pgfutil@empty\else + \sseq@obj@ifdef{class.\classname.name}{ + \sseq@error@nn{classoptions-class-already-named}{\coord}{\sseq@obj{class.\classname.name}}%could be warning + }{} + \sseq@cleanup@obj{class.\classname.name} + \sseq@cleanup@obj{class.namedclass.\sseq@class@name} + \sseq@namehandler + \sseq@obj@xdef{class.\classname.name}{\sseq@class@name} + \sseq@obj@xdef{class.namedclass.\sseq@class@name}{\coordnopar} + \fi + \ifcsname sseq@class@showname\endcsname + \sseq@eval{\@nx\sseq@handleclassquotes{\sseq@obj{class.\classname.name}}{\sseq@class@showname}} + \fi + \sseq@tempcount=\sseq@gen\relax + \advance\sseq@tempcount\m@ne + \loop + \advance\sseq@tempcount\@ne + \edef\classname{class.\coord[\the\sseq@tempcount]} + \sseq@cleanup@obj{\classname.options} + \sseq@classoptions@setup@pagerange + \sseq@classoptions@obj@addto@withpagerange{\classname.options}{\sseq@savedoptioncode} + % + \ifx\sseq@classnodetext\pgfutil@empty\else + \sseq@cleanup@obj{\classname.nodetext} + \sseq@classoptions@obj@addto@withpagerange{\classname.nodetext}{\sseq@classnodetext} + \fi + \ifx\sseq@classnodetextoptions\pgfutil@empty\else + \sseq@cleanup@obj{\classname.nodetext.options} + \sseq@classoptions@obj@addto@withpagerange{\classname.nodetext.options}{\sseq@classnodetextoptions} + \fi + \ifx\sseq@classlabelnodes\pgfutil@empty\else + \sseq@cleanup@obj{\classname.labelnodes} + \sseq@classoptions@obj@addto@withpagerange{\classname.labelnodes}{\sseq@classlabelnodes} + \fi + \@ifundefined{sseq@tempoffset}{}{ + \sseq@cleanup@obj{\classname.offset} + \tikz@scan@one@point\sseq@setoffset\sseq@tempoffset + } + \ifnum\sseq@tempcount<\sseq@genmax\repeat + \sseq@breakpoint + \endgroup +} +\def\sseq@classoptions@setup@pagerange{% + \@ifundefined{sseq@class@page}{ + \def\sseq@classoptions@obj@addto@withpagerange@{\sseq@obj@gaddto{\sseq@tempobj}} + }{ + \def\sseq@temp##1{##1} + \ifnum\sseq@tempcount=\sseq@gen\relax + \sseq@eval{\@nx\pretocmd\@nx\sseq@temp{\@nx\ifnum\sseq@thepagecount>\sseq@class@page\relax}{}{% + \@nx\sseq@error@x{this-shouldnt-happen}{file main, function \string\sseq@classoptions@setup@pagerange} + }}% + \apptocmd\sseq@temp{\fi}{}{\sseq@error@x{this-shouldnt-happen}{file main, function \string\sseq@classoptions@setup@pagerange}} + \fi + \ifnum\sseq@tempcount=\sseq@genmax\relax + \sseq@eval{\@nx\pretocmd\@nx\sseq@temp{\@nx\ifnum\sseq@thepagecount<\sseq@class@pagemax\relax}{}{\@nx\sseq@error@internal{}}} + \apptocmd\sseq@temp{\fi}{}{\sseq@error@internal{this-shouldnt-happen}{file main, function \string\sseq@classoptions@setup@pagerange}} + \fi + \@xp\def\@xp\sseq@temp\@xp##\@xp1\@xp{\@xp{\sseq@temp{##1}}} + \pretocmd\sseq@temp{\sseq@obj@gaddto{\sseq@tempobj}}{}{\sseq@error@internal{this-shouldnt-happen}{file main, function \string\sseq@classoptions@setup@pagerange}} + \let\sseq@classoptions@obj@addto@withpagerange@\sseq@temp + } +} +\def\sseq@classoptions@obj@addto@withpagerange#1#2{% + \def\sseq@tempobj{#1}% + \@xp\sseq@classoptions@obj@addto@withpagerange@\@xp{#2}% +} +\def\sseq@class@getgen#1{ + \bgroup + \ifnum\sseq@obj{class.\coord.num}>\z@ + \sseq@eval{\unexpanded{\sseq@obj@pagetogen{class.\coord}}{#1}} % stores in \sseq@gen + \else + \def\sseq@gen{0} + \fi + \sseq@smuggle@macro\sseq@gen + \egroup +} +\sseq@DeclareDocumentCommand\replaceclass{or()}{% + \begingroup + \sseq@xsetthiscall{\string\replaceclass\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}} + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@classstyle + \the\sseq@scope@toks + \sseq@options@normalmode + \IfNoValueF{#1}{% + \sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode + }% +% + \sseq@parsecoord\coord{#2}{\string\replaceclass} + \sseq@processlabels +% + \sseq@ifundefcoord\coord{\sseq@error@x{replaceclass-no-class}{\coordname}\sseq@break}{} + \sseq@ifdead\coord{}{\sseq@error@x{replaceclass-not-dead-yet}{\coordname}\sseq@break} + \ifsseq@keepchanges\else + \ifnum\the\numexpr\sseq@obj{class.\coord[\sseq@obj{class.\coord.num}].page}<\sseq@thepagecount\else + \edef\sseq@temp{\sseq@obj{class.\coord[\sseq@obj{class.\coord.num}].page}} + \sseq@error@xxx{replaceclass-no-effect-on-this-page}{\coord}{\sseq@temp}{\the\numexpr\sseq@temp+\@ne}% warning + \sseq@breakfifi + \fi + \fi + \let\partialcoord\coord@partial + \ifx\sseq@class@tag\pgfutil@empty\else + \sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{% + \sseq@error@nn{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{\sseq@partialcoord}% could be warning + }{}% + \sseq@cleanup@obj{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}% + \sseq@obj@xdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\nodenum}% + \fi + \ifx\sseq@class@name\pgfutil@empty\else + \sseq@cleanup@obj{class.\classname.name} + \sseq@cleanup@obj{class.namedclass.\sseq@class@name} + \sseq@namehandler + \sseq@obj@xdef{class.\classname.name}{\sseq@class@name} + \sseq@obj@xdef{class.namedclass.\sseq@class@name}{\coordnopar} + \fi + \ifcsname sseq@class@showname\endcsname + \sseq@eval{\@nx\sseq@handleclassquotes{\sseq@obj{class.\classname.name}}{\sseq@class@showname}} + \fi + \sseq@cleanup@obj{class.\coord.num} + \sseq@obj@inc{class.\coord.num} + \let\partialcoord\coord@partial + \ifx\sseq@class@tag\pgfutil@empty\else + \sseq@obj@ifdef{partialcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{% + \sseq@error@nn{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{\sseq@partialcoord}% could be warning + }{}% + \sseq@obj@xdef{partialcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\nodenum}% + \fi + \edef\classname{class.\coord[\sseq@obj{class.\coord.num}]} +% + \sseq@obj@xdef{\classname.page}{\sseq@infinity} + \sseq@obj@xodef{\classname.options}{\sseq@savedoptioncode} + \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext} + \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions} + \sseq@obj@xodef{\classname.labelnodes}{\sseq@classlabelnodes} + \sseq@obj@gdef{\classname.dependencies}{} + \sseq@obj@xdef{\classname.needstikz}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi} + \@ifundefined{sseq@tempoffset}{}{\tikz@scan@one@point\sseq@setoffset\sseq@tempoffset} +% + \sseq@breakpoint + \endgroup +} +\def\sseq@class@draw@ifpage#1{ + \bgroup + \sseq@obj@pagetogen{#1}{\sseq@thepage} % sets \sseq@gen + \ifnum\sseq@gen>\m@ne % -1 means no class to print + \ifnum\sseq@obj{#1[\sseq@gen].page}=\sseq@thepagecount + \sseq@thispagetrue + \fi + \sseq@gsetthiscall{class #1} + \sseq@class@drawnode{#1[\sseq@gen]} + \fi + \egroup +} +% #1 -- class +% #2 -- page +% If there is a class #1 drawn on page #2, set \sseq@gen to be the generation of that class, otherwise set \sseq@gen to be -1. +\def\sseq@obj@pagetogen#1#2{ + \bgroup + \def\sseq@gen{-1} + \sseq@tempcount=\m@ne + \sseq@tempcountb=\sseq@obj{#1.num}\relax + \loop + \advance\sseq@tempcount\@ne + \ifnum\sseq@obj{#1[\the\sseq@tempcount].page}<#2\relax\else + \edef\sseq@gen{\the\sseq@tempcount} + \sseq@tempcount=\sseq@tempcountb\relax + \fi + \ifnum\sseq@tempcount<\sseq@tempcountb\repeat + \sseq@smuggle@macro\sseq@gen + \egroup +} +%%% +%%% \d and \doptions +%%% + +\sseq@DeclareDocumentCommand\d{oU(r()d()}{% + \sseq@d@{d}{#1}{#2}{#3}{#4}% +} +\sseq@DeclareDocumentCommand\doptions{oU(r()d()}{% + \begingroup + \IfNoValueT{#1}{ + \sseq@xsetthiscall{\@xp\string\csname#1\endcsname\unexpanded{#2(#3)}\IfNoValueF{#4}{\unexpanded{(#4)}}}% + \sseq@error@x{cmdoptions-without-options}{\string\doptions}\sseq@break % could be warning + } + \sseq@d@{doptions}{#1}{#2}{#3}{#4}% + \sseq@breakpoint + \endgroup +} +\def\sseq@d@#1#2#3#4#5{% + \begingroup + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@edgestyle + \the\sseq@differentialstyle + \the\sseq@scope@toks + \sseq@options@normalmode + \IfNoValueF{#2}{ + \sseq@processoptions{differential}{#2}% Outputs result into \sseq@savedoptioncode + } + \sseq@xsetthiscall{\@xp\string\csname#1\endcsname\IfNoValueF{#2}{\unexpanded{[#2]}}\unexpanded{#3(#4)}\IfNoValueF{#5}{\unexpanded{(#5)}}}% + \sseq@ifintexpr{#3}{% + \sseq@tempcount=\numexpr#3\relax % this is a convenient way to get rid of spaces because #3 has to be a number + }{% + \sseq@error@n{d-invalid-page}{#3}\sseq@break% + }% + \@xp\sseq@dparsecoord\@xp{\the\sseq@tempcount}{#4}{#5}% + \sseq@eval{\unexpanded{\csname sseq@d@#1\endcsname{#2}}{\the\sseq@tempcount}}% + \sseq@breakpoint + \endgroup +} + +% #1 -- options +% #2 -- page +% #3 -- source coordinate +\def\sseq@d@d#1#2{%% + \sseq@d@setpageminrec{class.\source}{#2}{source}% automatically handles \sseq@cleanup@obj + \sseq@d@setpageminrec{class.\target}{#2}{target} +% + \ifsseq@drawdifferential + \sseq@obj@gdef{d.#2\source\target.page}{#2} + \sseq@obj@gdef{d.#2\source\target.style}{}% + \sseq@obj@xdef{d.#2\source\target.source}{\source} + \sseq@obj@xdef{d.#2\source\target.target}{\target} + \sseq@obj@xdef{d.#2\source\target.options}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi\unexpanded\@xp{\sseq@savedoptioncode}} +% + \sseq@savedpaths@adddifferential{d.#2\source\target}% + \else + \sseq@obj@gdef{d.#2\source\target.invisible}{} + \fi +} +\def\sseq@d@doptions#1#2{% + \sseq@obj@ifundef{d.#2\source\target.options}{\sseq@error@n{cmdoptions-feature-doesn't-exist}{differential}\sseq@break}{}% + \sseq@obj@ifdef{d.#2\source\target.invisible}{\sseq@error{doptions-invisible}\sseq@break} + \ifsseq@keepchanges\else + \@ifundefined{sseq@thepage}{}{ + \ifnum#2=\sseq@thepagecount\else\ifnum\sseq@thepagecount=\z@\else + \sseq@error@n{doptions-no-effect-on-this-page}{#2}\sseq@breakfififi + \fi\fi + }% + \fi +% + \sseq@cleanup@obj{d.#2\source\target.options} + \sseq@obj@xoaddto{d.#2\source\target.options}{\sseq@savedoptioncode} +} + +% Some helper macros: +% #1 -- class name for \sseq@obj +% #2 -- page +% #3 -- source or target for error handling purposes. +\def\sseq@d@setpageminrec#1#2#3{% not really recursive. + \sseq@cleanup@obj{#1[\sseq@obj{#1.num}].page} + \sseq@cleanup@obj{#1[\sseq@obj{#1.num}].deathinfo} + \sseq@cleanup@obj{#1[\sseq@obj{#1.num}].deathline} + \sseq@d@setpageclass{#1}{#2}{#3} + \sseq@obj@map{#1[\sseq@obj{#1.num}].dependencies}{ + \sseq@d@setpagemin{##1}{#2} % automatically handles cleanup + } +} + +% #1 -- class name for \sseq@obj +% #2 -- page +% #3 -- source or target for error handling purposes. +\def\sseq@d@setpageclass#1#2#3{ + \edef\sseq@classgenname{#1[\sseq@obj{#1.num}]} + % If the class is dead, then it's only not an error if it died on the current page + \ifnum\sseq@obj{\sseq@classgenname.page}<\sseq@infinitycount + % If the page it died on is greater than this one, hit-wrong-order error + \ifnum\sseq@obj{\sseq@classgenname.page}>#2\relax + \let\sseq@deadclass@genname\sseq@classgenname + \sseq@preparestacktrace + \sseq@error@xxxx{d-hit-wrong-order}{#3}{\csname #3name\endcsname}{#2}{\the\sseq@temptoks} + \sseq@breakfifi + \fi + % If the page it died on is less than this one, class-already-hit error + \ifnum\sseq@obj{\sseq@classgenname.page}<#2\relax + \let\sseq@deadclass@genname\sseq@classgenname + \sseq@preparestacktrace + \sseq@error@xxxx{d-class-already-hit}{#3}{\csname #3name\endcsname}{#2}{\the\sseq@temptoks} + \sseq@breakfifi + \fi + \fi + % If the class has been replaced before, that's only okay if it was replaced on a previous page. + \ifnum\sseq@obj{#1.num}>\z@ + \sseq@tempcount=\sseq@obj{#1.num}\relax + \advance\sseq@tempcount\m@ne + \ifnum\sseq@obj{#1[\the\sseq@tempcount].page}<#2\relax\else + \ifnum#2=\sseq@obj{#1[\the\sseq@tempcount].page} + \sseq@error@xxxx{d-hit-same-page-replaceclass}{#3}{\csname #3name\endcsname}{#2}{\sseq@obj{#1[\the\sseq@tempcount].deathinfo}} + \sseq@breakfififi + \else + \edef\sseq@deadclass@genname{#1[\the\numexpr\sseq@obj{#1.num}-\@ne]} + \sseq@preparestacktrace + \sseq@error@xxxx{d-hit-wrong-order}{#3}{\csname #3name\endcsname}{#2}{\the\sseq@temptoks} + \sseq@breakfififi + \fi + \fi + \fi + \sseq@obj@xdef{\sseq@classgenname.page}{#2} + \sseq@obj@xdef{\sseq@classgenname.deathinfo}{#3 of differential \sseq@thiscall\space on page #2} + \bgroup + \def\foreach{\@nx\@nx\@nx\foreach} + \protected\def\\{} + \let\sseq@possibleperiod\empty + \let\sseq@possibleperiodb\empty + \sseq@obj@xdef{\sseq@classgenname.deathlocation}{% + on input line \the\inputlineno\sseq@error@inforeachloop + } + \sseq@obj@xdef{\sseq@classgenname.deathline}{\the\inputlineno} + \sseq@tempiffalse + \edef\sseq@temp{\the\sseq@foreachcall} + \ifx\sseq@temp\pgfutil@empty\else\sseq@tempiftrue\fi + \ifx\sseq@restofstacktrace\pgfutil@empty\else\sseq@tempiftrue\fi + \sseq@obj@xdef{\sseq@classgenname.deathstacktrace}{% + \ifsseq@tempif + \unexpanded{\\\\}Stack trace for differential \sseq@thiscall\ that killed #3:\unexpanded{\\}% + \ifx\sseq@temp\sseq@empty\else\unexpanded{\ \ \ }\@nx\sseq@stack@unexpanded{\unexpanded\@xp{\the\sseq@foreachcall}}\fi + \unexpanded\@xp{\sseq@restofstacktrace}% + \fi + } + \egroup +} + +\def\sseq@preparestacktrace{ + \def\foreach{\@nx\foreach} + \edef\sseq@temp@i{\unexpanded\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathline}}} + \edef\sseq@temp@ii{\the\inputlineno} + \ifx\sseq@temp@i\sseq@temp@ii + \sseq@temptoks\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathinfo} (in the same \foreach loop)} + \else + \protected\def\\{} + \sseq@eval{\sseq@temptoks{\unexpanded\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathinfo}}\space(\sseq@obj{\sseq@classgenname.deathlocation})}} + \sseq@e@addto@macro\sseq@errorinfo{\unexpanded\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathstacktrace}}} + \fi +} + +\def\sseq@d@setpagemin#1#2{ + \ifnum\sseq@obj{#1.page}>#2\relax + \sseq@cleanup@obj{#1.page} + \sseq@obj@xdef{#1.page}{#2} + \fi +} +\def\sseq@differential@draw@ifpage#1{ + \ifnum\sseq@thepagecount=\z@ + \sseq@drawdifferential{#1} + \else + \ifnum\sseq@obj{#1.page}=\sseq@thepagecount\relax + \sseq@drawdifferential{#1} + \fi + \fi +} +\def\sseq@drawdifferential#1{ + \bgroup + \sseq@eval{ + \@nx\sseq@drawedge\sseq@obj{#1.source}\sseq@obj{#1.target}{differential}{% + \@xptwo\@nx\sseq@obj{#1.options} + } + } + \egroup +} +%%% +%%% \structline and \structlineoptions +%%% +\sseq@DeclareDocumentCommand\structline{or()r()}{% + \begingroup + \sseq@xsetthiscall{\string\structline\IfNoValueF{#1}{\unexpanded{[#1]}}\unexpanded{(#2)(#3)}}% + \sseq@structline@main{structline}{#1}{#2}{#3}% +} +\sseq@DeclareDocumentCommand\structlineoptions{or()r()}{% + \begingroup + \sseq@xsetthiscall{\string\structlineoptions\IfNoValueF{#1}{\unexpanded{[#1]}}\unexpanded{(#2)(#3)}}% + \IfNoValueT{#1}{\sseq@error@x{cmdoptions-without-options}{\string\structlineoptions}\sseq@break@withcleanup} + \sseq@structline@main{structlineoptions}{#1}{#2}{#3}% + \sseq@breakpoint\@gobble\endgroup +} +\def\sseq@structline@main#1#2#3#4{% + \sseq@options@firstpassmode + \the\sseq@sseqstyle + \the\sseq@edgestyle + \the\sseq@structlinestyle + \the\sseq@scope@toks + \sseq@options@normalmode + \IfNoValueF{#2}{% + \sseq@processoptions{struct line}{#2}% Outputs result into \sseq@savedoptioncode + }% + \sseq@parsecoord\source{#3}{source of structure line}% + \sseq@parsecoord\target{#4}{target of structure line}% + \@ifundefined{sseq@structline@page}{%this is repeated in circleclasses + \def\sseq@pagemin{0} + \ifnum\sseq@obj{class.\source.num}>\z@ + \edef\sseq@pagemin{\sseq@obj{class.\source[\the\numexpr\sseq@obj{class.\source.num}-1].page}} + \fi + \ifnum\sseq@obj{class.\target.num}>\z@ + \edef\sseq@test{\sseq@obj{class.\target[\the\numexpr\sseq@obj{class.\target.num}-1].page}} + \ifnum\sseq@test>\sseq@pagemin\relax + \let\sseq@pagemin\sseq@test + \fi + \fi + }{\edef\sseq@pagemin{\the\numexpr\sseq@structline@page-\@ne}} + \csname sseq@structline@#1\endcsname + \sseq@breakpoint + \endgroup +} +\def\sseq@structline@structline{ + \@ifundefined{sseq@structline@pagemax}{}{\sseq@error{structline-no-page-max}}% could be warning + \ifnum\sseq@pagemin<\sseq@obj{class.\source[\sseq@obj{class.\source.num}].page}\relax\else + \sseq@error{structline-stillborn} + \sseq@breakfi + \fi + \ifnum\sseq@pagemin<\sseq@obj{class.\target[\sseq@obj{class.\target.num}].page}\relax\else % If the \structline is dead before it is born, throw an error + \sseq@error{structline-stillborn} + \sseq@breakfi + \fi + \sseq@obj@ifdef{structline.\source\target.num}{% + \ifnum\sseq@obj{structline.\source\target[\sseq@obj{structline.\source\target.num}].page}=\sseq@infinitycount + \sseq@error@xx{structline-already-exists}{\sourcename}{\targetname} + \sseq@breakfi + \fi + \sseq@cleanup@obj{structline.\source\target.num} + \sseq@obj@inc{structline.\source\target.num} + }{ + \sseq@obj@gdef{structline.\source\target.num}{0} + \sseq@savedpaths@addstructline{structline.\source\target} + } + \edef\sseq@structlinename{structline.\source\target[\sseq@obj{structline.\source\target.num}]} + \sseq@obj@xdef{\sseq@structlinename.page}{\sseq@infinity} + \sseq@obj@xdef{\sseq@structlinename.pagemin}{\sseq@pagemin} + \sseq@obj@xdef{\sseq@structlinename.source}{\source} + \sseq@obj@xdef{\sseq@structlinename.target}{\target} + \sseq@cleanup@obj{structline.\source\target.num} + \sseq@class@adddependence{class.\source}{\sseq@structlinename}% If the source or target is already dead, this will set structlinename.page + \sseq@class@adddependence{class.\target}{\sseq@structlinename} + \sseq@obj@xdef{\sseq@structlinename.options}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi\unexpanded\@xp{\sseq@savedoptioncode}} +} +\def\sseq@structline@structlineoptions{ + \sseq@obj@ifundef{structline.\source\target.num}{ + \sseq@error@n{cmdoptions-feature-doesn't-exist}{\structline} + \sseq@break + }{} + \@ifundefined{sseq@structline@page}{ + \edef\sseq@gen{\sseq@obj{structline.\source\target.num}} + \let\sseq@genmax\sseq@gen + }{ + \sseq@structline@getgen{\sseq@structline@page} + \@ifundefined{sseq@structline@pagemax}{% + % If no max is present, apply options to all pages starting at specified minimum + \edef\sseq@genmax{\sseq@obj{structline.\source\target.num}}% + \let\sseq@structline@pagemax\sseq@infinity + }{ + \let\sseq@genmin\sseq@gen + \sseq@structline@getgen{\sseq@structline@pagemax} + \let\sseq@genmax\sseq@gen + \let\sseq@gen\sseq@genmin + } + \edef\sseq@structline@page{\the\numexpr\sseq@structline@page-1} + \edef\sseq@structline@pagemax{\the\numexpr\sseq@structline@pagemax+1} + } + \sseq@tempcount=\sseq@gen\relax + \advance\sseq@tempcount\m@ne + \loop + \advance\sseq@tempcount\@ne + \edef\sseq@structlinename{structline.\source\target[\the\sseq@tempcount]} + \sseq@cleanup@obj{\sseq@structlinename.options} + \ifsseq@needstikz + \sseq@obj@gaddto{\sseq@structlinename.options}{\sseq@needstikztrue} + \fi + \ifnum\sseq@tempcount=\sseq@gen\relax + \@ifundefined{sseq@structline@page}{}{ + \edef\sseq@savedoptioncode{\@nx\ifnum\sseq@thepagecount>\sseq@structline@page\relax\unexpanded\@xp{\sseq@savedoptioncode}\@nx\fi} + } + \fi + \ifnum\sseq@tempcount=\sseq@genmax\relax + \@ifundefined{sseq@structline@pagemax}{}{ + \edef\sseq@savedoptioncode{\@nx\ifnum\sseq@thepagecount<\sseq@structline@pagemax\relax\unexpanded\@xp{\sseq@savedoptioncode}\@nx\fi} + } + \fi + \sseq@obj@xoaddto{\sseq@structlinename.options}{\sseq@savedoptioncode} + \ifnum\sseq@tempcount<\sseq@genmax\repeat +} +\def\sseq@structline@getgen#1{ + \bgroup + \sseq@tempcount=\sseq@obj{structline.\source\target.num}\relax + \ifnum\sseq@tempcount>\z@ + \ifnum#1<\z@\relax + \@ifundefined{sseq@thepage}{ + \ifnum\sseq@obj{structline.\source\target[\the\sseq@tempcount].page}<\sseq@infinitycount + \sseq@tempcount=\sseq@obj{structline.\source\target[\the\sseq@tempcount].page}\relax + \else + \advance\sseq@tempcount\m@ne + \sseq@tempcount=\sseq@obj{structline.\source\target[\the\sseq@tempcount].page}\relax + \advance\sseq@tempcount\@ne + \fi + }{ + \sseq@tempcount=\sseq@thepagecount + } + \advance\sseq@tempcount\@ne + \advance\sseq@tempcount#1\relax + \fi + \sseq@eval{\unexpanded{\sseq@obj@pagetogen{structline.\source\target}}{\the\sseq@tempcount}} % stores in \sseq@gen + \else + \def\sseq@gen{0} + \fi + \sseq@smuggle@macro\sseq@gen + \egroup +} +\def\sseq@class@adddependence#1#2{ + \edef\sseq@temp{\sseq@obj{#1.num}} + \sseq@d@setpagemin{#2}{\sseq@obj{#1[\sseq@temp].page}}% automatically handles cleanup + \sseq@cleanup@obj{#1[\sseq@temp].dependencies} + \sseq@obj@xaddto{#1[\sseq@temp].dependencies}{\@nx\\{#2}} +} +\def\sseq@structline@draw@ifpage#1{ + \bgroup + \ifnum\sseq@thepagecount=\z@ + \ifnum\sseq@obj{#1[0].pagemin}=\z@ + \sseq@structline@draw{#1[0]} + \fi + \else + \sseq@obj@pagetogen{#1}{\sseq@thepage} % sets \sseq@gen + \ifnum\sseq@gen<\z@\else % negative sseq@gen means don't draw it + \ifnum\sseq@obj{#1[\sseq@gen].page}=\sseq@thepagecount + \sseq@thispagetrue + \fi + \ifnum\sseq@obj{#1[\sseq@gen].pagemin}<\sseq@thepagecount + \sseq@structline@draw{#1[\sseq@gen]} + \fi + \fi + \fi + \egroup +} +\def\sseq@structline@draw#1{\sseq@eval{\@nx\sseq@drawedge\sseq@obj{#1.source}\sseq@obj{#1.target}{structline}{\@nx\sseq@obj{#1.options}}}} + + + + + + +\newcount\sseq@circleclassuid +\sseq@DeclareDocumentCommand\circleclasses{or()r()}{ + \begingroup + \def\sseq@keysfortikzprim{} + \IfNoValueF{#1}{ + \sseq@processoptions{fit}{#1} + } + \sseq@parsecoord\coorda{#2}{first \@nx\circleclass class} + \sseq@parsecoord\coordb{#3}{second \@nx\circleclass class} +% +% + \ifsseq@keepchanges + \@ifundefined{sseq@fit@page}{% also in structline@main. TODO: refactor these chunks together? + \def\sseq@pagemin{0} + \ifnum\sseq@obj{class.\coorda.num}>\z@ + \edef\sseq@pagemin{\sseq@obj{class.\coorda[\the\numexpr\sseq@obj{class.\coorda.num}-\@ne].page}} + \fi + \ifnum\sseq@obj{class.\coordb.num}>\z@ + \edef\sseq@test{\sseq@obj{class.\coordb[\the\numexpr\sseq@obj{class.\coordb.num}-\@ne].page}} + \ifnum\sseq@test>\sseq@pagemin\relax + \let\sseq@pagemin\sseq@test + \fi + \fi + }{\edef\sseq@pagemin{\the\numexpr\sseq@fit@page-\@ne}} + \@ifundefined{sseq@fit@pagemax}{\let\sseq@pagemax\sseq@infinity}{\let\sseq@pagemax\sseq@fit@pagemax} + \else % Put it on the current page no matter what inside sseqpage + \let\sseq@pagemax\sseq@infinity\def\sseq@pagemin{-1} + \fi +% +% + \global\advance\sseq@circleclassuid\@ne + \edef\circleclassobjname{circleclass(\coordanopar)(\coordbnopar)\the\sseq@circleclassuid} +% +% + \sseq@obj@xodef{\circleclassobjname.options}{\sseq@savedoptioncode} + \sseq@obj@xodef{\circleclassobjname.tikzprimoptions}{\sseq@keysfortikzprim} + \sseq@obj@xdef{\circleclassobjname.fitnodes}{\@nx\tikz@lib@fit{(sseq{\coordanopar})(sseq{\coordbnopar})\sseq@fitalso}} + %\edef\temp{\@nx\sseq@circleclass@draw{\coorda@internalname}{\coordb@internalname}{\unexpanded\@xp{\sseq@savedoptioncode}}} + \sseq@savedpaths@xadd{\@nx\sseq@circleclass@draw@ifpage{\circleclassobjname}{\coordanopar}{\coordbnopar}} + \sseq@obj@xdef{\circleclassobjname.page}{\sseq@pagemax} + \sseq@obj@xdef{\circleclassobjname.pagemin}{\sseq@pagemin} + \@ifundefined{sseq@fit@pagemax}{ + \ifsseq@keepchanges + \sseq@class@adddependence{class.\coorda}{\circleclassobjname}% If the source or target is already dead, this will set structlinename.page + \sseq@class@adddependence{class.\coordb}{\circleclassobjname} + \fi + }{} + \sseq@breakpoint + \endgroup +} + +\ifsseq@patchfit\else + \sseq@DeclareDocumentCommand\circleclasses{or()r()}{% + \sseq@warning{circleclasses-not-provided} + } +\fi + +\def\sseq@circleclass@draw@ifpage#1#2#3{ + \ifnum\sseq@thepagecount<\numexpr\sseq@obj{#1.page}+\@ne + \ifnum\sseq@obj{#1.page}=\sseq@thepagecount + \sseq@thispagetrue + \fi + \ifnum\sseq@obj{#1.pagemin}<\sseq@thepagecount + \sseq@circleclass@draw{#1}{#2}{#3} + \fi + \fi +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex new file mode 100644 index 00000000000..c8fbbb1eb75 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex @@ -0,0 +1,508 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqmessages.code.tex +%% Exposes: Error message redirects? +%% +%% Set up fancy error messages +%% + + + +%% The error handling system is build on top of l3msg. l3msg produces errors like: +%% +%% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +%% ! +%% ! LaTeX error: "<package>/<error-name>" +%% ! +%% ! <error message text> +%% ! +%% ! See the <package> documentation for further information. % produced by \msg_see_documentation_text:n{<package>} +%% !............................................... +%% +%% The user will see underneath it l.<line number> <text on line> +%% +%% Unfortunately, if the error is in a \foreach statement, the user will only see the final line of the foreach loop, often just the close brace. +%% It's impossible to tell from this where in the \foreach the error occurred. Similar problems occur if the command is inside a user command. +%% +%% We're going to modify this file to improve the situation. +%% +%% If the command is in a forloop or a user command I want to: +%% -- annotate the error with the command that caused it, or the previous command if the error occurred before I can know what the current command looks like. +%% -- present a stack trace to inform the user where exactly the problem occurred +%% +%% +%% We automatically print the annotation and stack trace at the end of all l3msg messages by hooking into \msg_see_documentation_text:n. +%% The annotation and stack trace are prepared by a command \sseq@error@setup which we hook into the beginning of the latex3 message processing code. +%% +%% Here's an example of the result: +%% +%% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +%% ! +%% ! sseqpages error: "index-too-large" +%% ! +%% ! Index '-3' provided for target of structure line is too large -- only 1 +%% ! classes exist at position (32,8). +%% ! +%% ! (Error occurred during call "\structline(16,-1,-1)(16,0,-3)", in the % This is the annotation +%% ! \foreach block that ends on line 158, with variable values: \n = 2.) % it's stored in \sseq@error@annotation +%% ! +%% ! Stack trace: % This is the stack trace +%% ! \towergroupb (8*\n ,4*\n ) % Produced by \sseq@printstacktrace +%% ! \foreach \n in {2,3,4} +%% ! +%% ! See the sseqpages documentation for further information. +%% ! +%% ! Type <return> to continue. +%% !............................................... + + +\def\sseq@protecterror#1{\@nx\sseq@protecterror\unexpanded{{#1}}} + +% Stack, thiscall, foreachcall. +% Here we record what the user has said (as best we can tell) +\newtoks\sseq@thiscalltoks +\def\sseq@thiscall{\the\sseq@thiscalltoks} +\def\sseq@setthiscall#1{\sseq@seterrorannotation{call}\sseq@thiscalltoks{#1}} +\def\sseq@esetthiscall#1{\sseq@seterrorannotation{call}\sseq@eval{\sseq@thiscalltoks{#1}}} +\def\sseq@gsetthiscall{\sseq@seterrorannotation{call}\global\sseq@thiscalltoks} +\def\sseq@xsetthiscall#1{\sseq@eval{\@nx\sseq@gsetthiscall{#1}}} +\def\sseq@xsetlastcall#1{\sseq@eval{\global\sseq@thiscalltoks{#1}}} + +\def\sseq@usermacro@esetthiscall#1{\sseq@eval{\sseq@thiscalltoks{#1}}} % Don't set \sseq@error@annotation@call + +\newtoks\sseq@foreachcall +\newtoks\sseq@topofstacktrace +\sseq@topofstacktrace{} +\def\sseq@restofstacktrace{} + +\def\sseq@pushstacktrace#1{ + \edef\sseq@temp{\the\sseq@topofstacktrace} + \ifx\sseq@temp\pgfutil@empty\else + \edef\sseq@restofstacktrace{\unexpanded{\\\ \ \ }\@nx\sseq@stack@unexpanded{\the\sseq@topofstacktrace}\unexpanded\@xp{\sseq@restofstacktrace}} + \fi + \sseq@topofstacktrace{#1} +} +\def\sseq@opushstacktrace#1{\@xp\sseq@pushstacktrace\@xp{#1}} +\def\sseq@stack@unexpanded#1{\@nx\sseq@stack@unexpanded\unexpanded{{#1}}} + + + +% Positional information about the error: +% Lengths are five more than the correct length to account for the fact that the line starts with !<space> and to accommodate two quote characters and a comma. +\def\sseq@error@annotation@aftercall{\\\\Error occurred after call\sseq@printthiscall\sseq@error@inforeachloop} +\chardef\sseq@error@annotation@length@aftercall=34 +\def\sseq@error@annotation@call{\\\\Error occurred during call\sseq@printthiscall\sseq@error@inforeachloop} +\chardef\sseq@error@annotation@length@call=33 +\def\sseq@error@annotation@atbeginforeach{\\\\Error occurred at the beginning of \string\foreach\ statement\sseq@printthiscall\sseq@error@inforeachloop} +\chardef\sseq@error@annotation@length@atbeginforeach=60 +\def\sseq@error@annotation@atbeginusercmd{\\\\Error occurred at the beginning of user command\sseq@printthiscall\sseq@error@inforeachloop} +\chardef\sseq@error@annotation@length@atbeginusercmd=54 + +\def\sseq@seterrorannotation@drawing#1#2#3#4#5{% + \def\sseq@error@annotation{\\\\Error occurred while drawing class (#2,#3,#4)\ifnum#5>0 \space which has been replaced #5 time\ifnum#5>1s\fi\fi. + Look for a \ifnum#5>0\string\replaceclass\else\string\class\fi\space command that makes a class at that position. + Also make sure to check any \@nx\classoptions commands that could be the culprit.}% +} + +\def\sseq@seterrorannotation#1{% + \@xp\let\@xp\sseq@error@annotation\csname sseq@error@annotation@#1\endcsname + \@xp\let\@xp\sseq@error@annotation@length\csname sseq@error@annotation@length@#1\endcsname +} + +\sseq@seterrorannotation{aftercall} + + +\def\sseq@error@inforeachloop{\sseq@possibleperiod} +\def\sseq@error@inforeachloop@active{\sseq@possiblecomma in \foreach block with variable values:\sseq@for@printvars\sseq@possibleperiodb} +\def\sseq@error@setup@errorinfo{}% Changed during \foreach and user commands + +\def\sseq@possiblecomma{,\space} +\def\sseq@possibleperiod{.} +\def\sseq@possibleperiodb{.} + + +\def\sseq@error@announcestacktrace{\\\\Stack trace:} +\def\sseq@printstacktrace{ % Only prints rest of stack trace because top element is mentioned in annotation. + \ifx\sseq@restofstacktrace\pgfutil@empty\else + \sseq@error@announcestacktrace\sseq@restofstacktrace + \fi +} + +% \sseq@error@setup happens before the error is reported, \sseq@error@cleanup at the end. + +\ExplSyntaxOn + +\def\sseq@error@setup@withinfo{ + \bgroup + \def\foreach{\@nx\foreach} + \sseq@countthiscall + \ifnum\sseq@thiscallnumchars>\numexpr\l_iow_line_count_int-\sseq@error@annotation@length\relax + \def\sseq@printthiscall{:\\\@xp\iow_indent:n\@xp{\the\sseq@thiscalltoks}\\} + \let\sseq@possiblecomma\empty + \let\sseq@possibleperiod\empty + \fi + \let\sseq@stack@unexpanded\unexpanded + \sseq@error@setup@errorinfo + \sseq@error@hook +} + +\def\sseq@error@setup@noinfo {\bgroup\def\foreach{\@nx\foreach}\let\sseq@stack@unexpanded\unexpanded\def\sseq@error@annotation{}\sseq@error@hook} +\let\sseq@error@setup\sseq@error@setup@noinfo +\def\sseq@error@cleanup{\egroup\sseq@errortrue} % If the error was thrown in NewDocumentCommand, we need to process it. Just used in sseqmacromakers. + + +\def\sseq@printthiscall{\ "\the\sseq@thiscalltoks"} +% make \exp_args:NNNf: +\let \sseq_dummy:NNn \empty +\cs_generate_variant:Nn \sseq_dummy:NNn {NNf} + + +% Count the chars in thiscall +% Detokenize handles the control words, but keeps the spaces as spaces. To count them properly, we lowercase them into 0's (any nonspace character would do just fine). +\def\sseq@countthiscall{ + \bgroup\lccode`\ =`\0\relax + \edef\temp{\detokenize\@xp{\the\sseq@thiscalltoks}} + \exp_args:Nf\lowercase{ + \exp_args:NNNf\egroup + \edef\sseq@thiscallnumchars{ + \exp_args:NNo\@nx\tl_count:n{\temp} + } + } +} + +\ExplSyntaxOff + + +\def\sseq@error@hook{} % \sseq@error@hook is just used once in the isalive error handling to set \protect to relax. Probably a better way to do that... +\def\sseq@errorinfo{% + \sseq@error@annotation + \sseq@printstacktrace +} + + + +\def\sseq@atbeginusermacro@msgsetup{% + \let\protect\empty % prevent issues if protected variables like \xmax are used as the loop max + \let\sseq@error@setup@errorinfo\sseq@error@setup@errorinfo@active % Install foreach error annotations + \let\sseq@error@setup\sseq@error@setup@withinfo + \sseq@opushstacktrace{\the\sseq@thiscalltoks} +} + +\def\sseq@atbeginforeach@msgsetup{% + \let\protect\empty % prevent issues if protected variables like \xmax are used as the loop max + \let\sseq@error@build@foreachvarsinfo\sseq@error@build@foreachvarsinfo@active % Install stack annotation + \let\sseq@error@inforeachloop\sseq@error@inforeachloop@active % install message indicating foreach variable values + \let\sseq@error@setup\sseq@error@setup@withinfo + \sseq@foreachcall{\foreach} % Stack gets pushed at the beginning of the body of the foreach loop once we know what the call looks like +} + + +\def\sseq@error@setup@errorinfo@active{% + \edef\tempa{\the\sseq@thiscalltoks}\edef\tempb{\the\sseq@foreachcall} + \ifx\tempa\tempb % We're at the beginning of a for loop + \sseq@seterrorannotation{atbeginforeach} + \else + \edef\tempb{\the\sseq@topofstacktrace} + \ifx\tempa\tempb % we're at the beginning of a user macro + \sseq@seterrorannotation{atbeginusercmd} + \else + % The top of the stack trace doesn't get included in the stack trace because it is assumed to be + % mentioned in the annotation. Since we aren't at the beginning of the foreach or usercmd, + % that means it won't be mentioned. Push an empty thing onto the stack so the innermost \foreach or usercommand is mentioned. + \sseq@pushstacktrace{} + \fi + \fi +} + + + + + + +%%% +%%% Set up l3msg Hooks +%%% + + +\ExplSyntaxOn +\char_set_catcode_space:N\ % Needed to make pretocmd work -- there are always spaces after every command, and they need to be retokenized as spaces + +\def\sseqerrortowarning#1{ \msg_redirect_name:nnn { sseqpages } { #1 } { warning } } + +\def\sseq@error {\msg_error:nn {sseqpages}} +\def\sseq@error@n {\msg_error:nnn {sseqpages}} +\def\sseq@error@nn {\msg_error:nnnn {sseqpages}} +\def\sseq@error@nnn {\msg_error:nnnnn {sseqpages}} +\def\sseq@error@nnnn{\msg_error:nnnnnn{sseqpages}} +\def\sseq@error@x {\msg_error:nnx {sseqpages}} +\def\sseq@error@xx {\msg_error:nnxx {sseqpages}} +\def\sseq@error@xxx {\msg_error:nnxxx {sseqpages}} +\def\sseq@error@xxxx{\msg_error:nnxxxx{sseqpages}} +\def\sseq@warning {\msg_warning:nn{sseqpages}} + +\def\sseq@newerror#1#2{\msg_new:nnn{sseqpages}{#1}{#2}} +\def\sseq@newerror@internal#1#2{\msg_new:nnn{sseqpages}{#1}{Internal error: #2 \sseq@contactpackageauthor}} +\edef\sseq@contactpackageauthor{Contact package author \sseq@authorname\space at \sseq@authoremail.} + + +\cs_new_eq:NN \__sseq_hooked_msg_see_documentation_text:n \msg_see_documentation_text:n +\cs_new_eq:NN \__sseq_hooked_msg_fatal_code:nnnnnn \__msg_fatal_code:nnnnnn +\cs_new_eq:NN \__sseq_hooked_msg_error_code:nnnnnn \__msg_error_code:nnnnnn +\cs_new_eq:NN \__sseq_hooked_msg_warning_code:nnnnnn \__msg_warning_code:nnnnnn +\cs_new_eq:NN \__sseq_hooked_msg_info_code:nnnnnn \__msg_info_code:nnnnnn + + +\cs_new:Npn \sseq@installmsghooks {% + \cs_set_eq:NN \errmessage \sseq@errmessage + \cs_set_eq:NN \msg_see_documentation_text:n \__sseq_hooked_msg_see_documentation_text:n + \cs_set_eq:NN \__msg_fatal_code:nnnnnn \__sseq_hooked_msg_fatal_code:nnnnnn + \cs_set_eq:NN \__msg_error_code:nnnnnn \__sseq_hooked_msg_error_code:nnnnnn + \cs_set_eq:NN \__msg_warning_code:nnnnnn \__sseq_hooked_msg_warning_code:nnnnnn + \cs_set_eq:NN \__msg_info_code:nnnnnn \__sseq_hooked_msg_info_code:nnnnnn +} + +\sseq@newerror@internal{msg-patch-failed}{Failed to patch the latex 3 message system. The errors will not be as expressive.} + +\def\sseq@msgpatchfailed{ + \msg_error:nn{sseqpages}{msg-patch-failed} + \def\sseq@installmsghooks{} + \sseq@break +} + +\let\sseq@errmessage@std\errmessage +\def\sseq@errmessage#1{\sseq@error@setup\let\\\iow_newline:\sseq@errmessage@std{#1\sseq@error@annotation}\sseq@error@cleanup} + +\pretocmd\__sseq_hooked_msg_see_documentation_text:n{\sseq@errorinfo}{}{\sseq@msgpatchfailed} + + + +\pretocmd\__sseq_hooked_msg_fatal_code:nnnnnn {\sseq@error@setup} {}{\sseq@msgpatchfailed} +\pretocmd\__sseq_hooked_msg_error_code:nnnnnn {\sseq@error@setup} {}{\sseq@msgpatchfailed} +%\pretocmd\__sseq_hooked_msg_warning_code:nnnnnn{\sseq@msg@setup} {}{\sseq@msgpatchfailed} +%\pretocmd\__sseq_hooked_msg_info_code:nnnnnn {\sseq@msg@setup} {}{\sseq@msgpatchfailed} +\apptocmd\__sseq_hooked_msg_fatal_code:nnnnnn {\sseq@error@cleanup}{}{\sseq@msgpatchfailed} +\apptocmd\__sseq_hooked_msg_error_code:nnnnnn {\sseq@error@cleanup}{}{\sseq@msgpatchfailed} +%\apptocmd\__sseq_hooked_msg_warning_code:nnnnnn{\sseq@error@cleanup}{}{\sseq@msgpatchfailed} +%\apptocmd\__sseq_hooked_msg_info_code:nnnnnn {\sseq@error@cleanup}{}{\sseq@msgpatchfailed} + +\sseq@breakpoint + + + +%%%% +%%%% +%%%% Error message definitions +%%%% +%%%% + + +%% +%% +%% checkdefinitions -- patch-failed errors +%% +%% +\@ifpackagelater{tikz}{2015/07/08}{ + \sseq@newerror@internal{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with core features.} + \sseq@newerror@internal{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with \string\circleclasses.} + \sseq@newerror@internal{foreach-patch-failed}{Failed to patch \string\foreach. The errors sseqpages provides will be less comprehensive. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with parts of the error handling system.} + \sseq@newerror@internal{circleclasses-not-provided}{\@nx\circleclasses won't work because your copy of tikz is too new. Instead I'm doing nothing.} +}{ + \sseq@newerror{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with core features. Update tikz!} + \sseq@newerror{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with \string\circleclasses. Update tikz!} + \sseq@newerror{foreach-patch-failed}{Failed to patch \string\foreach. The errors sseqpages provides will be less comprehensive. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with parts of the error handling system.} + \sseq@newerror{circleclasses-not-provided}{\@nx\circleclasses won't work because your copy of tikz is too old. Instead I'm doing nothing. Update tikz!} +} + + +\def\sseq@pgfkeyspatchfailed { + \msg_critical:nn { sseqpages } { pgfkeys-patch-failed } +} + + +\sseq@newerror@internal{this-shouldnt-happen}{This branch of the code should be unreachable. Something really weird has happened. Error occurred in #1.} + +% Convexity thing +\sseq@newerror{clip-not-convex}{The clip you provided to the "clip" option was not convex and the current edge intersects it more than two times. I'm not going to draw it.} + + +%% +%% +%% macromakers +%% +%% +\sseq@newerror{won't-override-builtin}{Macro '#1' is a sseqpages builtin and I won't override it. Try a different name.} +\sseq@newerror{usermacro-not-free}{Macro '#1' has already been defined using \string\DeclareSseqCommand, \string\NewSseqCommand, \string\DeclareSseqGroup, or \string\NewSseqGroup. I am overriding it. If this is what you intended, you should either use \@nx\DeclareSseqGroup or \string\DeclareSseqCommand, which won't complain.} + +\sseq@newerror{macro-patch-failed}{Failed to patch macro '#1'. This is probably some annoying catcode issue. Try \@nx\tracingpatches to see more information about why the patch failed.} +\sseq@newerror{usermacro-unsupported-argument-type}{Unsupported argument type '#1'. All argument types in the 2017/05/29 release of xparse are supported except for v, e, and E.} + +%% +%% +%% parsers +%% +%% +\sseq@newerror{classpattern-already-defined}{Class pattern '#1' already defined. Overwriting it.} +\sseq@newerror{classpattern-unexpected-token}{Unexpected token '#1' in class pattern definition. Skipping the definition.} +\sseq@newerror{classpattern-missing-tokens}{Incomplete class pattern definition. Skipping the definition.} +\sseq@newerror{classpattern-extra-coord-ignored}{Extra coordinate '#1' ignored. You probably forgot a semicolon.} +\sseq@newerror{classpattern-too-few-coords}{Too few coordinates in row #1.} + +\sseq@newerror{classpattern-too-many-classes}{% + Too many classes in position #1. You are trying to add a #2th class, but the current class pattern is "#3" which only defines offset patterns for up to #4 classes. + If you need to have this many classes in this position, you can make your own class pattern with \string\sseqnewclasspattern, but you might want to consider alternatives like using one class to represent multiple generators in some way -- it is hard to make a diagram look good with large numbers of classes in one position.% +} + +\sseq@newerror{invalid-coordinate}{Invalid #1coordinate\sseq@printerrortype.} +\sseq@newerror{no-classes}{No classes yet exist in #1.} +\sseq@newerror{index-too-large}{Index '#1' provided\sseq@printerrortype\ is too large -- only #2 classes exist at position #3.} +\sseq@newerror{undefined-tag}{Index '#1' provided\sseq@printerrortype\ is not a valid integer expression or known tag in position #2.} +\sseq@newerror{class-no-tag}{The class #1 has no tag so I cannot get it.} + +\sseq@newerror{class-extra-coords}{Too many coordinates. Ignoring the extra ones.} +\sseq@newerror{named-coordinate-class}{You can't pass a named coordinate to \string\class.} % Probably not actually possible to obtain this error +\sseq@newerror{d-no-degree}{% + You must specify the degree of your spectral sequence if you want to use the differential command \string\d. + Specify the degree by providing 'degree={f(\#1)}{g(\#1)}' as an option to '\string\begin{sseqdata}', + where f(\#1) and g(\#1) are formulas for the x and y degree of the \#1th page differential.% +} +\sseq@newerror{d-named-coord-two-indexes}{You provided a named class and two indexes, but the named class already comes with an index so you can only provide one more for the target. Ignoring the second index.}% should be a warning +\sseq@newerror{d-target-index-target-coord}{You provided both a target index and a target coordinate, but this overdetermines the differential. Ignoring the target index.} +\sseq@newerror{d-wrong-degree}{Differential does not respect grading. The target should be in position #1 but instead it is #2 in position #3.} + +\sseq@newerror{index-ignored} {The coordinate #1 is not a class, but it has an index '#3'. Ignoring the index and treating it as the literal position #2.} +\sseq@newerror{anchor-ignored} {The coordinate #1 is not a class, but it has an anchor '#3'. Ignoring the anchor and treating it as the literal position #2.} +\sseq@newerror{invalid-tikz-coord}{The coordinate #1 does not refer to a tikz class but its #2 coordinate is not valid \string\pgfmathparse\ input.} + + +%% +%% +%% loadstore +%% +%% +\sseq@newerror{illegal-add-background-mode}{\string#1 occurred in background mode.} % Should be impossible to trigger + +%% +%% +%% keys +%% +%% + +\def\sseq@possiblecurrentvalue{\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi} +\def\sseq@possiblecurrentvaluemean{\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else={\@xp\sseq@macrogobble\meaning\pgfkeyscurrentvalue}\fi} + +\sseq@newerror{option-illegal}{% + You said '#1\sseq@possiblecurrentvalue', but the option '#1' is + illegal in the sseqdata and sseqpage environments#3.% +} +\sseq@newerror{option-illegal-as-global}{% + You passed '#1\sseq@possiblecurrentvalue' as a global option, but option '#1' is illegal as a global option.% +} +\sseq@newerror{option-global-only}{% + You said '#1\sseq@possiblecurrentvaluemean', but the option '#1' is + only allowed as a global option (as in '\string\begin{sseqdata}[#1\sseq@possiblecurrentvaluemean]' + or '\string\begin{sseqpage}[#1\sseq@possiblecurrentvaluemean]').% +} + +% Applies to name and page, and saying "sseqs={name=somename}" is just a bad idea. +\sseq@newerror{option-no-default-allowed}{% + You cannot set a default value for '#1'.% Try \@nx\sseqset{sseqs={#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi}}.% +} +\sseq@newerror{option-tikz-prims-only}{% + You can only use '#1' as an option for tikz primitives, not for \@nx\class, \@nx\replaceclass, \@nx\classoptions, \@nx\d, \@nx\doptions, \@nx\structline, or \@nx\structlineoptions.% +} + +\sseq@newerror{det-one-after-scale}{You cannot use the option '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi' as a global option after using 'xscale', 'yscale', or 'scale'. Please move '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi' before any scaling options.} +\sseq@newerror{negative-scale}{You said '#1scale=#2' as a global option, but scaling by negative numbers is not allowed as a global option. Instead, please use the option '#1mirror', and then scale by the absolute value.} + +\sseq@newerror{illegal-transform}{% + You said '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi', but + no coordinate transforms are allowed in the body of sseqpages or sseqdata other than shifts by unit-free integers + except as options for tikz primitives or for scopes that only contain tikz primitives. If you need a coordinate transformation, + first use the option 'standard parse'.% +} + +\sseq@newerror{unknown-key}{I do not know the key "\pgfkeyscurrentname".} +\sseq@newerror{unknown-global}{Undefined global option '\pgfkeyscurrentname\@xp\ifx\pgfkeyscurrentvalue\pgfkeysnovalue\else=\pgfkeyscurrentvalue\fi'.} + +\sseq@newerror{scope-quotes}{Quotes are not allowed as options to a scope.} +\sseq@newerror{tikz-edge-quotes}{If you want to use quotes on a tikz edge, please provide it directly to the 'to' command e.g., \@nx\draw (0,0) to["hi"] (1,0);} + +\sseq@newerror{change-style-data}{It's pointless to use 'change #1s' in the sseqdata environment. Try '#1s={##1}' instead.} +\sseq@newerror{change-style-standalone}{It's pointless to use 'change #1s' in a standalone sseqpage environment. Try '#1s={##1}' instead.} +\sseq@newerror{page-update-existing}{Option 'update existing' is only for the sseqdata environment.} +\sseq@newerror{page-no-name}{You can't specify a page but no name.} +\sseq@newerror{keep-changes-no-name}{Option 'keep changes' is only for named spectral sequences.} +\sseq@newerror{keep-changes-sseqdata}{Option 'keep changes' is only for the sseqpage environment.} +\sseq@newerror{unknown-grid}{Undefined grid style '#1'.} +\sseq@newerror{unknown-class-pattern}{Unknown class pattern '\sseq@classpattern'.} +\sseq@newerror{class-placement-shift}{Shifts are illegal in the transformations applied in "class placement" key. If you want to shift your nodes, use \string\sseqnewclasspattern.} % #1 <- x shift, #2 <- shift amount +\sseq@newerror{do-command-failed}{\string\sseq@pgfkeysdocommand{#1}{#2} failed.} + +\sseq@newerror{standard-parse}{You cannot use \string#1 inside a scope that has either the background key or coordinate transformations other than integer shifts.} + +%% +%% +%% main +%% +%% + +\sseq@newerror{env-inside-tikz}{#1 environment started inside tikz.} +\sseq@newerror{env-inside-sseq}{#1 environment started inside other sseq environment.} +\sseq@newerror{env-data-no-name}{Every 'sseqdata' environment must have a name. Specify one by saying 'name=your sseq name'.} +\sseq@newerror{env-data-already-exist}{A spectral sequence with the name '#1' already exists; updating it. If you want to add to an already existing spectral sequence, please pass the option 'update existing'.} % warning +\sseq@newerror{env-page-not-exist}{No spectral sequence named '#1' exists. Making a new one.} % warning + + +\sseq@newerror{is-alive-illegal-here}{You can't use \@nx\isalive outside of a page constraint for a tikz primitive.} + +\sseq@newerror{no-range}{Empty spectral sequence. For every spectral sequence you must either specify both the "x range" and "y range" or include at least one +\string\class.} % maybe warning? +\sseq@newerror{index-larger-than-stack}{Index #1 is larger than the current stack depth #2.} +\sseq@newerror{incomplete-tikz}{Incomplete tikz expression. What I have so far is #1 and I am stopping because I ran into #2. You probably forgot a semicolon.} + + +\sseq@newerror{cmdoptions-only}{You can only use the '#1' option with #2, not with #3.} % warning +\sseq@newerror{cmdoptions-without-options}{There is no reason to use \string#1 without giving options.} % warning +\sseq@newerror{cmdoptions-feature-doesn't-exist}{There is no #1 of the form '\sseq@thiscall' so I can't add options to it.} + +\sseq@newerror{classoptions-already-dead}{Generation #1 of the class #2 perished on page #3 so there is no reason to add an option to it on page \sseq@thepage.} +\sseq@newerror{classoptions-not-yet-born}{Generation #1 of the class #2 is not yet present on page \sseq@thepage\ so there is no reason to add an option to it.} +\sseq@newerror{classoptions-page-gen}{Don't use both "page" and "generation" for the same \@nx\classoption command.} % warning +\sseq@newerror{classoptions-class-already-named}{The class \coord\ already is named '\sseq@obj{class.\classname.name}'. Overwriting it. Use \@nx\nameclass if you want to give it a second name.}%warning +\sseq@newerror{doptions-invisible}{Cannot add options to invisible differential.} +\sseq@newerror{doptions-no-effect-on-this-page}{Adding an option to a differential on page #1 when the current page is \sseq@thepage\ and the 'keep changes' option is not present has no effect.} + + +\sseq@newerror{class-tag-already-defined}{A class with tag '#1' is already defined in position #2. Overwriting it.} % warning + +\sseq@newerror{replaceclass-not-dead-yet}{I cannot replace the class at #1 because it seems to be alive and well.} +\sseq@newerror{replaceclass-no-effect-on-this-page}{The class at #1 died on page #2 so replacing it only affects pages after #3, but the current page is \sseq@thepage.} % warning + + + +\sseq@newerror{d-invalid-page}{Invalid page '#1'.} +\sseq@newerror{d-class-already-hit}{% #1 <-#3, #2 <-\csname #3name\endcsname, #3 <- #2, #4 <- \unexpanded\@xpthree{\sseq@obj{\sseq@temp.deathinfo}} + The #1 #2 of differential \sseq@thiscall\ on page #3 has already been the #4. + Use \string\replaceclass#2 before \sseq@thiscall.% +} +\sseq@newerror{d-hit-same-page-replaceclass}{%#1 <- #3, #2 <- \csname #3name\endcsname, #3 <- #2, #3 <-\sseq@obj{#1[\the\sseq@tempcount].deathinfo}, + The #1 #2 of differential \sseq@thiscall\ was the #3. + If multiple differentials touch a class on the same page, they cannot be separated by a \@nx\replaceclass command.% +} +\sseq@newerror{d-hit-wrong-order}{% + The #1 #2 of differential \sseq@thiscall\ on page #3 has already been the #4. + First use the shorter differential, then \string\replaceclass#2, then the longer differential.% +} + + +\sseq@newerror{structline-no-page-max}{You cannot provide \@nx\structline with the option "page=min--max", only with "page=min".} %warning +\sseq@newerror{structline-already-exists}{Cannot add a structline from #1 to #2 because such a structline already exists.} +\sseq@newerror{structline-stillborn}{Structline dies before it is born. Perhaps you meant to specify a different source or target?} + + +\ExplSyntaxOff diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex new file mode 100644 index 00000000000..cbce7c25492 --- /dev/null +++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex @@ -0,0 +1,1324 @@ +%% +%% Package: spectralsequences.sty version 1.0 +%% Author: Hood Chatham +%% Email: hood@mit.edu +%% Date: 2017-06-18 +%% License: Latex Project Public License +%% +%% File: sseqparsers.code.tex +%% +%% Defines the parsers and input sanitizers. Also handles tikz primitive parsing and \isalive. +%% ExplSyntaxOn for this whole file! + +\ExplSyntaxOn + + +% Prevent \protect from causing trouble for \pgfmathparse +\let\sseq@pgfmathparse@orig\pgfmathparse +\def\sseq@pgfmathparse#1{\let\@@protect\protect\def\protect{}\sseq@pgfmathparse@orig{#1}\restore@protect} + + +%%% ifpgfmathexpr +% #1 -- expresion to test +% #2 -- true case +% #3 -- false case +% This tests true if \pgfmathparse{#1} throws an error or not. Luckily, \pgfmathparse pipes its errors through \pgfmath@error so this is easy. +\def\sseq@ifpgfmathexpr#1{ + \bgroup + \let\protect\pgfutil@empty + \global\sseq@gtempiftrue + \def\pgfmath@error##1##2{\global\sseq@gtempiffalse} + \pgfmathparse{#1} + \ifpgfmathunitsdeclared + \xdef\sseq@mathresult{\pgfmathresult pt} + \else + \xdef\sseq@mathresult{\pgfmathresult} + \fi + \egroup + \ifsseq@gtempif + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi +} + + +% Test if single token input is a digit +\def\sseq@ifdigit#1{ + \ifodd0 + \ifx#1 0 1 \else + \ifx#1 1 1 \else + \ifx#1 2 1 \else + \ifx#1 3 1 \else + \ifx#1 4 1 \else + \ifx#1 5 1 \else + \ifx#1 6 1 \else + \ifx#1 7 1 \else + \ifx#1 8 1 \else + \ifx#1 9 1 \else + \fi \fi \fi \fi \fi + \fi \fi \fi \fi \fi + \relax + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi +} + +%%% ifintexpr +% #1 -- expresion to test +% #2 -- true case +% #3 -- false case +% This tests true if \numexpr #1\relax throws no error and consumes all of #1 and false otherwise. + +% Spaces matter to us, because \sseq@ifintexpr{1 1} is false but \sseqsifintexpr{11} is true +% so we make spaces into catcode other and use \scantokens +\def\sseq@ifintexpr#1{% + \bgroup + \char_set_catcode_other:N \ % + \sseq@tempcount\z@ + \makeatletter + \scantokens{\sseq@ifintexpr@first{needsint}#1\sseq@nil}% + \@xp\egroup\next +} +\@xp\let\@xp\sseq@otherspace\c_catcode_other_space_tl % This has to be a let, no idea why +%\def\sseq@ifintexpr#1{\@firstoftwo} + +% Gobble the space of catcode other that scantokens inserts after \sseq@ifintexpr@first +\def\sseq@ifintexpr@first#1#2{\sseq@ifintexpr@{#2}} + +% We need to use \futurelet so that we can detect open braces even when they only surround one token like {1} +% so we have to store the state in \sseq@ifintexpr@state + +\def\sseq@ifintexpr@#1{\def\sseq@ifintexpr@state{#1}\futurelet\testtok\sseq@ifintexpr@@} +\def\sseq@ifintexpr@@{% + \ifx\testtok\bgroup% + \let\next\sseq@ifintexpr@false + \else + \ifx\testtok\sseq@nil + \@xp\let\@xp\next\csname sseq@ifintexpr@@\sseq@ifintexpr@state @done\endcsname + \else + % Even though I \let \sseq@otherspace to a space of catcode other up there, + % I still need this freaking expandafter here. God only knows why. Figured this out by trial and error. + % We need to check here for a space because \string<space> produces NO OUTPUT regardless of the catcode of the space. + % This fucks over \sseq@ifintexpr@@@ real hard because it doesn't expect \string#1 to produce no characters. + \@xp\ifx\sseq@otherspace\testtok + \def\next{\sseq@ifintexpr@next{~}\@xp\next\@gobble} + \else + \let\next\sseq@ifintexpr@@@ + \fi + \fi + \fi + \next +} + +\def\sseq@ifintexpr@@@#1{ + \ifcat$\@xp\@gobble\string#1$% + \@xp\sseq@ifintexpr@@@@\@xp#1 + \else + % scantokens puts an extra space character after control sequences, so to give them the best shot at working, eat that space character + % Then use f expansion. + \@xp\@xp\@xp\sseq@ifintexpr@@@fexpcs\@xp\@xp\@xp#1\@xp\@gobble + \fi +} + +% Unfortunately, if we have a macro that takes an argument inside another macro that takes an argument, this will fail (the inside macro will get a space) but such is life. +\def\sseq@ifintexpr@@@fexpcs{\exp_last_unbraced:Nf\sseq@ifintexpr@@@fexpcs@} +\def\sseq@ifintexpr@@@fexpcs@{\futurelet\testtok\sseq@ifintexpr@@@fexpcs@@} +\def\sseq@ifintexpr@@@fexpcs@@{ + \ifx\testtok\bgroup + \@xp\sseq@ifintexpr@false + \else + \@xp\sseq@ifintexpr@@@@ + \fi +} + + + +%\exp_last_unbraced:Nf\sseq@ifintexpr@@ + + +% We can't just use \futurelet because "\let\testtok(" makes \testtok unexpandable +% (I guess that makes sense, but why is it that I need \@xp\ifx\otherspace above if I've also \let\otherspace to a character? Mysterious...), +% so then "\csname hello\testtok\endcsname" is an error. This indexes into our state machine, +% cases: a digits, + or -, * or /, (, ), or something else (anything else always leads to false +\def\sseq@ifintexpr@@@@#1{% + \ifx#1\sseq@nil + \def\next{\csname sseq@ifintexpr@@\sseq@ifintexpr@state @done\endcsname\sseq@nil}% + \else + \sseq@ifdigit{#1}% + {\sseq@ifintexpr@next{digit}}% + {% + \ifx#1+% + \sseq@ifintexpr@next{+-} + \else + \ifx#1-% + \sseq@ifintexpr@next{+-} + \else + \ifx#1*% + \sseq@ifintexpr@next{*/} + \else + \ifx#1/% + \sseq@ifintexpr@next{*/} + \else + \pgfutil@ifundefined{sseq@ifintexpr@@\sseq@ifintexpr@state @#1}% + {\let\next\sseq@ifintexpr@false}% + {\sseq@ifintexpr@next{#1}}% + \fi + \fi + \fi + \fi + }% + \fi + \next +} + +% This has to eat the space +%\bgroup\lccode`\*=`\ \lowercase{\egroup + \def\sseq@ifintexpr@true#1\sseq@nil{\ifnum\sseq@tempcount=\z@ \let\next\@firstoftwo\else\let\next\@secondoftwo\fi} + \def\sseq@ifintexpr@false#1\sseq@nil{\let\next\@secondoftwo} +%} +\def\sseq@makeifint#1#2#3{\@xp\def\csname sseq@ifintexpr@@#1@#2\endcsname{#3}} +\def\sseq@ifintexpr@next#1{\@xp\let\@xp\next\csname sseq@ifintexpr@@\sseq@ifintexpr@state @#1\endcsname} + +\sseq@makeifint{needsint}{done}{\sseq@ifintexpr@false} +\sseq@makeifint{needsint}{digit}{\sseq@ifintexpr@{int}} +\sseq@makeifint{needsint}{*/}{\sseq@ifintexpr@false} +\sseq@makeifint{needsint}{+-}{\sseq@ifintexpr@{needsint}} +\sseq@makeifint{needsint}{(}{\advance\sseq@tempcount\@ne\sseq@ifintexpr@{needsint}} +\sseq@makeifint{needsint}{)}{\sseq@ifintexpr@false} +\sseq@makeifint{needsint}{\space}{\sseq@ifintexpr@{needsint}} + +\sseq@makeifint{int}{done}{\sseq@ifintexpr@true} +\sseq@makeifint{int}{digit}{\sseq@ifintexpr@{int}} +\sseq@makeifint{int}{*/}{\sseq@ifintexpr@{needsint}} +\sseq@makeifint{int}{+-}{\sseq@ifintexpr@{needsint}} +\sseq@makeifint{int}{(}{\sseq@ifintexpr@false} +\sseq@makeifint{int}{)}{ + \advance\sseq@tempcount\m@ne + \ifnum\sseq@tempcount<\z@\relax + \@xp\@xp\@xp\sseq@ifintexpr@false\@xp\@gobble + \else + \@xp\sseq@ifintexpr@ + \fi{nointallowed} +} +\sseq@makeifint{int}{\space}{\sseq@ifintexpr@{nointallowed}} + +\sseq@makeifint{nointallowed}{done}{\sseq@ifintexpr@true} +\sseq@makeifint{nointallowed}{digit}{\sseq@ifintexpr@false} +\sseq@makeifint{nointallowed}{*/}{\sseq@ifintexpr@{needsint}} +\sseq@makeifint{nointallowed}{+-}{\sseq@ifintexpr@{needsint}} +\sseq@makeifint{nointallowed}{(}{\sseq@ifintexpr@false} +\sseq@makeifint{nointallowed}{)}{ + \advance\sseq@tempcount\m@ne + \ifnum\sseq@tempcount<\z@ + \@xp\@xp\@xp\sseq@ifintexpr@false\@xp\@gobble + \else + \@xp\sseq@ifintexpr@ + \fi{nointallowed} +} +\sseq@makeifint{nointallowed}{\space}{\sseq@ifintexpr@{nointallowed}} + +%% +%% +%% New Class Pattern +%% +%% + +\newcount\sseq@cp@row +\newcount\sseq@cp@n + +\def\sseqnewclasspattern#1#2{ + \ifcsname sseq@#1xoffset1/1\endcsname\sseq@error@n{classpattern-already-defined}{#1}\fi % could be a warning + \begingroup + \def\sseq@name{#1} + \def\sseq@temp{} + \def\sseq@state{nocoord} + \sseq@cp@row=\@ne + \sseq@cp@n=\z@ + \let\next\sseq@newclasspattern@ + \sseq@newclasspattern@#2\sseq@nil +} + +\def\sseq@newclasspattern@{ + \@ifnextchar\bgroup{\sseq@error@n{classpattern-unexpected-token}{\{}}{\sseq@newclasspattern@processstate} +} + +\def\sseq@newclasspattern@processstate{ + \csname sseq@newclasspattern@processstate@\sseq@state\endcsname +} + +\def\sseq@newclasspattern@processstate@xcoord#1{ + \ifx#1, + \sseq@ifpgfmathexpr{\sseq@temp}{ + \let\sseq@tempx\sseq@mathresult + \def\sseq@temp{} + \def\sseq@state{ycoord} + }{ + \sseq@error{classpattern-not-integer-expression} + \let\next\sseq@newclasspattern@abort + } + \else + \ifx#1\sseq@nil + \sseq@error{classpattern-missing-tokens} + \let\next\endgroup + \else + \sseq@d@addto@macro\sseq@temp{#1} + \fi + \fi + \next +} + +\def\sseq@newclasspattern@processstate@ycoord#1{ + \ifx#1) + \sseq@ifpgfmathexpr{\sseq@temp}{% Need iffloatexpr =( + \let\sseq@tempy\sseq@mathresult + \def\sseq@temp{} + \def\sseq@state{nocoord} + \advance\sseq@cp@n\@ne + \ifnum\sseq@cp@n>\sseq@cp@row\relax + \sseq@error@x{classpattern-extra-coord-ignored}{(\sseq@tempx,\sseq@tempy)} + \else + \sseq@e@addto@macro\sseq@newclasspattern@dodefs{ + \def\@xp\@nx\csname sseq@\sseq@name xoffset\the\sseq@cp@n/\the\sseq@cp@row\endcsname{\sseq@tempx} + \def\@xp\@nx\csname sseq@\sseq@name yoffset\the\sseq@cp@n/\the\sseq@cp@row\endcsname{\sseq@tempy} + } + \fi + }{ + \sseq@error{classpattern-not-integer-expression} + \let\next\sseq@newclasspattern@abort + } + \else + \ifx#1\sseq@nil + \sseq@error{classpattern-missing-tokens} + \let\next\endgroup + \else + \sseq@d@addto@macro\sseq@temp{#1} + \fi + \fi + \next +} + +\def\sseq@newclasspattern@processstate@nocoord#1{ + \ifx#1( + \def\sseq@state{xcoord} + \else + \ifx#1; + \ifnum\sseq@cp@n=\sseq@cp@row\relax + \advance\sseq@cp@row\@ne + \sseq@cp@n=\z@ + \else + \sseq@error@x{classpattern-too-few-coords}{\the\sseq@cp@row} + \let\next\sseq@newclasspattern@abort + \fi + \else + \ifx#1\sseq@nil + \let\next\sseq@newclasspattern@finish + \else + \sseq@error@n{classpattern-unexpected-token}{#1} + \let\next\sseq@newclasspattern@abort + \fi + \fi + \fi + \next +} + +\def\sseq@newclasspattern@finish{ + \ifnum\sseq@cp@n=\z@\relax + \advance\sseq@cp@row\m@ne + \else + \ifnum\sseq@cp@n=\sseq@cp@row\relax\else + \sseq@error@x{classpattern-too-few-coords}{\the\sseq@cp@row} + \let\sseq@newclasspattern@dodefs\empty + \fi + \fi + % This will make a definition even if the class pattern was rejected because of the too-few-coords error + % It doesn't matter though, because we don't use this to check for existence + \sseq@e@addto@macro\sseq@newclasspattern@dodefs{% + \chardef\@xp\@nx\csname sseq@\sseq@name @maxclasses\endcsname=\the\sseq@cp@row\relax + }% + \@xp\endgroup + \sseq@newclasspattern@dodefs + + +} +\def\sseq@newclasspattern@dodefs{} +\def\sseq@newclasspattern@abort#1\sseq@nil{\endgroup} + + + + +%%%%%% %%%%%% +%% %% +%% Coordinate Parsers %% +%% %% +%%%%%% %%%%%% + +% Only works for full coordinates. Used for error checking in \replaceclass and \d. +\def\sseq@ifundefcoord{\@xp\sseq@ifundefcoord@} +\def\sseq@ifundefcoord@(#1){% + \sseq@obj@ifundef{class.(#1).num}% +} + +\def\sseq@ifdead#1{\ifnum\sseq@obj{class.#1[\sseq@obj{class.#1.num}].page}<\sseq@infinitycount\@xp\@firstoftwo\else\@xp\@secondoftwo\fi} + + +% These do all of the work of taking a coordinate of the form (x,y), (x,y,n), or (x,y,tag) and turning them +% into the internal representation needed for the rest of the package. +% This comes in two parts: +% \sseq@parsecoord@maincoord -- separates a coordinate into {x,y}{n or tag}, numerically evaluates x and y, and adds in the values of \sseq@x and \sseq@y +% \sseq@parsecoord@index -- decides which class {n or tag} represents +% +% There are three interface commands: +% \sseq@parsecoord -- for most things +% \sseq@cparsecoord -- for \class (but not for \replaceclass or \classoptions). Doesn't use \sseq@parsecoord@index at all. +% \sseq@dparsecoord -- for \d and \doptions +% \sseq@parsecoordex -- for \isalive: the body of a page constraint needs to be \edef'd so we need a completely expandable version. +% The expandable version doesn't have any error checking -- to get the error checking, we pass the coordinates once through the unexpandable version +% inside of an hbox. + +\def\sseq@errortype{} +\def\sseq@printerrortype{\@xp\sseq@ifempty\@xp{\sseq@errortype}{}{~ for ~ \sseq@errortype}} + +%% Pulls off x,y and evaluates them, puts n or empty into a separate variable. +% #1 -- a coordinate of the form {x,y} or {x,y,stuff} +\let\sseq@relax\relax +% The \sseq@relax is just to make \lastclass work. It has to pull an argument off the token stream to expandably check whether +% it is an integer. However, without this \sseq@relax, \lastclass could appear as the last token of the edef, which is no good. +\def\sseq@parsecoord@maincoord#1{\exp_last_unbraced:Nx\sseq@parsecoord@maincoord@{#1\sseq@relax}} +\def\sseq@parsecoord@maincoord@#1\sseq@relax{% + \pgfutil@in@ \sseq@protecterror { #1 } + \ifpgfutil@in@ + \bgroup + \sseq@restorefont + \let\sseq@protecterror\relax + \setbox0=\hbox{#1} % Trigger the error message + \egroup + \@xp\sseq@break + \else + \pgfutil@in@,{#1} + \ifpgfutil@in@ + \sseq@parsecoord@maincoord@@#1,\sseq@nil + \else + \sseq@obj@ifdef{class.namedclass.\detokenize{#1}}{ + \def\sourcename{#1} + \@xpthree\sseq@parsecoord@maincoord@named\sseq@obj{class.namedclass.#1}\sseq@nil + }{ + \sseq@error{invalid-coordinate}\sseq@breakfifi + } + \fi + \fi +} + +\def\sseq@parsecoord@maincoord@@#1,#2,#3\sseq@nil{% + \sseq@obj@ifdef{class.namedclass.\detokenize{#1}}{ + \def\sourcename{#1} + \@xpthree\sseq@parsecoord@maincoord@named\sseq@obj{class.namedclass.#1}\sseq@nil + \edef\sseq@restcoord{\sseq@removecomma#2,#3\sseq@nil} + }{ + \sseq@ifintexpr{#1}{ + \sseq@ifintexpr{#2}{}{\sseq@error@n{invalid-coordinate}{y }\sseq@breakfifi} % breakfifi to get out of ifs from maincoord@ + \edef\sseq@xcoord{\the\numexpr\sseq@x+(#1)\relax}% + \edef\sseq@ycoord{\the\numexpr\sseq@y+(#2)\relax}% + \edef\sseq@xycoord{\sseq@xcoord,\sseq@ycoord}% + \sseq@ifempty{#3}{\let\sseq@restcoord\pgfutil@empty}{% + \edef\sseq@restcoord{\sseq@removecomma#3\sseq@nil}% + }% + }{ + \sseq@error@n{invalid-coordinate}{x }\sseq@breakfifi % breakfifi to get out of ifs from maincoord@ + } + }% +}% + +\def\sseq@parsecoord@maincoord@named#1,#2,#3\sseq@nil{ + \def\sseq@xcoord{#1}% + \def\sseq@ycoord{#2}% + \edef\sseq@xycoord{\sseq@xcoord,\sseq@ycoord} + \def\sseq@restcoord{} + \pgfkeys@spdef\sseq@rawindex{#3} + \def\sseq@index{#3} + \let\rawindex\sseq@rawindex + \let\index\sseq@index +} + +\def\sseq@removecomma#1,\sseq@nil{#1} + + +% "Input" to this command is stored in the following commands: +% \sseq@xycoord -- x,y +% \sseq@rawindex -- n +% \sseq@errortype -- description for error messages +\def\sseq@errortype@tikzprim{tikz ~ primitive}% This is sort of a silly hack, but this first error check shouldn't happen in a tikz primitive. +\def\sseq@parsecoord@index{% + \sseq@obj@ifundef{partcoord.(\sseq@xycoord).numnodes}{ + \ifx\sseq@errortype\sseq@errortype@tikzprim + \def\sseq@index{}% Communicates to \sseq@tikzprimitives@coords@maybeclass that this is not a class + \else + \sseq@error@x{no-classes}{(\sseq@xycoord)}\@xp\sseq@break + \fi + }{ + \ifx\sseq@rawindex\pgfutil@empty + \def\sseq@index{1} + \else + \sseq@obj@ifdef{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@rawindex}{% If the raw index is a tag + \edef\sseq@index{\sseq@obj{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@rawindex}} + }{% + \sseq@ifintexpr{\sseq@rawindex}{% + \edef\sseq@rawindexeval{\the\numexpr\sseq@rawindex} + \ifnum\sseq@rawindexeval<\z@% + \edef\sseq@index{\the\numexpr\sseq@obj{partcoord.(\sseq@xycoord).numnodes} + \sseq@rawindex + \@ne\relax}% + \ifnum\sseq@index<\@ne + \sseq@error@xxx{index-too-large}{\sseq@rawindex}{\sseq@obj{partcoord.(\sseq@xycoord).numnodes}}{(\sseq@xycoord)}% + \edef\sseq@index{1}% or maybe I should break? + \fi + \else + \ifnum\sseq@rawindexeval>\sseq@obj{partcoord.(\sseq@xycoord).numnodes}\relax + \sseq@error@xxx{index-too-large}{\sseq@rawindex}{\sseq@obj{partcoord.(\sseq@xycoord).numnodes}}{(\sseq@xycoord)}% + \edef\sseq@rawindex{\sseq@obj{partcoord.(\sseq@xycoord).numnodes}}% or maybe I should break? + \fi + \edef\sseq@index{\the\numexpr\sseq@rawindex} + \fi + }{ + \sseq@error@xx{undefined-tag}{\sseq@rawindex}{(\sseq@xycoord)}% + \def\sseq@index{1}% + } + } + \fi + } +} + +% #1 -- name to define +% #2 -- coordinate +% #3 -- the error message +\def\sseq@parsecoord#1#2#3{% + \def\sseq@index{} + \def\sseq@errortype{#3} + \sseq@parsecoord@maincoord{#2}% + \let\sseq@rawindex\sseq@restcoord + \ifx\sseq@index\pgfutil@empty + \@xp\sseq@parsecoord@index + \fi + \@xp\let\csname x\sseq@macroname#1\endcsname\sseq@xcoord + \@xp\let\csname y\sseq@macroname#1\endcsname\sseq@ycoord + \@xp\let\csname \sseq@macroname#1@partial\endcsname\sseq@xycoord + \edef#1{(\sseq@xycoord,\sseq@index)}% + \@xp\edef\csname\sseq@macroname#1nopar\endcsname{\sseq@xycoord,\sseq@index} + \@xp\def\csname\sseq@macroname#1name\endcsname{(#2)}% + \@xp\def\csname\sseq@macroname#1nameunbraced\endcsname{#2}% + \@xp\edef\csname\sseq@macroname#1@internalname\endcsname{sseq{\sseq@xycoord,\sseq@index}}% +} + +% EXPOSE: a wrapper around \sseq@parsecoord. Use full name of coordinate to avoid name class with sseq@parsecoord. +\sseq@DeclareDocumentCommand \parsecoordinate { m r() }{% + \sseq@parsecoord{#1}{#2}{call of \string\parsecoord}% +} + +% #1 -- coordinate +\def\sseq@cparsecoord#1{% + \def\sseq@index{} + \sseq@parsecoord@maincoord{#1}% + \ifx\sseq@index\pgfutil@empty\else\sseq@error{named-coordinate-class}\fi% probably not possible to get this error + \ifx\sseq@restcoord\pgfutil@empty\else\sseq@error{class-extra-coords}\fi% + \let\partialcoord\sseq@xycoord + \let\xcoord\sseq@xcoord + \let\ycoord\sseq@ycoord + \edef\nodenum{\sseq@obj@ifundef{partcoord.(\partialcoord).numnodespp}{1}{\sseq@obj{partcoord.(\partialcoord).numnodespp}}}% + \edef\coordnopar{\xcoord,\ycoord,\nodenum} + \edef\coord{(\coordnopar)}% +} + + +% #1 -- page +% #2 -- coordinate +% #3 -- target coordinate or "No Value" +\def\sseq@dparsecoord#1#2#3{% + \def\sseq@index{}% + \def\sseq@errortype{differential}% + \sseq@parsecoord@maincoord{#2}% + \ifx\sseq@index\pgfutil@empty + \edef\sseq@rawsindex{\@xp\sseq@dparsecoord@getxindex\@xp{\sseq@restcoord}}% + \@xp\pgfkeys@spdef\@xp\sseq@rawsindex\@xp{\sseq@rawsindex} + \edef\sseq@rawtindex{\@xp\sseq@dparsecoord@getyindex\@xp{\sseq@restcoord}}% + \@xp\pgfkeys@spdef\@xp\sseq@rawtindex\@xp{\sseq@rawtindex} + % + \let\sseq@rawindex\sseq@rawsindex + \def\sseq@errortype{source ~ of ~ differential} + \@xp\sseq@parsecoord@index % the \@xp is needed so that \sseq@break inside of parsecoordindex works properly. + \else + \edef\sseq@rawtindex{\@xp\sseq@dparsecoord@getxindex\@xp{\sseq@restcoord}}% + \@xp\pgfkeys@spdef\@xp\sseq@rawtindex\@xp{\sseq@rawtindex} + \edef\sseq@shouldbeempty{\@xp\sseq@dparsecoord@getyindex\@xp{\sseq@restcoord}} + \ifx\sseq@shouldbeempty\pgfutil@empty\else + \sseq@error{d-named-coord-two-indexes} + \fi + \fi + \let\sourcecoord\sseq@xycoord + \edef\source{(\sseq@xycoord,\sseq@index)}% + \ifx\sourcename\undefined + \edef\sourcename{(\sseq@xycoord\ifx\sseq@rawindex\pgfutil@empty\else,\sseq@rawindex\fi)} + \fi + \IfNoValueTF{#3}{ + \ifsseq@hasdegree\else\sseq@error{d-no-degree}\@xp\sseq@break\fi + \sseq@eval{\edef\@nx\sseq@xycoord{\@nx\sseq@differential@gettarget{#1}{\sseq@xycoord}}} + \let\sseq@rawindex\sseq@rawtindex + \def\sseq@errortype{target ~ of ~ differential} + \sseq@parsecoord@index + \let\targetcoord\sseq@xycoord + \edef\target{(\sseq@xycoord,\sseq@index)}% + \edef\targetname{(\sseq@xycoord\ifx\sseq@rawindex\pgfutil@empty\else,\sseq@rawindex\fi)} + }{ + \ifx\sseq@rawtindex\pgfutil@empty\else + \sseq@error{d-target-index-target-coord} + \fi + \sseq@parsecoord\target{#3}{differential} + \let\targetcoord\target@partial + \ifsseq@hasdegree + \ifsseq@strictdegree + \sseq@eval{\edef\@nx\sseq@checktarget{\@nx\sseq@differential@gettarget{#1}{\sourcecoord}}} + \ifx\sseq@checktarget\targetcoord\else + \sseq@error@xxx{d-wrong-degree}{(\sseq@checktarget)}{\targetname}{(\targetcoord)} + \fi + \fi + \fi + } +} + +\def\sseq@differential@gettarget#1#2{\sseq@differential@gettarget@{#1}#2\sseq@nil} +\def\sseq@differential@gettarget@#1#2,#3\sseq@nil{\the\numexpr#2+\sseq@targetx{#1}\relax,\the\numexpr#3+\sseq@targety{#1}\relax} + +\def\sseq@getfirsttwoelts#1,#2,#3\sseq@nil{#1,#2} +\def\sseq@getdtarget#1#2#3{\sseq@eval{\edef\@nx#1{\@nx\sseq@differential@gettarget{#2}{\sseq@getfirsttwoelts#3,,\sseq@nil}}}} + +% Takes a comma separated list that can be empty, have one element, or two elements, returns first element (or empty if list is empty). +\def\sseq@dparsecoord@getxindex#1{\sseq@dparsecoord@getxindex@#1,\sseq@nil} +\def\sseq@dparsecoord@getxindex@#1,#2\sseq@nil{#1} +% Takes a comma separated list that can be empty, have one element, or two elements, returns second element (or empty if less than two elements). +\def\sseq@dparsecoord@getyindex#1{\sseq@dparsecoord@getyindex@#1,\sseq@nil} +\def\sseq@dparsecoord@getyindex@#1,#2\sseq@nil{% + \sseq@ifempty{#2}{}{% + \sseq@removecomma#2\sseq@nil% + }% +} + +\def\sseq@parsecoordinate#1#2{% + \sseq@parsecoord{#1}{#2}{call of \string\parsecoord}% +} + + +% EXPOSE: a wrapper around \sseq@parsecoord. Use full name of coordinate to avoid name class with sseq@parsecoord. +\sseq@DeclareDocumentCommand \parsedifferential { m r() }{% + \sseq@dparsecoord{#1}{#2}{call of \string\parsecoord}% +} + +% Expandable coordinate parsing for \isalive. +% Doesn't do any error checking -- the error checking is done by passing it through \sseq@parsecoord in a non-\edef context. +% #1 -- a callback. Must be a single command b/c it's an N in \exp_args +% #2 -- the coordinate +\cs_new:Npn \exp_last_unbraced:NNNf #1#2#3#4 + { + \exp_after:wN #1 + \exp_after:wN #2 + \exp_after:wN #3 \tex_romannumeral:D -`0 #4 + } + +\def\sseq@parsecoordex{\exp_last_unbraced:NNNf\sseq@parsecoordex@} +\def\sseq@parsecoordex@#1(#2){\sseq@parsecoordex@@#1#2,\@nil} +\def\sseq@parsecoordex@@#1#2,#3,#4\@nil{ + \ifx& + \exp_last_unbraced:NNo\sseq@parsecoord@indexex#1(\the\numexpr#2\@xp,\the\numexpr#3,1) + \else + \exp_args:NNo\sseq@parsecoord@indexex#1{\the\numexpr#2\@xp,\the\numexpr#3\@xp\relax\@xp}\@xp{\sseq@removecomma#4\sseq@nil} + \fi +} + + +% This is \sseq@parsecoord@index pared down as much as possible -- all error checking is removed because that will happen in a +% \setbox0=\hbox{stuff} sequestered calculation that uses \sseq@parsecoord@index instead. +% #1 -- callback which takes one argument -- the final coordinate in parentheses. +% #2 -- x,y +% #3 -- n +\def\sseq@parsecoord@indexex#1#2#3{% + \sseq@obj@ifdef{partcoord.(#2).tag.\sseq@class@tagprefix#3}{% If the raw index is a tag + \exp_args:NNo\sseq@parsecoord@indexex@#1{\the\numexpr\sseq@obj{partcoord.(#2).tag.\sseq@class@tagprefix#3}}{#2}% + }{% + \ifnum\numexpr#3<0\space + \exp_args:NNo\sseq@parsecoord@indexex@#1{\the\numexpr\sseq@obj{partcoord.(#2).numnodes} + #3 + 1}{#2}% + \else + \exp_args:NNo\sseq@parsecoord@indexex@#1{\the\numexpr#3}{#2}% + \fi + }% +} +\def\sseq@parsecoord@indexex@#1#2#3{ + #1(#3,#2) +} + + + + +%%% +%%% The Stack +%%% + +\sseq@addtostorelistlet\sseq@stacktop\relax +\def\sseq@stackitem#1#2#3{\csname sseq.\sseq@thename.stack.#1.#3\endcsname} % gobble #2 which we added in for the error message +\def\sseq@getstackentry#1{ + \exp_args:No\sseq@getstackentry@{\sseq@stacktop}{#1}{#1} % Second copy of #1 for error message +} + +\def\sseq@getstackentry@#1#2{ + \ifnum#2=\z@\@xp\@firstoftwo\else\@xp\@secondoftwo\fi + {\sseq@stackitem{#1}} + {\@ifundefined{sseq.\sseq@thename.stack.#1.next}{\sseq@getstackentry@indextoolarge}{ + \exp_args:Nf\sseq@getstackentry@{\csname sseq.\sseq@thename.stack.#1.next\@xp\endcsname\@xp}\@xp{\the\numexpr#2-1} + }} +} + +\def\sseq@getstackentry@indextoolarge#1{\sseq@protecterror{\sseq@error@xx{index-larger-than-stack}{#1}{\the\sseq@stackdepth}}} + +\def\sseq@pushstack(#1){ + \bgroup + \sseq@parsecoord\temp{#1}{} + \sseq@pushstack@\temp + \egroup +} + +\def\sseq@pushstack@{\@xp\sseq@pushstack@@} + +\def\sseq@pushstack@@(#1,#2,#3){ + \global\advance\sseq@stackdepth\@ne + \@xp\gdef\csname sseq.\sseq@thename.stack.\the\sseq@stackdepth.lastx\endcsname{#1} + \@xp\gdef\csname sseq.\sseq@thename.stack.\the\sseq@stackdepth.lasty\endcsname{#2} + \@xp\xdef\csname sseq.\sseq@thename.stack.\the\sseq@stackdepth.lastclass\endcsname{lastclass.\the\sseq@stackdepth} + \sseq@obj@gdef{class.namedclass.lastclass.\the\sseq@stackdepth}{#1,#2,#3} + \global\@xp\let\csname sseq.\sseq@thename.stack.\the\sseq@stackdepth.next\endcsname\sseq@stacktop + \xdef\sseq@stacktop{\the\sseq@stackdepth} +} + + +\newcount\sseq@userstacksavecount +\def\sseq@savestack{ + \global\advance\sseq@userstacksavecount\@ne + \sseq@savestack@name{usersave@\the\sseq@userstacksavecount} +} +\def\sseq@restorestack{ + \sseq@restorestack@name{usersave@\the\sseq@userstacksavecount} + \global\advance\sseq@userstacksavecount\m@ne +} + +\def\sseq@savestack@name#1{\sseq@obj@xdef{stack.save#1}{\sseq@stacktop}} + +\def\sseq@restorestack@name#1{\xdef\sseq@stacktop{\sseq@obj{stack.save#1}}} + +\def\sseq@lastx#1{ + % \romannumeral is testing here whether #1 is a nonnegative integer + % if #1 consists of a single nonnegative integer then -0#1 will be turned into some nonpositive integer + % and romannumeral produces no output when handed a nonpositive integer, so the result will be empty. + % If #1 has any nonnumerical tokens or is negative, there will be left over stuff. + \@xp\sseq@ifempty\@xp{\romannumeral-0#1}{ + \sseq@getstackentry{#1}{lastx} + }{ + \sseq@getstackentry{0}{lastx}#1 % #1 isn't a number so put it back + } +} +\def\sseq@lasty#1{ + \@xp\sseq@ifempty\@xp{\romannumeral-0#1}{ + \sseq@getstackentry{#1}{lasty} + }{ + \sseq@getstackentry{0}{lasty}#1 % #1 isn't a number so put it back + } +} + +\def\sseq@lastclass#1{ + \@xp\sseq@ifempty\@xp{\romannumeral-0#1}{ + \sseq@getstackentry{#1}{lastclass} + }{ + \sseq@getstackentry{0}{lastclass}#1 % #1 isn't a number so put it back + } +} + + +\def\sseq@nameclass#1(#2){ + \bgroup + \sseq@parsecoord\coord{#2}{} + \sseq@cleanup@obj{class.namedclass.#1} + \sseq@obj@xdef{class.namedclass.#1}{\coordnopar} + \egroup +} + +\def\sseq@tagclass#1(#2){% + \bgroup + \sseq@parsecoord\coord{#2}{}% + \sseq@obj@ifdef{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}{% + \sseq@error@nn{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{(\sseq@xycoord)}% could be warning + }% + \sseq@cleanup@obj{class.\coord.tag}% + \sseq@obj@xdef{class.\coord.tag}{\sseq@class@tagprefix\sseq@class@tag}% + \sseq@cleanup@obj{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}% + \sseq@obj@xdef{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\sseq@index}% + \egroup +} + +\def\sseq@gettag#1(#2){ + \bgroup + \sseq@parsecoord\coord{#2}{} + \sseq@obj@ifdef{class.\coord.tag}{ + \xdef#1{\sseq@obj{class.\coord.tag}} + }{ + \sseq@error@n{class-no-tag}{(#2)} + } + \egroup +} + + + + + +%%%%%% +%%% +%%% Tikz Primitives +%%% +%%%%%% + +% Replace a tikz command with a command that saves the command on savedpaths + +\def\sseq@modtikzcommands{% + \let\scope\sseq@scope + \let\endscope\sseq@endscope + \@xp\sseq@modtikzcommands@\sseq@tikzcommands\sseq@nil +} +\def\sseq@modtikzcommands@#1{% + \ifx#1\sseq@nil\else + \edef#1{\@xp\@nx\csname\sseq@macroname#1\space\endcsname\@nx#1}% + \@xp\let\csname\sseq@macroname#1\space\endcsname\sseq@defer@tikzcommand % This is just for error reporting so that it will say "Paragraph ended before \draw was complete" + \@xp\sseq@modtikzcommands@ + \fi +} + +\def\sseq@defer@tikzcommand#1{% + \begingroup + \let\sseq@isaliveprotect\sseq@isaliveprotect@protect + \sseq@callas{#1}% + \gdef\sseq@thepathsofar{#1[/utils/exec={\sseq@thesseqstyle\sseq@thetikzprimitivestyle\the\sseq@scope@toks\sseq@savedoptioncode}]}% + \xdef\sseq@whattheusersaid{\string#1} + \sseq@defer@tikzcommand@ +} + +\def\sseq@defer@tikzcommand@{% + \futurelet\testtok\sseq@defer@tikzcommand@@ +} + +\def\sseq@defer@tikzcommand@@{% + \ifx\testtok; + \let\next\sseq@defer@tikzcommand@finish + \else + \ifx\testtok[% + \let\next\sseq@defer@tikzcommand@option + \else + \ifx\testtok(% + \let\next\sseq@defer@tikzcommand@coord + \else + \@xp\ifx\space\testtok + \let\next\sseq@defer@tikzcommand@space + \else + \ifx\testtok\bgroup + \let\next\sseq@defer@tikzcommand@group + \else + \let\next\sseq@defer@tikzcommand@other + \fi + \fi + \fi + \fi + \fi + \sseq@call{\next}% +} + + +\def\sseq@defer@tikzcommand@option[#1]{% + \sseq@processoptions{tikz ~ primitives}{#1}% + \ifx\sseq@savedoptioncode\pgfutil@empty\else + \sseq@x@addto@macro\sseq@thepathsofar{[/utils/exec={\unexpanded\@xp{\sseq@savedoptioncode}}]}% + \fi + \sseq@g@addto@macro\sseq@whattheusersaid{[#1]} + \sseq@defer@tikzcommand@ +} + +\def\sseq@defer@tikzcommand@coord(#1){ + \sseq@tikzprimitives@coord(#1) + \sseq@g@addto@macro\sseq@whattheusersaid{(#1)} + \sseq@defer@tikzcommand@ +} + +% When do groups occur in tikz commands? should we try to parse the inside? +\def\sseq@defer@tikzcommand@group#1{ + \sseq@g@addto@macro\sseq@whattheusersaid{{#1}} + \sseq@xprotected@addto@macro\sseq@thepathsofar{{#1}}% + \sseq@defer@tikzcommand@ +} + +\long\def\sseq@defer@tikzcommand@other#1{ + \ifcat$\@xp\@gobble\string#1$ % test for control word. Won't catch active characters. + \@xp\use_i:nnn + \else + \@xp\ifx\csname sseq@illegalintikz@\string#1\endcsname\relax + \exp_last_unbraced:Nf \use_ii:nnn + \else + \exp_last_unbraced:Nf \use_iii:nnn + \fi + \fi{ % case i: it's not a control word. Just add it to the saved path + \sseq@g@addto@macro\sseq@whattheusersaid{#1} + \sseq@g@addto@macro\sseq@thepathsofar{#1}% + \sseq@defer@tikzcommand@ + }{ % case ii: it's some different control word. Let's try full expanding it. + % note that here we cannot figure out what the user actually said, so we just have to report the f-expanded version. + \def\tempa{#1} % save the current value + \exp_last_unbraced:Nf \sseq@defer@tikzcommand@other@cs#1 + }{ % case iii: it's an illegal control word (e.g., \class, \d, \begin, \end, ...) throw an error. + \sseq@error@xx{incomplete-tikz}{\unexpanded\@xp{\sseq@whattheusersaid}}{ + \ifx\par#1 the ~ start ~ of ~ a ~ new ~ paragraph + \else \string#1\fi + } + \sseq@defer@tikzcommand@finish@ % finish@ doesn't try to grab a semicolon, which is good because there isn't one. + #1 % Reinsert the token that is causing us to stop + } +} + +\def\sseq@defer@tikzcommand@other@cs#1{ % so we f expanded the control sequence, now we test if that did anything + \def\tempb{#1} % get the first f expanded token + \ifx\tempa\tempb + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi{% it didn't get expanded any more, so just add it to the stored stuff + \sseq@g@addto@macro\sseq@whattheusersaid{#1} + \sseq@g@addto@macro\sseq@thepathsofar{#1} + \sseq@defer@tikzcommand@ + }{% it got expanded. Run it through the main loop again. + \sseq@defer@tikzcommand@#1 + } +} + +% Illegal control words: +\long\def\sseq@setillegalcontrolwords#1{\sseq@setillegalcontrolwords@#1\sseq@nil} +\long\def\sseq@setillegalcontrolwords@#1{ + \ifx#1\sseq@nil\else + \@xp\def\csname sseq@illegalintikz@\string#1\endcsname{} + \@xp\sseq@setillegalcontrolwords@ + \fi +} + +% We missing anything here? +\sseq@setillegalcontrolwords{ + \class\classoptions\replaceclass\d\doptions\structline\structlineoptions\circleclasses + \savestack\restorestack\pushstack\nameclass\foreach\begin\end\par + \clip\coordinate\draw\fill\filldraw + \graph\matrix\node\path\pattern + \shade\shadedraw\useasboundingbox +} + + +\@xp\def\@xp\sseq@defer@tikzcommand@space\space{% + \sseq@g@addto@macro\sseq@thepathsofar{~}% + \sseq@g@addto@macro\sseq@whattheusersaid{~} + \sseq@defer@tikzcommand@ +} + +\def\sseq@defer@tikzcommand@finish;{ + \sseq@g@addto@macro\sseq@whattheusersaid{;} + \sseq@defer@tikzcommand@finish@ +} + +% If the expression was incomplete, we'll jump here +\def\sseq@defer@tikzcommand@finish@{ + \sseq@g@addto@macro\sseq@thepathsofar{;} + \global\sseq@thiscalltoks\@xp{\sseq@whattheusersaid} + \ifx\sseq@pageconstraint\sseq@pageconstraint@true + \sseq@savedpaths@xadd{\unexpanded\@xp{\sseq@thepathsofar}}% + \else + \sseq@savedpaths@xadd{% + \@nx\sseq@tikzcommand@conditionaldraw{\unexpanded\@xp{\sseq@thepathsofar}}{\unexpanded\@xp{\sseq@pageconstraint}} + }% + \fi + \endgroup +} + + +\def\sseq@tikzcommand@conditionaldraw#1#2{% + \sseq@pgfmathparse@rescan{#2}% + \ifnum\pgfmathresult>\z@ #1 \fi +} + +\def\sseq@pgfmathparse@rescan#1{\makeatletter\catcode`\&=12\relax\scantokens{\pgfmathparse{#1}}} + +%%% Coordinate parser, copied with huge simplifications from \tikz@@scan@@no@calculator, tikz.code.tex line 4994. +%%% We don't need to handle any of the weird cases, we just need to know about them so we can give up and let tikz do the work later. +% TODO: do same coordinate fixing for coordinates in calculations (yeah right! not even clear this is a good idea...) +\def\sseq@tikzprimitives@coord(#1){ + \begingroup + \let\next\sseq@tikzprimitives@coords@maybenamedclass + \ifsseq@tikzprims@integershift + \pgfutil@in@${#1} + \ifpgfutil@in@ + \let\next\sseq@tikzprimitives@coords@handlemath + \else + \pgfutil@in@ :{#1} + \ifpgfutil@in@\else + \pgfutil@in@{intersection }{#1} + \ifpgfutil@in@\else + \pgfutil@in@|{#1}% + \ifpgfutil@in@\else + \pgfutil@in@,{#1} + \ifpgfutil@in@ + \let\next\sseq@tikzprimitives@coords@maybeclass + \fi + \fi + \fi + \fi + \fi + \fi + \next{#1} + \endgroup +} +\def\sseq@tikzprimitives@coords@maybeclass#1{ + \let\next\sseq@tikzprimitives@coords@notaclass % most branches do this. + % First check whether there are any of the protect "to be determined later" variables like \xmax, etc. If there are, it's not a class + \sseq@protected@edef\sseq@temp@i{#1} + \edef\sseq@temp@ii{#1} + \ifx\sseq@temp@i\sseq@temp@ii + \@xp\sseq@tikzprimitive@getcoord@anchor#1.\sseq@nil % puts coord into \sseq@tempcoord, anchor if any into \sseq@tempanchor + \exp_args:NNo\pgfutil@in@.{\sseq@tempanchornopt} % If there's an extra . in the "anchor", it's not an anchor, and this is not a class + \ifpgfutil@in@\else + \exp_args:NNo \pgfutil@in@,{\sseq@tempcoord} % If the . we used to delineate the "anchor" was in the x-coordinate, it's not an anchor and this is not a class + \ifpgfutil@in@ + \exp_args:NNo \pgfutil@in@,{\sseq@tempanchornopt} % If there is a comma in the "anchor" it's not an anchor and this is not a class + \ifpgfutil@in@\else + \ifx\sseq@tempanchor\pgfutil@empty + \sseq@tempiftrue + \else % If there's an "anchor" we need to test whether the expression is a valid decimal coordinate. If it is, we're going to treat it as not a class + % outputs into sseq@tempif, sets sseq@tempiffalse if it IS valid math, b/c then we're not a anchor + \sseq@anchortrue % If this ends up getting handled as a tikz coordinate, we'll have to add an "anchor ignored" error + \sseq@tikzprimitives@testlastcoord@validmathexpression#1,\sseq@nil + \fi + \ifsseq@tempif + \@xp\sseq@tikzprimitives@ifintcoords\@xp{\sseq@tempcoord}{ % check we're all integer coordinates + \sseq@parsecoord\coord{\sseq@tempcoord}{tikz ~ primitive}% + \ifx\sseq@index\pgfutil@empty\else + \sseq@x@addto@macro\sseq@thepathsofar{(sseq{\sseq@removeparens\coord}\sseq@tempanchor)}% Okay, we're all set, it's a class + \let\next\@gobble % don't run \sseq@tikzprimitives@notaclass + \fi + }{}% + \fi + \fi + \fi + \fi + \fi + \next{#1} +} + +% Sets tempiffalse if if the second coordinate IS a valid math expression -- then t +\def\sseq@tikzprimitives@testlastcoord@validmathexpression#1,#2,#3\sseq@nil{ + \sseq@ifpgfmathexpr{#2}{ + \sseq@tempiffalse + }{ + \sseq@tempiftrue + } +} + +\def\sseq@tikzprimitives@coords@maybenamedclass#1{ + \sseq@tikzprimitive@getcoord@anchor#1.\sseq@nil % puts coord into \sseq@tempcoord, anchor if any into \sseq@tempanchor + \sseq@protectedeval{\@nx\sseq@obj@ifdef{class.namedclass.\@nx\detokenize{\sseq@tempcoord}}}{% need this detokenize here to prevent it from throwing errors when there's a command inside... + \sseq@x@addto@macro\sseq@thepathsofar{(sseq{\sseq@obj{class.namedclass.\sseq@tempcoord}\sseq@tempanchor})} + }{ + \sseq@tikzprimitives@coords@notaclass{#1} + } +} + +\let\sseq@tikzprimitives@coords@maybeclass@save\sseq@tikzprimitives@coords@maybeclass + + +\def\sseq@tikzprimitives@coords@notaclass#1{ + \def\next{\sseq@tikzprimitives@coords@notaclass@leavetotikz{#1}} + \pgfutil@in@${#1} + \ifpgfutil@in@\else + \pgfutil@in@ :{#1} + \ifpgfutil@in@\else + \pgfutil@in@{intersection }{#1} + \ifpgfutil@in@\else + \pgfutil@in@|{#1}% + \ifpgfutil@in@\else + \pgfutil@in@,{#1} + \ifpgfutil@in@ + \def\next{\sseq@tikzprimitives@coords@notaclass@handle{#1}} + \fi + \fi + \fi + \fi + \fi + \next +} + +\def\sseq@tikzprimitives@coords@notaclass@leavetotikz#1{ + \sseq@g@addto@macro\sseq@thepathsofar{(#1)} +} + +\def\sseq@tikzprimitives@coords@notaclass@handle#1{ + \ifsseq@anchor + % Still seems impossible to trigger this? + \sseq@error@xxx{anchor-ignored}{(#1)}{(\unexpanded\@xp{\sseq@tempcoord})}{\sseq@tempanchor} + \@xp\sseq@tikzprimitives@coords@notaclass@handle@\sseq@tempcoord,\sseq@nil + \else + \sseq@tikzprimitives@coords@notaclass@handle@#1,\sseq@nil + \fi +} + +\def\sseq@tikzprimitives@coords@notaclass@handle@#1,#2,#3\sseq@nil{ + \sseq@ifempty{#3}{ + \let\sseq@index\pgfutil@empty + }{ + \edef\sseq@index{,\unexpanded\@xp{\sseq@removecomma#3\sseq@nil}} + \edef\sseq@indexnocomma{\unexpanded\@xp{\sseq@removecomma#3\sseq@nil}} + } + \sseq@ifpgfmathexpr{#1}{ + % Decide whether we can keep the result, which is stored in \sseq@mathresult + \protected@edef\sseq@tempa{#1} + \edef\sseq@tempb{#1} + \ifx\sseq@tempa\sseq@tempb + \let\sseq@tempx\sseq@mathresult + \else + \def\sseq@tempx{#1} + \fi + }{ + \sseq@error@xx{invalid-tikz-coord}{(#1,#2\sseq@index)}{x} + \def\sseq@defer@tikzcommand@finish;{\endgroup} + } + \sseq@ifpgfmathexpr{#2}{ + % Decide whether we can keep the result, which is stored in \sseq@mathresult + \protected@edef\sseq@tempa{#2} + \edef\sseq@tempb{#2} + \ifx\sseq@tempa\sseq@tempb + \let\sseq@tempy\sseq@mathresult + \else + \def\sseq@tempy{#2} + \fi + }{ + \sseq@error@xx{invalid-tikz-coord}{(#1,#2\sseq@index)}{y} + \def\sseq@defer@tikzcommand@finish;{\endgroup} + } + \def\sseq@tempa{#1} + \ifx\sseq@index\pgfutil@empty\else + \sseq@error@xxx{index-ignored}{(\unexpanded{#1,#2}\unexpanded\@xp{\sseq@index})}{\unexpanded{(#1,#2)}}{\unexpanded\@xp{\sseq@indexnocomma}} + \fi + \sseq@xprotected@addto@macro\sseq@thepathsofar{(\sseq@tempx,\sseq@tempy)} +} + +\def\sseq@tikzprimitives@ifintcoords#1{\sseq@tikzprimitives@ifintcoords@#1,\sseq@nil} +\def\sseq@tikzprimitives@ifintcoords@#1,#2,#3\sseq@nil{% + \sseq@ifintexpr{#1}{% + \sseq@ifintexpr{#2}{% + \@firstoftwo + }{\@secondoftwo}% + }{\@secondoftwo}% +} +\def\sseq@tikzprimitives@coords@handlemath#1{\sseq@tikzprimitives@coords@handlemath@(#1)} +\def\sseq@tikzprimitives@coords@handlemath@#1$#2$){\sseq@g@addto@macro\sseq@thepathsofar{#1$#2$)}} +\def\sseq@tikzprimitive@getcoord@anchor#1.#2\sseq@nil{ + \def\sseq@tempcoord{#1} + \ifx\sseq@nil#2\sseq@nil + \def\sseq@tempanchor{} + \def\sseq@tempanchornopt{} + \else + \edef\sseq@tempanchor{.\sseq@tikzprimitive@getcoord@anchor@eatdot#2} + \edef\sseq@tempanchornopt{\sseq@tikzprimitive@getcoord@anchor@eatdot#2} + \fi +} +\def\sseq@tikzprimitive@getcoord@anchor@eatdot#1.{#1} +\def\sseq@uptopt#1.#2\sseq@nil{#1} +%%% Page constraint and \isalive +% #1 -- the new page constraint +% #2 -- a binary logical operator (&& or ||). +\def\sseq@updatepageconstraint#1#2{ + \def\sseq@isaliveprotect{} + \let\sseq@isalive@\sseq@isalive@active + \bgroup + % Was pretty hard to get \isalive to report errors correctly. And to work in general >_< + \let\sseq@isalive@parens\sseq@isalive@parens@check + \sseq@d@addto@macro\sseq@error@hook{\let\protect\relax}% + \let\protect\@unexpandable@protect + \edef\sseq@error@annotation{\unexpanded{.^^J(In page constraint "#1")}\unexpanded\@xp{\sseq@error@annotation}} + \selectfont\sseq@restorefont + \setbox0=\hbox{#1} + \egroup + \sseq@protected@edef\sseq@pageconstraint{(\unexpanded\@xp{\sseq@pageconstraint})#2(#1)} +} + + +%TODO: fix this... +\def\sseq@updatepageconstraintrange{% + \sseq@protected@edef\sseq@pageconstraint{% + (\unexpanded\@xp{\sseq@pageconstraint})&&(\temp<=\page \ifx\tempmax\empty\else&&\page<=\tempmax\fi)% + }% +} + +% This protect variant allows us to delay evaluation of \isalive, just so that we can +% capture something close to the original argument to (does this matter anymore?) +\let\sseq@isaliveprotect\relax +\def\sseq@isaliveprotect@protect{\@nx\sseq@isaliveprotect\@nx} +\def\sseq@isalive{\sseq@isaliveprotect\sseq@isalive@} +\def\sseq@isalive@{\sseq@isalive@error} +\def\sseq@isalive@error{\sseq@error{is-alive-illegal-here}} +\def\sseq@isalive@active#1{% + \@xp\ifx\@xp$\@gobble#1$% + \@xp\sseq@isalive@parens\@xp#1% + \else + \sseq@isalive@list#1\sseq@nil + \fi +} +\def\sseq@isalive@list(#1)#2{% + \sseq@isalive@parens(#1)% + \ifx\sseq@nil#2\else + &&\@xp\sseq@isalive@list\@xp#2% + \fi +} + +\def\sseq@isalive@parens@check(#1){ + \sseq@parsecoord\coord{#1}{\string\isalive} +} +\def\sseq@isalive@parens(#1){\sseq@parsecoordex\sseq@isalive@parens@(#1)} +\def\sseq@isalive@parens@(#1,#2,#3){\@nx\sseq@isalive@final{#1}{#2}{#3}{\sseq@obj{class.(#1,#2,#3).num}}} +\def\sseq@isalive@final#1#2#3#4{% + \ifnum\sseq@obj{class.(#1,#2,#3)[#4].page}<\sseq@thepagecount + 0% + \else + \ifnum#4=\z@ + 1% + \else + \ifnum\sseq@obj{class.(#1,#2,#3)[\the\numexpr #4-1\relax].page}=\sseq@thepagecount + 0% + \else + 1% + \fi + \fi + \fi +} + + + + + +%%% +%%% This is a macro for typesetting monomials. +%%% + +% We need to check for math subscript characters +\char_set_catcode_math_subscript:N \_ + +\protected\def\sseqnormalizemonomial#1{ + \bgroup + \def\sseq@support{} + \sseq@ifempty{#1}{1}{ + \sseqnormalizemonomial@#1\sseq@nil + } +} +\def\sseqnormalizemonomial@#1{ + \pgfkeys@spdef\sseq@var{#1} + \def\sseq@power{1} + \def\sseq@subscript{} + \futurelet\testtok\sseqnormalizemonomial@@ +} + +\def\sseqnormalizemonomial@@{ + \ifx\testtok^ + \let\next\sseqnormalizemonomial@sup + \else + \ifx\testtok_ + \let\next\sseqnormalizemonomial@sub + \else + \let\next\sseqnormalizemonomial@add + \fi + \fi + \next +} + +\def\sseqnormalizemonomial@sup^#1{ + \edef\sseq@power{\the\numexpr#1\relax} + \futurelet\testtok\sseqnormalizemonomial@@ +} + +\def\sseqnormalizemonomial@sub_#1{ + \def\sseq@subscript{_{#1}} + \futurelet\testtok\sseqnormalizemonomial@@ +} + +\def\sseqnormalizemonomial@add{ + \def\temp{1} + \ifx\sseq@var\temp\else + \edef\sseq@var{\unexpanded\@xp{\sseq@var}\unexpanded\@xp{\sseq@subscript}} + \@ifundefined{\sseqnormalizemonomial@varcs}{ + \@xp\edef\csname\sseqnormalizemonomial@varcs\endcsname{\sseq@power} + \sseq@e@addto@macro\sseq@support{\@nx\\{\unexpanded\@xp{\sseq@var}}{\sseqnormalizemonomial@varcs}}% + }{ + \@xp\edef\csname\sseqnormalizemonomial@varcs\endcsname{\the\numexpr\csname\sseqnormalizemonomial@varcs\endcsname + \sseq@power} + } + \fi + \sseqnormalizemonomial@testend +} + +% This is supposed to take a space out of the input stream. For some reason \futurelet grabs it even though it's not supposed to... +% Make sure braces go around argument, except that if they go around \sseq@nil, \futurelet will grab the the open brace and not see +% the \sseq@nil. So we use a full expansion and don't put braces around \sseq@nil if that's our argument. +% MOTHERFUCKING SPACES. +\def\sseqnormalizemonomial@id#1{ + \ifx\sseq@nil#1 + \@xp\@firstoftwo + \else + \@xp\@secondoftwo + \fi{\@nx\sseq@nil}{{#1}} +} + +\def\sseqnormalizemonomial@testend{ + \ifx\testtok\sseq@nil + \sseqnormalizemonomial@done + \sseq@smuggle@macro\processedlabel + \egroup + \let\next\@gobble + \else + \@xp\ifx\space\testtok % not sure why I have to test for spaces like this -- figured it out with trial and error, like in \ifintexpr + % I'm not really sure why a space can show up here, but it crashes the macro and we don't care about spaces. + % I can't \@gobble the space because it will ignore it and take the next argument. What I can do is \@firstofone it away, but that deletes braces + % and in our case it's safe to put in extra braces but not to delete them. So I have \sseqnormalizemonomial@id... + % LaTeX is really really weird. + \def\next{\@xp\futurelet\@xp\testtok\@xp\sseqnormalizemonomial@testend\romannumeral-`0\sseqnormalizemonomial@id} + \else + \let\next\sseqnormalizemonomial@ + \fi + \fi + \next +} + +\def\sseqnormalizemonomial@varcs{sseqnormalizemonomial@var@\detokenize\@xp{\sseq@var}} + +\def\sseqnormalizemonomial@done{ + \def\processedlabel{} + \def\\##1##2{ + \sseq@tempcount=\csname ##2\endcsname\relax + \ifnum\sseq@tempcount=\z@ + \else + \ifnum\sseq@tempcount=\@ne + \sseq@d@addto@macro\processedlabel{##1} + \else + \sseq@e@addto@macro\processedlabel{\unexpanded{##1}^{\the\sseq@tempcount}} + \fi + \fi + } + \sseq@support + \ifx\processedlabel\pgfutil@empty % use 1 for empty monomial + \def\processedlabel{1} + \fi +} + +% Restore catcode of underscore to letter +\catcode`\_ = 11\relax + + + + +\ExplSyntaxOff
\ No newline at end of file |