texlive[46038] Master/texmf-dist: spectralsequences (11dec17)

commits+karl at tug.org commits+karl at tug.org
Mon Dec 11 23:22:32 CET 2017


Revision: 46038
          http://tug.org/svn/texlive?view=revision&revision=46038
Author:   karl
Date:     2017-12-11 23:22:32 +0100 (Mon, 11 Dec 2017)
Log Message:
-----------
spectralsequences (11dec17)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/spectralsequences/README.md
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KZ3.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequences-howitworks.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual-layoutcharts.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.pdf
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex
    trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-KORP8.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2a.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2b.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-imJ.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-insert.tex
    trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-tikz.tex

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/README.md	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/README.md	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,9 +1,9 @@
 
-spectralsequences v1.1.1
+spectralsequences v1.2.0
 ========================
 Author: Hood Chatham  
 Email: hood at mit.edu  
-Date: 2017-09-16  
+Date: 2017-12-10  
 License: All files have the Latex Project Public License.  
 Description: Print spectral sequence diagrams using pgf/tikz.  
 
@@ -12,16 +12,44 @@
 Email me at hood at mit.edu to submit bug reports, request new features, etc. The current development copy is hosted at https://github.com/hoodmane/spectralsequences. 
 
 Changelog:
-==========    
-## [1.1.1]
+==========
+## [1.2.0]
+### Added:
+- \replacesource and \replacetarget
+- \copypage
+- "name handler" option
+- \SseqAHSSNameHandler
+- \SseqNormalizeMonomialSetVariables
+- "show name" option
+- predicates \IfExistsTF, \IfAliveTF, \IfValidDifferentialTF, and \DrawIfValidDifferentialTF
+- "quiet" environment
 
+### Changed:
+- class label handlers now must output result into \result
+- renamed \sseqnormalizemonomial to \SseqNormalizeMonomial, and now outputs into \result
+- renamed \sseqifempty to \SseqIfEmptyTF 
+- renamed \sseqerrortowarning to \SseqErrorToWarning
+- tooltips now disabled unless you use the package option "tooltips" to prevent extraneous auxiliary files.
+
 ### Fixed:
+- A bug that made "y axis gap" adjust both axes and "x axis gap" do nothing (reported by Achim Krause).
+- A bug where a random definition of \\ was leaked into global scope (reported by Achim Krause).
+- Now a \structline defined with option page=n will not be deleted by a shorter differential.
+- A parser error that caused infinite recurse under certain conditions
+- Class names now work with commands in their name (particularly, greek letters)
+- \sseq at ifintexpr no longer breaks if the expression ends in \empty
+- Using \sseqset to give default scaling values for xscale and yscale now works as expected.
+
+    
+## [1.1.1] (2017-09-18)
+
+### Fixed:
 - Groups defined with \SseqNewGroup now correctly handle arithmetic in their arguments.
 - Labels inside a node now replace each other if two are given so you can make the label change on a given page with \classoptions (reported by Steve Wilson). 
 - \kill had a bug in it that sometimes caused it to act on the wrong page (reported by Steve Wilson).
 
 
-## [1.1.0] 
+## [1.1.0] (2017-08-06)
 
 ### Added:
 - \sseqparseint
@@ -55,3 +83,4 @@
 - Fixed a bug with ranges and the sseqpage environment where classes lying outside the printed range would enlarge the range even if an explicit range was specified.
 - The chess grid works correctly now
 
+## [1.0.0] (2017-06-21)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_2.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,7 +1,7 @@
 %%
 %% Description: Adams Novikov Spectral Sequence for $S_2$
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 % figure out how to get width("\noexpand\small 16") working
 \sseqset{ppower/.sseq style={

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ANSS-S_3.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -9,7 +9,7 @@
 %%    Compare this to page 5 of example_ass3
 %%
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 \begin{document}
 % tower definitions
 \NewSseqCommand\alphaclass{d()}{

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_2.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -9,7 +9,7 @@
 %%
 
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 
 \begin{document}
@@ -111,7 +111,7 @@
 }
 
 \NewSseqGroup \Phonegroup {G{}}{
-    \sseqset{class label handler = { \sseqnormalizemonomial{##1} }}
+    \sseqset{class label handler = \SseqNormalizeMonomial }
     \czero["#1c_0" above](-1,-2)
     \Phone[imJ]{P#1}{}
     \nuclass[imJ]\divtwoclass[imJ]\divtwoclass["#1d_0" left,name=d0]
@@ -161,8 +161,6 @@
     class labels={above left=0.2em,black},
     x range={0}{46},
     y range={0}{23},
-   % xscale=0.7,
-   % yscale=0.8,
     differentials = blue,
     classes = { tooltip = { (\xcoord,\ycoord) } },
     grid = go,

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-S_3.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -6,7 +6,7 @@
 %%    Copied from page 11 of the green book.
 %%
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 \begin{document}
 

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/ASS-tmf_2.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -25,7 +25,7 @@
 %
 % 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{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 \begin{document}
 

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-EO2_3.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -12,7 +12,7 @@
 %%    HFPSS for KO = KU^{hC_2} (see example_KUHFPSS).
 %%
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 \begin{document}
 \begin{sseqdata}[name=EO(2),Adams grading,

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/HFPSS-KO.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -3,7 +3,6 @@
 %%
 %% 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
@@ -43,6 +42,8 @@
 % This is just to make sure the bounding box doesn't move around
 \path[background] (\xmin-1,\ymin-1) rectangle (\xmax+1,\ymax+1);
 
+\def\xmin{-12}
+\def\xmax{14}
 \sseqparseint\xitstart{\xmin/8*8-16} % division is integer division (I think with rounding towards 0...) so /8*8 rounds up to the nearest multiple of 8?
 \sseqparseint\xitgap{\xitstart+4}
 \sseqparseint\xitend{\xmax+2}
@@ -73,6 +74,7 @@
 
 \newpage
 \begin{sseqpage}[name=KRHFPSS,page=0,keep changes]
+\def\xmin{-12}\def\xmax{14}
 \pgfmathsetmacro\antidiag{min(-\xmin,\ymax+0.8)}
 \clip[background,xshift=0.2cm,yshift=-0.33cm](-\antidiag,\antidiag)--(-1,1)--(-0.4,0)--(\xmax + 0.28,0)--(\xmax+0.28,\antidiag)--cycle;
 \foreach \z in {2,6}{

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/J_RPinfty.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: example_endofVFoS.tex

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-bo-A1.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -7,7 +7,7 @@
 %%
 
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 
 \NewSseqCommand\tower {} {
     \class(0,0)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/MaySS-tmf-A2.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -5,7 +5,7 @@
 %%
 
 
-\documentclass{spectralsequence-example}
+\documentclass[tooltips]{spectralsequence-example}
 \begin{document}
 \sseqset{htwostructstyle/.sseq style = {gray,very thin, run off=-}}
 %\pgfkeys{/sseqpages/struct line/htwostructstyle/.show code}

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KF3n.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -18,7 +18,7 @@
     class placement transform={scale=1.3, rotate=90},
     class pattern=linear,
     classes={draw=none},
-    class label handler = {\sseqnormalizemonomial{#1}},
+    class label handler = \SseqNormalizeMonomial,
     bocksteinSS/.style={
         page=0, y range={-1}{0},
         no differentials, no labels, no y ticks, no title,

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/SSS-KZ3.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/hatcher.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: example_hatcher.tex

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/examples/unstable_ASS_SO.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: example_unstable_ASS_SO.tex

Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-KORP8.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-KORP8.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-KORP8.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,34 @@
+
+
+\NewSseqCommand \KOstar {m}{
+    \begin{scope}[xshift = -#1, xshift=8*\b, yshift = #1]
+        \class[rectangle,name=b^{\b}[0]](0,0)
+        \class[name=b^{\b} e[0]](1,0) \structline
+        \class[name=b^{\b} e^2[0]](2,0) \structline
+        \class[rectangle,fill=none,name=b^{\b} u[0]](4,0)
+    \end{scope}
+}
+\NewSseqCommand \KOpcell {m}{
+    \d1(b^{\b}[#1])   \replacetarget
+    \d1(b^{\b} u[#1]) \replacetarget
+    \structline(b^{\b}[#1+1])(b^{\b} e[#1+1])
+    \structline[page=2,dashed](b^{\b} e[#1])(b^{\b} e^2[#1+1])
+    \structline[page=2,dashed](b^{\b} e^2[#1])(b^{\b} u[#1+1])
+}
+\NewSseqCommand \KOetacell {m}{
+    \DrawIfValidDifferential2(b^{\b}[#1])
+    \d2(b^{\b} e[#1])
+    \DrawIfValidDifferential3(b^{\b} e^2[#1])
+}
+\begin{sseqdata}[name=KO^*RP^8, Adams grading, class name handler=\SseqAHSSNameHandler,
+    classes=fill, x range={-8}{10},xscale=0.7, yscale=0.5, x tick step = 4 ]
+\foreach \b in {-2,...,2}{
+    \foreach \n in {0,...,6}{\KOstar{\n}}
+    \foreach \n in {1,3,...,5}{\KOpcell{\n}}
+    \foreach \n in {2,3}{\KOetacell{\n}}
+    \structline[dashed](b^{\b}e^2[2])(b^{\b}u[4])
+    \structline[dashed](b^{\b}[4])(b^{\b}e[5])
+}
+\end{sseqdata}
+\printpage[name=KO^*RP^8, title=AHSS for $KO^*\mathbb{R}P^8$]\vskip6pt
+\printpage[name=KO^*RP^8,page=6] 
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-KORP8.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2a.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2a.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2a.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,24 @@
+\begin{sseqdata}[ name = page_example2, Adams grading, xscale = 0.6, yscale = 0.5 ]
+\class(0,2)\class(1,0)
+\d2(1,0)
+\replacesource
+\class(0,3)
+\d3(1,0)
+\replacesource
+\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 ] 
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2a.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2b.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2b.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2b.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,18 @@
+\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) 
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-class-page2b.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-imJ.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-imJ.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-imJ.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,32 @@
+\SseqNewFamily{imJ}
+\begin{sseqdata}[
+    name=ANSS-S_2, Adams grading,
+    class labels={below}, label distance=-1pt,
+    class placement transform={rotate=90,scale=2},
+    differentials=blue,
+    x range={0}{9}, y range={0}{4},
+    xscale=0.7, grid=go
+]
+% Image of J classes
+\begin{scope}[imJ]
+\class[rectangle,fill,inner sep=3pt](0,0)
+\DoUntilOutOfBoundsThenNMore{3}{\etaclass}
+\classoptions["\alpha_1" above left](1,1)
+\class["\alpha_{2/2}",circlen=2](3,1)
+\structline(0,0) \structline[dashed](3,3)
+\class["\alpha_3"](5,1) \d3\relax
+\DoUntilOutOfBounds{ \etaclass \d3 }
+\class["\alpha_{4/4}", rectangle, "16" {font=\tiny,inside}, inner sep=1pt](7,1)
+\DoUntilOutOfBoundsThenNMore{3}{\etaclass}
+\end{scope}
+
+% Other classes
+\class["\beta_{2/2}" {below right=-4pt}, insert = 1](6,2)
+\structline(3,1)
+\class["\beta_{2}" left](8,2)
+\etaclass\structline(6,2,2) % This is a *nu
+\end{sseqdata}
+
+\printpage[name=ANSS-S_2, title = with image of J, imJ style=purple]
+
+\printpage[name=ANSS-S_2, no imJ, x range={2}{9}, title = without image of J]
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-imJ.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-insert.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-insert.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-insert.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,33 @@
+\DeclareSseqGroup \tower {} {
+    \class(0,0)
+    \DoUntilOutOfBounds {
+        \class(\lastx,\lasty+1)
+        \structline
+    }
+}
+
+\begin{sseqdata}[name=insert-example, y range={0}{4}, class pattern = linear]
+\tower(0,2)
+\tower(0,3)
+\tower(0,1)
+\end{sseqdata}
+\qquad
+\begin{sseqpage}[name=insert-example]
+\tower[red,classes={insert=1}](0,0)
+\end{sseqpage}
+\qquad
+\begin{sseqpage}[name=insert-example]
+\tower[red,classes={insert=2}](0,0)
+\end{sseqpage}
+\qquad
+\begin{sseqpage}[name=insert-example]
+\tower[red,classes={insert=3}](0,0)
+\end{sseqpage}
+\qquad
+\begin{sseqpage}[name=insert-example]
+\tower[red,classes={insert=-2}](0,0)
+\end{sseqpage}
+\qquad
+\begin{sseqpage}[name=insert-example]
+\tower[red,classes={insert=-3}](0,0)
+\end{sseqpage}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-insert.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-tikz.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-tikz.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-tikz.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -0,0 +1,25 @@
+\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}
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/examples/spectralsequencesmanual-tikz.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequences-howitworks.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequences-howitworks.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequences-howitworks.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -30,7 +30,7 @@
 
 So, having heard this simple description, a reasonable question to ask is: why does it take in excess of 8000 lines of TeX code to accomplish these simple tasks? There are a few reasons. Firstly, the package handles a lot of use cases and has a quite a few different features and there is a large amount of intrinsic complexity to getting these things right. Another huge reason is that \TeX\ is a completely unreasonable coding environment. This is responsible for a good deal of the complexity in \file{sseqparsers}, for example.
 
-Perhaps the biggest single contributor to code complexity is performance. \tikzname\ is very robust, but it is not fast. \spectralsequences\ draws roughly cubically many classes in large diagrams, and my larger test examples have as many as 5,000 classes. If each class takes an extra millisecond a second to draw, that comes out to an extra five seconds of compilation time. Because of this, unless the performance critical drawing code is super optimized, the package will be way too slow on large diagrams. Most of the added complexity due to performance considerations is contained in \file{sseqdrawing}, but the hard parts of the key value code are all related to performance too.
+Perhaps the biggest single contributor to code complexity is performance. \tikzname\ is very robust, but it is not fast. \spectralsequences\ draws roughly cubically many classes in large diagrams, and my larger test examples have as many as 5,000 classes. If each class takes an extra millisecond to draw, that comes out to an extra five seconds of compilation time. Because of this, unless the performance critical drawing code is super optimized, the package will be way too slow on large diagrams. Most of the added complexity due to performance considerations is contained in \file{sseqdrawing}, but the hard parts of the key value code are all related to performance too.
 
 The last major source of complexity is the robust error handling code. Most \LaTeX\ packages have crappy error handling and result in inscrutable errors even in relatively reasonable use conditions. There are a two main reasons for this as far as I can tell: \LaTeX\ doesn't have good error handling tools and most people who write \LaTeX\ packages are not primarily programmers and have other priorities than ensuring that their packages have clean failure modes. The files \file{sseqmessages} and \file{sseqforeach} are entirely devoted to error handling, and almost all of the complexity of \file{sseqmacromakers} is tied up in error handling too.
 

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual-layoutcharts.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual-layoutcharts.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual-layoutcharts.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,7 +1,7 @@
 \sseqset{
     distance label/.sseq style = {orange,{<[width = 4pt]}-},
     description/.sseq style = {black, align = center},
-    title style={yshift=25pt,font=\Large}
+    title style={yshift=35pt,font=\Large}
 }
 \catcode`\| = 12 % | is active to be verbatim, but we need to use it here for our arrowhead specification.
 %
@@ -9,7 +9,7 @@
     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,
-    title = {Axis type border layout},    
+    title = {Axis type border layout}
 ]
 \begin{scope}[background]
 \sseq at savedpaths@add{\color{red}\pgfsetpath\sseq at theclippath\pgfusepath{draw}}
@@ -79,6 +79,7 @@
 \class(0,5)
 \end{sseqpage}
 
+\vskip20pt
 
 \begin{sseqpage}[ grid = chess, axes type=frame,
     title = {Axes type frame layout},
@@ -201,4 +202,4 @@
 \class(0,0)
 \class(5,0)
 \class(0,5)
-\end{sseqpage}
\ No newline at end of file
+\end{sseqpage} 
\ No newline at end of file

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanual.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: spectralsequencesmanual.tex
@@ -12,16 +12,17 @@
 
 %
 % TODO:
-%  families
 %
+%  maybe move more examples into external files?
+%
 %  consistency issues?
 %  perhaps think about ordering, particularly of "Misc commands" section
 %  tutorial
 %  explain / cross reference examples folder?
 %
+\def\version{Version 1.2.0}
 
 
-
 \input spectralsequencesmanualpreamble
 
 
@@ -51,8 +52,8 @@
 The \sseqpages\  package consists of two main environments -- the \sseqdataenv\  environment, which specifies the data for a named spectral sequence, and the \sseqpageenv\  environment, which prints a single page of a spectral sequence. The |\printpage| command is also available as a synonym for a \sseqpageenv\  environment with an empty body.
 
 Here is a basic example:
-\begin{codeexample}[width = 9cm]
-\begin{sseqdata}[ name = ex1, scale = 0.6,
+\begin{codeexample}[width = 8.7cm]
+\begin{sseqdata}[ name = basic, xscale = 0.6,
                   cohomological Serre grading ]
 \class(0,0)
 \class(0,2)
@@ -60,10 +61,10 @@
 \class(3,2)
 \d3(0,2)
 \end{sseqdata}
-\printpage[ name = ex1, page = 3 ]  \quad
-\printpage[ name = ex1, page = 4 ]
+\printpage[ name = basic, page = 3 ]  \quad
+\printpage[ name = basic, page = 4 ]
 \end{codeexample}
-|\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\  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.
+\codeverb|\begin{sseqdata}[name = basic, cohomological Serre grading]| starts the declaration of the data of a spectral sequence named |basic| with cohomological Serre grading -- that is, the page $\mathtt{r}$ differentials go $\mathtt{r}$ to the right and down $\mathtt{r-1}$. Then we specify four classes and one page 3 differential, and we ask \sseqpages\  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{Installation}
 In both \miktex\ and \texlive\ installation should be automatic -- your \TeX\ distribution should automatically install the package the first time you include |\usepackage{spectralsequences}| in a document and compile it. However, in 2016, \texlive\ made an incompatible change to their database, so no new packages will run on versions of \texlive\ from before 2016. This includes \sseqpages. If you have an old version of \texlive, you can either perform a manual install,
@@ -77,7 +78,7 @@
 Another option is to increase the static memory caps for \pdfLaTeX. See \href{https://tex.stackexchange.com/a/26213}{this \TeX stack exchange post} for instructions on how to do this.
 
 \subsection{A warning about fragile macros}
-All the data in a \sseqpages\  environment is stored and used later. As a result, most of the \sseqpages\  commands currently cannot tolerate fragile macros. Unfortunately, it is impossible for \sseqpages\  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.}
+All the data in a \sseqpages\  environment is stored and used later. As a result, most of the \sseqpages\  commands currently cannot tolerate fragile macros. Unfortunately, it is impossible for \sseqpages\  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 might be 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{Package Options and Environments}
@@ -132,8 +133,8 @@
 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{commandlist}{{\replaceclass\ooptions\parargthreeopt{x}{y}{n}},\replaceclass\ooptions\pararg{classname}, \replacesource\ooptions, \replacetarget\ooptions}
+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. The variants |\replacesource| and |\replacetarget| replace the source and target respectively of the most recent differential.
 \begin{codeexample}[]
 \begin{sseqdata}[name = replace class example, Adams grading, classes = {draw = none } ]
 \class["\mathbb{Z}"](0,3)
@@ -140,9 +141,9 @@
 \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)
+\replacetarget["\mathbb{Z}/2"] %\replaceclass["\mathbb{Z}/2"](0,3)
+\d[-> >]3(1,0)
+\replacesource["2\mathbb{Z}"]    % \replaceclass["2\mathbb{Z}"](1,0)
 \end{sseqdata}
 \printpage[ name = replace class example, page = 2 ] \qquad
 \printpage[ name = replace class example, page = 3 ] \qquad
@@ -265,7 +266,7 @@
 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 = 7cm]
+\begin{codeexample}[width = 7.5cm]
 \DeclareSseqGroup\tower {} {
     \class(0,0)
     \foreach \y in {1,...,5} {
@@ -279,7 +280,7 @@
 \begin{sseqdata}[ name = structline example,
                   classes = { circle, fill },
                   Adams grading, no axes,
-                  yscale = 1.39 ]
+                  yscale = 1.28 ]
 \class(1,1) \class(1,2)
 \class(2,3) \class(2,3) \class(2,5)
 \tower[classes = blue](0,0)
@@ -302,33 +303,7 @@
 
 \begin{commandlist}{\draw,\path,\node,\clip}
 Any code that would work in a \tikzpictureenv\  environment will also work unchanged in a \sseqdataenv\  or \sseqpageenv\  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}
+\codeexample[from file=tikz]
 \end{commandlist}
 
 
@@ -518,19 +493,41 @@
 \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)|:
+The |\class| command makes a \tikzpkg\ node on appropriate pages. You can refer to this node using \tikzpkg\ commands by using its coordinates. Using the |class:name| option, you can give the node a name, which you can use to refer to the class. Using names creates more readable code. The |show name| option can be used to display the names of classes. You can modify the names of classes systematically using the options |class name prefix|, |class name postfix|, and |class name handler|.
 
+Named classes are 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)
+\begin{sseqpage}[classes = { show name=above }]
+\class[class:name = 1](0,0)
+\class[class:name = \eta](1,1)
 \class(2,1)
-\draw[xshift = 1] (id) -- (eta);
-\draw[xshift = 1,blue] (id) -- (1,1);
+\structline[xshift = 1] (1) (\eta)
+\structline[xshift = 1,blue] (1) (1,1)
 \end{sseqpage}
 \end{codeexample}
 \end{key}
 
+\begin{key}{show name = \meta{label options}}
+This option is like saying |"class name"\marg{label options}| if the class has a name, and does nothing if the class has no name. If the class has multiple names, only the most recent is used. This is particularly useful with class styles, . For instance, by saying |this page classes = { show name = above }| you can display names of all of the sources and targets of differentials on each page.
+\begin{codeexample}[width=7cm]
+\begin{sseqdata}[
+    name = show name example,
+    this page classes = { show name = {above right, pin} }
+]
+\class[name=a](0,2)
+\class[name=b](0,3)
+\class[name=x](1,0)
+\d2(x)(a)
+\replacesource[name=2x]
+\d3(x)(b)
+\end{sseqdata}
+
+\printpage[name=show name example,page=2]
+
+\printpage[name=show name example,page=3]
+\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]
@@ -562,44 +559,8 @@
 \end{key}
 
 \begin{key}{insert = \meta{integer}}
-If there are multiple classes in the same position, this option allows you to insert classes later into earlier positions. This is intended to help you put logically related classes next to each other. If the integer is positive, it inserts the class in the specified position, and if the integer is negative, it counts backwards from the end. Providing |0| is the same as omitting the option entirely. Values larger in absolute value than the total number of classes are truncated.
- Consider:
-\begin{codeexample}[]
-\DeclareSseqGroup \tower {} {
-    \class(0,0)
-    \DoUntilOutOfBounds {
-        \class(\lastx,\lasty+1)
-        \structline
-    }
-}
-
-\begin{sseqdata}[name=test, y range={0}{4}, class pattern = linear]
-\tower(0,2)
-\tower(0,3)
-\tower(0,1)
-\end{sseqdata}
-\qquad
-\begin{sseqpage}[name=test]
-\tower[red,classes={insert=1}](0,0)
-\end{sseqpage}
-\qquad
-\begin{sseqpage}[name=test]
-\tower[red,classes={insert=2}](0,0)
-\end{sseqpage}
-\qquad
-\begin{sseqpage}[name=test]
-\tower[red,classes={insert=3}](0,0)
-\end{sseqpage}
-\qquad
-\begin{sseqpage}[name=test]
-\tower[red,classes={insert=-2}](0,0)
-\end{sseqpage}
-\qquad
-\begin{sseqpage}[name=test]
-\tower[red,classes={insert=-3}](0,0)
-\end{sseqpage}
-\end{codeexample}
-
+If there are multiple classes in the same position, this option allows you to insert classes later into earlier positions. This is intended to help you put logically related classes next to each other. If the integer is positive, it inserts the class in the specified position, and if the integer is negative, it counts backwards from the end. Providing |0| is the same as omitting the option entirely. Values larger in absolute value than the total number of classes are truncated. Consider:
+\codeexample[from file=insert]
 \end{key}
 
 \begin{key}{offset = \{\pars{\meta{x offset},\meta{y offset}}\}}
@@ -614,8 +575,8 @@
 \draw(0,1)--(0,2);
 \class(1,0)
 \d2(1,0,,1)
+\replacetarget
 \d2(1,0,,2)
-\replaceclass(0,2)
 \end{sseqdata}
 \printpage[name = offset example, page=2]
 \printpage[name = offset example, page=3]
@@ -628,7 +589,7 @@
 \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 charts 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.
+The tooltip is made using the |\pdftooltip| command from the |pdfcomment| package. The |pdfcomment| package generates two extra auxiliary files, so it is not included by default. In order to use the |tooltip| option, you have to use the |tooltips| package option (e.g., load \sseqpages\ with |\usepackage[tooltips]{spectralsequences}|). 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}[]
@@ -658,53 +619,8 @@
 \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\  environment, or on the generation appropriate to the current page in a \sseqpageenv\  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}
+\codeexample[from file=class-page2a]
+\codeexample[from file=class-page2b]
 \end{keylist}
 
 \begin{commandlist}{\xcoord,\ycoord}
@@ -775,10 +691,8 @@
 \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)
+\d2(1,0)(0,2) \replacesource
+\d3(1,1)(0,4) \replacesource
 \structline(1,0)(1,1)
 \end{sseqdata}
 \printpage[name = structpage example,page = 3]
@@ -794,10 +708,8 @@
 \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)
+\d2(1,0)(0,2) \replacesource
+\d3(1,1)(0,4) \replacesource
 \structline[structline:page = 2](1,0)(1,1)
 \end{sseqdata}
 \printpage[name = structpage example2,page = 1]
@@ -919,18 +831,19 @@
 \end{key}
 
 \begin{keylist}{page constraint = \meta{predicate}, page constraint or = \meta{predicate}}
+\declarecustomhandler{page constraint}{\codehandler}
 This places a constraint on the pages in which the \tikzpkg\  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\  and again for the individual \tikzpkg\ primitive.
+\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\  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}}}|}}|$$
+\[|page constraint = {\pars{\meta{x},\meta{y}\opt{,}\oarg{index}}}}}|\]
 will print the \tikzpkg\  primitive only on pages where the specified class is alive. Saying
-$$|page constraint = ||{\isalive|\pars{\meta{coordinate 1}}\,\cdots\,\pars{\meta{coordinate n}}|}|$$
+\[|page constraint = {\isalive(\meta{coordinate 1})|\,\cdots\,|(\meta{coordinate n})}|\]
 is equivalent to
-$$|page constraint = ||{\isalive|\pararg{coordinate 1}| &&|\,\cdots\,|&& \isalive|\pararg{coordinate n}|}|$$
+\[|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);|$$
+\[\codeverb|\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}
@@ -986,10 +899,16 @@
 \end{keylist}
 \end{command}
 
-\begin{command}{\sseqerrortowarning\meta{error-name}}
+\begin{command}{\SseqErrorToWarning\meta{error-name}}
 Turns the error with the given name into a warning. An error message will start by saying \let\eatclnifpresent\empty|spectralsequences error: "error-name"|. This is the name you need to put into this command.
 \end{command}
 
+\begin{environment}{{quiet}}
+This environment quiets error messages that occur inside of it. \sseqpages\ is pretty good at error recovery, and so most of commands will fail gracefully and do nothing if their preconditions aren't met. If there are any parsing errors in the body of the |{quiet}| environment, prepare to see low level internal error messages. You might also run into bugs in \sseqpages\ -- the error recovery code hasn't been that carefully tested. If you do get low level error messages, remember to comment out the |{quiet}| environment before trying to debug.
+
+This is particularly useful for code reuse commands. Sometimes there is a source of long differentials that only applies to classes that haven't already supported shorter differentials. Sometimes there should be a structure line if a certain class exists, but it might not exist. In these cases, the |{quiet}| environment will help you out. See also |\DrawIfValidDifferential|, which is a variant of |\d| that behaves as if it were inside a |{quiet}| environment.
+\end{environment}
+
 \subsection{Code reuse commands}
 \begin{command}{\foreach }
 This command is from \tikzpkg\  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. The basic usage is |\foreach \x in {\meta{xmin},...,\meta{xmax}} \marg{loop body}| which will execute |\meta{loop body}| with |\x| set to each value between \meta{xmin} and \meta{xmax} inclusive. If you want a step greater than 1, try |\foreach \x in {\meta{xmin},\meta{xmin}+\meta{xstep},...,\meta{xmax}} \marg{loop body}|.
@@ -1073,6 +992,7 @@
 \end{commandlist}
 \begin{commandlist}{\NewSseqCommand    \cmdarg{command}\marg{argspec}\marg{body},
                     \DeclareSseqCommand\cmdarg{command}\marg{argspec}\marg{body}}
+% TODO: Explain the difference between NewSseqCommand and DeclareSseqCommand!
 The \xparsepkg\ package provides these very powerful commands for defining macros. They are used internally to the \sseqpages\  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|.
@@ -1178,58 +1098,49 @@
 Here we define a command which takes an options list, a coordinate, and a single mandatory argument. The options are applied to all the classes and structlines, the coordinate shifts the origin, and the mandatory argument is the length of the tower.
 \end{commandlist}
 
+\begin{command}{\SseqCopyPage\cmdarg{command}\marg{spectral sequence name}\marg{page}}
+This copies all of the classes and structlines on page |\meta{page}| of the spectral sequence named |\meta{spectral sequence name}|, throwing out differentials and tikz primitives. The resulting |\cmdarg{command}| has syntax as if you had used |\DeclareSseqGroup| with no extra arguments -- that is, it takes an optional options list, which are passed to a scope, and an optional coordinate pair.
+\end{command}
+
 \subsection{Families}
-\spectralsequences\ has a concept of ``class families'' that can be drawn or suppressed as a group, and that can have styling options applied to them as a group. 
-\begin{command}{\sseqnewfamily\marg{family name}}
-This makes a new family with name \meta{family name}. The effect of this is to define global options |\meta{family name} style| which apply options to all classes in the family, |draw \meta{family name}| which causes the family to be drawn, and |no \meta{family name}| which suppresses the family (drawing is the default behavior of course). It also defines an option |\meta{family name}| which puts a feature into the family -- so it can be used as an option to any of the normal commands like |\class|, |\d|, |\structline|, etc and to a scope. 
+\spectralsequences\ has a concept of ``class families'' that can be drawn or suppressed as a group, and that can have styling options applied to them as a group.
+\begin{command}{\SseqNewFamily\marg{family name}}
+This makes a new family with name \meta{family name}. The effect of this is to define global options |\meta{family name} style| which apply options to all classes in the family, |draw \meta{family name}| which causes the family to be drawn, and |no \meta{family name}| which suppresses the family (drawing is the default behavior of course). It also defines an option |\meta{family name}| which puts a feature into the family -- so it can be used as an option to any of the normal commands like |\class|, |\d|, |\structline|, etc and to a scope.
 
-\begin{codeexample}[vbox]
-\sseqnewfamily{imJ}
-\begin{sseqdata}[
-    name=ANSS-S_2, Adams grading,
-    class labels={below}, label distance=-1pt,
-    class placement transform={rotate=90,scale=2},
-    differentials=blue,
-    x range={0}{9}, y range={0}{4},
-    xscale=0.7, grid=go
-]
-% Image of J classes
-\begin{scope}[imJ]
-\class[rectangle,fill,inner sep=3pt](0,0)
-\DoUntilOutOfBoundsThenNMore{3}{\etaclass}
-\classoptions["\alpha_1" above left](1,1)
-\class["\alpha_{2/2}",circlen=2](3,1)
-\structline(0,0) \structline[dashed](3,3)
-\class["\alpha_3"](5,1) \d3\relax
-\DoUntilOutOfBounds{ \etaclass \d3 }
-\class["\alpha_{4/4}", rectangle, "16" {font=\tiny,inside}, inner sep=1pt](7,1)
-\DoUntilOutOfBoundsThenNMore{3}{\etaclass}
-\end{scope}
-
-% Other classes
-\class["\beta_{2/2}" {below right=-4pt}, insert = 1](6,2)
-\structline(3,1)
-\class["\beta_{2}" left](8,2)
-\etaclass\structline(6,2,2) % This is a *nu
-\end{sseqdata}
-
-\printpage[name=ANSS-S_2, title = with image of J, imJ style=purple]
-
-\printpage[name=ANSS-S_2, no imJ, x range={2}{9}, title = without image of J]
-\end{codeexample}
+\codeexample[vbox, from file=imJ]
 \end{command}
 
 
 \subsection{Utilities}
-\begin{command}{\sseqparseint\cmdarg{macro}\marg{integer expression}}
+\begin{command}{\SseqParseInt\cmdarg{macro}\marg{integer expression}}
 Stores the result of evaluating an integer expression into \cmdarg{macro}. An integer expression consists of |+|, |-|, |*|, |/|, parentheses, and macros that expand to more of the same. The exact rules regarding what is a valid expression are pretty much what you would expect. Note that juxtaposition is a syntax error, not multiplication, so |2(1+1)| is invalid, you must say |2*(1+1)|.
 \end{command}
 
-\begin{command}{\sseqifempty\marg{expression}\marg{true code}\marg{false code}}
-This tests if an expression is the empty expression. This is mainly useful for giving systematic labels to things. Probably it won't ever matter to you.
-\end{command}
+\begin{commandlist}{
+    \SseqIfEmptyTF\marg{expression}\marg{true code}\marg{false code},
+    \SseqIfEmptyT\marg{expression}\marg{true code},
+    \SseqIfEmptyF\marg{expression}\marg{false code}
+}
+This tests if an expression is the empty expression. This is mainly useful for giving systematic labels to things.
+\end{commandlist}
 
 \begin{commandlist}{
+    \IfExistsTF\marg{page}\pararg{coordinate}\marg{true code}\marg{false code},
+    \IfExistsT\marg{page}\pararg{coordinate}\marg{true code},
+    \IfExistsF\marg{page}\pararg{coordinate}\marg{false code}
+}
+Test whether a class of the given description exists. The description can be any valid coordinate, including a named coordinate. If the coordinate is not valid, this will return false.
+\end{commandlist}
+
+\begin{commandlist}{
+    \IfAliveTF\marg{page}\pararg{coordinate}\marg{true code}\marg{false code},
+    \IfAliveT\marg{page}\pararg{coordinate}\marg{true code},
+    \IfAliveF\marg{page}\pararg{coordinate}\marg{false code}
+}
+Test whether a class is alive on the given page. If the class doesn't exist, this will return false.
+\end{commandlist}
+
+\begin{commandlist}{
     \IfOutOfBoundsTF\pararg{coordinate}\marg{true code}\marg{false code},
     \IfOutOfBoundsT\pararg{coordinate}\marg{true code},
     \IfOutOfBoundsF\pararg{coordinate}\marg{false code},
@@ -1237,20 +1148,50 @@
     \IfInBoundsT\pararg{coordinate}\marg{true code},
     \IfInBoundsF\pararg{coordinate}\marg{false code}
 }
-Test whether an existing class is in bounds or out of bounds. I don't have an obvious use for these. I had to make commands to do this as part of the drawing code and in order to make |\DoUntilOutOfBounds| and it was no extra effort to expose them. Maybe they will be helpful at some point.
+Test whether a class is in bounds or out of bounds. If no such class exists, returns false.
 \end{commandlist}
 
+\begin{commandlist}{
+    \IfValidDifferentialTF\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{true code}\marg{false code},
+    \IfValidDifferentialT\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{true code},
+    \IfValidDifferentialF\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{false code},
+    \DrawIfValidDifferentialTF\ooptions\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{true code}\marg{false code},
+    \DrawIfValidDifferentialT\ooptions\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{true code},
+    \DrawIfValidDifferentialF\ooptions\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{false code},
+    \DrawIfValidDifferential\ooptions\meta{page}\pararg{coordinate}\opt{\pararg{target coordinate}}\marg{false code}
+}
+Test whether a differential is valid. There are many possible reasons for a differential to not be valid -- the source or target class could not exist, the target could not be in the correct grading, etc. If any error would be generated if you supplied the same arguments to |\d|, this tests false. Otherwise, this tests true. The command |\DrawIfValidDifferental| draws the differential if it is valid, whereas |\DrawIfValidDifferentalT| draws the differential and executes the true code if it is valid,
+|\DrawIfValidDifferentalF| draws the differential or executes false code if it isn't valid, etc.
+\end{commandlist}
 
-\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{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. The variables are sorted by first occurrence, use |\SseqNormalizeMonomialSetVariables| to set a different sort order. It outputs its result into |\result|. This command is specifically meant to be used as a value for |class label handler| or |class name handler|. See the example in the documentation for |class label handler| for a realistic example. 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$
+\SseqNormalizeMonomial{x^0y^0} $\result$, \quad
+\SseqNormalizeMonomial{x^3yx^{-1}z^0} $\result$, \quad
+\SseqNormalizeMonomial{1x_2^2x^2_2} $\result$
 \end{codeexample}
 \end{command}
 
+\begin{command}{\SseqNormalizeMonomialSetVariables}
+This command takes an undelimited list sets up |\SseqNormalizeMonomial| to sort the variables in the input in the specified order. This is useful for consistency, and particularly important for when you use it to name classes.  For example:
+\begin{codeexample}[]
+% We always want a first, then b, then x_1, then x_2, then x_3
+\SseqNormalizeMonomialSetVariables{abx_1x_2x_3}
+\SseqNormalizeMonomial{ba} $\result$, \quad
+\SseqNormalizeMonomial{bx_1} $\result$, \quad
+\SseqNormalizeMonomial{abx_2x_3x_1} $\result$
+\end{codeexample}
+\SseqNormalizeMonomialSetVariables{}
+\end{command}
 
+
+\begin{command}{\SseqAHSSNameHandler}
+This command expects an argument of the form |\meta{monomial}[\meta{integer expression}]| and defines |\result| to be |m[n]| where |m| is the result of applying |\SseqNormalizeMonomial| to the monomial, and |n| is the result of evaluation the integer expression plus any |yshift| that is present. This is intended for use with in drawing Atiyah Hirzebruch spectral sequences. See |class name handler| for an example of the calculation of $KO^*\mathbb{R}P^8$.
+\end{command}
+
 \subsection{Coordinate parsers and related}
 %    \parsecoordinate and \parsedifferential
 \begin{command}{\parsecoordinate\cmdarg{macro}(\meta{coordinate})}
@@ -1291,10 +1232,8 @@
                 (source) -- (intersection-1);
 }
 \begin{sseqdata}[ name = cathex, Adams grading, differentials = { blue } ]
-\class(0,2)
-\class(0,2)
+\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 ]
@@ -1313,8 +1252,8 @@
 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\cmdarg{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{command}{\gettag\cmdarg{macro}\pararg{coordinate}}
+The |\gettag| command finds the most recent tag applied to the coordinate and stores it into |\cmdarg{macro}|. 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]
@@ -1388,11 +1327,11 @@
 \end{sseqpage}
 \end{codeexample}
 
-You can use |\lastx| and |\lasty| in other contexts than in the body of a \sseqpages\ command, most notably inside |\sseqparseint| (they also go fine inside |\pgfmathparse| if you need it or one of its siblings). For instance, consider the following tower command:
+You can use |\lastx| and |\lasty| in other contexts than in the body of a \sseqpages\ command, most notably inside |\SseqParseInt| (they also go fine inside |\pgfmathparse| if you need it or one of its siblings). For instance, consider the following tower command:
 \begin{codeexample}[width=6cm]
 \DeclareSseqCommand \tower { } {
     \savestack
-    \sseqparseint\numclasses{\ymax-\lasty0}
+    \SseqParseInt\numclasses{\ymax-\lasty0}
     \foreach \n in {1,...,\numclasses}{
         \class(\lastx,\lasty+1)
         \structline
@@ -1420,16 +1359,16 @@
 \section{Styles}
 The \sseqpages\  package has a large number of styles which control the appearance of specific components (e.g., classes, differentials, or structure lines) 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\  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 ]
+\begin{sseqdata}[ name = style example ]
 \class(0,0)\class(1,1)
 \end{sseqdata}
-\begin{sseqpage}[ name = stylesex,
+\begin{sseqpage}[ name = style example,
                   classes = { fill, blue },
                   title = change new classes ]
 \class(0,1)\class(1,0)
 \end{sseqpage}
 \quad
-\begin{sseqpage}[ name = stylesex,
+\begin{sseqpage}[ name = style example,
                   change classes = { fill, blue },
                   title = change old classes ]
 \class(0,1)\class(1,0)
@@ -1524,7 +1463,7 @@
 \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|
+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 } ]
@@ -1612,20 +1551,20 @@
 
 \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|.
+The value of |class label handler| is a function that is applied to all labels before displaying them. It should put its output into |\result|.
 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.
+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 = { \sseqparseint\processedlabel{#1} }
+    class label handler = { \SseqParseInt\result{#1} }
 ]
 \class["1+1"](0,0)
 \class["1+2*(1+3*(4-1))"](1,1)
 \end{sseqpage}
 \end{codeexample}
-Here's an example using |\sseqnormalizemonomial|:
+Here's an example using |\SseqNormalizeMonomial|:
 \begin{codeexample}[width = 6cm]
 \NewSseqGroup \test {m} {
     \class["1#1"](0,0)
@@ -1634,7 +1573,7 @@
     \class["\alpha y#1"](1,1)
 }
 \begin{sseqpage}[
-    class label handler = { \sseqnormalizemonomial{#1} },
+    class label handler = { \SseqNormalizeMonomial{#1} },
     classes = { draw = none }, class labels = { font = \small } ]
 \test{}
 \test[red](2,0){y^2}
@@ -1643,13 +1582,13 @@
 \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.
+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.
 %\pgfmanualpdflabel{normalizemonomialex-labels}
 \begin{codeexample}[width=8cm]
 \begin{sseqpage}[
   xscale = 1.4,
   classes = { draw = none },
-  class label handler = {\sseqnormalizemonomial{#1}} ]
+  class label handler = {\SseqNormalizeMonomial{#1}} ]
 
 \foreach \x/\xlabel in
   { 0/1, 2/\iota_2, 3/{{Sq^1\iota_2}}, 4/\iota_2^2 }
@@ -1663,6 +1602,35 @@
 \end{key}
 
 
+\begin{key}{class name handler = \meta{function}}
+\declarecustomhandler{class name handler}{\codehandler}
+The value of |class name handler| is a function that is applied to all names before using them. It should put its output into |\result|.
+The main functions intended for use here are |\SseqAHSSNameHandler| and |\SseqNormalizeMonomial|, though you can make your own. This is applied both when you name the class, as in \codeverb|\class[name=a](\meta{coordinate})| and when you refer to a class by name, as in |\structline(a)(b)|. One advantage if you are using |\SseqNormalizeMonomial| is that you can ensure that |xy| and |yx| refer to the same class:
+\begin{codeexample}[]
+\SseqNormalizeMonomialSetVariables{xy}
+\begin{sseqpage}[ class name handler = \SseqNormalizeMonomial,
+                  classes = {show name = {right,pin}} ]
+\class[name=xy](0,0)
+\class[name=yxy](0,1)
+\class(1,0)
+\structline(yx)(yyx)
+\end{sseqpage}
+\end{codeexample}
+The next page is an example drawing the Atiyah Hirzebruch spectral sequence computing $KO^*\mathbb{R}P^{8}$.
+% Have to load from file so that \afterpage doesn't cause trouble with verbatim reading.
+\afterpage{%
+    An AHSS using \scantokens{|class name handler = \SseqAHSSNameHandler|:}
+    \par
+    \codeexample[from file=KORP8,vbox]
+    \newpage
+}
+\end{key}
+
+\begin{keylist}{class name prefix = \meta{prefix}, class name postfix = \meta{postfix}}
+These keys add respectively a prefix or a postfix to all names of all classes in the scope. This is applied both when you name the class, as in \codeverb|\class[name=a](\meta{coordinate})| and when you refer to a class by name, as in |\structline(a)(b)|.
+The prefix and postfix are added to the command before the |class name handler| is applied, so if you say |name=\meta{the name}| then the name actually given to the class is the value of |\result| after saying |\classnamehander{\meta{name prefix}\meta{the name}\meta{name postfix}}|
+\end{keylist}
+
 \section{Global Options}
 These options can only be set at the beginning of a \sseqdataenv\  or \sseqpageenv\  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}}
@@ -1698,7 +1666,7 @@
 \end{sseqpage}
 \end{codeexample}
 \begin{codeexample}[width = 6cm]
-% equivalent to degree = {-1}{#1-1}:
+% equivalent to degree = {-1}{#1}:
 \begin{sseqpage}[ Adams grading ]
 \class(0,2)
 \class(1,0)
@@ -1827,7 +1795,7 @@
 \end{key}
 
 
-\begin{key}{class placement transform = \marg{transform keys}, add class placement transform = \marg{transform keys} }
+\begin{keylist}{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\  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]
@@ -1853,7 +1821,7 @@
 \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:
+With multiple large class labels, 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,
@@ -1875,7 +1843,7 @@
 \class["\iota_2\beta P^1\iota_3"](8,2)
 \end{sseqpage}
 \end{codeexample}
-\end{key}
+\end{keylist}
 
 \begin{key}{math nodes = \meta{boolean} (default true)(initially true)}
 This key instructs \sseqpages\  to put all labels in math mode automatically.
@@ -1989,19 +1957,19 @@
 \end{keylist}
 
 \begin{keylist}{
-    x major tick step=\meta{nonnegative integer} (initially 0),
-    y major tick step=\meta{nonnegative integer} (initially 0),
-    major tick step=\meta{nonnegative integer},
-    x minor tick step=\meta{nonnegative integer} (initially 0),
-    y minor tick step=\meta{nonnegative integer} (initially 0),
-    minor tick step=\meta{nonnegative integer}%
+    x major tick step = \meta{nonnegative integer} (initially 0),
+    y major tick step = \meta{nonnegative integer} (initially 0),
+    major tick step = \meta{nonnegative integer},
+    x minor tick step = \meta{nonnegative integer} (initially 0),
+    y minor tick step = \meta{nonnegative integer} (initially 0),
+    minor tick step = \meta{nonnegative integer}%
 }
 If these are nonzero, they control the placement of tick marks on the axes. The value 0 prevents tick marks from being drawn. Uses |x tick offset| as an offset.
 \begin{codeexample}[width=7cm]
-\begin{sseqpage}[ 
+\begin{sseqpage}[
     tick step = 5,
-    major tick step = 5, 
-    minor tick step = 1, 
+    major tick step = 5,
+    minor tick step = 1,
     scale = 0.4,
     axes type = frame
 ]
@@ -2046,7 +2014,6 @@
 \end{codeexample}
 \end{keylist}
 
-\newpage
 \subsection{Layout}
 \begin{keylist}{x axis type = \meta{type} (initially border), y axis type = \meta{type} (initially border),axes type = \meta{type} (initially border), no x axis, no y axis, no axes}
 The \meta{type} is either |border|, |center|, |frame|, or |none|. |no axes| is a shorthand for |axes type=none|. The |border| type is the default and puts the axes on the bottom and left of the picture. The |center| type by default places the axes to pass through $(0,0)$; this can be modified using the |x axis origin| and |y axis origin| keys. See \example{KRAHSS} and \example{KUHFPSS} for examples where this is used. The |frame| type draws a frame around the entire chart:
@@ -2061,7 +2028,7 @@
 
 \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.
+If you use |axes type = 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)}
@@ -2073,7 +2040,7 @@
 \end{keylist}
 %
 \begin{keylist}{
-    x axis start extend = \meta{dimension} (initially 0.5cm), y axis start extend = \meta{dimension} (initially 0.5cm),
+    x axis extend start = \meta{dimension} (initially 0.5cm), y axis extend start = \meta{dimension} (initially 0.5cm),
     x axis extend end = \meta{dimension} (initially 0.5cm), y axis extend end = \meta{dimension} (initially 0.5cm),
     x axis tail = \meta{dimension} (initially 0.9cm), y axis tail = \meta{dimension} (initially 0.9cm)%
 }

Modified: trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/doc/latex/spectralsequences/manual/spectralsequencesmanualpreamble.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: spectralsequencesmanualpreamble.tex
@@ -14,7 +14,7 @@
 
 \documentclass{ltxdoc}
 \usepackage[a4paper,left=2.25cm,right=2.25cm,top=2.5cm,bottom=2.5cm,nohead]{geometry}
-\usepackage{spectralsequences}
+\usepackage[tooltips]{spectralsequences}
 \usetikzlibrary{shapes.geometric}
 \usepackage{amssymb}
 \usepackage{afterpage}
@@ -190,6 +190,9 @@
   \foreach \xx in {#2} {%
     \expandafter\extractkey\xx\space= \marg{keys}\@nil%
     \declareasstyle{\@xp\removespace\mykey\nil}% tells latex not to italicize body
+    % The link created in \extractkey is named "key name " with a space at the end.
+    % So it won't work. We need to make our own link without the space in it.
+    \sseq at eval{\@nx\pgfmanualpdflabel{\@xp\removespace\mykey\nil}{}}%
   }%
   \pgfmanualbody
 }{%
@@ -428,7 +431,16 @@
 }
 %\pgfqkeys{/codeexample}{every codeexample/.style={width=6cm}}
 
+% This macro in pgfmanual-en-macros.tex seems not to work because the call to \openin is wrong...
+\def\do at codeexamplefromfile{%
+  \immediate\openin\examplesource examples/spectralsequencesmanual-\codeexamplesource.tex\relax % I only changed this line
+  \def\examplelines{}%
+  \readexamplelines
+  \closein\examplesource
+  \expandafter\endofcodeexample\expandafter{\examplelines}%
+}
 
+
 \pgfqkeys{/sseqpages}{
     class/class:name/.forward to=/sseqpages/class/name,
     class/class:page/.forward to=/sseqpages/class/page,
@@ -440,7 +452,7 @@
 
 
 \hypersetup{
-    pdftitle={The Sseqpages Package},
+    pdftitle={The Spectralsequences Package},
     pdfauthor={Hood Chatham},
     pdfsubject={A spectral sequence drawing package build on tikz},
     pdfkeywords={spectral sequences,algebraic topology,homotopy theory,math,tikz,sseq},
@@ -463,7 +475,6 @@
 \def\targetn{\meta{target n}}
 \def\sourcename{\meta{source name}}
 
-\def\version{version 1.0.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}
@@ -515,5 +526,5 @@
   \end{center}\par\vskip1.5em}
 \def\abstractname{}
 \def\mailtoHC{\href % some PDF viewers don't like spaces:
-    {mailto:<hood at mit.edu>\%20Hood\%20Chatham?subject=[sseqpages]}
+    {mailto:<hood at mit.edu>\%20Hood\%20Chatham?subject=[spectralsequences\%20package]}
     {\texttt{hood at mit.edu}}} 
\ No newline at end of file

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% A package for drawing spectral sequences
@@ -10,8 +10,10 @@
 
 
 % TODO:
-%
+%  Try catch blocks
 %  Make an argument type for the \d page argument.
+%  deal with xmin, xmax, etc (was there actually a problem we were trying to fix?)
+%  Make xmirror not mirror axes labels
 %
 %  Redo sseqerrortest and set up regression test script as part of build (damn I didn't realize we'd lost anything imporant with that find -d disaster)
 %  Maybe we should add some other regression tests too
@@ -25,13 +27,12 @@
 
 
 \NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{spectralsequences}[2017/09/16 v1.1.1]
+\ProvidesPackage{spectralsequences}[2017/12/10 v1.2.0]
 
 \RequirePackage{tikz}
 \RequirePackage{etoolbox}
 \RequirePackage{xparse}
 \RequirePackage{verbatim}
-\RequirePackage{pdfcomment}
 
 \usetikzlibrary{quotes}
 \usetikzlibrary{fit}
@@ -44,9 +45,15 @@
 %\usetikzlibrary{profiler}
 
 \newif\ifsseq at draftmode
+\newif\ifsseq at tooltip
 \DeclareOption{draft}{\sseq at draftmodetrue}
+\DeclareOption{tooltips}{\sseq at tooltiptrue}
 \ProcessOptions\relax
 
+\ifsseq at tooltip
+    \RequirePackage{pdfcomment}
+\fi
+
 \def\sseq at authorname{Hood Chatham}
 \def\sseq at authoremail{hood at mit.edu}
 
@@ -54,12 +61,18 @@
 % Commands we are going to expose just inside of environments
 \def\sseq at macrolist{%
     \xcoord\ycoord\page %\xmin\xmax\ymin\ymax % these just get protected
+    % Defined in sseqmessages:
+    \quiet\endquiet
     % These are defined in sseqmain:
-    \class\classoptions\replaceclass\d\doptions\kill\structline\structlineoptions\circleclasses
+    \class\classoptions\replaceclass\replacesource\replacetarget
+    \d\doptions\kill\structline\structlineoptions\circleclasses
     % The following are defined in sseqparsers:
     \pgfmathparse\isalive\lastx\lasty\lastclass\savestack\restorestack\pushstack\nameclass\tagclass
     \parsecoordinate\parsedifferential\getdtarget\gettag
     \IfOutOfBoundsTF\IfOutOfBoundsT\IfOutOfBoundsF\IfInBoundsTF\IfInBoundsT\IfInBoundsF
+    \IfExistsTF\IfExistsT\IfExistsF\IfAliveTF\IfAliveT\IfAliveF
+    \IfValidDifferentialTF\IfValidDifferentialT\IfValidDifferentialF
+    \DrawIfValidDifferentialTF\DrawIfValidDifferentialT\DrawIfValidDifferentialF\DrawIfValidDifferential
     % sseqforeach
     \Do\DoUntilOutOfBounds\DoUntilOutOfBoundsThenNMore
 }
@@ -121,7 +134,7 @@
 \newcount\sseq at tempy
 \newcount\sseq at tempxb
 \newcount\sseq at tempyb
-\newcount\sseq at xoffset % We add these to everything to avoid overflow errors as much as we possible
+\newcount\sseq at xoffset % We add these to everything to avoid overflow errors as much as possible
 \newcount\sseq at yoffset
 
 \newcount\sseq at stackdepth
@@ -279,6 +292,7 @@
 \input sseqparsers.code.tex         % Responsible for making tikz modifications, exposes directly \sseqnormalizemonomial, \sseqparseint
 
 
+
 \ifsseq at patchforeach
     \input sseqforeach.code.tex
 \else
@@ -286,10 +300,21 @@
 \fi
 
 \input sseqkeys.code.tex            % Exposes directly: \sseqset, \sseqnewfamily
-\input sseqmain.code.tex            % Defines all the main commands. Exposes directly: the environments, \xmin, \xmax, etc.
+\input sseqmain.code.tex            % Defines all the main commands. Exposes directly: the environments, \xmin, \xmax, etc, \SseqCopyPage
 \input sseqdrawing.code.tex
 
+% Give standard definitions for savedpaths wrappers
+\def\sseq at beginscope@object{\begin{scope}}
+\def\sseq at endscope@object{\end{scope}}
+\let\sseq at scope@object\@firstofone
+\let\sseq at style@object\@firstofone
+\let\sseq at class@object\sseq at class@draw at ifpage
+\let\sseq at differential@object\sseq at differential@draw at ifpage
+\let\sseq at structline@object\sseq at structline@draw at ifpage
+\let\sseq at circleclass@object\sseq at circleclass@draw at ifpage
+\let\sseq at tikzpath@object\@firstofone
 
+
 %%% Some default key settings
 \sseqset{
     edge labels={auto=right},
@@ -301,8 +326,14 @@
     pins=help lines
 }
 
+\ifsseq at tooltip
+    \let\sseqtooltip\sseq at tooltip@wrapper
+\fi
+
 % Extra commands to expose:
 \let\sseqifempty\sseq at ifempty
+\let\SseqParseInt\sseqparseint
+\let\SseqNewFamily\sseqnewfamily
 
 \def\sseqpower#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{1}}
 \def\sseqpowerempty#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{}}

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqcheckdefinitions.code.tex

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqdrawing.code.tex
@@ -245,7 +245,7 @@
     \sseq at tickloop@generic{\sseq at xmin}{\sseq at xmax}{\sseq at xtickstep}{\sseq at xtickstepoffset}{\sseq at yaxisorigin}{-\sseq at xaxisgap}{
         \sseq at xtickstyle
         \tikz at options
-        \pgftransformshift{\pgfqpoint{0pt}{-\sseq at ylabelgap}}
+        \pgftransformshift{\pgfqpoint{0pt}{-\sseq at xlabelgap}}
         \pgftext{\hbox{$\sseq at xtickfn{\the\sseq at tempx}$}}%
     }
     \ifnum\sseq at xmajortickstep>\z@
@@ -565,7 +565,7 @@
     \sseq at tempy=#3\relax
 }
 
-\def\sseqtooltip#1#2{%
+\def\sseq at tooltip@wrapper#1#2{%
     \edef\temp{\detokenize\@xpthree{#2}}%
     \edef\temp{\@xp\sseqtooltip at replaceslashes\@xp{\temp}}%
     \sseq at eval{\@nx\pdftooltip{\unexpanded{#1}}{\temp}}%
@@ -627,7 +627,7 @@
             \fi
             \def\sseq at collections@featuretype{class}
             \the\sseq at scope@toks
-            \sseq at obj{#1.options}%
+            \sseq at obj{#1.options}
         \pgftransformshift{\pgfqpointxy{\numexpr\sseq at tempx +\sseq at xoffset-\sseq at x\relax}{\numexpr\sseq at tempy + \sseq at yoffset-\sseq at y\relax}}
         \iftikz at fullytransformed\pgfgettransform{\savetransform}\fi
         \pgftransformresetnontranslations
@@ -638,19 +638,28 @@
         }%
         \iftikz at fullytransformed\pgfsettransform{\savetransform}\else\pgftransformresetnontranslations\ifsseq at rotatelabels\sseq at globalrotatetransform\fi\fi
         \tikz at options
+        % the value of \sseq at class@showname comes from styles. If there was a local option with showname, it's stored in #1.showname.
+        % local value takes priority.
+        \let\sseq at classlabelnodes\pgfutil at empty
+        \edef\sseq at classnodetextoptions{\sseq at obj@ifdef{#1.nodetext.options}{\@xptwo\@nx\sseq at obj{#1.nodetext.options}}{}}
+        \edef\sseq at classnodetext{\sseq at obj@ifdef{#1.nodetext}{\@xptwo\@nx\sseq at obj{#1.nodetext}}{}}
+        \sseq at obj@ifdef{#1.showname}{\sseq at lettoobj\sseq at class@showname{#1.showname}}{}
+        \ifcsname sseq at class@showname\endcsname
+            \sseq at obj@ifdef{#1.name}{
+	            \sseq at eval{\@nx\sseq at handleclassquotes@inner{\sseq at obj{#1.name}}{\sseq at class@showname}}
+	       }{}
+        \fi
         \ifsseq at needstikz
             \let\sseq at mode\tikz at mode
-            \tikzset{every text node part/.code/.expand once={\sseq at globalrotatetransform\sseq at obj@ifdef{#1.nodetext.options}{\sseq at obj{#1.nodetext.options}}{}}}%
+            \tikzset{every text node part/.code/.expand once={\sseq at globalrotatetransform\sseq at classnodetextoptions{}}}%
             \sseq at eval{%
                 \@nx\node[/utils/exec={\let\@nx\tikz at mode\@nx\sseq at mode},
                     /handlers/first char syntax/the character "/.initial=\@nx\sseq at handlequote
-                ] (\sseq at thisnodename) {\sseq at obj@ifdef{#1.nodetext}{\unexpanded\@xpthree{\sseq at obj{#1.nodetext}}}{}}
+                ] (\sseq at thisnodename) {\unexpanded\@xp{\sseq at classnodetext}}
                 [every text node part/.code={}];
             }%
         \else
             \tikz at node@textfont
-            \edef\sseq at classnodetextoptions{\sseq at obj@ifdef{#1.nodetext.options}{\@xptwo\@nx\sseq at obj{#1.nodetext.options}}{}}
-            \edef\sseq at classnodetext{\sseq at obj@ifdef{#1.nodetext}{\@xptwo\@nx\sseq at obj{#1.nodetext}}{}}
             \sseq at setnodetext{\sseq at classnodetext}{\sseq at classnodetextoptions}
             \let\tikz at fig@name\sseq at thisnodename
             \pgfmultipartnode{\tikz at shape}{\tikz at anchor}{\tikz at fig@name}{\sseq at drawnode}%
@@ -657,6 +666,7 @@
             \tikz at alias
         \fi
         \sseq at obj{#1.labelnodes}
+        \sseq at classlabelnodes % classlabelnodes comes from show name
         \sseq at obj@ifdef{#1.tooltip}{
             \pgfpointanchor{\sseq at thisnodename}{west}
             \pgf at xa=\pgf at x
@@ -880,10 +890,10 @@
     % If either class is part of a family we aren't drawing, don't draw the edge either.
     \expandafter\ifx\csname pgf at sh@pi at sseq{#1}\endcsname\pgfpictureid\else
         \@xp\sseq at break
-    \fi    
+    \fi
     \expandafter\ifx\csname pgf at sh@pi at sseq{#2}\endcsname\pgfpictureid\else
         \@xp\sseq at break
-    \fi    
+    \fi
     \def\sseq at edgetype{#3}
     \let\sseq at collections@featuretype\sseq at edgetype
     \let\sseq at edgesourceanchor\pgfutil at empty

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqforeach.code.tex
@@ -68,7 +68,7 @@
 \def\sseq at DoUntilOutOfBounds@ #1 {
     \sseq at esetthiscall{\string\DoUntilOutOfBoundsThenNMore}
     \sseq at opushstacktrace{\string\DoUntilOutOfBounds}
-    \ifx\xmin\sseq at xmin\else\ifx\ymin\sseq at ymin\else
+    \ifx\sseq at xminmax\@gobbletwo\else\ifx\sseq at yminmax\@gobbletwo\else
         \sseq at error@x{DoUntil-no-bound}{\string\DoUntilOutOfBounds}
         \sseq at breakfifi
     \fi\fi
@@ -90,7 +90,7 @@
 \def\sseq at DoUntilOutOfBoundsThenNMore@ #1#2 {
     \sseq at esetthiscall{\string\DoUntilOutOfBoundsThenNMore\unexpanded{#1}}
     \sseq at opushstacktrace{\string\DoUntilOutOfBoundsThenNMore{#1}}
-    \ifx\xmin\sseq at xmin\else\ifx\ymin\sseq at ymin\else
+    \ifx\sseq at xminmax\@gobbletwo\else\ifx\sseq at yminmax\@gobbletwo\else
         \sseq at error@n{DoUntil-no-bound}{\DoUntilOutOfBoundsThenNMore}
         \sseq at breakfifi
     \fi\fi
@@ -131,7 +131,7 @@
             \sseq at tempy=\lasty{0}\relax
             \bool_set_false:N \l_tmpb_bool % This is to record whether there is a defined x range or y range. If neither, we'll throw an error.
 %            \def\sseq at checkbound{\bool_set_false:N \l_tmpb_bool}
-            \ifx\xmin\sseq at xmin
+            \ifx\sseq at xminmax\@gobbletwo
                 \ifnum\sseq at tempx>\sseq at tempxb
                     \bool_set_true:N \l_tmpb_bool % We have a descent condition
 %                    \sseq at d@addto at macro\sseq at checkbound{
@@ -150,7 +150,7 @@
                     \fi
                 \fi
             \fi
-            \ifx\ymin\sseq at ymin
+            \ifx\sseq at yminmax\@gobbletwo
                 \ifnum\sseq at tempy>\sseq at tempyb
                     \bool_set_true:N \l_tmpb_bool
 %                    \sseq at d@addto at macro\sseq at checkbound{

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqkeys.code.tex
@@ -203,6 +203,7 @@
     }%
 }
 
+
 \def\sseq at keys@unknown at handlecolor{%
   \sseq at add@tikzkey at to@options{\@nx\sseq at options@secondpass{\@nx\tikz at addoption{\@nx\tikz at compat@color at set{\tikz at key}}}}%
   \sseq at add@tikzkey at to@options{\@nx\sseq at options@secondpass{\def\@nx\tikz at textcolor{\tikz at key}}}%
@@ -294,6 +295,7 @@
     \fi
 }
 
+
 % This has to be expandable, so \sseq at tempa and \sseq at tempb are set to "/tikz/" and "/pgf/" ahead of time
 % Defer the command if it is in directories /pgf or /tikz, otherwise run it now. TODO: explain here why we need this.
 \def\sseq at options@secondpass at iftikz{%
@@ -386,6 +388,7 @@
     \@ifnextchar[{\sseq at setlabeldirectionkeys@{#1}}{\sseq at setlabeldirectionkeys@{#1}[/.code]}%]
 }
 \def\sseq at setlabeldirectionkeys@#1[#2]#3{
+    \bgroup
     \def\sseq at temp##1{#3}
     \sseq at temptoks{}
     \def\\##1{
@@ -392,11 +395,12 @@
         \sseq at eval{\sseq at temptoks{\the\sseq at temptoks##1#2={\unexpanded\@xp{\sseq at temp{##1}}},}}
     }
     \sseq at labeldirectionlist
-    \sseq at eval{\@nx\pgfqkeys{#1}{\the\sseq at temptoks}}
+    \sseq at eval{\egroup\@nx\pgfqkeys{#1}{\the\sseq at temptoks}}
 }
-
+\begingroup
 \def\\#1{\@xp\sseq at addtostorelist\csname sseq at default@#1 at distance\endcsname{1ex}}
 \sseq at labeldirectionlist
+\endgroup
 \def\sseq at defaultlabeldistance#1{\@xp\csname sseq at default@#1 at distance\endcsname}
 \def\sseq at setdefaultlabeldistance#1#2{\sseq at savedpaths@add{\@xp\gdef\csname sseq at default@#1 at distance\endcsname{#2}}}
 \def\sseq at setdefaultlabeldistances#1{\def\\##1{\sseq at setdefaultlabeldistance{##1}{#1}}\sseq at labeldirectionlist}
@@ -419,8 +423,11 @@
 
 
 
-\sseq at addtostorelist\sseq at classlabeltextfn{} % \sseq at classlabeltextfn is public via "class label handler"
-\def\sseq at classlabeltextfn@default#1{\def\processedlabel{#1}}
+\sseq at addtostorelist\sseq at classlabel@handler{} % \sseq at classlabel@handler is public via "class label handler"
+\def\sseq at classlabel@handler at default#1{\def\result{#1}}
+\sseq at addtostorelist\sseq at classname@handler{} % \sseq at classname@handler is public via "class name handler"
+\def\sseq at classname@handler at default#1{\def\result{#1}}
+
 \def\sseq at labeltextfn#1{#1} % labeltextfn is private
 \def\sseq at labeltextfn@rotatescale#1{%
     \@nx\ifmmode
@@ -488,13 +495,13 @@
     }
 }
 
-
+% We just do the parsing in sseqkeys, \sseq at handleclassquotes@inner which does the main work is defined sseqmain.
 \def\sseq at handlescopequotes#1#2{% We use this via \let\tikz at quotes@as\sseq at handleclassquotes
     /utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out.
        \global\let\sseq at classnodetext\pgfutil at empty%
        \global\let\sseq at classnodetextoptions\pgfutil at empty%
        \global\let\sseq at classlabelnodes\pgfutil at empty%
-       \sseq at handleclassquotes@inner{#1}{#2}%
+       \sseq at handleclassquotes@inner{#1}{#2}
     }
 }
 
@@ -535,7 +542,6 @@
     \let\structline\sseq at structline
 }
 
-
 \sseq at pgfqkeysdirlist{/sseqpages,/sseqpages/tikz primitives}{%
     standard parse/.code={
         \let\sseq at firstpass@shifttransform\@gobbletwo
@@ -556,6 +562,7 @@
     /tikz/handle quote/.code={\sseq at error{tikz-edge-quotes}}
 }
 
+
 \sseq at pgfqkeysdirlist{/sseqpages/class,/sseqpages/differential}{
     standard parse/.sseq @ first pass code={\sseq at error@n{option-tikz-prims-only}{standard parse}},
     background/.sseq @ first pass code={\sseq at error@n{option-tikz-prims-only}{background}}
@@ -575,14 +582,25 @@
 }
 
 \def\sseq at classinsert{}
+\def\sseq at classnameprefix{}
+\def\sseq at classnamepostfix{}
+\pgfqkeys{/sseqpages}{
+	class name prefix/.store in=\sseq at classnameprefix,
+	class name postfix/.store in=\sseq at classnamepostfix
+}
+
 \pgfqkeys{/sseqpages/class}{
-    name/.code={\def\sseq at class@name{#1}\pgfkeysalso{/sseqpages/alias=#1}},
+    name/.code={%
+	\sseq at protectedeval{\@nx\sseq at classname@handler{\sseq at classnameprefix#1\sseq at classnamepostfix}}%
+	\edef\sseq at class@name{\unexpanded\@xp{\result}}%
+	\pgfkeysalso{/sseqpages/alias/.expand once=\detokenize\@xp{\sseq at class@name}}%
+    },
     show name/.store in=\sseq at class@showname,
     page/.code={\sseq at getnumrange\sseq at class@page{#1}},% page & gen are only for \classoptions.
     generation/.code={\sseq at getnumrange\sseq at gen{#1}}, % \class tests if \sseq at class@page is set and throw an error if so.
     tag/.code={\sseq at d@addto at macro\sseq at class@tag{#1}},
     offset/.store in=\sseq at tempoffset,
-    tooltip/.sseq @ first pass code={\def\sseq at tooltip{#1}},
+    tooltip/.sseq @ first pass code={\ifx\sseqtooltip\undefined \sseq at error{no-tooltip}\else \def\sseq at tooltip{#1}\fi},
     insert/.store in=\sseq at classinsert
 }
 
@@ -792,7 +810,7 @@
         #1s/.ecode={%
             \@nx\sseq at addstylecodetotoks{\sseq at tempcmd}{\sseq at temppath}{##1}
             \@nx\ifsseq at inprogress
-                \@nx\sseq at savedpaths@xadd{\sseq at tempcmd{\@nx\the\sseq at tempcmd}}%
+                \@nx\sseq at savedpaths@xadd{\@nx\sseq at style@object{\sseq at tempcmd{\@nx\the\sseq at tempcmd}}}%
             \@nx\fi
         },%
         change #1s/.ecode={%
@@ -826,7 +844,7 @@
         }%
         \sseq at addstylecodetomacro\sseq at sseqstyle@globalpart{/sseqpages/global}{#1}%
         \ifsseq at inprogress
-            \sseq at savedpaths@xadd{\sseq at sseqstyle{\the\sseq at sseqstyle}}%
+            \sseq at savedpaths@xadd{\@nx\sseq at style@object{\sseq at sseqstyle{\the\sseq at sseqstyle}}}%
         \fi
         % Restore hook
         \let\sseq at addstylecodetooptions@unknown\sseq at keys@unknown
@@ -892,8 +910,8 @@
 %%  Families (also called collections in code)
 %%
 %%    These are supposed to make it easy to display / hide and change appearance of logically connected families of classes.
-%%    In order to allow a set of options to be given that applies uniformly to all features, we separately apply the options in each of these bins.    
-%%    
+%%    In order to allow a set of options to be given that applies uniformly to all features, we separately apply the options in each of these bins.
+%%
 
 
 \def\sseq at featurelist{\\{class}\\{differential}\\{structline}\\{circleclass}\\{tikzprimitive}}
@@ -1311,9 +1329,11 @@
 }
 \def\sseq at keys@removehandler#1{\sseq at keys@removehandler@#1=\sseq at nil}
 \def\sseq at keys@removehandler@#1/.#2=#3\sseq at nil{%
+    \bgroup
     \def\sseq at temp{#2}%
-    \def\\##1{\def\sseq at tempii{##1}\ifx\sseq at tempii\sseq at temp \sseq at tempiffalse\let\\\@gobble\fi}%
+    \def\\##1{\def\sseq at tempii{##1}\ifx\sseq at tempii\sseq at temp \global\sseq at tempiffalse\let\\\@gobble\fi}%
     \sseq at keys@ignorehandlers
+    \egroup
     \def\sseq at temp{#1}%
 }
 
@@ -1477,6 +1497,7 @@
 
 \sseq at addiftostorelist{specifiedxrange}
 \sseq at addiftostorelist{specifiedyrange}
+% We used to \let\xmin\sseq at xmin in here, but that's a bad idea. Hopefully things work now...
 \def\sseq at xrange#1#2{%
     \global\let\sseq at xminmax\@gobbletwo % Don't need to calculate range of nodes if user specifies it
     \global\sseq at specifiedxrangetrue
@@ -1484,22 +1505,19 @@
     \sseq at sanitize@intexpr{#2}{x range={#1}{#2}}
     \xdef\sseq at xmin{\the\numexpr#1}%
     \xdef\sseq at xmax{\the\numexpr#2}%
-    \let\xmin\sseq at xmin
-    \let\xmax\sseq at xmax
     % Need to know decremented \xmin and incremented \xmax to decide which nodes to print
     \sseq at tempcount=#1 \advance\sseq at tempcount-1\xdef\sseq at xminmm{\the\sseq at tempcount}%
     \sseq at tempcount=#2 \advance\sseq at tempcount1\xdef\sseq at xmaxpp{\the\sseq at tempcount}%
     \sseq at breakpoint
 }
+
 \def\sseq at yrange#1#2{%
     \global\let\sseq at yminmax\@gobbletwo %
-    \sseq at sanitize@intexpr{#1}{x range={#1}{#2}}
-    \sseq at sanitize@intexpr{#2}{x range={#1}{#2}}
+    \sseq at sanitize@intexpr{#1}{y range={#1}{#2}}
+    \sseq at sanitize@intexpr{#2}{y range={#1}{#2}}
     \global\sseq at specifiedyrangetrue
-    \gdef\sseq at ymin{#1}%
-    \gdef\sseq at ymax{#2}%
-    \let\ymin\sseq at ymin
-    \let\ymax\sseq at ymax
+    \xdef\sseq at ymin{\the\numexpr#1}%
+    \xdef\sseq at ymax{\the\numexpr#2}%
     \sseq at tempcount=#1 \advance\sseq at tempcount-1\xdef\sseq at yminmm{\the\sseq at tempcount}%
     \sseq at tempcount=#2 \advance\sseq at tempcount1\xdef\sseq at ymaxpp{\the\sseq at tempcount}%
 }
@@ -1625,30 +1643,54 @@
     x tick handler/.sseq default code={\def\sseq at xtickfn@default##1{#1}},
     y tick handler/.code={\def\sseq at ytickfn##1{#1}},
     y tick handler/.sseq default code={\def\sseq at ytickfn@default##1{#1}},
-    class label handler/.code = { % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...)
-        \long\def\sseq at classlabeltextfn##1{#1}
-        \ifx\sseq at classlabeltextfn\@gobble
-            \def\sseq at classlabeltextfn##1{\def\processedlabel{##1}}
+    class label handler/.code = { % \long so that \ifx\sseq at classname@handler\@gobble compares true if this is empty (\@gobble is long...)
+        \long\def\sseq at classlabel@handler##1{#1}
+        \ifx\sseq at classlabel@handler\@gobble
+            \def\sseq at classlabel@handler##1{\def\result{##1}}
         \else
-            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabeltextfn{}}}
-            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabeltextfn{blah}}}
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabel@handler{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabel@handler{blah}}}
             \ifx\sseq at tempa\sseq at tempb
-                \long\def\sseq at classlabeltextfn##1{#1{##1}}
+                \long\def\sseq at classlabel@handler##1{#1{##1}}
             \fi
         \fi
     },
     class label handler/.sseq default code={
-        \long\def\sseq at classlabeltextfn@default##1{#1}
-        \ifx\sseq at classlabeltextfn@default\@gobble
-            \def\sseq at classlabeltextfn@default##1{\def\processedlabel{##1}}
+        \long\def\sseq at classlabel@handler at default##1{#1}
+        \ifx\sseq at classlabel@handler at default\@gobble
+            \def\sseq at classlabel@handler at default##1{\def\result{##1}}
         \else
-            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabeltextfn@default{}}}
-            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabeltextfn@default{blah}}}
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabel@handler at default{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabel@handler at default{blah}}}
             \ifx\sseq at tempa\sseq at tempb
-                \long\def\sseq at classlabeltextfn@default##1{#1{##1}}
+                \long\def\sseq at classlabel@handler at default##1{#1{##1}}
             \fi
         \fi
     },
+    class name handler/.code = { % \long so that \ifx\sseq at classname@handler\@gobble compares true if this is empty (\@gobble is long...)
+        \long\def\sseq at classname@handler##1{#1}
+        \ifx\sseq at classname@handler\@gobble
+            \def\sseq at classname@handler##1{\def\result{##1}}
+        \else
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classname@handler{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classname@handler{blah}}}
+            \ifx\sseq at tempa\sseq at tempb
+                \long\def\sseq at classname@handler##1{#1{##1}}
+            \fi
+        \fi
+    },
+    class name handler/.sseq default code={
+        \long\def\sseq at classname@handler at default##1{#1}
+        \ifx\sseq at classname@handler at default\@gobble
+            \def\sseq at classname@handler at default##1{\def\result{##1}}
+        \else
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classname@handler at default{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classname@handler at default{blah}}}
+            \ifx\sseq at tempa\sseq at tempb
+                \long\def\sseq at classname@handler at default##1{#1{##1}}
+            \fi
+        \fi
+    },
     x tick style/.sseq store in=\sseq at xtickstyle{},
     y tick style/.sseq store in=\sseq at ytickstyle{},
     tick style/.sseq x y alias,
@@ -1700,17 +1742,29 @@
 \let\sseq at axistypesanitizer\sseq at axistypesanitizera
 
 \pgfqkeys{/sseqpages}{%
-    class label handler/.code = { % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...)
-        \long\def\sseq at classlabeltextfn##1{#1}
-        \ifx\sseq at classlabeltextfn\@gobble
-            \def\sseq at classlabeltextfn##1{\def\processedlabel{##1}}
+    class label handler/.code = { % \long so that \ifx\sseq at classlabel@handler\@gobble compares true if this is empty (\@gobble is long...)
+        \long\def\sseq at classlabel@handler##1{#1}
+        \ifx\sseq at classlabel@handler\@gobble
+            \def\sseq at classlabel@handler##1{\def\result{##1}}
         \else
-            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabeltextfn{}}}
-            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabeltextfn{blah}}}
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classlabel@handler{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classlabel@handler{blah}}}
             \ifx\sseq at tempa\sseq at tempb
-                \long\def\sseq at classlabeltextfn##1{#1{##1}}
+                \long\def\sseq at classlabel@handler##1{#1{##1}}
             \fi
         \fi
+    },
+    class name handler/.code = { % \long so that \ifx\sseq at classname@handler\@gobble compares true if this is empty (\@gobble is long...)
+        \long\def\sseq at classname@handler##1{#1}
+        \ifx\sseq at classname@handler\@gobble
+            \def\sseq at classname@handler##1{\def\result{##1}}
+        \else
+            \edef\sseq at tempa{\unexpanded\@xp{\sseq at classname@handler{}}}
+            \edef\sseq at tempb{\unexpanded\@xp{\sseq at classname@handler{blah}}}
+            \ifx\sseq at tempa\sseq at tempb
+                \long\def\sseq at classname@handler##1{#1{##1}}
+            \fi
+        \fi
     }
 }
 
@@ -1762,7 +1816,11 @@
 }
 \def\sseq at globalscaleoption#1{%
     \sseq at globaldetonefalse
-    \@xp\gdef\@xp\sseq at globalscaletransform\@xp{\sseq at globalscaletransform#1}%
+    \@ifundefined{sseq at globalscaletransform}{
+        \@xp\gdef\@xp\sseq at globalscaletransform@default\@xp{\sseq at globalscaletransform@default#1}%
+    }{
+        \@xp\gdef\@xp\sseq at globalscaletransform\@xp{\sseq at globalscaletransform#1}%
+    }
 }
 \pgfqkeys{/sseqpages/global}{%
     x/.sseq @ illegal,
@@ -1802,8 +1860,13 @@
             \sseq at break
         \fi
         \sseq at globalscaleoption{\pgfsetxvec{\pgfpointxy{#1}{0}}}
-        \pgfmathparse{\sseq at xscale*#1}
-        \edef\sseq at xscale{\pgfmathresult}
+        \@ifundefined{sseq at xscale}{
+            \pgfmathparse{\sseq at xscale@default*#1}
+            \edef\sseq at xscale@default{\pgfmathresult}
+        }{
+            \pgfmathparse{\sseq at xscale*#1}
+            \edef\sseq at xscale{\pgfmathresult}
+        }
         \sseq at breakpoint
     },
     xscale/.value required,
@@ -1821,8 +1884,13 @@
             \sseq at break
         \fi
         \sseq at globalscaleoption{\pgfsetyvec{\pgfpointxy{0}{#1}}}
-        \pgfmathparse{\sseq at yscale*#1}
-        \edef\sseq at yscale{\pgfmathresult}
+        \@ifundefined{sseq at yscale}{
+            \pgfmathparse{\sseq at yscale@default*#1}
+            \edef\sseq at yscale@default{\pgfmathresult}
+        }{
+            \pgfmathparse{\sseq at yscale*#1}
+            \edef\sseq at yscale{\pgfmathresult}
+        }
         \sseq at breakpoint
     },
     yscale/.value required,

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqloadstore.code.tex
@@ -97,7 +97,9 @@
 \def\sseq at obj@xoaddto#1{\sseq at obj@ifundef{#1}{\sseq at obj@xodef{#1}}{\@xp\sseq at g@addto at macro\csname \sseq at obj@fullname{#1}\@xp\endcsname\@xp}}
 \def\sseq at obj@map#1#2{\def\\##1{#2}\sseq at obj{#1}}
 
+\def\sseq at lettoobj#1#2{\sseq at obj@ifdef{#2}{\@xp\let\@xp#1\csname\sseq at obj@fullname{#2}\endcsname}{\let#1\empty}}
 
+
 \def\sseq at obj@ifchanged#1#2#3{\sseq at obj@ifundef{#1.changed}{#3}{#2}}
 \def\sseq at obj@changedtrue#1{\sseq at obj@gdef{#1.changed}{}}
 \def\sseq at obj@changedfalse#1{\sseq at obj@undef{#1.changed}}
@@ -124,10 +126,10 @@
 % This simplifies the code a lot because I don't have to check again where I should put things.
 \sseq at addtostorelist\sseq at savedpaths{}
 \def\sseq at tempsavedpaths{}
-\def\sseq at savedpaths@addclass at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at class@draw at ifpage{#1}}}
-\def\sseq at savedpaths@adddifferential at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at differential@draw at ifpage{#1}}}
-\def\sseq at savedpaths@addstructline at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at structline@draw at ifpage{#1}}}
-\def\sseq at savedpaths@xaddtikzpath at standard#1{\sseq at x@addto at macro\sseq at savedpaths{#1}}
+\def\sseq at savedpaths@addclass at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at class@object{#1}}}
+\def\sseq at savedpaths@adddifferential at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at differential@object{#1}}}
+\def\sseq at savedpaths@addstructline at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at structline@object{#1}}}
+\def\sseq at savedpaths@xaddtikzpath at standard#1{\sseq at x@addto at macro\sseq at savedpaths{\@nx\sseq at tikzpath@object{#1}}}
 \def\sseq at savedpaths@add at standard{\sseq at g@addto at macro\sseq at savedpaths}
 \def\sseq at savedpaths@xadd at standard{\sseq at x@addto at macro\sseq at savedpaths}
 \def\sseq at savedpaths@show at standard{\show\sseq at savedpaths}

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqmacromakers.code.tex

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqmain.code.tex
@@ -63,6 +63,12 @@
     \sseq at installmacros
     \sseq at installmsghooks
     \sseq at install@xparse at Uarggrabber
+    % The behavior of xmax and xmin is very particular, so it's best not to mess with them. 
+    % In particular, they shouldn't be expanded until printing no matter what, but we don't want
+    % \pgfmathparse to barf on them. \pgfmathparse really doesn't like engine protected macros,
+    % so in no case should this be engine protected. (Wish we could test an argument for the presence 
+    % of engine protected macros). If we try to do that, \sseq at ifpgfmathexpr will break in 
+    % \sseq at tikzprimitives@coords at notaclass@handle at .
     \def\xmin{\protect\sseq at xmin}\def\xmax{\protect\sseq at xmax}
     \def\ymin{\protect\sseq at ymin}\def\ymax{\protect\sseq at ymax}
 %
@@ -96,7 +102,7 @@
         \global\let\@xp\@nx\csname pgfk@/sseqpages/global/{\sseq at currentoptionpath} options/. at cmd\endcsname
             \@xp\@nx\csname pgfk@/sseqpages/global/{\sseq at currentoptionpath} options/. at cmd\endcsname
     }
-    \sseq at savedpaths@xadd{\sseq at stylelist}
+    \sseq at savedpaths@xadd{\@nx\sseq at style@object{\sseq at stylelist}}
     \sseq at savedpaths@add{\begingroup} % prevent some of the two-pass user macros horrors
     \let\sseq at error@setup\sseq at error@setup at withinfo
 }
@@ -218,6 +224,10 @@
 %
     \ifx\sseq at xmin\sseq at infinity\sseq at error{no-range}\def\sseq at xmin{0}\def\sseq at xmax{0}\@xp\sseq at break\fi % could be warning
     \ifx\sseq at ymin\sseq at infinity\sseq at error{no-range}\def\sseq at ymin{0}\def\sseq at ymax{0}\@xp\sseq at break\fi
+    \let\xmin\sseq at xmin
+    \let\xmax\sseq at xmax
+    \let\ymin\sseq at ymin
+    \let\ymax\sseq at ymax
 %
     \ifnum\numexpr\sseq at xmax-\sseq at xmin\relax>\numexpr\maxdimen/\dimexpr1pt\relax-1\relax
         \sseq at error@xx{range-super-overflow}{x}
@@ -266,7 +276,6 @@
     \sseq at setlayoutparameters
     \begin{tikzpicture}[/sseqpages/global/{default} options,\ifsseq at hasname/sseqpages/global/{\sseq at thename} options\fi,/sseqpages/global/{this page} options]%
     \sseq at sseqstyle@globalpart
-    %\pgftransformreset
     \sseq at globaldetonetransform
     \sseq at globalscaletransform
 %
@@ -315,7 +324,6 @@
     \ifsseq at mathnodes
         \tikzset{execute at begin node=$,execute at end node=$}%
     \fi
-    %\let\sseq at error@setup\sseq at error@setup at withinfo
 %
     \begingroup
     \sseq at savedbackgroundpaths
@@ -324,10 +332,10 @@
     \sseq at useclip
 %
     \ifsseq at drawdifferentials\else
-        \let\sseq at differential@draw at ifpage\@gobble
+        \let\sseq at differential@object\@gobble
     \fi
     \ifsseq at drawstructlines\else
-        \let\sseq at structline@draw at ifpage\@gobble
+        \let\sseq at structline@object\@gobble
     \fi
 %
     \sseq at usesavedpaths
@@ -351,12 +359,48 @@
     \end{sseqpage}%
 }
 
+
+\def\SseqCopyPage#1#2#3{
+    \begingroup
+    \def#1{\begingroup}
+    \global\let\sseq at copymacro\empty
+    \def\sseq at thename{#2}
+    \global\let\sseq at savedpaths@save\sseq at savedpaths
+    \sseq at storelist@get\sseq at savedpaths
+    \def\sseq at thepage{#3}
+    \sseq at thepagecount=#3\relax
+    \def\sseq at beginscope@object{\sseq at g@addto at macro#1{\sseq at savedpaths@add{\sseq at beginscope@object}}}
+    \def\sseq at endscope@object{\sseq at g@addto at macro#1{\sseq at savedpaths@add{\sseq at endscope@object}}}
+    \def\sseq at scope@object##1{\sseq at g@addto at macro#1{\sseq at savedpaths@add{\sseq at scope@object{##1}}}}
+    \def\sseq at style@object##1{\sseq at g@addto at macro#1{\sseq at savedpaths@add{\sseq at style@object{##1}}}}
+    \let\sseq at class@drawnode\sseq at copypage@addclass
+    \let\sseq at differential@object\@gobble
+    \let\sseq at structline@draw\sseq at copypage@addstructline
+    \let\sseq at tikzpath@object\@gobble
+    \let\sseq at pgfkeysdocommand\@gobbletwo
+    \sseq at savedpaths
+    \sseq at g@addto at macro#1{\endgroup}
+    \endgroup
+    \@xp\let\csname\sseq at macroname#1 code\endcsname\sseq at copymacro
+    \DeclareSseqGroup #1 {} { \csname\sseq at macroname#1 code\endcsname }
+    \let\sseq at savedpaths\sseq at savedpaths@save
+}
+
+\def\sseq at copypage@addclass#1{
+    \sseq at x@addto at macro\sseq at copymacro{\@nx\sseq at class@copy{\sseq at thename}{#1}}
+}
+
+\def\sseq at copypage@addstructline#1{
+    \sseq at x@addto at macro\sseq at copymacro{\@nx\sseq at structline@copy{\sseq at thename}{#1}}
+}
+
+
 %%% Scope
 \newcount\sseq at scope@savestackid
 \def\sseq at scope@secondpasstoks{}
 \def\sseq at scope{\@ifnextchar[{\sseq at scope@}{\sseq at scope@[]}}%]
 \def\sseq at scope@[#1]{%
-    \sseq at scope@savedpaths at add{\begin{scope}}%
+    \sseq at scope@savedpaths at add{\sseq at beginscope@object}%
     % This is a funky hack to fix a problem with shifts. On tmfass, if we don't handle shifts specially, we actually put so much stuff into
     % this \sseq at scope@secondpasstoks macro that we exceed TeX's upper bound for the maximum total macro memory. Or something like that -- I don't understand the error,
     % but it definitely only depends on how much stuff there is overall and on there being lots of scopes, not on any particular part of the diagram.
@@ -364,12 +408,12 @@
     \let\sseq at options@scopeshiftsecondpass\sseq at scope@savedpaths at add
     \sseq at processoptions{scope}{#1}% outputs into \sseq at savedoptioncode
     \edef\sseq at scope@secondpasstoks{\unexpanded\@xp{\sseq at scope@secondpasstoks}\unexpanded\@xp{\sseq at savedoptioncode}}
-    \sseq at eval{\@nx\sseq at scope@savedpaths at add{\sseq at scope@toks{\unexpanded\@xp{\sseq at scope@secondpasstoks}}}}%
+    \sseq at eval{\@nx\sseq at scope@savedpaths at add{\@nx\sseq at scope@object{\sseq at scope@toks{\unexpanded\@xp{\sseq at scope@secondpasstoks}}}}}%
     %\advance\sseq at scope@savestackid\@ne
     %\sseq at savestack@name{scope at save\the\sseq at scope@savestackid}
 }
 \def\sseq at endscope{%
-    \sseq at scope@savedpaths at add{\end{scope}}
+    \sseq at scope@savedpaths at add{\sseq at endscope@object}
     %\sseq at restorestack@name{scope at save\the\sseq at scope@savestackid
 }
 
@@ -411,11 +455,11 @@
             \sseq at obj@xdef{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{\nodenum}%
         \fi
         \ifx\sseq at class@name\pgfutil at empty\else
-            \sseq at cleanup@obj{class.\classname.name}
-            \sseq at cleanup@obj{class.namedclass.\sseq at class@name}
+            \sseq at cleanup@obj{\classname.name}
+            \sseq at cleanup@obj{class.namedclass.\detokenize\@xp{\sseq at class@name}}
             \sseq at namehandler
-            \sseq at obj@xdef{class.\classname.name}{\sseq at class@name}
-            \sseq at obj@xdef{class.namedclass.\sseq at class@name}{\coordnopar}
+            \sseq at obj@xdef{\classname.name}{\sseq at class@name}
+            \sseq at obj@xdef{class.namedclass.\detokenize\@xp{\sseq at class@name}}{\coordnopar}
         \fi
         \sseq at breakpoint
         \endgroup
@@ -463,7 +507,14 @@
         \sseq at breakfi
     \fi
 %%%% No more breaks after this point
+
+    \sseq at processlabels % This sets up the label nodes, now that we know the position of the class (I think that's what we needed?)
+    \sseq at class@main % We segment off the main part of the class so that we can call it separately from the copy method
+    \sseq at breakpoint
+    \endgroup
+}
 %
+\def\sseq at class@main{
     \ifx\sseq at classinsert\empty
         % by default, just insert to the right of previous classes
         \edef\sseq at classinsert{\nodenum}
@@ -483,7 +534,6 @@
         \fi
     \fi
 %
-    \sseq at processlabels % This sets up the label nodes, now that we know the position of the class (I think that's what we needed?)
 %
     \sseq at xminmax{\xcoord}{\ycoord}%
     \sseq at yminmax{\xcoord}{\ycoord}%
@@ -500,15 +550,11 @@
         \sseq at obj@xdef{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{\nodenum}%
     \fi
     \ifx\sseq at class@name\pgfutil at empty\else
-        \sseq at cleanup@obj{class.\classname.name}
-        \sseq at cleanup@obj{class.namedclass.\sseq at class@name}
-        \sseq at namehandler
-        \sseq at obj@xdef{class.\classname.name}{\sseq at class@name}
-        \sseq at obj@xdef{class.namedclass.\sseq at class@name}{\coordnopar}
+        \sseq at cleanup@obj{\classname.name}
+        \sseq at cleanup@obj{class.namedclass.\detokenize\@xp{\sseq at class@name}}
+        \sseq at obj@xdef{\classname.name}{\sseq at class@name}
+        \sseq at obj@xdef{class.namedclass.\detokenize\@xp{\sseq at class@name}}{\coordnopar}
     \fi
-    \ifcsname sseq at class@showname\endcsname
-        \sseq at eval{\@nx\sseq at handleclassquotes{\sseq at obj{class.\classname.name}}{\sseq at class@showname}}
-    \fi
     \sseq at pushstack@\coord
 %
 %
@@ -530,6 +576,9 @@
     \ifx\sseq at classlabelnodes\pgfutil at empty\else
         \sseq at obj@xodef{\classname.labelnodes}{\sseq at classlabelnodes}%
     \fi
+    \ifcsname sseq at class@showname\endcsname
+        \sseq at obj@xodef{\classname.showname}{\sseq at class@showname}
+    \fi
     \ifsseq at needstikz
         \sseq at obj@xdef{\classname.needstikz}{\sseq at needstikztrue}%
     \fi
@@ -541,11 +590,36 @@
     \fi
 %
     \sseq at savedpaths@addclass{class.\coord}%
-    \sseq at breakpoint
-    \endgroup
 }
 \def\sseq at setoffset#1{\sseq at obj@gdef{\classname.offset}{\pgftransformshift{#1}}}
 
+\def\sseq at copy@nameprefix{}
+
+\def\sseq at class@copy#1#2{
+    \begingroup
+    \let\sseq at thename@saved\sseq at thename
+    \def\sseq at thename{#1}
+    \sseq at lettoobj\sseq at familylist{#2.familylist}
+    \sseq at lettoobj\sseq at savedoptioncode{#2.options}
+    \sseq at lettoobj\sseq at classnodetext{#2.nodetext}
+    \sseq at lettoobj\sseq at classnodetextoptions{#2.nodetext.options}
+    \sseq at lettoobj\sseq at classlabelnodes{#2.labelnodes}
+    \sseq at obj@ifdef{#2.showname}{\sseq at lettoobj\sseq at class@showname{#2.showname}}{}
+    \sseq at lettoobj\sseq at class@name{#2.name}
+    \edef\sseq at class@name{\unexpanded\@xp{\sseq at copy@nameprefix}\unexpanded\@xp{\sseq at class@name}}
+    \sseq at obj{#2.needstikz}
+    \sseq at lettoobj\sseq at tooltip{#2.tooltip}
+    \sseq at class@getparts#2.
+    \sseq at quieterror{class-tag-already-defined}
+    \edef\sseq at class@tag{copiedfrom\sseq at thisposnum}
+    \let\sseq at thename\sseq at thename@saved
+    \sseq at eval{\@nx\sseq at cparsecoord{\the\sseq at tempx,\the\sseq at tempy}}
+    \let\sseq at pushstack@\@gobble
+    \sseq at class@main
+    \endgroup
+}
+
+
 % This is for use with "insert" key. Add one to offset index of each class later than the one currently being inserted
 % Takes the partial coordinate "x,y" in #1, and the position that the new class is being inserted into in \sseq at classinsert.
 \def\sseq at class@adjustclasses#1{
@@ -643,14 +717,13 @@
         \sseq at obj@xdef{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{\sseq at index}%
     \fi
     \ifx\sseq at class@name\pgfutil at empty\else
-        \sseq at obj@ifdef{class.\classname.name}{
-            \sseq at error@nn{classoptions-class-already-named}{\coord}{\sseq at obj{class.\classname.name}}%could be warning
+        \sseq at obj@ifdef{\classname.name}{
+            \sseq at error@nn{classoptions-class-already-named}{\coord}{\sseq at obj{\classname.name}}%could be warning
         }{}
-        \sseq at cleanup@obj{class.\classname.name}
-        \sseq at cleanup@obj{class.namedclass.\sseq at class@name}
-        \sseq at namehandler
-        \sseq at obj@xdef{class.\classname.name}{\sseq at class@name}
-        \sseq at obj@xdef{class.namedclass.\sseq at class@name}{\coordnopar}
+        \sseq at cleanup@obj{\classname.name}
+        \sseq at cleanup@obj{class.namedclass.\detokenize\@xp{\sseq at class@name}}
+        \sseq at obj@xdef{\classname.name}{\sseq at class@name}
+        \sseq at obj@xdef{class.namedclass.\detokenize\@xp{\sseq at class@name}}{\coordnopar}
     \fi
     \sseq at tempcount=\sseq at gen\relax
     \advance\sseq at tempcount\m at ne
@@ -679,6 +752,9 @@
             \sseq at cleanup@obj{\classname.labelnodes}
             \sseq at classoptions@obj at addto@withpagerange{\classname.labelnodes}{\sseq at classlabelnodes}
         \fi
+        \ifcsname sseq at class@showname\endcsname
+            \sseq at obj@xodef{\classname.showname}{\sseq at class@showname}
+        \fi
         \ifx\sseq at familylist\pgfutil at empty\else
             \sseq at cleanup@obj{\classname.familylist}
             \sseq at classoptions@obj at addto@withpagerange{\classname.familylist}{\sseq at familylist}
@@ -725,10 +801,38 @@
         \sseq at smuggle@macro\sseq at gen
     \egroup
 }
+
 \sseq at DeclareDocumentCommand\replaceclass{od()}{%
     \begingroup
     \sseq at loadinputline
     \sseq at xsetthiscall{\string\replaceclass\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}
+%
+    \IfNoValueTF{#2}{
+        \def\sseq at coord{\lastclass0}
+    }{
+        \def\sseq at coord{#2}
+    }
+    \sseq at parsecoord\coord{\sseq at coord}{coordinate passed to \string\replaceclass}%
+    \sseq at replaceclassmain{#1}
+}
+
+\sseq at DeclareDocumentCommand\replacesource{o}{
+    \begingroup
+    \sseq at loadinputline
+    \sseq at xsetthiscall{\string\replacesource\IfNoValueF{#1}{[\unexpanded{#1}]}}
+    \sseq at parsedcoord@restore{\coord}{lastsource}
+    \sseq at replaceclassmain{#1}
+}
+
+\sseq at DeclareDocumentCommand\replacetarget{o}{
+    \begingroup
+    \sseq at loadinputline
+    \sseq at xsetthiscall{\string\replacetarget\IfNoValueF{#1}{[\unexpanded{#1}]}}
+    \sseq at parsedcoord@restore{\coord}{lasttarget}
+    \sseq at replaceclassmain{#1}
+}
+
+\def\sseq at replaceclassmain#1{
     \sseq at options@firstpassmode
     \the\sseq at sseqstyle
     \the\sseq at classstyle
@@ -737,24 +841,23 @@
     \IfNoValueF{#1}{%
         \sseq at processoptions{class}{#1}% Outputs result into \sseq at savedoptioncode
     }%
-%
-    \IfNoValueTF{#2}{
-        \def\sseq at coord{\lastclass0}
-    }{
-        \def\sseq at coord{#2}
-    }
-    \sseq at parsecoord\coord{\sseq at coord}{\string\classoptions}%
     \sseq at processlabels
-%
     \sseq at obj@ifundef{class.\coord.num}{\sseq at error@x{replaceclass-no-class}{\coordname}\sseq at break}{}
     \sseq at ifdead\coord{}{\sseq at error@x{replaceclass-not-dead-yet}{\coordname}\sseq at break}
+%
+    \edef\oldclassname{class.\coord[\sseq at obj{class.\coord.num}]}
+    \sseq at cleanup@obj{class.\coord.num}
+    \sseq at obj@inc{class.\coord.num}
+    \edef\classname{class.\coord[\sseq at obj{class.\coord.num}]}
+%
     \ifsseq at keepchanges\else
-        \ifnum\the\numexpr\sseq at obj{class.\coord[\sseq at obj{class.\coord.num}].page}<\sseq at thepagecount\else
-            \edef\sseq at temp{\sseq at obj{class.\coord[\sseq at obj{class.\coord.num}].page}}
+        \ifnum\the\numexpr\sseq at obj{\oldclassname.page}<\sseq at thepagecount\else
+            \edef\sseq at temp{\sseq at obj{\oldclassname.page}}
             \sseq at error@xxx{replaceclass-no-effect-on-this-page}{\coord}{\sseq at temp}{\the\numexpr\sseq at temp+\@ne}% warning
             \sseq at breakfifi
         \fi
     \fi
+%
     \let\partialcoord\coord at partial
     \ifx\sseq at class@tag\pgfutil at empty\else
         \sseq at obj@ifdef{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{%
@@ -763,18 +866,20 @@
         \sseq at cleanup@obj{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}%
         \sseq at obj@xdef{partcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{\nodenum}%
     \fi
-    \ifx\sseq at class@name\pgfutil at empty\else
-        \sseq at cleanup@obj{class.\classname.name}
-        \sseq at cleanup@obj{class.namedclass.\sseq at class@name}
-        \sseq at namehandler
-        \sseq at obj@xdef{class.\classname.name}{\sseq at class@name}
-        \sseq at obj@xdef{class.namedclass.\sseq at class@name}{\coordnopar}
+    \ifx\sseq at class@name\pgfutil at empty
+        \sseq at obj@ifdef{\oldclassname.name}{
+            \sseq at lettoobj\sseq at class@name{\oldclassname.name}
+            \sseq at cleanup@obj{\classname.name}
+            \sseq at cleanup@obj{class.namedclass.\detokenize\@xp{\sseq at class@name}}
+            \sseq at obj@xdef{\classname.name}{\sseq at class@name}
+            \sseq at obj@xdef{class.namedclass.\detokenize\@xp{\sseq at class@name}}{\coordnopar}
+        }{}
+    \else
+        \sseq at cleanup@obj{\classname.name}
+        \sseq at cleanup@obj{class.namedclass.\detokenize\@xp{\sseq at class@name}}
+        \sseq at obj@xdef{\classname.name}{\sseq at class@name}
+        \sseq at obj@xdef{class.namedclass.\detokenize\@xp{\sseq at class@name}}{\coordnopar}
     \fi
-    \ifcsname sseq at class@showname\endcsname
-        \sseq at eval{\@nx\sseq at handleclassquotes{\sseq at obj{class.\classname.name}}{\sseq at class@showname}}
-    \fi
-    \sseq at cleanup@obj{class.\coord.num}
-    \sseq at obj@inc{class.\coord.num}
     \let\partialcoord\coord at partial
     \ifx\sseq at class@tag\pgfutil at empty\else
         \sseq at obj@ifdef{partialcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{%
@@ -782,8 +887,10 @@
         }{}%
         \sseq at obj@xdef{partialcoord.(\partialcoord).tag.\sseq at class@tagprefix\sseq at class@tag}{\nodenum}%
     \fi
-    \edef\classname{class.\coord[\sseq at obj{class.\coord.num}]}
 %
+    \ifcsname sseq at class@showname\endcsname
+        \sseq at obj@xodef{\classname.showname}{\sseq at class@showname}
+    \fi
     \sseq at obj@xodef{\classname.familylist}{\sseq at familylist}
     \sseq at obj@xdef{\classname.page}{\sseq at infinity}
     \sseq at obj@xodef{\classname.options}{\sseq at savedoptioncode}
@@ -794,6 +901,9 @@
         \sseq at obj@xodef{\classname.nodetext.options}{\sseq at classnodetextoptions}
     \fi
     \sseq at obj@xodef{\classname.labelnodes}{\sseq at classlabelnodes}
+    \ifcsname sseq at class@showname\endcsname
+        \sseq at obj@xodef{\classname.showname}{\sseq at class@showname}
+    \fi
     \sseq at obj@gdef{\classname.dependencies}{}
     \ifsseq at needstikz
         \sseq at obj@xdef{\classname.needstikz}{\sseq at needstikztrue}
@@ -819,6 +929,7 @@
     \fi
     \egroup
 }
+
 % #1 -- class
 % #2 -- page
 % If there is a class #1 drawn on page #2, set \sseq at gen to be the generation of that class, otherwise set \sseq at gen to be -1.
@@ -856,6 +967,8 @@
 \sseq at DeclareDocumentCommandAs\sseq at kill@\kill {d()} {
     \sseq at xsetthiscall{\string\kill\unexpanded\@xp{\sseq at dpage}\IfNoValueF{#1}{(#1)}}%
     \sseq at parsecoord\coordinate{\IfNoValueTF{#1}{\lastclass}{#1}}{}%
+    \sseq at parsedcoord@save{lastsource}{\coordinate}
+    \sseq at parsedcoord@save{lasttarget}{\coordinate}
     \sseq at ifintexpr{\sseq at dpage}{%
         \sseq at tempcount=\numexpr\sseq at dpage\relax % this is a convenient way to get rid of spaces because #3 has to be a number
     }{%
@@ -934,6 +1047,8 @@
 \def\sseq at d@d#1#2{%%
     \sseq at d@setpageminrec{class.\source}{#2}{source}%  automatically handles \sseq at cleanup@obj
     \sseq at d@setpageminrec{class.\target}{#2}{target}
+    %%% This is the last point we might break, so now the differential is good.
+    %%% Note that we can break inside \sseq at d@setpageclass inside \sseq at d@setpageminrec
 %
     \ifsseq at drawdifferential % TODO: probably should get rid of invisible now that we have \kill...
         \sseq at obj@xodef{d.#2\source\target.familylist}{\sseq at familylist}
@@ -1017,7 +1132,7 @@
         \fi
     \fi
     \sseq at obj@xdef{\sseq at classgenname.page}{#2}
-    \sseq at obj@xdef{\sseq at classgenname.deathinfo}{#3 of differential \sseq at thiscall\space on page #2}
+    \sseq at obj@xdef{\sseq at classgenname.deathinfo}{#3 of differential \sseq at thiscall\ on page #2}
     \bgroup
     \def\foreach{\@nx\@nx\@nx\foreach}
     \protected\def\\{}
@@ -1033,7 +1148,7 @@
     \ifx\sseq at restofstacktrace\pgfutil at empty\else\sseq at tempiftrue\fi
     \sseq at obj@xdef{\sseq at classgenname.deathstacktrace}{%
         \ifsseq at tempif
-            \unexpanded{\\\\}Stack trace for differential \sseq at thiscall\ that killed #3:\unexpanded{\\}%
+            \unexpanded{\\\\}Stack trace for differential \@nx\unexpanded{\sseq at thiscall} that killed #3:\unexpanded{\\}%
             \ifx\sseq at temp\sseq at empty\else\unexpanded{\ \ \ }\@nx\sseq at stack@unexpanded{\unexpanded\@xp{\the\sseq at foreachcall}}\fi
             \unexpanded\@xp{\sseq at restofstacktrace}%
         \fi
@@ -1056,8 +1171,10 @@
 
 \def\sseq at d@setpagemin#1#2{
     \ifnum\sseq at obj{#1.page}>#2\relax
-        \sseq at cleanup@obj{#1.page}
-        \sseq at obj@xdef{#1.page}{#2}
+	\ifnum\sseq at obj{#1.pagemin}>#2\relax\else % prevent a d1 from getting rid of a structline that was supposed to start on page 5
+	        \sseq at cleanup@obj{#1.page}
+	        \sseq at obj@xdef{#1.page}{#2}
+	\fi
     \fi
 }
 \def\sseq at differential@draw at ifpage#1{
@@ -1262,6 +1379,27 @@
         \sseq at obj@xoaddto{\sseq at structlinename.familylist}{\sseq at familylist}
     \ifnum\sseq at tempcount<\sseq at genmax\repeat
 }
+
+\def\sseq at structline@copy#1#2{
+    \begingroup
+    \sseq at structline@copy at decomposename#2
+    \let\sseq at thename@saved\sseq at thename
+    \def\sseq at pagemin{0}
+    \sseq at parsecoord\source{\sourcename}{source of structure line}%
+    \sseq at parsecoord\target{\targetname}{target of structure line}
+    \def\sseq at thename{#1}
+    \sseq at lettoobj\sseq at familylist{#2.familylist}
+    \sseq at lettoobj\sseq at savedoptioncode{#2.options}
+    \let\sseq at thename\sseq at thename@saved
+    \sseq at structline@structline
+    \endgroup
+}
+
+\def\sseq at structline@copy at decomposename#1.(#2,#3,#4)(#5,#6,#7){
+    \def\sourcename{#2,#3,copiedfrom#4}
+    \def\targetname{#5,#6,copiedfrom#7}
+}
+
 \def\sseq at structline@getgen#1{
     \bgroup
         \sseq at tempcount=\sseq at obj{structline.\source\target.num}\relax
@@ -1366,7 +1504,7 @@
     \sseq at obj@xodef{\circleclassobjname.tikzprimoptions}{\sseq at keysfortikzprim}
     \sseq at obj@xdef{\circleclassobjname.fitnodes}{\@nx\tikz at lib@fit{(sseq{\coordanopar})(sseq{\coordbnopar})\sseq at fitalso}}
     %\edef\temp{\@nx\sseq at circleclass@draw{\coorda at internalname}{\coordb at internalname}{\unexpanded\@xp{\sseq at savedoptioncode}}}
-    \sseq at savedpaths@xadd{\@nx\sseq at circleclass@draw at ifpage{\circleclassobjname}{\coordanopar}{\coordbnopar}}
+    \sseq at savedpaths@xadd{\@nx\sseq at circleclass@object{\circleclassobjname}{\coordanopar}{\coordbnopar}}
     \sseq at obj@xdef{\circleclassobjname.page}{\sseq at pagemax}
     \sseq at obj@xdef{\circleclassobjname.pagemin}{\sseq at pagemin}
     \@ifundefined{sseq at fit@pagemax}{
@@ -1425,13 +1563,13 @@
     \the\sseq at scope@toks
     \sseq at options@normalmode
     \sseq at processoptions{class/label}{#2}%
-    \sseq at classlabeltextfn{#1}% labeltextfn is a private handler, classlabeltextfn is exposed via "class label handler"
+    \sseq at classlabel@handler{#1}% labeltextfn is a private handler for transformations, sseq at classlabel@handler is exposed via "class label handler"
     \ifsseq at classlabel
         \sseq at options@firstpassmode
         \the\sseq at outerclasslabelstyle
         \sseq at x@addto at macro\sseq at classlabelnodes{%
             \@nx\sseq at drawlabel{%
-                \sseq at maybemathswitch\unexpanded\@xp{\processedlabel}\sseq at maybemathswitch}%
+                \sseq at maybemathswitch\unexpanded\@xp{\result}\sseq at maybemathswitch}%
                 {% This is setup to prevent a bug where \classoptions and class label style don't work correctly together
                     \the\sseq at sseqstyle\@nx\the\sseq at sseqstyle@page
                     \the\sseq at labelstyle\@nx\the\sseq at labelstyle@page
@@ -1449,7 +1587,7 @@
         \the\sseq at innerclasslabelstyle
         \sseq at options@normalmode
         \sseq at protectedeval{\@nx\pgfqkeys{/sseqpages/class/label}{#2}}%
-        \sseq at protected@xdef\sseq at classnodetext{\sseq at maybemathswitch\processedlabel\sseq at maybemathswitch}%
+        \sseq at protected@xdef\sseq at classnodetext{\sseq at maybemathswitch\result\sseq at maybemathswitch}%
         \xdef\sseq at classnodetextoptions{%
             %\unexpanded{\def\pgfkeysdefaultpath{/sseqpages/class/node texts/}}%
             \sseq at thelabelstyle\sseq at theclasslabelstyle\sseq at theinnerclasslabelstyle

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqmessages.code.tex
@@ -260,7 +260,9 @@
 \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 { spectralsequences } { #1 } { warning } }
+\def\SseqErrorToWarning#1{\msg_redirect_name:nnn{spectralsequences}{#1}{warning}}
+\let\sseqerrortowarning\SseqErrorToWarning
+\def\sseq at quieterror#1{\msg_redirect_name:nnn{spectralsequences}{#1}{none}}
 
 \def\sseq at error     {\msg_error:nn    {spectralsequences}}
 \def\sseq at error@n   {\msg_error:nnn   {spectralsequences}}
@@ -416,6 +418,13 @@
 \sseq at 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 at newerror{invalid-tikz-coord}{The coordinate #1 does not refer to a tikz class but its #2 coordinate is not valid \string\pgfmathparse\ input.}
 
+% handlers
+\sseq at newerror{NormalizeMonomial-invalid-exponent}{The exponent #1 of the variable #2 in the monomial #3 is not a valid integer expression. Giving up on processing this monomial -- I will leave it alone and hope for the best.}
+\sseq at newerror{AHSSNameHandler-missing-cell}{The name #1 has no cell (an integer expression surrounded by brackets). Giving up on processing it and returning my input in \string\result.}
+\sseq at newerror{AHSSNameHandler-invalid-integer}{The cell degree #1 of #2 is not a valid integer expression. I am leaving it alone, but I processed the monomial.}
+
+
+
 %%
 %%
 %% foreach
@@ -491,10 +500,14 @@
 \sseq at newerror{unknown-grid}{Undefined grid style '#1'.}
 \sseq at newerror{unknown-class-pattern}{Unknown class pattern '\sseq at classpattern'.}
 \sseq at 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 at newerror{do-command-failed}{\string\sseq at pgfkeysdocommand{#1}{#2} failed.}
+\sseq at newerror@internal{do-command-failed}{\string\sseq at pgfkeysdocommand{#1}{#2} failed.}
 
 \sseq at newerror{standard-parse}{You cannot use \string#1 inside a scope that has either the background key or coordinate transformations other than integer shifts.}
 
+\sseq at newerror{no-tooltip}{You cannot use the 'tooltip' option without either using the 'tooltips' package option or giving your own definition for '\string\sseqtooltip'.
+    Tooltips aren't enabled by default because they use the 'pdfcomment' package which creates two extra auxiliary files.%
+}
+
 %%
 %%
 %% main
@@ -559,4 +572,7 @@
 \sseq at newerror{structline-source-target-equal}{The source and target of a \@nx\structline cannot be equal.}
 
 
+\protected\def\sseq at quiet{\msg_redirect_module:nnn{spectralsequences}{error}{info}}
+\protected\def\sseq at endquiet{}
+
 \ExplSyntaxOff

Modified: trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex	2017-12-11 22:22:10 UTC (rev 46037)
+++ trunk/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex	2017-12-11 22:22:32 UTC (rev 46038)
@@ -1,8 +1,8 @@
 %%
-%% Package: spectralsequences v1.1.1 2017-09-16 2017-09-16
+%% Package: spectralsequences v1.2.0 2017-09-16 2017-09-16
 %% Author: Hood Chatham
 %% Email: hood at mit.edu
-%% Date: 2017-09-16
+%% Date: 2017-12-10
 %% License: Latex Project Public License
 %%
 %% File: sseqparsers.code.tex
@@ -99,10 +99,12 @@
 
 % Spaces matter to us, because \sseq at ifintexpr{1 1} is false but \sseqsifintexpr{11} is true
 % so we make spaces into catcode other and use \scantokens
+\def\sseq at fexpsafenil{\@nx\sseq at fexpsafenil}
+
 \def\sseq at ifintexpr#1{%
     \bgroup
     \sseq at tempcount\z@
-    \sseq at ifintexpr@{needsint}#1\sseq at nil%
+    \sseq at ifintexpr@{needsint}#1\sseq at fexpsafenil%
     \@xp\egroup\next
 }
 
@@ -113,7 +115,7 @@
     \ifx\testtok\bgroup%
         \let\next\sseq at ifintexpr@false
     \else
-        \ifx\testtok\sseq at nil
+        \ifx\testtok\sseq at fexpsafenil
             \@xp\let\@xp\next\csname sseq at ifintexpr@@\sseq at ifintexpr@state @done\endcsname
         \else
             % We need to check here for a space because \string<space> produces NO OUTPUT regardless of the catcode of the space.
@@ -155,8 +157,8 @@
 % 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 at ifintexpr@@@@#1{%
-    \ifx#1\sseq at nil
-        \def\next{\csname sseq at ifintexpr@@\sseq at ifintexpr@state @done\endcsname\sseq at nil}%
+    \ifx#1\sseq at fexpsafenil
+        \def\next{\csname sseq at ifintexpr@@\sseq at ifintexpr@state @done\endcsname\sseq at fexpsafenil}%
     \else
         \sseq at ifdigit{#1}%
             {\sseq at ifintexpr@next{digit}}%
@@ -187,8 +189,8 @@
     \next
 }
 
-\def\sseq at ifintexpr@true#1\sseq at nil{\ifnum\sseq at tempcount=\z@ \let\next\@firstoftwo\else\let\next\@secondoftwo\fi}
-\def\sseq at ifintexpr@false#1\sseq at nil{\let\next\@secondoftwo}
+\def\sseq at ifintexpr@true#1\sseq at fexpsafenil{\ifnum\sseq at tempcount=\z@ \let\next\@firstoftwo\else\let\next\@secondoftwo\fi}
+\def\sseq at ifintexpr@false#1\sseq at fexpsafenil{\let\next\@secondoftwo}
 
 \def\sseq at makeifint#1#2#3{\@xp\def\csname sseq at ifintexpr@@#1@#2\endcsname{#3}}
 \def\sseq at ifintexpr@next#1{\@xp\let\@xp\next\csname sseq at ifintexpr@@\sseq at ifintexpr@state @#1\endcsname}
@@ -234,6 +236,8 @@
 %%
 %% This parser defines the syntax for the page argument of \d.
 %%
+%% #1 -- callback. Will pass control to this function when done.
+%% stores output in \sseq at dpage
 \def\sseq at d@grabpage#1{
     \let\sseq at grabdpage@return#1
     \futurelet\testtok\sseq at grabdpage@
@@ -497,11 +501,18 @@
         \ifpgfutil at in@
             \sseq at parsecoord@maincoord@@#1,\sseq at nil
         \else
-            \sseq at obj@ifdef{class.namedclass.\detokenize{#1}}{
-                \def\sourcename{#1}
-                \@xpthree\sseq at parsecoord@maincoord at named\sseq at obj{class.namedclass.#1}\sseq at nil
+            \pgfutil at in@{lastclass}{#1}
+            \ifpgfutil at in@
+                \def\handledname{#1}
+            \else
+                \sseq at protectedeval{\@nx\sseq at classname@handler{\sseq at classnameprefix#1\sseq at classnamepostfix}}
+                \let\handledname\result
+            \fi
+            \sseq at obj@ifdef{class.namedclass.\detokenize\@xp{\handledname}}{
+                \let\sourcename\handledname
+                \@xpthree\sseq at parsecoord@maincoord at named\sseq at obj{class.namedclass.\detokenize\@xp{\sourcename}}\sseq at nil
             }{
-                \sseq at error{invalid-coordinate}\sseq at breakfifi
+                 \sseq at error{invalid-coordinate}\sseq at breakfifi
             }
         \fi
     \fi
@@ -508,22 +519,29 @@
 }
 
 \def\sseq at parsecoord@maincoord@@#1,#2,#3\sseq at nil{%
-    \sseq at obj@ifdef{class.namedclass.\detokenize{#1}}{
-        \def\sourcename{#1}
-        \@xpthree\sseq at parsecoord@maincoord at named\sseq at obj{class.namedclass.#1}\sseq at nil
-        \edef\sseq at restcoord{\sseq at removecomma#2,#3\sseq at nil}
-    }{
-        \sseq at ifintexpr{#1}{
-            \sseq at ifintexpr{#2}{}{\sseq at error@n{invalid-coordinate}{y~}\sseq at breakfifi} % breakfifi to get out of ifs from maincoord@
-            \edef\sseq at xcoord{\the\numexpr\sseq at x+(#1)\relax}%
-            \edef\sseq at ycoord{\the\numexpr\sseq at y+(#2)\relax}%
-            \edef\sseq at xycoord{\sseq at xcoord,\sseq at ycoord}%
-            \sseq at ifempty{#3}{\let\sseq at restcoord\pgfutil at empty}{%
-                \edef\sseq at restcoord{\sseq at removecomma#3\sseq at nil}%
-            }%
-        }{
+    \sseq at ifintexpr{#1}{%
+        \sseq at ifintexpr{#2}{}{\sseq at error@n{invalid-coordinate}{y~}\sseq at breakfifi} % breakfifi to get out of ifs from maincoord@
+        \edef\sseq at xcoord{\the\numexpr\sseq at x+(#1)\relax}%
+        \edef\sseq at ycoord{\the\numexpr\sseq at y+(#2)\relax}%
+        \edef\sseq at xycoord{\sseq at xcoord,\sseq at ycoord}%
+        \sseq at ifempty{#3}{\let\sseq at restcoord\pgfutil at empty}{%
+            \edef\sseq at restcoord{\sseq at removecomma#3\sseq at nil}%
+        }%
+    }{%
+        \pgfutil at in@{lastclass}{#1}%
+        \ifpgfutil at in@
+            \def\handledname{#1}%
+        \else
+            \sseq at protectedeval{\@nx\sseq at classname@handler{\sseq at classnameprefix#1\sseq at classnamepostfix}}%
+            \let\handledname\result
+        \fi
+        \sseq at obj@ifdef{class.namedclass.\detokenize\@xp{\handledname}}{%
+            \def\sourcename{#1}
+            \@xpthree\sseq at parsecoord@maincoord at named\sseq at obj{class.namedclass.\detokenize{#1}}\sseq at nil
+            \edef\sseq at restcoord{\sseq at removecomma#2,#3\sseq at nil}%
+        }{%
             \sseq at error@n{invalid-coordinate}{x~}\sseq at breakfifi % breakfifi to get out of ifs from maincoord@
-        }
+        }%
     }%
 }%
 
@@ -587,14 +605,19 @@
 % #1 -- name to define
 % #2 -- coordinate
 % #3 -- the error message
+\def\sseq at eatparens(#1){#1}
 \def\sseq at parsecoord#1#2#3{%
-    \def\sseq at index{}
-    \def\sseq at errortype{#3}
+    \def\sseq at index{}%
+    \def\sseq at errortype{#3}%
     \sseq at parsecoord@maincoord{#2}%
     \let\sseq at rawindex\sseq at restcoord
     \ifx\sseq at index\pgfutil at empty
         \@xp\sseq at parsecoord@index
     \fi
+    \sseq at parsecoord@setupvariables{#1}{#2}
+}
+
+\def\sseq at parsecoord@setupvariables#1#2{
     % TODO: clean this up a bit? it's pretty ad-hoc.
     % Whenever you update this, make sure to update sseq at paredcoords@swap below too.
     \@xp\let\csname x\sseq at macroname#1\endcsname\sseq at xcoord
@@ -603,29 +626,55 @@
     \@xp\let\csname \sseq at macroname#1 at partial\endcsname\sseq at xycoord
     \edef#1{(\sseq at xycoord,\sseq at index)}%
     \@xp\edef\csname\sseq at macroname#1nopar\endcsname{\sseq at xycoord,\sseq at index}
-    \@xp\def\csname\sseq at macroname#1name\endcsname{(#2)}%
-    \@xp\def\csname\sseq at macroname#1nameunbraced\endcsname{#2}%
+    \@xp\edef\csname\sseq at macroname#1name\endcsname{(#2)}%
+    \@xp\edef\csname\sseq at macroname#1nameunbraced\endcsname{\@xptwo\sseq at eatparens\csname\sseq at macroname#1name\endcsname}% edef?
     \@xp\edef\csname\sseq at macroname#1 at internalname\endcsname{sseq{\sseq at xycoord,\sseq at index}}%
 }
 
+
+% This quiets parsecoord for the rest of the current scope.
+% The reason we did it this way is because parsecoord makes too many local definitions...
+\def\sseq at quiet@parsecoord{
+    \msg_redirect_name:nnn {spectralsequences}{invalid-coordinate}{none}
+    \msg_redirect_name:nnn {spectralsequences}{no-classes}{none}
+    \msg_redirect_name:nnn {spectralsequences}{index-too-large}{none}
+    \msg_redirect_name:nnn {spectralsequences}{undefined-tag}{none}
+}
+
+
+% These are used for \replacesource and \replacetarget, though they might be useful for other things too.
+\def\sseq at parsedcoord@save#1#2{
+    \cs_gset_eq:cc { sseq at parsedcoord@save at x#1 } { x\sseq at macroname#2 }
+    \cs_gset_eq:cc { sseq at parsedcoord@save at y#1 } { y\sseq at macroname#2 }
+    \cs_gset_eq:cc { sseq at parsedcoord@save at n#1 } { n\sseq at macroname#2 }
+    \cs_gset_eq:cc { \sseq at macroname#1 at partial } { \sseq at macroname#2 at partial }
+    \cs_gset_eq:cN { sseq at parsedcoord@save@#1 } #2
+    \cs_gset_eq:cc { sseq at parsedcoord@save@#1nopar } { \sseq at macroname#2nopar }
+    \cs_gset_eq:cc { sseq at parsedcoord@save@#1name } { \sseq at macroname#2name }
+    \cs_gset_eq:cc { sseq at parsedcoord@save@#1nameunbraced } { \sseq at macroname#2nameunbraced }
+    \cs_gset_eq:cc { sseq at parsedcoord@save@#1 at internalname } { \sseq at macroname#2 at internalname }
+}
+
+\def\sseq at parsedcoord@restore#1#2{
+    \cs_set_eq:cc { x\sseq at macroname#1 } { sseq at parsedcoord@save at x#2 }
+    \cs_set_eq:cc { y\sseq at macroname#1 } { sseq at parsedcoord@save at y#2 }
+    \cs_set_eq:cc { n\sseq at macroname#1 } { sseq at parsedcoord@save at n#2 }
+    \cs_set_eq:cc { \sseq at macroname#1 at partial } { #2 at partial }
+    \cs_set_eq:Nc #1 { sseq at parsedcoord@save@#2 }
+    \cs_set_eq:cc { \sseq at macroname#1nopar } { sseq at parsedcoord@save@#2nopar }
+    \cs_set_eq:cc { \sseq at macroname#1name } { sseq at parsedcoord@save@#2name }
+    \cs_set_eq:cc { \sseq at macroname#1nameunbraced } { sseq at parsedcoord@save@#2nameunbraced }
+    \cs_set_eq:cc { \sseq at macroname#1 at internalname } { sseq at parsedcoord@save@#2 at internalname }
+}
+
 % #1 & #2 -- the two base commands that were handed to \sseq at parsecoord to swap.
 % This is only used in \structline to normalize the name of structure lines, so that sseqpages knows what you are talking about
 % if you say \structline(coorda)(coordb) and then later \structline(coordb)(coorda)
-\cs_new:Npn \sseq_swapmacros:NN #1#2 {
-    \let\sseq at temp#1 \let#1#2 \let#2\sseq at temp
-}
-\cs_generate_variant:Nn \sseq_swapmacros:NN { cc }
-
 \def\sseq at parsedcoords@swap#1#2{
-    \sseq_swapmacros:cc { x\sseq at macroname#1 } { x\sseq at macroname#2 }
-    \sseq_swapmacros:cc { y\sseq at macroname#1 } { y\sseq at macroname#2 }
-    \sseq_swapmacros:cc { n\sseq at macroname#1 } { n\sseq at macroname#2 }
-    \sseq_swapmacros:cc { \sseq at macroname#1 at partial } { \sseq at macroname#2 at partial }
-    \sseq_swapmacros:NN #1 #2
-    \sseq_swapmacros:cc { \sseq at macroname#1nopar } { \sseq at macroname#2nopar }
-    \sseq_swapmacros:cc { \sseq at macroname#1name } { \sseq at macroname#2name }
-    \sseq_swapmacros:cc { \sseq at macroname#1nameunbraced } { \sseq at macroname#2nameunbraced }
-    \sseq_swapmacros:cc { \sseq at macroname#1 at internalname } { \sseq at macroname#2 at internalname }
+    \sseq at parsedcoord@save{swaptempa}{#1}
+    \sseq at parsedcoord@save{swaptempb}{#2}
+    \sseq at parsedcoord@restore{#1}{swaptempb}
+    \sseq at parsedcoord@restore{#2}{swaptempa}
 }
 
 % EXPOSE: a wrapper around \sseq at parsecoord. Use full name of coordinate to avoid name class with sseq at parsecoord.
@@ -672,16 +721,8 @@
             \sseq at error{d-named-coord-two-indexes}
         \fi
     \fi
-    \let\sourcecoord\sseq at xycoord
-%
-    \let\xsource\sseq at xcoord
-    \let\ysource\sseq at ycoord
-    \let\nsource\sseq at index
-%
-    \edef\source{(\sseq at xycoord,\sseq at index)}%
-    \ifx\sourcename\undefined
-        \edef\sourcename{(\sseq at xycoord\ifx\sseq at rawindex\pgfutil at empty\else,\sseq at rawindex\fi)}
-    \fi
+    \sseq at parsecoord@setupvariables{\source}{(\sseq at xycoord\ifx\sseq at rawindex\pgfutil at empty\else,\sseq at rawindex\fi)}
+    \let\sourcecoord\source at partial
     \IfNoValueTF{#3}{
         \ifsseq at hasdegree\else\sseq at error{d-no-degree}\@xp\sseq at break\fi
         \sseq at eval{\edef\@nx\sseq at xycoord{\@nx\sseq at differential@gettarget{#1}{\sseq at xycoord}}}
@@ -689,11 +730,7 @@
         \def\sseq at errortype{target ~ of ~ differential}
         \sseq at parsecoord@index
         \let\targetcoord\sseq at xycoord
-        \edef\target{(\sseq at xycoord,\sseq at index)}%
-        \let\xtarget\sseq at xcoord
-        \let\ytarget\sseq at ycoord
-        \let\ntarget\sseq at index
-        \edef\targetname{(\sseq at xycoord\ifx\sseq at rawindex\pgfutil at empty\else,\sseq at rawindex\fi)}
+        \sseq at parsecoord@setupvariables{\target}{(\sseq at xycoord\ifx\sseq at rawindex\pgfutil at empty\else,\sseq at rawindex\fi)}
     }{
         \ifx\sseq at rawtindex\pgfutil at empty\else
             \sseq at error{d-target-index-target-coord}
@@ -709,6 +746,8 @@
             \fi
         \fi
     }
+    \sseq at parsedcoord@save{lastsource}{\source}
+    \sseq at parsedcoord@save{lasttarget}{\target}
 }
 
 \def\sseq at differential@gettarget#1#2{\sseq at differential@gettarget@{#1}#2\sseq at nil}
@@ -735,10 +774,14 @@
 
 
 % EXPOSE: a wrapper around \sseq at dparsecoord.
-\sseq at DeclareDocumentCommand \parsedifferential { m r() d() }{%
-    \sseq at dparsecoord{#1}{#2}{#3}%
+\protected\def\sseq at parsedifferential{%
+    \sseq at d@grabpage\sseq at parsedifferential@
 }
 
+\DeclareDocumentCommand \sseq at parsedifferential@ { d() d() } {%
+    \sseq at eval{\@nx\sseq at dparsecoord{\sseq at dpage}{\IfNoValueTF{#1}{\lastclass0}{\unexpanded{#1}}}{\unexpanded{#2}}}%
+}
+
 % Expandable coordinate parsing for \isalive.
 % Doesn't do any error checking -- the error checking is done by passing it through \sseq at parsecoord in a non-\edef context.
 % #1 -- a callback. Must be a single command b/c it's an N in \exp_args
@@ -913,9 +956,35 @@
     \egroup
 }
 
+\prg_new_conditional:Npnn \sseq_if_empty:n #1 {T,F,TF} {
+    \sseq at ifempty{\prg_return_true:}{\prg_return_false:}
+}
+
+\let\SseqIfEmptyTF\sseq_if_empty:nTF
+\let\SseqIfEmptyT\sseq_if_empty:nT
+\let\SseqIfEmptyF\sseq_if_empty:nF
+
+% Test if a class exists.
+\prg_new_conditional:Npnn \sseq_if_exists:n #1 { T ,  F , TF } {
+    \bgroup
+    \sseq at tempiftrue
+    \sseq at quiet@parsecoord
+    \sseq at parsecoord\coord{#1}{}
+    \@gobbletwo\sseq at breakpoint\sseq at tempiffalse % this executes \sseq at tempiffalse if we broke, otherwise it gets gobbled
+    \ifsseq at tempif
+        \egroup
+        \prg_return_true:
+    \else
+        \egroup
+        \prg_return_false:
+    \fi
+}
+
+% Test if a class is out of bounds. Return false if the class doesn't exist.
 \prg_new_conditional:Npnn \sseq_if_out_of_bounds:n #1 { T ,  F , TF } {
     \bgroup
     \sseq at tempiftrue
+    \sseq at quiet@parsecoord
     \sseq at parsecoord\coord{#1}{}
     \@gobbletwo\sseq at breakpoint\sseq at tempiffalse % this executes \sseq at tempiffalse if we broke, otherwise it gets gobbled
     \ifsseq at tempif
@@ -922,12 +991,11 @@
         \sseq_if_out_of_bounds_noparse:nnTF { \xcoord } { \ycoord }{\egroup\prg_return_true:}{\egroup\prg_return_false:}
     \else
         \egroup
-        \prg_return_false
+        \prg_return_false:
     \fi
 }
 
 % For internal use b/c it's faster not to call \sseq at parsecoord
-% There's no noticeable performance boost though... =(
 \prg_new_conditional:Npnn \sseq_if_out_of_bounds_noparse:nn #1#2 {TF} {
     \sseq at tempiftrue
     \ifnum#1<\sseq at xmaxpp\relax\ifnum#1>\sseq at xminmm\relax\ifnum#2<\sseq at ymaxpp\relax\ifnum#2>\sseq at yminmm\relax
@@ -940,7 +1008,116 @@
     \fi
 }
 
+\prg_new_conditional:Npnn \sseq_if_alive:nn #1 #2 { T, F, TF } {
+    \bgroup
+    \sseq at tempiftrue
+    \sseq at quiet@parsecoord
+    \sseq at parsecoord\coord{#2}{}
+    \@gobbletwo\sseq at breakpoint\sseq at tempiffalse
+    \ifsseq at tempif
+	\sseq at obj@pagetogen{class.\coord}{#1}
+        \ifnum\sseq at gen>-1\relax
+		\egroup
+		\prg_return_true:
+	\else
+		\egroup
+		\prg_return_false:
+	\fi
+    \else
+        \egroup
+        \prg_return_false:
+    \fi
+}
 
+
+\protected\def\sseq at DrawIfValidDifferential{\sseq at DrawIfValidDifferential@{}{}}
+\protected\def\sseq at DrawIfValidDifferentialT{\sseq at DrawIfValidDifferential@{T}{}}
+\protected\def\sseq at DrawIfValidDifferentialF{\sseq at DrawIfValidDifferential@{}{F}}
+\protected\def\sseq at DrawIfValidDifferentialTF{\sseq at DrawIfValidDifferential@{T}{F}}
+
+\DeclareDocumentCommand\sseq at DrawIfValidDifferential@{mmO{}}{%
+    \begingroup
+    \sseq at loadinputline
+    \def\sseq at dtype{d}
+    \def\sseq at trueclause{#1}
+    \def\sseq at falseclause{#2}
+    \def\sseq at doptions{#3}
+    \sseq at d@grabpage\sseq at DrawIfValidDifferential@@
+}
+
+
+% #4 -- first coord
+% #5 -- possible second coord
+\DeclareDocumentCommand \sseq at DrawIfValidDifferential@@ { d() d() } {%
+    \ifx\sseq at trueclause\pgfutil at empty
+        \@xp\@firstoftwo
+    \else
+        \@xp\@secondoftwo
+    \fi{\sseq at DrawIfValidDifferential@@@{#1}{#2}{}}
+       {\sseq at DrawIfValidDifferential@@@{#1}{#2}}
+}
+
+% #1 -- first coord
+% #2 -- possible second coord
+% #3 -- rest of true clause
+\def \sseq at DrawIfValidDifferential@@@#1#2#3{
+    \sseq at eval{\endgroup%\@nx\tracingall
+        \exp_not:c{sseq_if_valid_differential:nnT\sseq at falseclause}{\sseq at dpage}{\IfNoValueTF{#1}{\lastclass0}{\unexpanded{#1}}}{\unexpanded{#2}}{%
+            \@nx\d[\exp_not:o{\sseq at doptions}]\sseq at dpage\IfNoValueF{#1}{(\unexpanded{#1})}\IfNoValueF{#2}{(\unexpanded{#2})}%
+            \unexpanded{#3}%
+        }%
+    }%
+}
+
+\protected\def\sseq at IfValidDifferentialTF{\sseq at IfValidDifferential{TF}}
+\protected\def\sseq at IfValidDifferentialT{\sseq at IfValidDifferential{T}}
+\protected\def\sseq at IfValidDifferentialF{\sseq at IfValidDifferential{F}}
+
+\protected\def\sseq at IfValidDifferential#1{%
+    \bgroup
+    \def\sseq at truefalseclauses{#1}
+    \sseq at d@grabpage{\sseq at IfValidDifferential@}
+}
+
+\DeclareDocumentCommand \sseq at IfValidDifferential@ { d() d() } {%
+    \sseq at eval{\egroup\exp_not:c{sseq_if_valid_differential:nn\sseq at truefalseclauses}{\sseq at dpage}{\IfNoValueTF{#1}{\lastclass0}{\unexpanded{#1}}}{\unexpanded{#2}}}%
+}
+
+\prg_new_conditional:Npnn \sseq_if_valid_differential:nn #1 #2 #3 { T, F, TF } {
+    \bgroup
+    \sseq at tempiftrue
+    \sseq at ifintexpr{#1}{%
+        \edef\sseq at pagenum{\the\numexpr#1\relax}
+    }{%
+        \sseq at break% return false
+    }%
+    \sseq at quiet@parsecoord
+    \msg_redirect_name:nnn {spectralsequences} {d-wrong-degree}              {none}
+    \msg_redirect_name:nnn {spectralsequences} {d-target-index-target-coord} {none}
+    \msg_redirect_name:nnn {spectralsequences} {d-named-coord-two-indexes}   {none}
+    \msg_redirect_name:nnn {spectralsequences} {d-hit-wrong-order}           {none}
+    \msg_redirect_name:nnn {spectralsequences} {d-class-already-hit}         {none}
+    \msg_redirect_name:nnn {spectralsequences} {d-hit-same-page-replaceclass}{none}
+    \sseq at dparsecoord{\sseq at pagenum}{#2}{#3}
+    \let\sseq at obj@xdef\@gobbletwo
+    \sseq at d@setpageclass{class.\source}{\sseq at pagenum}{source}
+    \sseq at d@setpageclass{class.\target}{\sseq at pagenum}{target}
+    \@gobbletwo\sseq at breakpoint\sseq at tempiffalse
+    \ifsseq at tempif
+		\egroup
+		\prg_return_true:
+    \else
+        \egroup
+        \prg_return_false:
+    \fi
+}
+
+
+
+\sseq at DeclareDocumentCommand \IfExistsTF { r() } { \sseq_if_exists:nTF { #1 } }
+\sseq at DeclareDocumentCommand \IfExistsT  { r() } { \sseq_if_exists:nT  { #1 } }
+\sseq at DeclareDocumentCommand \IfExistsF  { r() } { \sseq_if_exists:nF  { #1 } }
+
 \sseq at DeclareDocumentCommand \IfOutOfBoundsTF { r() } { \sseq_if_out_of_bounds:nTF { #1 } }
 \sseq at DeclareDocumentCommand \IfOutOfBoundsT  { r() } { \sseq_if_out_of_bounds:nT  { #1 } }
 \sseq at DeclareDocumentCommand \IfOutOfBoundsF  { r() } { \sseq_if_out_of_bounds:nF  { #1 } }
@@ -948,7 +1125,11 @@
 \sseq at DeclareDocumentCommand \IfInBoundsT  { r() } { \sseq_if_out_of_bounds:nF  { #1 } }
 \sseq at DeclareDocumentCommand \IfInBoundsF  { r() } { \sseq_if_out_of_bounds:nT  { #1 } }
 
+\sseq at DeclareDocumentCommand \IfAliveTF { mr() }{ \sseq_if_alive:nnTF{#1}{#2}}
+\sseq at DeclareDocumentCommand \IfAliveT { mr() } { \sseq_if_alive:nnT{#1}{#2}}
+\sseq at DeclareDocumentCommand \IfAliveF { mr() } { \sseq_if_alive:nnF{#1}{#2}}
 
+
 %%%%%%
 %%%
 %%%   Tikz Primitives
@@ -1201,13 +1382,15 @@
     }
 }
 
-\def\sseq at tikzprimitives@coords at maybenamedclass#1{
+\def\sseq at tikzprimitives@coords at maybenamedclass#1{%
     \sseq at tikzprimitive@getcoord at anchor#1.\sseq at nil % puts coord into \sseq at tempcoord, anchor if any into \sseq at tempanchor
-    \sseq at protectedeval{\@nx\sseq at obj@ifdef{class.namedclass.\@nx\detokenize{\sseq at tempcoord}}}{% need this detokenize here to prevent it from throwing errors when there's a command inside...
-        \sseq at x@addto at macro\sseq at thepathsofar{(sseq{\sseq at obj{class.namedclass.\sseq at tempcoord}\sseq at tempanchor})}
-    }{
-        \sseq at tikzprimitives@coords at notaclass{#1}
-    }
+    \protected at edef\sseq at tempcoord{\sseq at tempcoord}%
+    % need this detokenize here to prevent it from throwing errors when there's a command inside...
+    \sseq at obj@ifdef{class.namedclass.\detokenize\@xp{\sseq at tempcoord}}{
+        \sseq at x@addto at macro\sseq at thepathsofar{(sseq{\sseq at obj{class.namedclass.\detokenize\@xp{\sseq at tempcoord}}\sseq at tempanchor})}%
+    }{%
+        \sseq at tikzprimitives@coords at notaclass{#1}%
+    }%
 }
 
 \let\sseq at tikzprimitives@coords at maybeclass@save\sseq at tikzprimitives@coords at maybeclass
@@ -1255,7 +1438,7 @@
         \edef\sseq at index{,\unexpanded\@xp{\sseq at removecomma#3\sseq at nil}}
         \edef\sseq at indexnocomma{\unexpanded\@xp{\sseq at removecomma#3\sseq at nil}}
     }
-    \sseq at ifpgfmathexpr{#1}{
+    \sseq at ifpgfmathexpr{#1}{%
         % Decide whether we can keep the result, which is stored in \sseq at mathresult
         \protected at edef\sseq at tempa{#1}
         \edef\sseq at tempb{#1}
@@ -1388,25 +1571,46 @@
 % We need to check for math subscript characters
 \char_set_catcode_math_subscript:N \_
 
-\protected\def\sseqnormalizemonomial#1{
+\def\sseq at support@std{}
+\protected\def\SseqNormalizeMonomialSetVariables#1{%
     \bgroup
-    \def\sseq at support{}
-    \sseq at ifempty{#1}{1}{
+    \gdef\sseq at support@std{}%
+    \def\sseqnormalizemonomial at add{%
+        \def\temp{1}%
+        \ifx\sseq at var\temp\else
+            \edef\sseq at var{\unexpanded\@xp{\sseq at var}\unexpanded\@xp{\sseq at subscript}}%
+            \@ifundefined{\sseqnormalizemonomial at varcs}{%
+                \@xp\xdef\csname\sseqnormalizemonomial at varcs\endcsname{0}%
+                \sseq at x@addto at macro\sseq at support@std{\@nx\\{\unexpanded\@xp{\sseq at var}}{\sseqnormalizemonomial at varcs}}%
+            }{}%
+        \fi
+        \sseqnormalizemonomial at testend
+    }%
+    \SseqNormalizeMonomial{#1}%
+    \egroup
+}
+
+
+\protected\def\SseqNormalizeMonomial#1{%
+    \bgroup
+    \def\sseq at ourinput{#1}%
+    \let\sseq at support\sseq at support@std
+    \sseq at ifempty{#1}{\egroup\def\result{1}}{%
         \sseqnormalizemonomial@#1\sseq at nil
-    }
+    }%
 }
-\def\sseqnormalizemonomial@#1{
-    \pgfkeys at spdef\sseq at var{#1}
-    \def\sseq at power{1}
-    \def\sseq at subscript{}
+\def\sseqnormalizemonomial@#1{%
+    \pgfkeys at spdef\sseq at var{#1}%
+    \def\sseq at power{1}%
+    \def\sseq at subscript{}%
     \futurelet\testtok\sseqnormalizemonomial@@
 }
 
-\def\sseqnormalizemonomial@@{
-    \ifx\testtok^
+\def\sseqnormalizemonomial@@{%
+    \ifx\testtok^%
         \let\next\sseqnormalizemonomial at sup
     \else
-        \ifx\testtok_
+        \ifx\testtok_%
             \let\next\sseqnormalizemonomial at sub
         \else
             \let\next\sseqnormalizemonomial at add
@@ -1415,40 +1619,46 @@
     \next
 }
 
-\def\sseqnormalizemonomial at sup^#1{
-    \edef\sseq at power{\the\numexpr#1\relax}
+\def\sseqnormalizemonomial at sup^#1{%
+    \sseq at ifintexpr{#1}{%
+        \edef\sseq at power{\the\numexpr#1\relax}%
+    }{%
+        \sseq at error@xxx{NormalizeMonomial-invalid-exponent}{\unexpanded{#1}}{\unexpanded\@xp{\sseq at var}}{\unexpanded\@xp{\sseq at ourinput}}
+        \let\result\sseq at ourinput
+        \sseq at gobble@to at nil
+    }
     \futurelet\testtok\sseqnormalizemonomial@@
 }
 
-\def\sseqnormalizemonomial at sub_#1{
-    \def\sseq at subscript{_{#1}}
+\def\sseqnormalizemonomial at sub_#1{%
+    \def\sseq at subscript{_{#1}}%
     \futurelet\testtok\sseqnormalizemonomial@@
 }
 
-\def\sseqnormalizemonomial at add{
-    \def\temp{1}
+\def\sseqnormalizemonomial at add{%
+    \def\temp{1}%
     \ifx\sseq at var\temp\else
-        \edef\sseq at var{\unexpanded\@xp{\sseq at var}\unexpanded\@xp{\sseq at subscript}}
-        \@ifundefined{\sseqnormalizemonomial at varcs}{
-            \@xp\edef\csname\sseqnormalizemonomial at varcs\endcsname{\sseq at power}
+        \edef\sseq at var{\unexpanded\@xp{\sseq at var}\unexpanded\@xp{\sseq at subscript}}%
+        \@ifundefined{\sseqnormalizemonomial at varcs}{%
+            \@xp\edef\csname\sseqnormalizemonomial at varcs\endcsname{\sseq at power}%
             \sseq at e@addto at macro\sseq at support{\@nx\\{\unexpanded\@xp{\sseq at var}}{\sseqnormalizemonomial at varcs}}%
-        }{
-            \@xp\edef\csname\sseqnormalizemonomial at varcs\endcsname{\the\numexpr\csname\sseqnormalizemonomial at varcs\endcsname + \sseq at power}
-        }
+        }{%
+            \@xp\edef\csname\sseqnormalizemonomial at varcs\endcsname{\the\numexpr\csname\sseqnormalizemonomial at varcs\endcsname + \sseq at power}%
+        }%
     \fi
     \sseqnormalizemonomial at testend
 }
 
 
-\def\sseqnormalizemonomial at testend{
+\def\sseqnormalizemonomial at testend{%
     \ifx\testtok\sseq at nil
         \sseqnormalizemonomial at done
-        \sseq at smuggle@macro\processedlabel
+        \sseq at smuggle@macro\result
         \egroup
         \let\next\@gobble
     \else
         \@xp\ifx\space\testtok
-            \def\next{\@xp\futurelet\@xp\testtok\@xp\sseqnormalizemonomial at testend\romannumeral-`0}
+            \def\next{\@xp\futurelet\@xp\testtok\@xp\sseqnormalizemonomial at testend\romannumeral-`0}%
         \else
             \let\next\sseqnormalizemonomial@
         \fi
@@ -1458,22 +1668,22 @@
 
 \def\sseqnormalizemonomial at varcs{sseqnormalizemonomial at var@\detokenize\@xp{\sseq at var}}
 
-\def\sseqnormalizemonomial at done{
-    \def\processedlabel{}
-    \def\\##1##2{
+\def\sseqnormalizemonomial at done{%
+    \def\result{}%
+    \def\\##1##2{%
         \sseq at tempcount=\csname ##2\endcsname\relax
         \ifnum\sseq at tempcount=\z@
         \else
             \ifnum\sseq at tempcount=\@ne
-                \sseq at d@addto at macro\processedlabel{##1}
+                \sseq at d@addto at macro\result{##1}%
             \else
-                \sseq at e@addto at macro\processedlabel{\unexpanded{##1}^{\the\sseq at tempcount}}
+                \sseq at e@addto at macro\result{\unexpanded{##1}^{\the\sseq at tempcount}}%
             \fi
         \fi
-    }
+    }%
     \sseq at support
-    \ifx\processedlabel\pgfutil at empty % use 1 for empty monomial
-        \def\processedlabel{1}
+    \ifx\result\pgfutil at empty % use 1 for empty monomial
+        \def\result{1}%
     \fi
 }
 
@@ -1481,6 +1691,44 @@
 \catcode`\_ = 11\relax
 
 
+\def\SseqAHSSNameHandler#1{
+    \pgfutil at in@[{#1}
+    \ifpgfutil at in@
+        \@xp\@firstofone
+    \else
+        \sseq at error{AHSSNameHandler-missing-cell}{#1}
+        \def\result{#1}
+        \@xp\@gobble
+    \fi{
+        \SseqAHSSNameHandler@#1\sseq at nil
+    }
+}
 
 
-\ExplSyntaxOff 
\ No newline at end of file
+\def\SseqAHSSNameHandler@#1[#2\sseq at nil{
+    \pgfutil at in@]{#2}
+    \ifpgfutil at in@
+        \@xp\@firstofone
+    \else
+        \sseq at error{AHSSNameHandler-missing-cell}{#1[#2}
+        \def\result{#1[#2}
+        \@xp\@gobble
+    \fi{
+        \SseqAHSSNameHandler@@{#1}#2\sseq at nil
+    }
+}
+
+\def\SseqAHSSNameHandler@@#1#2]#3\sseq at nil{
+	\SseqNormalizeMonomial{#1#3}
+    \sseq at ifintexpr{#2}{
+	    \edef\result{\unexpanded\@xp{\result}[\the\numexpr#2+\sseq at y]}
+    }{
+        \sseq at error{AHSSNameHandler-invalid-integer}{#2}{#1[#2]#3}
+        \edef\result{\unexpanded\@xp{\result[#2]}}
+    }
+}
+
+
+
+
+\ExplSyntaxOff



More information about the tex-live-commits mailing list