summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/spectralsequences
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2017-08-03 21:07:30 +0000
committerKarl Berry <karl@freefriends.org>2017-08-03 21:07:30 +0000
commitff587f620cc7c6d0068c33b27a8e554bce2b08fe (patch)
tree0857cebe6e2e1325bb94305516fbf9b6e27326c0 /Master/texmf-dist/tex/latex/spectralsequences
parent29d69088963132c0a036286f984331c74ac99f1a (diff)
spectralsequences (3aug17)
git-svn-id: svn://tug.org/texlive/trunk@44942 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/spectralsequences')
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty279
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex47
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex924
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex216
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex892
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex41
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex234
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex617
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex142
-rw-r--r--Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex344
10 files changed, 2568 insertions, 1168 deletions
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty b/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty
deleted file mode 100644
index 62ff3e40a4f..00000000000
--- a/Master/texmf-dist/tex/latex/spectralsequences/spectralsequences.sty
+++ /dev/null
@@ -1,279 +0,0 @@
-%%
-%% Package: spectralsequences.sty version 1.0
-%% Author: Hood Chatham
-%% Email: hood@mit.edu
-%% Date: 2017-06-18
-%% License: Latex Project Public License
-%%
-%% A package for drawing spectral sequences
-%%
-
-
-% TODO:
-% label handler key, \sseqnormalizepolynomial
-% speed up off page edges (uses 10% of the draw time for page 0 of tmfass)
-% speed up label nodes
-% try to restrict fragility issues to tooltips and tikz primitives... annoying
-% error messages that should be warnings by default?
-% improve axes options? allow axis to be centered on coordinate or centered between coordinates
-% recover from failing to patch pgfkeys
-
-\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{spectralsequences}[2017/06/04 v1.0]
-
-\RequirePackage{tikz}
-\RequirePackage{etoolbox}
-\RequirePackage{xparse}
-\RequirePackage{verbatim}
-\RequirePackage{pdfcomment}
-
-\usetikzlibrary{quotes}
-\usetikzlibrary{fit}
-\usetikzlibrary{positioning}
-\usetikzlibrary{intersections}
-\usetikzlibrary{backgrounds}
-\usepgflibrary{arrows.meta}
-\usetikzlibrary{shapes}
-%\usetikzlibrary{profiler}
-
-\newif\ifsseq@draftmode
-\DeclareOption{draft}{\sseq@draftmodetrue}
-\ProcessOptions\relax
-
-\def\sseq@authorname{Hood Chatham}
-\def\sseq@authoremail{hood@mit.edu}
-
-
-%\sseq@draftmodetrue
-
-%%%%%% %%%%%%
-%% %%
-%% Declarations and preliminaries %%
-%% %%
-%%%%%% %%%%%%
-\newif\ifsseq@inprogress
-
-\newif\ifsseq@hasname
-\newif\ifsseq@updateexisting
-\newif\ifsseq@ispageenv
-\newif\ifsseq@keepchanges
-\newif\ifsseq@keepglobaloptions
-\newif\ifsseq@globaldetone
-
-\newif\ifsseq@needstikz
-\newif\ifsseq@thispage
-\newif\ifsseq@outofrange
-\newif\ifsseq@classlabel
-\newif\ifsseq@draworphanedges
-\newif\ifsseq@drawedge
-\newif\ifsseq@tikzprims@integershift
-\newif\ifsseq@anchor
-\sseq@drawedgetrue
-\sseq@tikzprims@integershifttrue
-
-\newif\ifsseq@patchforeach
-\newif\ifsseq@patchfit
-
-\newif\ifsseq@tempif
-\newif\ifsseq@gtempif
-\newif\ifsseq@error
-
-\newtoks\sseq@temptoks
-\newtoks\sseq@temptoksii
-\newtoks\sseq@scope@toks
-
-\newcount\sseq@thepagecount
-\newcount\sseq@anonsseqcount
-\newcount\sseq@x
-\newcount\sseq@y
-\newcount\sseq@tempcount
-\newcount\sseq@tempcountb
-\newcount\sseq@tempx
-\newcount\sseq@tempy
-\newcount\sseq@tempxb
-\newcount\sseq@tempyb
-
-\newcount\sseq@stackdepth
-
-\newdimen\sseq@tooltip@height
-\newdimen\sseq@tooltip@width
-\newdimen\sseq@gridstrokethickness
-\sseq@gridstrokethickness=.1pt
-
-% Ensure \@xp and \@nx have the correct values in case that amsmath isn't loaded
-\let\@xp\expandafter
-\let\@nx\noexpand
-\def\@xptwo{\@xp\@xp\@xp}
-\def\@xpthree{\@xp\@xp\@xp\@xp\@xp\@xp\@xp}
-\def\sseq@nil{\sseq@thisshouldnthappen@nil unique expansion} % This expansion text should be unique so that \ifx\sseq@nil\othercommand is false.
-\def\sseq@infinity{10000} % Larger than any coordinate anyone will ever use.
-\newcount\sseq@infinitycount
-\sseq@infinitycount=\sseq@infinity\relax
-\def\sseq@macroname{\@xp\@gobble\string}
-\def\sseq@gobble@to@nil#1\sseq@nil{}
-\def\sseq@macrogobble#1->{}
-
-% These are only used by defertikzcommand now
-\def\sseq@callas#1{\def\sseq@callcmd{#1}}
-\def\sseq@call#1{\bgroup\@xp\let\sseq@callcmd#1\@xptwo\egroup\sseq@callcmd}
-
-\def\sseq@getfirstchar#1#2\sseq@nil{#1} % used in shift/checkshift transform
-\def\sseq@smuggle@macro#1#2\egroup{\@xp\egroup\@xp\def\@xp#1\@xp{#1}}
-
-
-\def\sseq@protected@edef{\let\sseq@store@slsl\\\def\\{\protect\\}\let\@@protect \protect \let \protect \@unexpandable@protect \afterassignment \sseq@restore@protect \edef}
-\def\sseq@protected@xdef{\let\sseq@store@slsl\\\def\\{\protect\\}\let\@@protect \protect \let \protect \@unexpandable@protect \afterassignment \sseq@restore@protect \xdef}
-\def\sseq@restore@protect{\let\protect\@@protect\let\\\sseq@store@slsl}
-
-\def\sseq@eval#1{\bgroup\edef\sseq@temp{#1}\@xp\egroup\sseq@temp}% I got this from sseq.sty
-\def\sseq@protectedeval#1{\bgroup\sseq@protected@edef\sseq@temp{#1}\@xp\egroup\sseq@temp}
-\def\sseq@eval@show#1{\bgroup\edef\sseq@temp{#1}\show\sseq@temp\@xp\egroup\sseq@temp}
-\def\sseq@profilenew#1#2{\pgfprofilenew{#1}\pretocmd#2{\pgfprofilestart{#1}}{}{\error}\apptocmd#2{\pgfprofileend{#1}}{}{\error}}
-
-%%%% add to macro commands
-\def\sseq@d@addto@macro#1#2{\@xp\def\@xp#1\@xp{#1#2}}
-\def\sseq@e@addto@macro#1#2{\edef#1{\unexpanded\@xp{#1}#2}} % let #2 be expanded
-\def\sseq@eo@addto@macro#1#2{\edef#1{\unexpanded\@xp{#1}\unexpanded\@xp{#2}}} % let #2 be expanded once
-\def\sseq@g@addto@macro#1#2{\@xp\gdef\@xp#1\@xp{#1#2}}
-\def\sseq@x@addto@macro#1#2{\xdef#1{\unexpanded\@xp{#1}#2}} % let #2 be expanded
-\def\sseq@xprotected@addto@macro#1#2{\sseq@protected@xdef#1{\unexpanded\@xp{#1}#2}}
-
-\def\sseq@d@addto@toks#1#2{#1\@xp{\the#1#2}}
-\def\sseq@e@addto@toks#1#2{\sseq@eval{#1{\the#1#2}}}
-
-\def\sseq@d@addto@temptoks{\sseq@d@addto@toks\sseq@temptoks}
-\def\sseq@e@addto@temptoks{\sseq@e@addto@toks\sseq@temptoks}
-
-
-% Used in sseqkeys to delete spaces from style commands.
-\def\sseq@setmacronospaces#1#2{%
- \bgroup\catcode`\ =9\relax
- \scantokens{\@xp\egroup\@xp\def\@xp#1\@xp{\csname #2\endcsname}}%
-}
-
-
-\def\sseq@removeparens{\@xp\sseq@removeparens@}
-\def\sseq@removeparens@(#1){#1}
-
-% Stolen from trimspaces.sty
-\bgroup
-\catcode`\Q=3
-\gdef\sseq@trimspaces#1{%
- \romannumeral-`\q\sseq@trim@trim@\noexpand#1Q Q%
-}
-\long\gdef\sseq@trim@trim@#1 Q{\sseq@trim@trim@@#1Q}
-\long\gdef\sseq@trim@trim@@#1Q#2{#1}
-\egroup
-\def\sseq@trimleadingspaces{\romannumeral-`q}
-
-\def\sseq@ifempty#1{%
- \@xp\ifx\@xp\sseq@nil\detokenize{#1}\sseq@nil
- \@xp\@firstoftwo
- \else
- \@xp\@secondoftwo
- \fi
-}
-
-\def\sseq@ifnil#1{
- \ifx\sseq@nil#1
- \@xp\@firstoftwo
- \else
- \@xp\@secondoftwo
- \fi
-}
-
-\let\sseq@breakpoint\relax
-\def\sseq@break#1\sseq@breakpoint{}
-\def\sseq@break@withcleanup#1\sseq@breakpoint#2{}
-
-\def\sseq@breakfi{\fi\sseq@break}
-\def\sseq@breakfifi{\fi\fi\sseq@break}
-\def\sseq@breakfififi{\fi\fi\fi\sseq@break}
-\long\def\sseq@breakdataenv#1\end#2{
- \def\sseq@tempa{sseqdata}\def\sseq@tempb{#2}\ifx\sseqtempa\sseqtempb
- \@xp\sseq@breakdataenv@
- \else
- \@xp\sseq@breakdataenv
- \fi
-}
-\def\sseq@breakdataenv@{\let\endsseqdata\sseq@breakendsseqdata\end{sseqdata}}
-
-\long\def\sseq@breakpageenv#1\end#2{
- \def\sseq@tempa{sseqpage}\def\sseq@tempb{#2}\ifx\sseqtempa\sseqtempb
- \@xp\sseq@breakpageenv@
- \else
- \@xp\sseq@breakpageenv
- \fi
-}
-\def\sseq@breakpageenv@{\let\endsseqpage\sseq@breakendsseqpage\end{sseqpage}}
-\def\sseq@breakendsseqdata{}
-\def\sseq@breakendsseqpage{}
-
-\def\sseq@seteverythingtonoops{%
- \let\sseqdata\comment
- \let\sseqpage\comment
- \let\sseqkeys\@gobble
- \let\sseqnewgroup\@gobblethree
-}
-
-% Commands we are going to expose just inside of environments
-\def\sseq@macrolist{%
- % These are defined in sseqmain:
- \class\replaceclass\d\structline\classoptions\doptions\structlineoptions\circleclasses
- % The following are defined in sseqparsers:
- \pgfmathparse\isalive\lastx\lasty\lastclass\savestack\restorestack\pushstack\nameclass\tagclass
- \parsecoordinate\parsedifferential\getdtarget\gettag
- \xcoord\ycoord\page %\xmin\xmax\ymin\ymax % these just get protected
-}
-
-% All the tikz commands. We replace these in our environment too. Replacements defined in sseqparsers.
-\def\sseq@tikzcommands{%
- \clip\coordinate\draw\fill\filldraw
- \graph\matrix\node\path\pattern
- \shade\shadedraw\useasboundingbox
-}
-
-
-\input sseqmessages.code.tex % Exposes directly: \sseqerrortowarning
-\input sseqcheckdefinitions.code.tex
-
-%\sseq@patchforeachfalse
-
-\ifsseq@tempif\else % Set to false in checkdefinitions if it failed to patch the key-value system.
- \sseq@seteverythingtonoops
- \sseq@pgfkeyspatchfailed
-\fi
-
-\input sseqloadstore.code.tex % Responsible for installing environment-only macros
-\input sseqmacromakers.code.tex % Exposes directly: \DeclareSseqCommand, \NewSseqCommand, \DeclareSseqGroup, \NewSseqGroup
-
-\input sseqparsers.code.tex % Responsible for making tikz modifications, exposes directly \sseqnormalizemonomial
-
-
-\ifsseq@patchforeach
- \input sseqforeach.code.tex
-\else
- \def\sseq@patchfor{}
-\fi
-
-\input sseqkeys.code.tex % Exposes directly: \sseqset
-\input sseqmain.code.tex % Defines all the main commands. Exposes directly: the environments, \xmin, \xmax, etc.
-\input sseqdrawing.code.tex
-
-
-%%% Some default key settings
-\sseqset{
- edge labels={auto=right},
- classes={draw,circle,inner sep=0pt,minimum size=0.35em},
- circle classes={newellipse, ellipse ratio=1.2,draw, inner sep=2pt},
- edges=draw,
- math nodes,
- differentials=->
-}
-
-% Extra commands to expose:
-\let\sseqifempty\sseq@ifempty
-
-\def\sseqpower#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{1}}
-\def\sseqpowerempty#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{}}
-\def\sseqtypesetpower@#1#2#3{\ifnum#1=\z@#3\else\ifnum#1=\@ne#2\else#2^{#1}\fi\fi}
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex
index bdbc68f51b5..a9de53c794c 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqcheckdefinitions.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqcheckdefinitions.code.tex
@@ -15,13 +15,54 @@
\sseq@tempiftrue
\begingroup
-
+\def\sseq@checkprotecteddef#1{\def\sseq@temp{\sseq@checkdef@{#1}}\afterassignment\sseq@temp\protected\long\@xp\def\csname sseq@check@\sseq@macroname#1\endcsname}
\def\sseq@checkdef#1{\def\sseq@temp{\sseq@checkdef@{#1}}\afterassignment\sseq@temp\@xp\def\csname sseq@check@\sseq@macroname#1\endcsname}
\def\sseq@checkdef@#1{\@xp\ifx\csname sseq@check@\sseq@macroname#1\endcsname#1\else
\sseq@tempiffalse
\fi}
%%
+%% sseqmacromakers.code.tex
+%%
+
+\ExplSyntaxOn
+% I should work out how old the version of xparse has to be before this breaks, but I'm too lazy.
+% It would also be nice if I could figure out how to ensure that my trick of setting \l__xparse_grab_expandably_bool to false works correctly, but this might be difficult
+\@ifpackagelater{xparse}{2017/02/08}{
+ \sseq@checkprotecteddef \__xparse_grab_u:w #1#2 \__xparse_run_code:{
+ \__xparse_grab_u_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn
+ }
+
+ \sseq@checkprotecteddef\__xparse_grab_u_aux:nnN #1#2#3
+ {
+ \tl_set:Nn \l__xparse_signature_tl {#2}
+ \exp_after:wN #3 \l__xparse_fn_tl ##1 #1
+ { \__xparse_add_arg:n {##1} }
+ \l__xparse_fn_tl
+ }
+
+
+ \sseq@checkprotecteddef \__xparse_normalize_type_u:w #1 {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \__xparse_bad_arg_spec:wn }
+ \__xparse_normalize_check_lu:N u
+ \__xparse_add_arg_spec:n { u {#1} }
+ \int_incr:N \l__xparse_mandatory_args_int
+ \tl_clear:N \l__xparse_last_delimiters_tl
+ \__xparse_normalize_arg_spec_loop:n
+ }
+
+ \ifsseq@tempif
+ \global\sseq@patchxparseUtrue
+ \else
+ %\sseq@warning{fit-patch-failed}
+ \global\sseq@patchxparseUfalse
+ \fi
+ \sseq@tempiftrue
+}{}
+
+\ExplSyntaxOff
+
+%%
%% sseqkeys.code.tex
%%
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
index 098e73f9110..c8bba066b23 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqdrawing.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqdrawing.code.tex
@@ -14,165 +14,314 @@
%% the axes ticks was taking about 1/3 of the compile time (a little under 1s out of a 3.2)
%%
+% Only for integer valued coordinates...
+\def\sseq@qpointxy#1#2{\pgfqpointxy{\numexpr#1+\sseq@xoffset\relax}{\numexpr#2+\sseq@yoffset\relax}}
+\def\sseq@transform@xymirror{
+ \pgfsetxvec{\pgfqpoint{1cm}{0cm}}
+ \pgfsetyvec{\pgfqpoint{0cm}{1cm}}
+ \pgftransformcm{0}{1}{1}{0}{\pgfpointxy{\sseq@xoffset*\sseq@xscale }{\sseq@yoffset*\sseq@yscale}} % Reflect x and y axes,
+ \pgftransformshift{\pgfpointxy{-\sseq@xoffset*\sseq@yscale}{-\sseq@yoffset*\sseq@xscale}} % but we need to conjugate by a shift of (xoffset,yoffset)
+ \pgfsetyvec{\pgfqpoint{0cm}{\sseq@xscale cm}}
+ \pgfsetxvec{\pgfqpoint{\sseq@yscale cm}{0cm}}
+}
+
+
+\def\sseq@setlayoutparameter#1#2{\@xp\let\csname sseq@#1\@xp\endcsname\csname sseq@#1@#2\endcsname}
+\def\sseq@setlayoutparameters{
+ \sseq@setlayoutparameter{yaxisorigin}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{drawyaxis}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{yaxisstartoffset}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{yaxisendoffset}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{bottomgridpadding}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{topgridpadding}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{bottomclippadding}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{topclippadding}{x\sseq@xaxistype}
+ \sseq@setlayoutparameter{xlabelposition}{x\sseq@xaxistype}
+%
+ \sseq@setlayoutparameter{xaxisorigin}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{drawxaxis}{y\sseq@xaxistype}
+ \sseq@setlayoutparameter{xaxisstartoffset}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{xaxisendoffset}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{leftgridpadding}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{rightgridpadding}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{leftclippadding}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{rightclippadding}{y\sseq@yaxistype}
+ \sseq@setlayoutparameter{ylabelposition}{y\sseq@xaxistype}
+}
+
+% The appropriate one of these is chosen by the "axis type" keys in sseqkeys.
+
+% Used to determine axis and ticks placement
+\def\sseq@xaxisorigin@yborder{\sseq@xmin}
+\def\sseq@xaxisorigin@yframe{\sseq@xmin}
+\def\sseq@xaxisorigin@ycenter{\sseq@xaxisorigin@center@}
+\def\sseq@yaxisorigin@xborder{\sseq@ymin}
+\def\sseq@yaxisorigin@xframe{\sseq@ymin}
+\def\sseq@yaxisorigin@xcenter{\sseq@yaxisorigin@center@}
+
+% Used to determine clipping and grid boundaries
+\def\sseq@leftgridpadding@yborder{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@rightgridpadding@yborder{\sseq@xaxis@end@extend}
+\def\sseq@leftgridpadding@ycenter{\sseq@xaxis@start@extend}
+\def\sseq@rightgridpadding@ycenter{\sseq@xaxis@end@extend}
+\def\sseq@leftgridpadding@yframe{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@rightgridpadding@yframe{5cm} % Just make it big enough to push off the end of the clip
+\def\sseq@leftgridpadding@ynone{\sseq@yaxisgap}
+\def\sseq@rightgridpadding@ynone{\sseq@yaxisgap}
+
+
+\def\sseq@bottomgridpadding@xborder{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@topgridpadding@xborder{\sseq@yaxis@end@extend}
+\def\sseq@bottomgridpadding@xcenter{\sseq@yaxis@start@extend}
+\def\sseq@topgridpadding@xcenter{\sseq@yaxis@end@extend}
+\def\sseq@bottomgridpadding@xframe{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@topgridpadding@xframe{5cm}
+\def\sseq@bottomgridpadding@xnone{\sseqxaxisgap}
+\def\sseq@topgridpadding@xnone{\sseq@xaxisgap}
+
+\def\sseq@leftclippadding@yborder{\dimexpr-\sseq@yaxisgap+\sseq@yclip@axisgap\relax}
+\def\sseq@rightclippadding@yborder{\dimexpr\sseq@xaxis@end@extend+\sseq@clip@padding@right\relax}
+\def\sseq@leftclippadding@ycenter{\dimexpr-\sseq@xaxis@start@extend-\sseq@clip@padding@left\relax}
+\def\sseq@rightclippadding@ycenter{\dimexpr\sseq@xaxis@end@extend+\sseq@clip@padding@right\relax}
+\def\sseq@leftclippadding@yframe{\dimexpr-\sseq@yaxisgap+\sseq@yclip@axisgap\relax}
+\def\sseq@rightclippadding@yframe{\dimexpr\sseq@yaxisgap-\sseq@yclip@axisgap\relax}
+\def\sseq@leftclippadding@ynone{\dimexpr-\sseq@yaxisgap-\sseq@clip@padding@left\relax}
+\def\sseq@rightclippadding@ynone{\dimexpr\sseq@yaxisgap+\sseq@clip@padding@right\relax}
+
+\def\sseq@bottomclippadding@xborder{\dimexpr-\sseq@xaxisgap+\sseq@xclip@axisgap\relax}
+\def\sseq@topclippadding@xborder{\dimexpr\sseq@yaxis@end@extend+\sseq@clip@padding@top\relax}
+\def\sseq@bottomclippadding@xcenter{\dimexpr-\sseq@yaxis@start@extend-\sseq@clip@padding@bottom\relax}
+\def\sseq@topclippadding@xcenter{\dimexpr\sseq@yaxis@end@extend+\sseq@clip@padding@top\relax}
+\def\sseq@bottomclippadding@xframe{\dimexpr-\sseq@xaxisgap+\sseq@xclip@axisgap\relax}
+\def\sseq@topclippadding@xframe{\dimexpr\sseq@xaxisgap-\sseq@xclip@axisgap\relax}
+\def\sseq@bottomclippadding@xnone{\dimexpr-\sseq@xaxisgap-\sseq@clip@padding@bottom\relax}
+\def\sseq@topclippadding@xnone{\dimexpr\sseq@xaxisgap+\sseq@clip@padding@top\relax}
+
+% Used to figure out how much further beyond (min -- max) to draw axes
+\def\sseq@xaxisstartoffset@yborder{\dimexpr\sseq@xaxis@tail+\sseq@yaxisgap\relax}
+\def\sseq@xaxisendoffset@yborder{\sseq@xaxis@end@extend}
+\def\sseq@xaxisstartoffset@ycenter{\sseq@xaxis@start@extend}
+\def\sseq@xaxisendoffset@ycenter{\sseq@xaxis@end@extend}
+\def\sseq@xaxisstartoffset@yframe{\sseq@yaxisgap}
+\def\sseq@xaxisendoffset@yframe{\sseq@yaxisgap}
+\def\sseq@yaxisstartoffset@xborder{\dimexpr\sseq@yaxis@tail+\sseq@xaxisgap\relax}
+\def\sseq@yaxisendoffset@xborder{\sseq@yaxis@end@extend}
+\def\sseq@yaxisstartoffset@xcenter{\sseq@yaxis@start@extend}
+\def\sseq@yaxisendoffset@xcenter{\sseq@yaxis@end@extend}
+\def\sseq@yaxisstartoffset@xframe{\sseq@xaxisgap}
+\def\sseq@yaxisendoffset@xframe{\sseq@xaxisgap}
+
+\def\sseq@xlabelposition@xborder{(0,-\sseq@xaxisstartoffset)}
+\def\sseq@xlabelposition@xcenter{(-\sseq@yaxisgap,-\sseq@xaxisstartoffset-5pt)}
+\def\sseq@xlabelposition@xframe{(0,-\sseq@xaxisgap-\sseq@xlabelgap-10pt)}
+\def\sseq@xlabelposition@xnone{(0,0)}
+
+\def\sseq@ylabelposition@yborder{(0,\sseq@yaxisstartoffset)}
+\def\sseq@ylabelposition@ycenter{(-\sseq@xaxisgap,\sseq@yaxisstartoffset+5pt)}
+\def\sseq@ylabelposition@yframe{(0,\sseq@yaxisgap+\sseq@ylabelgap+10pt)}
+\def\sseq@ylabelposition@ynone{(0,0)}
%%%
%%% Draw axes and clip
%%%
\def\sseq@handlexaxis{
- \ifsseq@drawxaxis
- \bgroup
- \ifsseq@borderxaxis\else
- \let\sseq@ymin\sseq@yaxisorigin % Warning: this is a stupid, lazy hack.
- \fi
- \sseq@drawxaxis
- \ifsseq@drawxaxisticks
- \sseq@drawxticks
- \fi
- \egroup
+ \bgroup
+ \sseq@drawxaxis
+ \ifsseq@drawxaxisticks
+ \sseq@drawxticks
\fi
+ \egroup
}
\def\sseq@handleyaxis{
- \ifsseq@drawyaxis
- \bgroup
- \ifsseq@borderyaxis\else
- \let\sseq@xmin\sseq@xaxisorigin % Warning: this is a stupid, lazy hack.
- \fi
- \sseq@drawyaxis
- \ifsseq@drawyaxisticks
- \sseq@drawyticks
- \fi
- \egroup
+ \bgroup
+ \sseq@drawyaxis
+ \ifsseq@drawyaxisticks
+ \sseq@drawyticks
\fi
+ \egroup
}
-\def\sseq@drawxaxis{
- \bgroup
- \pgftransformreset
- \sseq@globaldetonetransform
- %
+
+% Draws an x axis. Use with \sseq@transform@xymirror to draw y axis.
+% #1 -- horizontal start offset
+% #2 -- horizontal end offset
+% #3 -- vertical offset
+% #4 -- start value
+% #5 -- end value
+% #6 -- vertical value
+\def\sseq@drawaxis@generic#1#2#3#4#5#6{
\bgroup
- \pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformyshift{-\sseq@xaxisgap}
- \sseq@globalscaletransform
- \pgfpathmoveto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+ \pgftransformshift{\pgfqpoint{#2}{#3}}
+ \pgfpathmoveto{\sseq@qpointxy{#5}{#6}}
\egroup
+%
\bgroup
- \pgftransformxshift{-\sseq@yaxisgap}
- %\pgftransformxshift{-\sseq@ylabelgap}
- \pgftransformxshift{-\sseq@xaxis@start@extend}
- \pgftransformyshift{-\sseq@xaxisgap}
- \sseq@globalscaletransform
- \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
- \egroup
+ \pgftransformshift{\pgfqpoint{#1}{#3}}
+ \pgfpathlineto{\sseq@qpointxy{#4}{#6}}
\egroup
+}
+
+\def\sseq@drawxaxis@ynone{
+ \sseq@drawxaxisticksfalse
+}
+\def\sseq@drawyaxis@xnone{
+ \sseq@drawyaxisticksfalse
+}
+
+\def\sseq@drawxaxis@yborder{
+ \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{-\sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@yaxisorigin}
\pgfusepath{stroke}
}
-\def\sseq@drawyaxis{
- \bgroup
- \pgftransformreset
- \sseq@globaldetonetransform
+\let\sseq@drawxaxis@ycenter\sseq@drawxaxis@yborder
+
+\def\sseq@drawxaxis@yframe{
+ \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{-\sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@ymin}
+ \sseq@drawaxis@generic{-\sseq@xaxisstartoffset}{\sseq@xaxisendoffset}{ \sseq@xaxisgap}{\sseq@xmin}{\sseq@xmax}{\sseq@ymax}
+ \pgfusepath{stroke}
+}
+\def\sseq@drawyaxis@xborder{
\bgroup
- \pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformxshift{-\sseq@yaxisgap}
- \sseq@globalscaletransform
- \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+ \sseq@transform@xymirror
+ \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{-\sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xaxisorigin}
+ \pgfusepath{stroke}%
\egroup
+}
+\let\sseq@drawyaxis@xcenter\sseq@drawyaxis@xborder
+\def\sseq@drawyaxis@xframe{
\bgroup
- \pgftransformyshift{-\sseq@xaxisgap}
- %\pgftransformyshift{-\sseq@xlabelgap}
- \pgftransformyshift{-\sseq@yaxis@start@extend}
- \pgftransformxshift{-\sseq@yaxisgap}
- \sseq@globalscaletransform
- \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
- \egroup
- \egroup
+ \sseq@transform@xymirror
+ \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{-\sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xmin}
+ \sseq@drawaxis@generic{-\sseq@yaxisstartoffset}{\sseq@yaxisendoffset}{ \sseq@yaxisgap}{\sseq@ymin}{\sseq@ymax}{\sseq@xmax}
\pgfusepath{stroke}%
+ \egroup
}
-\def\sseq@drawxticks{
- \sseq@tempy=\sseq@ymin\relax
- \sseq@tempx=\sseq@xmax\relax
- \advance\sseq@tempx\@ne\relax
- \edef\sseq@temp{\the\sseq@tempx}%
- \sseq@tempx=\sseq@xmin\relax
+
+\ExplSyntaxOn
+\def\sseq@intdivceiling#1#2{%
+ \ifnum#1>\z@ % \int_div_truncate:nn rounds towards 0. We want \int_div_ceiling
+ \int_div_truncate:nn{#1+#2-1}{#2} % if positive, use ceil(p/q)=floor((p+q-1)/q) for p,q integers
+ \else
+ \int_div_truncate:nn{#1}{#2} % if we are negative, towards 0 is ceiling
+ \fi
+}
+\def\sseq@intdivfloor#1#2{%
+ \ifnum#1<\z@ % \int_div_truncate:nn rounds towards 0. We want \int_div_floor
+ \int_div_truncate:nn{#1-#2+1}{#2} % if we are negative, use floor(p/q) = ceil(p-q+1/q) for p,q integers
+ \else
+ \int_div_truncate:nn{#1}{#2} % if positive, towards 0 is floor
+ \fi
+}
+\ExplSyntaxOff
+
+% #1 -- xmin
+% #2 -- xmax
+% #3 -- step
+% #4 -- offset
+% #5 -- ymin
+% #6 -- xaxisgap
+% #7 -- code
+\def\sseq@tickloop@generic#1#2#3#4#5#6#7{
+ \sseq@tempx=\numexpr % min
+ \sseq@intdivceiling{#1}{#3} * #3
+ -
+ \sseq@intdivceiling{#4}{#3} * #3 + #4
+ \relax
+ \ifnum\sseq@tempx<#1\relax
+ \advance\sseq@tempx#3\relax
+ \fi
+ \sseq@tempxb=\numexpr#2+1\relax % max
\loop
\bgroup
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
- \pgftransformresetnontranslations
- \sseq@globaldetonetransform
- \pgftransformyshift{-\sseq@xlabelgap}\pgftransformyshift{-\sseq@xaxisgap}
- \pgftransformresetnontranslations
- \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
+ \pgftransformshift{\sseq@qpointxy{\sseq@tempx}{#5}}%
+ \pgftransformshift{\pgfqpoint{0pt}{#6}}
+ #7
+ \egroup
+ \advance\sseq@tempx#3\relax
+ \ifnum\sseq@tempx<\sseq@tempxb\repeat
+}
+
+
+\def\sseq@drawxticks{%
+ \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xtickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
\sseq@xtickstyle
\tikz@options
- \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}}
- \egroup
- \advance\sseq@tempx\sseq@xtickstep\relax
- \ifnum\sseq@tempx<\sseq@temp\repeat
-}
-\def\sseq@drawyticks{
- \sseq@tempx=\sseq@xmin\relax
- \sseq@tempy=\sseq@ymax\relax
- \advance\sseq@tempy\@ne\relax
- \edef\sseq@tempmax{\the\sseq@tempy}
- \sseq@tempy=\sseq@ymin\relax
- \loop
- \bgroup
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
- \pgftransformresetnontranslations
- \sseq@globaldetonetransform
- \pgftransformxshift{-\sseq@ylabelgap}\pgftransformxshift{-\sseq@yaxisgap}
- \pgftransformresetnontranslations
- \ifsseq@rotatelabels\sseq@globalrotatetransform\fi
+ \pgftransformshift{\pgfqpoint{0pt}{-\sseq@ylabelgap}}
+ \pgftext{\hbox{$\sseq@xtickfn{\the\sseq@tempx}$}}%
+ }
+ \ifnum\sseq@xmajortickstep>\z@
+ \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xmajortickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
+ \pgfpathmoveto{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0}{-0.4*\sseq@xaxisgap}}
+ }
+ \fi
+ \ifnum\sseq@xminortickstep>\z@
+ \sseq@tickloop@generic{\sseq@xmin}{\sseq@xmax}{\sseq@xminortickstep}{\sseq@xtickstepoffset}{\sseq@yaxisorigin}{-\sseq@xaxisgap}{
+ \pgfpathmoveto{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0}{-0.2*\sseq@xaxisgap}}
+ }
+ \fi
+ \pgfusepath{stroke}
+}
+\def\sseq@drawyticks{%
+ \sseq@transform@xymirror
+ \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@ytickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
\sseq@ytickstyle
\tikz@options
- \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempy}$}}
- \egroup
- \advance\sseq@tempy\sseq@ytickstep\relax
- \ifnum\sseq@tempy<\sseq@tempmax\repeat
+ \pgftransformshift{\pgfqpoint{0pt}{-\sseq@ylabelgap}}
+ \pgftransformresetnontranslations
+ \pgftext{\hbox{$\sseq@ytickfn{\the\sseq@tempx}$}}%
+ }
+ \ifnum\sseq@ymajortickstep>\z@
+ \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@ymajortickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
+ \pgfpathmoveto{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0}{-0.4*\sseq@yaxisgap}}
+ }
+ \fi
+ \ifnum\sseq@yminortickstep>\z@
+ \sseq@tickloop@generic{\sseq@ymin}{\sseq@ymax}{\sseq@yminortickstep}{\sseq@ytickstepoffset}{\sseq@xaxisorigin}{-\sseq@yaxisgap}{
+ \pgfpathmoveto{\pgfpointorigin}
+ \pgfpathlineto{\pgfpoint{0}{-0.2*\sseq@yaxisgap}}
+ }
+ \fi
+ \pgfusepath{stroke}
}
+
+
\def\sseq@setupclip{
%\clip(\sseq@xmin-0.4,\sseq@ymin-0.4) rectangle (\sseq@xmax+0.5,\sseq@ymax+0.5);%
\ifsseq@clip
\ifx\sseq@customclip\pgfutil@empty
\bgroup
- \pgftransformreset
- \sseq@globaldetonetransform
- \ifsseq@borderyaxis
- \def\xmin{\pgftransformxshift{-\sseq@yaxisgap}\pgftransformxshift{\sseq@yclip@axisgap}}
- \else
- \def\xmin{\pgftransformxshift{-\sseq@xaxis@start@extend}\pgftransformxshift{-\sseq@clip@padding@left}}
- \fi
- \ifsseq@borderxaxis
- \def\ymin{\pgftransformyshift{-\sseq@xaxisgap}\pgftransformyshift{\sseq@xclip@axisgap}}
- \else
- \def\ymin{\pgftransformyshift{-\sseq@yaxis@start@extend}\pgftransformyshift{-\sseq@clip@padding@bottom}}
- \fi
- \def\xmax{\pgftransformxshift{\sseq@xaxis@end@extend}\pgftransformxshift{\sseq@clip@padding@right}}
- \def\ymax{\pgftransformyshift{\sseq@yaxis@end@extend}\pgftransformyshift{\sseq@clip@padding@top}}
+ \def\xmin{\pgftransformshift{\pgfqpoint{\sseq@leftclippadding}{0pt}}}
+ \def\ymin{\pgftransformshift{\pgfqpoint{0pt}{\sseq@bottomclippadding}}}
+ \def\xmax{\pgftransformshift{\pgfqpoint{\sseq@rightclippadding}{0pt}}}
+ \def\ymax{\pgftransformshift{\pgfqpoint{0pt}{\sseq@topclippadding}}}
\bgroup
- \xmin\ymin\sseq@globalscaletransform
- \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
+ \xmin\ymin
+ \pgfpathmoveto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
\egroup
\bgroup
- \xmin\ymax\sseq@globalscaletransform
- \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
+ \xmin\ymax
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
\egroup
\bgroup
- \xmax\ymax\sseq@globalscaletransform
- \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
+ \xmax\ymax
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
\egroup
\bgroup
- \xmax\ymin\sseq@globalscaletransform
- \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+ \xmax\ymin
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
\egroup
\egroup
\pgfpathclose
- \pgfgetpath\sseq@theclippath % This stores the clipping so I can find intersections later
+ \pgfgetpath\sseq@theclippath % This stores the clipping so I can apply it later
\pgfusepath{discard}% This has to be after the egroup or else the clipping gets screwed up
+%
\bgroup
- %\sseq@globalscaletransform
- \pgfpathmoveto{\pgfpoint{\sseq@xmin cm}{\sseq@ymin cm}}
- \pgfpathlineto{\pgfpoint{\sseq@xmin cm}{\sseq@ymax cm}}
- \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymax cm}}
- \pgfpathlineto{\pgfpoint{\sseq@xmax cm}{\sseq@ymin cm}}
+ \pgfpathmoveto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmin+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymax+\sseq@yoffset\relax}}
+ \pgfpathlineto{\pgfqpointxy{\numexpr\sseq@xmax+\sseq@xoffset\relax}{\numexpr\sseq@ymin+\sseq@yoffset\relax}}
\pgfpathclose
\egroup
\pgfgetpath\sseq@therangepath % Only for deciding whether to draw "tricky edges"
@@ -188,66 +337,194 @@
\fi
}
\def\sseq@useclip{\ifx\sseq@theclippath\relax\else\pgfsetpath\sseq@theclippath\pgfusepath{clip}\fi}
+
+
+% sets \pgf@xa and \pgf@ya equal to the coordinates of (1,1), sets \pgf@xb and \pgf@xb equal to (x grid step, y grid step)
+\def\sseq@grid@setstepandgridstep{
+ \pgf@process{\pgfqpointxy{1}{1}}
+ \pgf@xa=\pgf@x
+ \pgf@ya=\pgf@y
+ \pgf@process{\pgfqpointxy{\sseq@xgridstep}{\sseq@ygridstep}}
+ \pgf@xb=\pgf@x
+ \pgf@yb=\pgf@y
+}
+
+% #1 -- macro to store result in
+% #2 -- "x" or "y" as appropriate
+% #3 -- length (with units)
+% #4 -- fraction of gridstep
+% If #2 is x, then it either sets #1 to #3/(x scale) or xgridstep*#4, whichever is smaller
+% The output is intended for use with \pgfpointxy.
+\def\sseq@grid@atmostgridstep#1#2#3#4{
+ \ifdim#3<\dimexpr\csname pgf@#2b\endcsname*#4\relax
+ \pgfmathparse{#3/\csname pgf@#2a\endcsname}
+ \let#1\pgfmathresult
+ \else
+ \edef#1{\csname sseq@#2gridstep\endcsname*#4}
+ \fi
+}
+
+% This grid was a huge pain in the ass to get right...
\def\sseq@grid@chess{
- \bgroup
- \pgfscope
- \sseq@useclip
- \pgflowlevelsynccm
- \pgfsetlinewidth{1cm}
- \pgfsetdash{{1cm}{1cm}}{1cm}
- \pgfsetcolor{lightgray}
- \pgfpathgrid[stepx=2cm,stepy=2cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\sseq@xmax cm+0.499cm}{\sseq@ymax cm+0.499cm}}
- \pgfusepath{stroke}
- \endpgfscope
- \egroup
+ \bgroup
+ \pgfscope
+ % Pad on the right and top by either the grid padding, or the remaining piece of the checkerboard before it would start a new square
+ % (it looks ugly to have a tiny sliver). Annoyingly, mod returns its result with the same sign as its input, so in order to reduce mod
+ % \sseq@xgridstep and get a positive result, we have to do it twice. The 0.5cm*scale here matches the -0.5 in the \pgfpathgrid call.
+ \pgfmathsetmacro\sseq@rightpadding{min(
+ \sseq@rightgridpadding,
+ 1cm* mod(mod(-\sseq@xmax,\sseq@xgridstep)+\sseq@xgridstep,\sseq@xgridstep)+0.5cm*\sseq@xscale-0.05cm
+ )}
+ \pgfmathsetmacro\sseq@toppadding{min(
+ \sseq@topgridpadding,
+ 1cm * mod(mod(-\sseq@ymax,\sseq@ygridstep)+\sseq@ygridstep,\sseq@ygridstep)+0.5cm*\sseq@yscale-0.02cm
+ )}
+ % Because of complicated aliasing issues that arise when misusing the \pgfgrid command in this way,
+ % it's more convenient to add a clip than to actually stop things in the right place.
+ \clip (\sseq@xmin-\sseq@xoffset,\sseq@ymin-\sseq@yoffset) ++ (-0.48, -0.48)
+ rectangle ([shift={(\sseq@rightpadding pt,\sseq@toppadding pt)}]\sseq@xmax,\sseq@ymax);
+%
+ \sseq@useclip
+ \pgfsetcolor{\sseq@gridcolor}
+ \pgfsetstrokeopacity{0.3} % We don't set low opacity for the other grids, but this one is visible even if it is very faint.
+ \sseq@grid@setstepandgridstep
+%
+% Use ifdim with cm to compare real scalars b/c tex is dumb.
+ % okay, now we need to be careful in order to avoid overflows. The hack we are using requires that the xvec and the yvec are equal
+ % because we can't apply these via lowlevelsynccm. However, xvec and yvec are the things that prevent overflows.
+ % What we need to do is set them both equal to the smaller value. Now the scale factor determines the size of the squares,
+ % so we mix in the grid steps. We also need to scale the larger scaled coordinate by the ratio of the two scales.
+ \ifdim\sseq@xscale cm<\sseq@yscale cm\relax
+ % x is smaller so set both x and y vecs to \sseq@xscale cm.
+ \pgfsetxvec{\pgfpoint{\sseq@xscale cm}{0cm}}
+ \pgfsetyvec{\pgfpoint{0cm}{\sseq@xscale cm}}
+ \def\sseq@xadjustscale{\sseq@xgridstep}
+ \def\sseq@yadjustscale{\sseq@yscale/\sseq@xscale*\sseq@ygridstep}
+ \def\sseq@stepscale{\sseq@xscale}
+ \else
+ \pgfsetxvec{\pgfpoint{\sseq@yscale cm}{0cm}}
+ \pgfsetyvec{\pgfpoint{0cm}{\sseq@yscale cm}}
+ \def\sseq@xadjustscale{(\sseq@xscale/\sseq@yscale*\sseq@xgridstep)}
+ \def\sseq@yadjustscale{\sseq@ygridstep}
+ \def\sseq@stepscale{\sseq@yscale}
+ \fi
+ \pgftransformxscale{\sseq@xadjustscale}
+ \pgftransformyscale{\sseq@yadjustscale}
+ % Now we have to put in some ridiculously complicated shift in order to get the bottom corner in the right place.
+ % I found this formula mostly by trial and error.
+ % The basic idea that we should be making something divisible by twice the grid step (which is the actual period of our grid)
+ % is reasonable enough, but what the heck are these other two terms for? I don't know either, thank god it works.
+ \pgftransformshift{\pgfpointxy{
+ floor((\sseq@xgridstep-1)/2)/\sseq@xgridstep
+ + \ifodd\sseq@xgridstep\space 0 \else 0.5/\sseq@xgridstep\fi
+ + mod(1+\sseq@xmin/\sseq@xgridstep,2*\sseq@xgridstep)
+ }{
+ floor((\sseq@ygridstep-1)/2)/\sseq@ygridstep
+ + \ifodd\sseq@ygridstep\space 0\else 0.5/\sseq@ygridstep\fi
+ + mod(1+\sseq@ymin/\sseq@ygridstep,2*\sseq@ygridstep)
+ }
+ }
+ % We use lowlevelsynccm to make the scale adjust the line width. Normally scaling doesn't affect line width, text size, etc, which is sensible.
+ % When you apply \pgflowlevelsynccm, pgf loses track of the coordinate matrix and it gets indiscriminately applied to everything.
+ % This is good for us, because we're doing this absurd thing where we make a checkerboard by drawing a really really fat line.
+ \pgflowlevelsynccm
+ \pgfsetlinewidth{1cm*\sseq@stepscale}
+ \pgfsetdash{{1cm*\sseq@stepscale}{1cm*\sseq@stepscale}}{1cm*\sseq@stepscale}
+%
+ % Naturally some trial and error occurred here too.
+ % Note the huge multiples of \sseq@xgridstep I added in -- they probably aren't necessary, but I don't understand what's going on so whatever.
+ % The basic idea is that things need to be divisible by twice the grid step. The part I added in the shift above
+ % was the remainder when you divide \sseq@xmin by twice the grid step, now we need to add in the multiple of twice the grid step.
+ % The -0.5 is ensuring that the checkerboard boundaries lie at half-integer coordinates (I think).
+ \pgfpathgrid[stepx= 2cm*\sseq@stepscale,stepy=2cm*\sseq@stepscale]
+ { \pgfpointxy
+ { -0.5 + \sseq@intdivfloor{\numexpr\sseq@xmin - \sseq@xgridstep\relax}{2*\sseq@xgridstep}*2*\sseq@xgridstep + \sseq@xoffset - 50*\sseq@xgridstep }
+ { -0.5 + \sseq@intdivfloor{\numexpr\sseq@ymin - \sseq@ygridstep\relax}{2*\sseq@ygridstep}*2*\sseq@ygridstep + \sseq@yoffset - 50*\sseq@ygridstep}
+ }{ \pgfpointxy
+ { \sseq@xmax + \sseq@xoffset + 50*\sseq@xgridstep }
+ { \sseq@ymax + \sseq@yoffset + 50*\sseq@ygridstep }
+ }
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
}
+
\def\sseq@grid@crossword{
- \bgroup
- \pgfscope
- \pgfsetlinewidth{\the\sseq@gridstrokethickness}
- \sseq@useclip
- \pgftransformxshift{-0.5cm}
- \pgftransformyshift{-0.5cm}
- \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.99cm}{\ymax cm+0.99cm}}
- \pgfusepath{stroke}
- \endpgfscope
- \egroup
+ \bgroup
+ \pgfscope
+ \sseq@useclip
+ \pgfsetcolor{\sseq@gridcolor}
+ \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+ \sseq@grid@setstepandgridstep
+%
+ % We don't want the grid to end with an extra line, so extend it by one half the step distance or
+ % \sseq@---gridpadding, whichever is shorter.
+ \sseq@grid@atmostgridstep\sseq@xminpadding{x}{\sseq@leftgridpadding}{1/2}
+ \sseq@grid@atmostgridstep\sseq@xmaxpadding{x}{\sseq@rightgridpadding}{1/2}
+ \sseq@grid@atmostgridstep\sseq@yminpadding{y}{\sseq@bottomgridpadding}{1/2}
+ \sseq@grid@atmostgridstep\sseq@ymaxpadding{y}{\sseq@topgridpadding}{1/2}
+%
+ \pgftransformshift{\pgfpointxy{-\sseq@xgridstep/2}{-\sseq@ygridstep/2}}
+ \pgfpathgrid[stepx=\pgf@xb,stepy=\pgf@yb]
+ { \pgfpointxy
+ { \sseq@xmin - \sseq@xminpadding + 0.01 + \sseq@xoffset + \sseq@xgridstep/2 }
+ { \sseq@ymin - \sseq@yminpadding + 0.01 + \sseq@yoffset + \sseq@ygridstep/2 } }
+ { \pgfpointxy
+ { \sseq@xmax + \sseq@xmaxpadding - 0.01 + \sseq@xoffset + \sseq@xgridstep/2 }
+ { \sseq@ymax + \sseq@ymaxpadding - 0.01 + \sseq@yoffset + \sseq@ygridstep/2 } }
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
}
\def\sseq@grid@go{
- \bgroup
- \pgfscope
- \sseq@useclip
- \pgfsetlinewidth{\the\sseq@gridstrokethickness}
- \pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-1cm}{-1cm}}{\pgfpoint{\xmax cm+0.5cm}{\ymax cm+0.5cm}}
- \pgfusepath{stroke}
- \endpgfscope
- \egroup
+ \bgroup
+ \pgfscope
+ \sseq@useclip
+ \pgfsetcolor{\sseq@gridcolor}
+ \pgfsetlinewidth{\the\sseq@gridstrokethickness}
+ \sseq@grid@setstepandgridstep
+%
+ % We don't want the grid to end with an extra line, so extend it by one step distance or
+ % \sseq@---gridpadding, whichever is shorter.
+ \sseq@grid@atmostgridstep\sseq@xminpadding{x}{\sseq@leftgridpadding}{1}
+ \sseq@grid@atmostgridstep\sseq@xmaxpadding{x}{\sseq@rightgridpadding}{1}
+ \sseq@grid@atmostgridstep\sseq@yminpadding{y}{\sseq@bottomgridpadding}{1}
+ \sseq@grid@atmostgridstep\sseq@ymaxpadding{y}{\sseq@topgridpadding}{1}
+%
+ \pgfpathgrid[stepx=\pgf@xb,stepy=\pgf@yb]
+ { \pgfpointxy
+ { \sseq@xmin - \sseq@xminpadding + 0.01 + \sseq@xoffset }
+ { \sseq@ymin - \sseq@yminpadding + 0.01 + \sseq@yoffset } }
+ { \pgfpointxy
+ { \sseq@xmax + \sseq@xmaxpadding - 0.01 + \sseq@xoffset }
+ { \sseq@ymax + \sseq@ymaxpadding - 0.01 + \sseq@yoffset }
+ }
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
}
\def\sseq@grid@none{}
\def\sseq@grid@dots{
- \bgroup
- \pgfscope
- \pgfgettransform\sseq@savetransform
- \pgftransformreset
- \sseq@globalscaletransform
- \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v}
- \pgfsettransform\sseq@savetransform
- \sseq@useclip
- \pgftransformxshift{-1.5cm}
- \pgftransformyshift{-0.5cm}
- \pgfsetdash{{1pt}{\sseq@a*1cm-1pt}}{0.5cm+.5pt}
- \pgfsetlinewidth{1pt}
- \sseq@tempy=\sseq@ymin\relax
- \advance\sseq@tempy\m@ne
- \loop
- \advance\sseq@tempy\@ne
- \pgfpathmoveto{\pgfpoint{\sseq@xmin cm+0.5cm/\sseq@a}{\the\sseq@tempy cm}}
- \pgfpathlineto{\pgfpoint{\sseq@xmax cm+1.01cm }{\the\sseq@tempy cm}}
- \ifnum\sseq@tempy<\sseq@ymax\repeat
- %\pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\xmax cm-0.5cm}{\ymax cm-0.5cm}}
- \pgfusepath{stroke}
- \endpgfscope
- \egroup
+ \bgroup
+ \pgfscope
+ \pgfgettransform\sseq@savetransform
+ \pgfgettransformentries{\sseq@a}{\sseq@b}{\sseq@c}{\sseq@d}{\sseq@u}{\sseq@v}
+ \pgfsettransform\sseq@savetransform
+ \sseq@useclip
+ \pgftransformshift{\pgfqpoint{-1.5cm}{-0.5cm}}
+ \pgfsetdash{{1pt}{\sseq@a*1cm-1pt}}{0.5cm+.5pt}
+ \pgfsetlinewidth{1pt}
+ \sseq@tempy=\sseq@ymin\relax
+ \advance\sseq@tempy\m@ne
+ \loop
+ \advance\sseq@tempy\@ne
+ \pgfpathmoveto{\pgfpointxy{\sseq@xmin + 0.5/\sseq@a}{\the\sseq@tempy}}
+ \pgfpathlineto{\pgfpointxy{\sseq@xmax + 1.01 }{\the\sseq@tempy}}
+ \ifnum\sseq@tempy<\sseq@ymax\repeat
+ %\pgfpathgrid[stepx=1cm,stepy=1cm]{\pgfpoint{-0.5cm}{-0.5cm}}{\pgfpoint{\xmax cm-0.5cm}{\ymax cm-0.5cm}}
+ \pgfusepath{stroke}
+ \endpgfscope
+ \egroup
}
%%%
%%% Draw Classes
@@ -261,6 +538,7 @@
(-0.16,-0.16)(0.16,-0.16)(-0.16,0.16)(0.16,0.16)(0,0);
(-0.13,-0.2)(-0.13,0)(-0.13,0.2)(0.13,-0.2)(0.13,0)(0.13,0.2);
}
+
\sseqnewclasspattern{linear}{
(0,0);
(-0.13,0)(0.13,0);
@@ -270,15 +548,21 @@
(-0.5,0)(-0.3,0)(-0.1,0)(0.1,0)(0.3,0)(0.5,0);
}
\def\sseq@offset#1#2{
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{0\csname sseq@\sseq@classpattern xoffset#1/#2\endcsname cm}{0\csname sseq@\sseq@classpattern yoffset#1/#2\endcsname cm}}}
+ \sseq@eval{\@nx\pgftransformshift{
+ \@nx\pgfqpointxy
+ { \csname sseq@\sseq@classpattern xoffset#1/#2\endcsname }
+ { \csname sseq@\sseq@classpattern yoffset#1/#2\endcsname }
+ }}
}
\def\sseq@class@getparts#1(#2,#3,#4)[#5].{
\sseq@seterrorannotation@drawing{#1}{#2}{#3}{#4}{#5}
\def\sseq@thisclassname{class.(#2,#3,#4)}
\def\sseq@thisnodename{sseq{#2,#3,#4}}
\def\sseq@thispos{(#2,#3)}
- \def\sseq@thisposnum{#4}
+ \edef\sseq@thisposnum{\sseq@obj{class.(#2,#3,#4).n}}
\def\sseq@thisclassnum{#5}
+ \sseq@tempx=#2\relax
+ \sseq@tempy=#3\relax
}
\def\sseqtooltip#1#2{%
@@ -298,11 +582,14 @@
}
% #1 -- the name of the node object
+% Someday I should document this horrible mess of code here
+\newif\ifsseq@permanentcycle
+\newcount\sseq@totalclassesdrawn
+\AtEndDocument{\message{Total classes: \the\sseq@totalclassesdrawn}}
\def\sseq@class@drawnode#1{%
+ \global\advance\sseq@totalclassesdrawn\@ne
\begingroup
\sseq@class@getparts#1.
- \sseq@tempx=\sseq@obj{\sseq@thisclassname.x}\relax
- \sseq@tempy=\sseq@obj{\sseq@thisclassname.y}\relax
\sseq@needstikzfalse
\sseq@options@firstpassmode
\sseq@thesseqstyle
@@ -318,7 +605,7 @@
\the\sseq@scope@toks
\sseq@obj{#1.needstikz}
%
- \sseq@outofrangetrue
+ \sseq@outofrangetrue\relax % Mysterious that we need this \relax here...
\ifnum\sseq@tempx<\sseq@xmaxpp\relax\ifnum\sseq@tempx>\sseq@xminmm\relax\ifnum\sseq@tempy<\sseq@ymaxpp\relax\ifnum\sseq@tempy>\sseq@yminmm\relax
\sseq@outofrangefalse
\pgfscope
@@ -329,17 +616,19 @@
\sseq@thesseqstyle
\sseq@theclassstyle
\ifnum\sseq@obj{#1.page}=\sseq@infinitycount
+ \sseq@permanentcycletrue % This is to communicate with family style code...
\sseq@thepermanentcyclestyle
\else
+ \sseq@permanentcyclefalse
\sseq@thetransientcyclestyle
\ifsseq@thispage
\sseq@thethispagecyclestyle
\fi
\fi
+ \def\sseq@collections@featuretype{class}
\the\sseq@scope@toks
\sseq@obj{#1.options}%
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
+ \pgftransformshift{\pgfqpointxy{\numexpr\sseq@tempx +\sseq@xoffset-\sseq@x\relax}{\numexpr\sseq@tempy + \sseq@yoffset-\sseq@y\relax}}
\iftikz@fullytransformed\pgfgettransform{\savetransform}\fi
\pgftransformresetnontranslations
\sseq@globalrotatetransform
@@ -351,24 +640,23 @@
\tikz@options
\ifsseq@needstikz
\let\sseq@mode\tikz@mode
- \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj{#1.nodetext.options}}}%
+ \tikzset{every text node part/.code/.expand once={\sseq@globalrotatetransform\sseq@obj@ifdef{#1.nodetext.options}{\sseq@obj{#1.nodetext.options}}{}}}%
\sseq@eval{%
\@nx\node[/utils/exec={\let\@nx\tikz@mode\@nx\sseq@mode},
/handlers/first char syntax/the character "/.initial=\@nx\sseq@handlequote
- ] (\sseq@thisnodename) {\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}}
- [every text node part/.code={}]
- \@nx\sseq@obj{#1.labelnodes};
+ ] (\sseq@thisnodename) {\sseq@obj@ifdef{#1.nodetext}{\unexpanded\@xpthree{\sseq@obj{#1.nodetext}}}{}}
+ [every text node part/.code={}];
}%
\else
\tikz@node@textfont
- \edef\sseq@classnodetextoptions{\@xptwo\@nx\sseq@obj{#1.nodetext.options}}
- \edef\sseq@classnodetext{\@xptwo\@nx\sseq@obj{#1.nodetext}}
- \sseq@setnodetext
+ \edef\sseq@classnodetextoptions{\sseq@obj@ifdef{#1.nodetext.options}{\@xptwo\@nx\sseq@obj{#1.nodetext.options}}{}}
+ \edef\sseq@classnodetext{\sseq@obj@ifdef{#1.nodetext}{\@xptwo\@nx\sseq@obj{#1.nodetext}}{}}
+ \sseq@setnodetext{\sseq@classnodetext}{\sseq@classnodetextoptions}
\let\tikz@fig@name\sseq@thisnodename
\pgfmultipartnode{\tikz@shape}{\tikz@anchor}{\tikz@fig@name}{\sseq@drawnode}%
\tikz@alias
- \sseq@obj{#1.labelnodes}
\fi
+ \sseq@obj{#1.labelnodes}
\sseq@obj@ifdef{#1.tooltip}{
\pgfpointanchor{\sseq@thisnodename}{west}
\pgf@xa=\pgf@x
@@ -386,7 +674,7 @@
\endpgfinterruptpicture
}
{%
- \pgftransformshift{\pgfpoint{\pgf@xa}{\pgf@ya}}%
+ \pgftransformshift{\pgfqpoint{\pgf@xa}{\pgf@ya}}%
\pgfapproximatenonlineartransformation%
\pgfqboxsynced{\tikz@tempbox}%
}%
@@ -394,8 +682,7 @@
\endpgfscope
\fi\fi\fi\fi
\ifsseq@outofrange
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{\the\sseq@tempx cm}{\the\sseq@tempy cm}}}%
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}
+ \sseq@eval{\@nx\pgftransformshift{\@nx\pgfqpointxy{\numexpr\sseq@tempx+\sseq@xoffset-\sseq@x\relax}{\numexpr\sseq@tempy+\sseq@yoffset-\sseq@y\relax}}}%
\pgftransformresetnontranslations
\sseq@globalrotatetransform
\sseq@classplacementtransform
@@ -404,11 +691,14 @@
\fi
\endgroup
}
-\def\sseq@setnodetext{%
+
+% #1 -- label text
+% #2 -- options
+\def\sseq@setnodetext#1#2{%
\setbox\pgfnodeparttextbox=\hbox{%
\pgfscope%
+ #2
\tikzset{every text node part/.try}%
- \sseq@classnodetextoptions
\ifx\tikz@textopacity\pgfutil@empty%
\else%
\pgfsetfillopacity{\tikz@textopacity}%
@@ -430,7 +720,7 @@
\fi%
\pgfsetcolor{.}%
\tikz@atbegin@node%
- \sseq@classnodetext%
+ #1%
\tikz@atend@node%
\ifx\tikz@text@width\pgfutil@empty%
\else%
@@ -489,6 +779,51 @@
\global\pgflinewidth=\pgfutil@tempdima%
}
+%%% Labels
+
+% #1 -- label text
+% #2 -- options
+\def\sseq@drawlabel#1#2{
+ \bgroup\pgfscope
+ \def\tikz@mode{}
+ \let\sseq@tikz@transform@save\tikz@transform
+ \pgfkeyssetvalue{/pgf/inner xsep}{2pt}
+ \pgfkeyssetvalue{/pgf/inner ysep}{2pt}
+ \def\tikz@shape{rectangle}
+ \let\tikz@transform\empty % The next line was set up to fix the classlabelstyle glitch
+ \sseq@options@secondpassmode
+ \sseq@thesseqstyle\sseq@thelabelstyle\sseq@theclasslabelstyle#2
+ \tikz@options
+ \pgftransformreset
+ \pgftransformshift{\tikz@node@at}
+ \tikz@lib@pos@call
+ \tikz@transform
+ \tikz@mode
+ \let\tikz@transform\sseq@tikz@transform@save
+ \sseq@setnodetext{\sseq@labeltextfn{#1}}{}
+ \pgfmultipartnode{\tikz@shape}{\tikz@anchor}{label}{\sseq@drawnode}%
+ \ifsseq@pin
+ \def\sseq@pinoptions{}
+ \let\tikz@options\empty
+ \let\tikz@mode\empty
+ \sseq@thepinstyle
+ #2
+ \sseq@pinoptions
+ \tikz@options
+ \tikz@mode
+ \sseq@drawedge@findsourcetarget{\tikz@fig@name}{}{label}{}
+ \pgfpathmoveto{\sseq@sourcecoord}%
+ \pgfpathlineto{\sseq@targetcoord}%
+ \sseq@eval{\noexpand\pgfusepath{%
+ draw
+ \iftikz@mode@fill fill,\fi
+ \iftikz@mode@draw draw,\fi
+ }}%
+ \fi
+ \endpgfscope\egroup
+}
+
+
%%%
%%% Drawing edges
%%%
@@ -506,6 +841,34 @@
\fi
}
+% #1 -- source node
+% #2 -- source anchor
+% #3 -- target node
+% #4 -- target anchor
+% Calculate actual start and end of the edge (node borders), return the results stored in \sseq@sourcecoord, \sseq@targetcoord
+\def\sseq@drawedge@findsourcetarget#1#2#3#4{
+ \edef\sseq@edgesourceanchor{#2}
+ \edef\sseq@edgetargetanchor{#4}
+ \let\tempaf\pgfutil@empty
+ \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
+ \def\tempa{\pgfpointanchor{#1}{center}}% if so, start by taking the center of that coordinate
+ \else
+ \edef\tempa{\@nx\pgfpointanchor{#1}{\sseq@edgesourceanchor}} % If it has an anchor, use that
+ \let\tempaf\tempa
+ \fi
+ \ifx\sseq@edgetargetanchor\pgfutil@empty % check that the target doesn't have a specified anchor
+ \def\tempb{\pgfpointshapeborder{#3}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate
+ \else
+ \edef\tempb{\@nx\pgfpointanchor{#3}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that
+ \fi
+ \let\tempbf\tempb
+ \ifx\tempaf\pgfutil@empty%
+ \def\tempaf{\pgfpointshapeborder{#1}{\tempb}}%
+ \fi
+ \let\sseq@sourcecoord\tempaf
+ \let\sseq@targetcoord\tempbf
+}
+
\def\sseq@fullcoord@to@partialcoord(#1){\sseq@fullcoord@to@partialcoord@#1,\@nil}
\def\sseq@fullcoord@to@partialcoord@#1,#2,#3\@nil{{#1cm}{#2cm}}
% #1 -- source (full)
@@ -514,7 +877,15 @@
% #4 -- options
\def\sseq@drawedge(#1)(#2)#3#4{%
\begingroup\pgfscope
+ % If either class is part of a family we aren't drawing, don't draw the edge either.
+ \expandafter\ifx\csname pgf@sh@pi@sseq{#1}\endcsname\pgfpictureid\else
+ \@xp\sseq@break
+ \fi
+ \expandafter\ifx\csname pgf@sh@pi@sseq{#2}\endcsname\pgfpictureid\else
+ \@xp\sseq@break
+ \fi
\def\sseq@edgetype{#3}
+ \let\sseq@collections@featuretype\sseq@edgetype
\let\sseq@edgesourceanchor\pgfutil@empty
\let\sseq@edgetargetanchor\pgfutil@empty
%
@@ -524,40 +895,34 @@
\sseq@thesseqstyle
\sseq@theedgestyle\csname sseq@the#3style\endcsname\the\sseq@scope@toks
#4%
- \sseq@eval{\@nx\pgftransformshift{\@nx\pgfpoint{-\the\sseq@x cm}{-\the\sseq@y cm}}}%
- % First calculate actual start and end of the edge
- \let\tempaf\pgfutil@empty
- \ifx\sseq@edgesourceanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
- \def\tempa{\pgfpointanchor{sseq{#1}}{center}}% if so, start by taking the center of that coordinate
- \else
- \edef\tempa{\@nx\pgfpointanchor{sseq{#1}}{\sseq@edgesourceanchor}} % If it has an anchor, use that
- \let\tempaf\tempa
- \fi
- \ifx\sseq@edgetargetanchor\pgfutil@empty % check that the target doesn't have a specified anchor
- \def\tempb{\pgfpointshapeborder{sseq{#2}}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate
- \else
- \edef\tempb{\@nx\pgfpointanchor{sseq{#2}}{\sseq@edgetargetanchor}}% If it has a specified anchor, use that
- \fi
- \let\tempbf\tempb
- \ifx\tempaf\pgfutil@empty%
- \def\tempaf{\pgfpointshapeborder{sseq{#1}}{\tempb}}%
- \fi
+ \csname sseq@collections@#3@hook\endcsname
+ \pgftransformshift{\pgfqpointxy{-\the\sseq@x}{-\the\sseq@y}}%
+ % puts results into \sseq@sourcecoord and \sseq@targetcoord
+ \sseq@drawedge@findsourcetarget{sseq{#1}}{\sseq@edgesourceanchor}{sseq{#2}}{\sseq@edgetargetanchor}
%
\tikz@options
\tikz@mode
\def\temparrowstartspec{}%
\def\temparrowendspec{}%
- \pgfcoordinate{tempa}{\tempaf}%
- \pgfcoordinate{tempb}{\tempbf}%
+ \pgfcoordinate{tempa}{\sseq@sourcecoord}%
+ \pgfcoordinate{tempb}{\sseq@targetcoord}%
\pgftransformreset
- \sseq@ifinrange(#1){\sseq@ifinrange(#2){\sseq@outofrangefalse}{\sseq@outofrangetrue}}{\sseq@outofrangetrue}%
+ \sseq@outofrangefalse
+ \sseq@ifinrange(#1){}{
+ \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}
+ \sseq@outofrangetrue
+ }%
+ \sseq@ifinrange(#2){}{
+ \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
+ \sseq@outofrangetrue
+ }
\ifsseq@outofrange
- \sseq@handleoffpageedge{#1}{#2}{#3}%
+ \sseq@handleoffpageedge{#1}{#2}%
\fi
\ifsseq@drawedge
% TODO: should some sort of transformation manipulation be here? Maybe allow user to specify preference?
% Don't draw dots on very short segments
- \pgfpointdiff{\tempbf}{\tempaf}
+ \pgfpointdiff{\sseq@targetcoord}{\sseq@sourcecoord}
\pgfmathveclen{\pgf@x}{\pgf@y}%
\@xp\pgfmathint\@xp{\pgfmathresult}%
\ifnum\pgfmathresult<10\relax%%17? % TODO: Fix this predicate
@@ -591,10 +956,10 @@
\endpgfscope\endgroup
}
-% TODO: this macro is super expensive. Make it faster (avoid
-\def\sseq@handleoffpageedge#1#2#3{
- \pgfpathmoveto{\tempaf}%
- \pgfpathlineto{\tempbf}%
+% TODO: this macro is super expensive. Make it faster
+\def\sseq@handleoffpageedge#1#2{
+ \pgfpathmoveto{\sseq@sourcecoord}%
+ \pgfpathlineto{\sseq@targetcoord}%
\pgfgetpath\thispath
\pgfusepath{discard}%
\pgfintersectionofpaths{\pgfsetpath\sseq@theclippath}{\pgfsetpath\thispath}%
@@ -603,20 +968,16 @@
\sseq@ifinrange(#1){% If the first endpoint is in range, the second must be out of range b/c sseq@outofrange is true.
%\edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
}{%
- \sseq@ifinrange(#2){%
- \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}
- }{\sseq@drawedge@handletrickyedge}% uh-oh, both ends are out of range
+ \sseq@ifinrange(#2){}{\sseq@drawedge@handletrickyedge}% uh-oh, both ends are out of range
}%
\or
\sseq@ifinrange(#1){% If the startpoint is in range, the intersection must be the end.
- \def\tempbf{\pgfpointintersectionsolution{1}}
- \edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@#3@spec\endcsname}}
- \pgfcoordinate{tempb}{\tempbf}
+ \def\sseq@targetcoord{\pgfpointintersectionsolution{1}}
+ \pgfcoordinate{tempb}{\sseq@targetcoord}
}{%
\sseq@ifinrange(#2){% If the startpoint is out of range and the endpoint is in range, the intersection must be the start
- \def\tempaf{\pgfpointintersectionsolution{1}}%
- \edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@#3@spec\endcsname}}%
- \pgfcoordinate{tempa}{\tempaf}%
+ \def\sseq@sourcecoord{\pgfpointintersectionsolution{1}}%
+ \pgfcoordinate{tempa}{\sseq@sourcecoord}%
}{\sseq@drawedge@handletrickyedge}% Uh-oh, both ends are out of range.
}
\or% an orphan
@@ -653,26 +1014,33 @@
\def\sseq@drawedge@handleorphan{%
- \def\tempaf{\pgfpointintersectionsolution{1}}%
- \def\tempbf{\pgfpointintersectionsolution{2}}%
+ \def\sseq@sourcecoord{\pgfpointintersectionsolution{1}}%
+ \def\sseq@targetcoord{\pgfpointintersectionsolution{2}}%
\edef\temparrowstartspec{\@nx\pgfsetarrowsstart{\csname sseq@runoffarrow@start@\sseq@edgetype @spec\endcsname}}%
\edef\temparrowendspec{\@nx\pgfsetarrowsend{\csname sseq@runoffarrow@end@\sseq@edgetype @spec\endcsname}}%
- \pgfcoordinate{tempa}{\tempaf}%
- \pgfcoordinate{tempb}{\tempbf}%
+ \pgfcoordinate{tempa}{\sseq@sourcecoord}%
+ \pgfcoordinate{tempb}{\sseq@targetcoord}%
}
-%
-% #1 -- first coordinate
-% #2 -- second coordinate
-% #3 -- uid
+% #1 -- uid
+% #2 -- first coordinate
+% #3 -- second coordinate
\def\sseq@circleclass@draw#1#2#3{
\begingroup
+ % If either class is part of a family we aren't drawing, don't draw the fit either.
+ \expandafter\ifx\csname pgf@sh@pi@sseq{#2}\endcsname\pgfpictureid\else
+ \@xp\sseq@break
+ \fi
+ \expandafter\ifx\csname pgf@sh@pi@sseq{#3}\endcsname\pgfpictureid\else
+ \@xp\sseq@break
+ \fi
\pgfmathanglebetweenpoints{\pgfpointanchor{sseq{#2}}{center}}{\pgfpointanchor{sseq{#3}}{center}}
\let\tempangle\pgfmathresult
\let\tikz@lib@fit@scan@handle\sseq@fit@tikz@lib@fit@scan@handle % install fit modifications.
\let\tikz@calc@anchor\sseq@fit@tikz@calc@anchor
\sseq@tempiftrue
+ \sseq@options@secondpassmode
\node[
rotate fit=\tempangle,
/utils/exec={\sseq@thesseqstyle\sseq@thecircleclassstyle\the\sseq@scope@toks\sseq@savedoptioncode
@@ -681,6 +1049,7 @@
\@xp\pgfkeysalso\@xp{\romannumeral0\sseq@obj{#1.tikzprimoptions}}
}
] {};
+ \sseq@breakpoint
\endgroup
}
% Modifies tikz commands \tikz@lib@fit@scan@handle from \pgf\frontendlayer\tikz\libraries\tikzlibraryfit.code.tex line 81 and
@@ -711,6 +1080,94 @@
}
+%%
+%% Patch tikz coords
+%%
+
+\def\sseq@patchtikzcoords{
+ \let\sseq@tikz@scan@one@point@noshift\sseq@tikz@scan@one@point@noshift@active
+ \tikzoption{shift}{\sseq@tikzshift{##1}}
+ \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular
+ \let\tikz@to@curve@path\sseq@tikz@to@curve@path
+ \let\tikz@@@to@compute@relative\sseq@tikz@@@to@compute@relative
+
+ \let\tikz@grid\sseq@tikz@grid
+ \let\tikz@scan@handle@options\sseq@tikz@scan@handle@options
+ \let\tikz@@@parse@polar\sseq@tikz@@@parse@polar
+}
+
+% Some of the stuff in tikzlibrarycalc will probably be broken, hopefully not too much
+\let\sseq@tikz@scan@one@point@noshift\tikz@scan@one@point
+\let\sseq@tikz@@@parse@regular@save\tikz@@@parse@regular
+
+\def\sseq@tikz@scan@one@point@noshift@active#1{%
+ \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular@save
+ \def\sseq@scanonepoint@cmd{\let\tikz@@@parse@regular\sseq@tikz@@@parse@regular#1}
+ \tikz@scan@one@point\sseq@scanonepoint@cmd%
+}
+
+% Probably there are more places that shouldn't have shifts inserted.
+\def\sseq@tikzshift#1{\tikz@addtransform{\sseq@tikz@scan@one@point@noshift\pgftransformshift#1\relax}}
+
+
+\def\sseq@tikz@to@curve@path{%
+ [every curve to]
+ \pgfextra{
+ \let\tikz@@@parse@regular\sseq@tikz@@@parse@regular@save % I added this to prevent repeated offsets from screwing us up
+ %\let\sseq@tikz@scan@one@point@noshift\tikz@scan@one@point
+ \iftikz@to@relative\tikz@to@compute@relative\else\tikz@to@compute\fi
+ }
+ \tikz@computed@path
+ \tikztonodes%
+}
+
+\let\sseq@tikz@@@to@compute@relative\tikz@@@to@compute@relative
+
+
+\patchcmd\sseq@tikz@@@to@compute@relative{%
+ \let\tikz@second@point=\tikz@toto
+}{%
+ \pgf@process{\pgfpointadd{\tikz@toto}{\pgfqpointxy{\sseq@xoffset}{\sseq@yoffset}}}%
+ \edef\tikz@toto{\@nx\pgfpoint{\the\pgf@x}{\the\pgf@y}}%
+ \let\tikz@second@point=\tikz@toto
+}{}{\error}
+
+
+
+
+% \tikz@parse@splitxyz: we should set up an error to make this unreachable?
+\let\sseq@tikz@grid\tikz@grid % line 3158
+\let\sseq@tikz@scan@handle@options\tikz@scan@handle@options % 4959
+\let\sseq@tikz@@@parse@polar\tikz@@@parse@polar % 5063
+
+\def\sseq@tikz@@@parse@regular#1#2#3){%
+ \pgfutil@in@,{#3}%
+ \ifpgfutil@in@%
+ \tikz@parse@splitxyz{#1}{#2}#3,%
+ \else%
+ \tikz@checkunit{#2}%
+ \iftikz@isdimension%
+ \tikz@checkunit{#3}%
+ \iftikz@isdimension%
+ \def\@next{#1{\pgfpointxy{(#2)/1cm+\sseq@xoffset}{(#3)/1cm+\sseq@yoffset}}}%
+ \else%
+ \def\@next{#1{\pgfpointxy{(#2)/1cm+\sseq@xoffset}{#3+\sseq@yoffset}}}%
+ \fi%
+ \else%
+ \tikz@checkunit{#3}%
+ \iftikz@isdimension%
+ \def\@next{#1{\pgfpointxy{#2+\sseq@xoffset}{(#3)/1cm+\sseq@yoffset}}}%
+ \else%
+ \def\@next{#1{\pgfpointxy{#2+\sseq@xoffset}{#3+\sseq@yoffset}}}%
+ \fi%
+ \fi%
+ \fi%
+ \@next%
+}
+
+
+
+
%% New shapes and arrows
%% These use lots of keys with spaces so it's convenient to turn off ExplSyntax.
@@ -987,4 +1444,5 @@
\pgfusepathqfill
},
defaults = { length = 0.3cm }
-} \ No newline at end of file
+}
+
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex
index 0d4c4758215..4e2a5da7e89 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqforeach.code.tex
@@ -1,31 +1,218 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqforeach.code.tex
%%
%% Patches the \foreach command to obtain better error reporting
+%% Also defines some of my own looping commands, \Do, \DoUntilOutOfBounds, \DoUntilOutOfBoundsThenNMore
+%% All of the \foreach stuff we are modifying is defined by tikz in the file /pgf/utilities/pgffor.code.tex
%%
-
-% All of this \foreach stuff is defined by tikz in the file /pgf/utilities/pgffor.code.tex
-
-\def\sseq@for@nopatch{\sseq@error{foreach-patch-failed}\def\sseq@patchfor{}\endinput}
-
-\newtoks\sseq@foreachcall
-
\def\sseq@for@vars{}
\def\sseq@for@savemacro#1{\sseq@d@addto@macro\sseq@for@vars{\sseq@for@vars@do#1}}
+\def\sseq@for@savemacro@noslash#1{\sseq@d@addto@macro\sseq@for@vars{\sseq@for@vars@do@noslash#1}}
\def\sseq@for@vars@do#1{; \string#1 = #1}
-\def\sseq@for@vars@donx#1{; \string#1= #1}
+\def\sseq@for@vars@do@noslash#1{; \sseq@macroname#1 = #1}
+
\ExplSyntaxOn
\def\sseq@for@printvars{\ifx\sseq@for@vars\pgfutil@empty\else\exp_last_unbraced:Nf\@gobble\sseq@for@vars\fi}
+
+\newcount\sseq@Do@depth
+
+\def\sseq@save@Do@var{
+ \sseq@atbeginforeach@msgsetup
+ \advance\sseq@Do@depth\@ne
+ \exp_args:Nc \sseq@for@savemacro@noslash { iteration ~ \the \sseq@Do@depth }
+ \def\iteration{0}
+}
+
+\def\sseq@stepiteration{
+ \edef\iteration{\the\numexpr\iteration+1}
+ \cs_set_eq:cN { iteration ~ \the \sseq@Do@depth } \iteration
+}
+
+\protected\def\sseq@Do{
+ \begingroup
+ \edef\sseq@inputline{\the\inputlineno}
+ \sseq@callas{\Do}
+ \sseq@call{\sseq@Do@}
+}
+
+\def\sseq@Do@#1#2{
+ \sseq@esetthiscall{\string\Do\unexpanded{#1}}
+ \sseq@opushstacktrace{\string\Do{#1}}
+ \sseq@ifintexpr{#1}{
+ \sseq@savestack
+ \sseq@save@Do@var
+ \prg_replicate:nn {#1} {
+ \sseq@stepiteration
+ #2
+ \relax
+ }
+ \sseq@restorestack
+ }{\sseq@error@xx{Do-invalid-int-expr}{\string\Do}{\unexpanded{#1}}}
+ \endgroup
+}
+
+\protected\def\sseq@DoUntilOutOfBounds{
+ \begingroup
+ \edef\sseq@inputline{\the\inputlineno}
+ \sseq@callas{\DoUntilOutOfBounds}
+ \sseq@call{\sseq@DoUntilOutOfBounds@}
+}
+
+\def\sseq@DoUntilOutOfBounds@ #1 {
+ \sseq@esetthiscall{\string\DoUntilOutOfBoundsThenNMore}
+ \sseq@opushstacktrace{\string\DoUntilOutOfBounds}
+ \ifx\xmin\sseq@xmin\else\ifx\ymin\sseq@ymin\else
+ \sseq@error@x{DoUntil-no-bound}{\string\DoUntilOutOfBounds}
+ \sseq@breakfifi
+ \fi\fi
+ \def\sseq@commandname{\string\DoUntilOutOfBounds}
+ \sseq@savestack % so we can nest these
+ \sseq@DoUntilOutOfBounds@body{#1}
+ \sseq@restorestack
+ \sseq@breakpoint
+ \endgroup
+}
+
+\protected\def\sseq@DoUntilOutOfBoundsThenNMore{
+ \begingroup
+ \edef\sseq@inputline{\the\inputlineno}
+ \sseq@callas{\DoUntilOutOfBoundsThenNMore}
+ \sseq@call{\sseq@DoUntilOutOfBoundsThenNMore@}
+}
+
+\def\sseq@DoUntilOutOfBoundsThenNMore@ #1#2 {
+ \sseq@esetthiscall{\string\DoUntilOutOfBoundsThenNMore\unexpanded{#1}}
+ \sseq@opushstacktrace{\string\DoUntilOutOfBoundsThenNMore{#1}}
+ \ifx\xmin\sseq@xmin\else\ifx\ymin\sseq@ymin\else
+ \sseq@error@n{DoUntil-no-bound}{\DoUntilOutOfBoundsThenNMore}
+ \sseq@breakfifi
+ \fi\fi
+ \sseq@ifintexpr{#1}{}{
+ \sseq@error@xx{Do-invalid-int-expr}{\string\DoUntilOutOfBoundsThenNMore}{\unexpanded{#1}}
+ \sseq@break
+ }
+ \def\sseq@commandname{\string\DoUntilOutOfBoundsThenNMore}
+ \sseq@savestack
+ \sseq@DoUntilOutOfBounds@body{#2}
+ \prg_replicate:nn {#1} {
+ \sseq@stepiteration
+ #2
+ \relax
+ }
+ \sseq@restorestack
+ \sseq@breakpoint
+ \endgroup
+}
+
+\def\sseq@DoUntilOutOfBounds@body#1{
+ \sseq@save@Do@var % Set iteration so that \DoUntilOutOfBoundsThenNMore doesn't get upset if we're already out of bounds
+ % If we're already out of bounds, we'll just do nothing.
+ \sseq_if_out_of_bounds_noparse:nnTF{\lastx{0}}{\lasty{0}}{
+ \bool_set_true:N \l_tmpa_bool
+ }{
+ \bool_set_false:N \l_tmpa_bool
+ % Now we need to set up the loop descent condition.
+ \sseq@tempxb=\lastx{0}\relax % Record current x and y values
+ \sseq@tempyb=\lasty{0}\relax
+ \sseq@stepiteration
+ #1 % run loop body once
+ \relax % protect from \d page grabber
+ \sseq_if_out_of_bounds_noparse:nnTF{\lastx{0}}{\lasty{0}}{ % If we're out of bounds now, we can quit
+ \bool_set_true:N \l_tmpa_bool
+ }{ % Otherwise, determine descent check
+ \sseq@tempx=\lastx{0}\relax % store new last value for comparison
+ \sseq@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@checkbound{\bool_set_false:N \l_tmpb_bool}
+ \ifx\xmin\sseq@xmin
+ \ifnum\sseq@tempx>\sseq@tempxb
+ \bool_set_true:N \l_tmpb_bool % We have a descent condition
+% \sseq@d@addto@macro\sseq@checkbound{
+% \ifnum\sseq@tempx>\sseq@tempxb % Any stage of the loop is okay as long as it increases x
+% \bool_set_true:N \l_tmpb_bool
+% \fi
+% }
+ \else
+ \ifnum\sseq@tempx<\sseq@tempxb
+ \bool_set_true:N \l_tmpb_bool
+% \sseq@d@addto@macro\sseq@checkbound{ % Any stage of the loop is okay as long as it decreases x
+% \ifnum\sseq@tempx<\sseq@tempxb
+% \bool_set_true:N \l_tmpb_bool
+% \fi
+% }
+ \fi
+ \fi
+ \fi
+ \ifx\ymin\sseq@ymin
+ \ifnum\sseq@tempy>\sseq@tempyb
+ \bool_set_true:N \l_tmpb_bool
+% \sseq@d@addto@macro\sseq@checkbound{
+% \ifnum\sseq@tempy>\sseq@tempyb
+% \bool_set_true:N \l_tmpb_bool
+% \fi
+% }
+ \else
+ \ifnum\sseq@tempy<\sseq@tempyb
+ \bool_set_true:N \l_tmpb_bool
+% \sseq@d@addto@macro\sseq@checkbound{
+% \ifnum\sseq@tempy<\sseq@tempyb
+% \bool_set_true:N \l_tmpb_bool
+% \fi
+% }
+ \fi
+ \fi
+ \fi
+ \if_bool:N \l_tmpb_bool\else:
+ \sseq@error@x{DoUntil-no-progress}{\sseq@commandname}
+ \fi:
+ }
+ }
+ \bool_until_do:Nn \l_tmpa_bool {
+ \sseq@stepiteration
+ #1
+ \relax
+ \sseq_if_out_of_bounds_noparse:nnTF{\lastx{0}}{\lasty{0}}{% we're done
+ \bool_set_true:N \l_tmpa_bool
+ }{% Check descent condition
+% \ifnum\iteration/10*10-\iteration=\z@
+% \sseq@tempx=\lastx{0}\relax % store new last value for comparison
+% \sseq@tempy=\lasty{0}\relax
+% \bool_set_false:N \l_tmpb_bool
+% \sseq@checkbound
+% \if_bool:N \l_tmpb_bool\else:
+% \sseq@error{DoUntilOutOfBounds-descent-failed}
+% \fi:
+% \sseq@tempxb=\sseq@tempx
+% \sseq@tempyb=\sseq@tempx
+% \fi
+ }
+ }
+}
+
+
+
\ExplSyntaxOff
+\def\sseq@for@nopatch{\sseq@error{foreach-patch-failed}\def\sseq@patchfor{}\endinput}
+
+\newtoks\sseq@foreachcall
+
+\def\sseq@pgffor@atbeginforeach{%
+ \begingroup %
+ \sseq@atbeginforeach@msgsetup
+ % \pgffor@macro@list calls \pgffor@normal@list, so we need to mark that the list has already been added to foreachcall.
+ \sseq@tempiftrue
+}
+
+
\def\sseq@patchfor{%
\let\pgffor@atbeginforeach\sseq@pgffor@atbeginforeach
\let\pgffor@@vars@opt\sseq@pgffor@@vars@opt
@@ -47,17 +234,8 @@
}
-
\bgroup\lccode`\*=`\#\lowercase{\egroup
-
-\def\sseq@pgffor@atbeginforeach{%
- \begingroup %
- \sseq@atbeginforeach@msgsetup
- % \pgffor@macro@list calls \pgffor@normal@list, so we need to mark that the list has already been added to foreachcall.
- \sseq@tempiftrue
-}
-
% Modify the foreach argument parser commands to put the call into \sseq@foreachcall and to tell us what the variables are
\def\sseq@pgffor@@vars@opt[#1]{\sseq@foreachcall\@xp{\the\sseq@foreachcall#1}\pgfkeys{/sseqpages/foreach/.cd,#1}\pgffor@vars}
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex
index 74667335805..a231aca7b42 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqkeys.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqkeys.code.tex
@@ -12,7 +12,7 @@
%%
-
+% Run \pgfqkeys{directory}{keys} but for a list of directories. Helps to avoid code duplication.
\def\sseq@pgfqkeysdirlist#1#2{%
\sseq@temptoks{#2}%
\sseq@pgfqkeysdirlist@#1,\sseq@nil
@@ -27,7 +27,7 @@
% These are the things that are used outside of this section:
\let\sseq@pgfkeys@error@save\pgfkeys@error
\pgfkeys{/sseqpages/userstyles/.unknown/.code={\sseq@passoptionto{\sseq@sseqsetdirectory}}}
-\def\sseqset#1{\pgfqkeys{/sseqpages/userstyles}{#1}}
+\protected\def\sseqset#1{\pgfqkeys{/sseqpages/userstyles}{#1}}
\def\sseq@sseqsetdirectory{/sseqpages/global/default}
@@ -60,7 +60,7 @@
% on the first pass. Some only do things on the first pass or only do things on the second pass.
% For example, shifts: shifts apply a coordinate transform on the second pass, but also need to factor into the coordinates of
% classes etc which are computed at specification time not at draw time. So xshift=2 increases \sseq@x by 2 on it's first pass and
-% applies a coordinate transfrom by 2cm on the second pass.
+% applies a coordinate transform by 2cm on the second pass.
% normal mode does the firstpass options now and saves the secondpass options in \sseq@savedoptioncode for later use.
% firstpass mode does the firstpass options and throws away the secondpass options.
@@ -131,24 +131,33 @@
% This is for .unknown handlers. Try same key in different directory #1.
\def\sseq@passoptionto#1{\sseq@eval{\@nx\pgfqkeys{#1}{\pgfkeyscurrentname={\unexpanded\@xp{\pgfkeyscurrentvalue}}}}}
+% Immediately execute a key that is either a tikz or pgf key.
+% #1 -- key
+% #2 -- value
\def\sseq@pgfkeysdocommand#1#2{
\sseq@tempiffalse
- \sseq@pgfkeysdocommand@try{/tikz/#1}{#2}
- \sseq@pgfkeysdocommand@try{/pgf/#1}{#2}
- % is this really an internal error? Maybe we should have failed earlier?
+ \sseq@pgfkeysdocommand@try{/tikz}{#1}{#2}
+ \sseq@pgfkeysdocommand@try{/pgf}{#1}{#2}
\ifsseq@tempif\else\sseq@error@internal@nn{do-command-failed}{#1}{#2}\fi
}
-\def\sseq@pgfkeysdocommand@try#1#2{
+% Execute a key if \sseq@tempif is true and it is defined, if so set \sseq@tempif to false.
+% These are meant to cascade.
+% #1 -- directory
+% #2 -- key
+% #3 -- value
+\def\sseq@pgfkeysdocommand@try#1#2#3{
\ifsseq@tempif\else
- \pgfkeysifdefined{#1/.@cmd}{
+ \pgfkeysifdefined{#1/#2/.@cmd}{
\sseq@tempiftrue
- \pgfkeysgetvalue{#1/.@cmd}{\pgfkeys@code}%
- \pgfkeys@code#2\pgfeov
+ \def\pgfkeysdefaultpath{#1/}
+ \edef\pgfkeyscurrentkey{#1/#2}
+ \pgfkeysgetvalue{#1/#2/.@cmd}{\pgfkeys@code}%
+ \pgfkeys@code#3\pgfeov
}{
- \pgfkeysifdefined{#1}{
+ \pgfkeysifdefined{#1/#2}{
\sseq@tempiftrue
- \pgfkeyssetvalue{#1}{#2}
+ \pgfkeyssetvalue{#1/#2}{#3}
}{}
}
\fi
@@ -180,13 +189,13 @@
\@xp\pgfutil@in@\@xp-\@xp{\tikz@key}%
\ifpgfutil@in@%
% Ah, an arrow spec!
- \sseq@add@tikzkey@to@options{\@nx\tikz@processarrows{\tikz@key}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\@nx\tikz@processarrows{\tikz@key}}}%
\else%
% Ok, third chance: A shape!
\@xp\ifx\csname pgf@sh@s@\tikz@key\endcsname\relax%
\sseq@keys@unknown@error%
\else%
- \sseq@add@tikzkey@to@options{\def\@nx\tikz@shape{\tikz@key}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\def\@nx\tikz@shape{\tikz@key}}}%
\fi%
\fi%
}%
@@ -195,8 +204,8 @@
}
\def\sseq@keys@unknown@handlecolor{%
- \sseq@add@tikzkey@to@options{\@nx\tikz@addoption{\@nx\tikz@compat@color@set{\tikz@key}}}%
- \sseq@add@tikzkey@to@options{\def\@nx\tikz@textcolor{\tikz@key}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\@nx\tikz@addoption{\@nx\tikz@compat@color@set{\tikz@key}}}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\def\@nx\tikz@textcolor{\tikz@key}}}%
}
%%% \sseq@keys@try@addtooptions
@@ -223,9 +232,10 @@
\def\pgfkeysdefaultpath{#1/}%
\def\next{\egroup\@ifnextchar\sseq@nil{\@xp\@secondoftwo\@gobble}{\sseq@keys@try@addtooptions@}}%
\pgfkeysifdefined{#1/\pgfkeyscurrentname/.@cmd}{%
+ \edef\pgfkeyscurrentkey{#1/\pgfkeyscurrentname}%
\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text% Hmm... no value
\pgfkeysifdefined{#1/\pgfkeyscurrentname/.@def}%
- {\pgfkeysgetvalue{#1/\pgfkeyscurrentname/.@def}{\pgfkeyscurrentvalue}}
+ {\pgfkeysgetvalue{#1/\pgfkeyscurrentname/.@def}{\pgfkeyscurrentvalue}}%
{}% no default, so leave it
\fi%
\pgfkeysgetvalue{#1/\pgfkeyscurrentname/.@cmd}{\pgfkeys@code}%
@@ -236,29 +246,70 @@
}{%
\pgfkeysifdefined{#1/\pgfkeyscurrentname}{%
\egroup
- \sseq@add@tikzkey@to@options{\@nx\pgfkeyssetvalue{#1/\pgfkeyscurrentname}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\@nx\pgfkeyssetvalue{#1/\pgfkeyscurrentname}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}}%
\def\next{\@xp\@firstoftwo\sseq@gobble@to@nil}%
}{}%
}%
\next
}
+% Iterate over list and run \pgfkeysalso's when we find them. Note that we use our variants of \pgfkeys@case@... which hand control back to this command,
+% so this is recursive -- the result is guaranteed not to have any instance of \pgfkeysalso in it!
\def\sseq@keys@addtooptions@checkalso#1{%
\let\pgfkeys@case@one\sseq@pgfkeys@case@one@store
\let\pgfkeys@case@two@extern\sseq@pgfkeys@case@two@extern@store
\sseq@keys@addtooptions@checkalso@#1\pgfkeysalso\sseq@nil
}
+
\def\sseq@keys@addtooptions@checkalso@#1\pgfkeysalso#2{%
- \sseq@add@tikzkey@to@options{\unexpanded{#1}}%
- \ifx\sseq@nil#2%
+ \def\sseq@tempa{/tikz/}%
+ \def\sseq@tempb{/pgf/}%
+ % This is an extra hook I needed to add so that my own keys can execute code when they need to...
+ \sseq@keys@addtooptions@checkdo#1\sseq@keys@do\sseq@nil
+ \ifx\sseq@nil#2% We're done, restore pgfkeys.
\let\pgfkeys@case@one\sseq@pgfkeys@case@one@save
\let\pgfkeys@case@two@extern\sseq@pgfkeys@case@two@extern@save
\else
- \pgfkeysalso{#2}%
- \@xp\sseq@keys@addtooptions@checkalso@
+ \ifx\expandafter#2 % if they wanted to expand the first token, handle that
+ \sseq@add@tikzkey@to@options{\sseq@options@secondpass@iftikz{\relax\relax}}% The last token was an \expandafter, we need to keep it from doing anything
+ \@xptwo\sseq@keys@addtooptions@checkalso@xp
+ \else
+ \pgfkeysalso{#2}%
+ \@xptwo\sseq@keys@addtooptions@checkalso@
+ \fi
+ \fi
+}
+
+\def\sseq@keys@addtooptions@checkalso@xp#1{%
+ \@xp\pgfkeysalso\@xp{#1}%
+ \sseq@keys@addtooptions@checkalso@
+}
+
+% Used to get collections code to run right.
+\def\sseq@keys@addtooptions@checkdo#1\sseq@keys@do#2{%
+ \sseq@add@tikzkey@to@options{\sseq@options@secondpass@iftikz{\unexpanded{#1}}}%
+ \ifx#2\sseq@nil\else
+ #2%
+ \@xp\sseq@keys@addtooptions@checkdo
+ \fi
+}
+
+% This has to be expandable, so \sseq@tempa and \sseq@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@options@secondpass@iftikz{%
+ \ifx\pgfkeysdefaultpath\sseq@tempa
+ \@nx\sseq@options@secondpass
+ \else
+ \ifx\pgfkeysdefaultpath\sseq@tempb
+ \@nx\sseq@options@secondpass
+ \else
+ \@xptwo\@firstofone
+ \fi
\fi
}
+
+% Here we hook into pgfkeys. This is remarkably easy!
\let\sseq@pgfkeys@case@one@save\pgfkeys@case@one
\let\sseq@pgfkeys@case@two@extern@save\pgfkeys@case@two@extern
\def\sseq@pgfkeys@case@one@store{%
@@ -275,7 +326,7 @@
\else%
% The following line is the only change, it used to be (roughly) \pgfkeyssetvalue{\pgfkeyscurrentkey}{\pgfkeyscurrentvalue}
% which would immediately set the value. Instead we store in it \sseq@savedoptioncode
- \sseq@add@tikzkey@to@options{\@nx\pgfkeyssetvalue{\pgfkeyscurrentkey}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}%
+ \sseq@add@tikzkey@to@options{\@nx\sseq@options@secondpass{\@nx\pgfkeyssetvalue{\pgfkeyscurrentkey}{\unexpanded\@xp{\pgfkeyscurrentvalue}}}}%
\fi%
}
@@ -296,6 +347,7 @@
/sseqpages/class/.is family,
/sseqpages/class/label/.is family,
/sseqpages/class/label/.unknown/.code={\sseq@keys@unknown},
+ /sseqpages/class/label/pin/.unknown/.code={\sseq@keys@unknown},
/sseqpages/class/node texts/.is family,
/sseqpages/class/node texts/.unknown/.code={\sseq@passoptionto{/tikz}},
/sseqpages/differential/.is family,
@@ -307,6 +359,7 @@
/sseqpages/tikz primitives/.is family,
/sseqpages/tikz primitives/.unknown/.code={\sseq@keys@unknown},
% One off directories
+ /sseqpages/fit/.is family,
/sseqpages/fit/.unknown/.code={\sseq@passoptionto{/sseqpages}},
/sseqpages/foreach/.unknown/.code={\sseq@passoptionto{/pgf/foreach}},
/sseqpages/class placement/.unknown/.code={\sseq@passoptionto{/tikz}}
@@ -314,10 +367,18 @@
\pgfqkeys{/sseqpages/class}{shape/.code={\edef\tikz@shape{\pgfkeyscurrentname}}} % shape=whatever shape passing
+\newif\ifsseq@pin
\pgfqkeys{/sseqpages/class/label}{% maybe implement multipart node labels this way? No way!
node/.sseq @ first pass code={\sseq@classlabelfalse},
- inside/.sseq @ first pass code={\sseq@classlabelfalse}
+ inside/.sseq @ first pass code={\sseq@classlabelfalse},
+ pin/.sseq @ first pass code = {
+ \let\sseq@savedoptioncode@save\sseq@savedoptioncode
+ \sseq@processoptions{class/label/pin}{#1}
+ \edef\sseq@savedoptioncode{\unexpanded\@xp{\sseq@savedoptioncode@save}\@nx\sseq@d@addto@macro\@nx\sseq@pinoptions{\unexpanded\@xp{\sseq@savedoptioncode}}}
+ },
+ pin/.sseq @ second pass append code = {\sseq@pintrue}
}
+\def\sseq@pinoptions{}
%% label directions
\def\sseq@labeldirectionlist{\\{above}\\{below}\\{left}\\{right}\\{above left}\\{above right}\\{below left}\\{below right}}
@@ -342,8 +403,7 @@
-\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.sseq @ first pass code]
- {\sseq@classlabeltrue\def\sseq@class@labelposition@name{#1}\def\sseq@class@labelposition@distance{##1}}
+\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.sseq @ first pass code]{\sseq@classlabeltrue}
\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.sseq @ second pass append code]{\sseq@class@positionlabel{#1}{##1}}
\sseq@setlabeldirectionkeys{/sseqpages/class/label}[/.default]{\sseq@defaultlabeldistance{#1}}
\sseq@setlabeldirectionkeys{/sseqpages/global/class/label}[/.default]{\sseq@defaultlabeldistance{#1}}
@@ -355,12 +415,12 @@
label distance/.code={\sseq@setdefaultlabeldistances{#1}}
}
-\def\sseq@class@positionlabel#1#2{\sseq@pgfkeysdocommand{#1}{#2}}
+\def\sseq@class@positionlabel#1#2{\ifx\tikz@fig@name\undefined\else\sseq@pgfkeysdocommand{#1}{#2 of \tikz@fig@name}\fi}
\sseq@addtostorelist\sseq@classlabeltextfn{} % \sseq@classlabeltextfn is public via "class label handler"
-\let\sseq@classlabeltextfn@default\@gobble
+\def\sseq@classlabeltextfn@default#1{\def\processedlabel{#1}}
\def\sseq@labeltextfn#1{#1} % labeltextfn is private
\def\sseq@labeltextfn@rotatescale#1{%
\@nx\ifmmode
@@ -403,8 +463,15 @@
\def\sseq@edgeoptionhook{}% This is just to make description work.
+%% Labels
+%% The code for this that actually does most of the work is inside of sseqmain.code.tex -- search for "Labels"
+%% This just handles the interface with the keyvalue system here.
+
+
%% Quote handling
% \sseq@handlequote will be installed later as the 'first char syntax' for ".
+% Problem is that 'first char syntax' isn't allowed to care what directory it is in, but we need different handling
+% for classes versus edges versus scopes. Solution is to use \pgfkeysalso and then define the handler in a key.
\def\sseq@protectlabel{\@nx\sseq@protectlabel\@nx}
\def\sseq@handlequote#1{\pgfkeysalso{handle quote=#1}}
\pgfkeys{%
@@ -415,20 +482,13 @@
\let\tikz@quotes@as\tikz@quotes@as@save
},
/sseqpages/handle quote/.code={%
- \begingroup % group gets ended by handleedgequotes
\let\tikz@quotes@as\sseq@handleedgequotes
\tikz@quote@parser{#1}%
+ \let\tikz@quotes@as\tikz@quotes@as@save
}
}
-\def\sseq@processlabels@default{%
- \global\let\sseq@classnodetext\pgfutil@empty
- \global\let\sseq@classnodetextoptions\pgfutil@empty
- \global\let\sseq@classlabelnodes\pgfutil@empty
-}
-\let\sseq@processlabels\sseq@processlabels@default
-
\def\sseq@handlescopequotes#1#2{% We use this via \let\tikz@quotes@as\sseq@handleclassquotes
/utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out.
\global\let\sseq@classnodetext\pgfutil@empty%
@@ -442,103 +502,6 @@
% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out.
\def\sseq@handleclassquotes#1#2{/utils/exec={\sseq@d@addto@macro\sseq@processlabels{\sseq@handleclassquotes@inner{#1}{#2}}}}
-\def\sseq@handleclassquotes@inner#1#2{%
- \begingroup\pgfscope
- \sseq@options@firstpassmode
- \sseq@thesseqstyle
- \sseq@thelabelstyle
- \sseq@theclasslabelstyle
- \the\sseq@scope@toks
- \sseq@options@normalmode
- \sseq@processoptions{class/label}{#2}%
- \ifx\sseq@classlabeltextfn\@gobble
- \def\processedlabel{#1}%
- \else
- \sseq@classlabeltextfn{#1}% labeltextfn is a private handler, classlabeltextfn is exposed via "class label handler"
- \fi
- \ifsseq@classlabel
- \sseq@options@firstpassmode
- \the\sseq@outerclasslabelstyle
- \sseq@xprotected@addto@macro\sseq@classlabelnodes{
- \@nx\ifsseq@needstikz
- node[
- /sseqpages/class/label,
- /utils/exec={
- \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform
- \let\@nx\tikz@transform\relax % The next line was set up to fix the classlabelstyle glitch
- \the\sseq@sseqstyle\@nx\the\sseq@sseqstyle@page
- \the\sseq@labelstyle\@nx\the\sseq@labelstyle@page\the\sseq@classlabelstyle\@nx\the\sseq@classlabelstyle@page
- \sseq@theouterclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode}%
- % \@nx\iftikz@fullytransformed\@nx
- % \@nx\tikz@fullytransformedtrue
- % \else
- % \@nx{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform}
- % \@nx\fi
- \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save
- }%
- ]{\sseq@labeltextfn{\processedlabel}}%
- \@nx\else
- \@nx\node[
- /sseqpages/class/label,
- /utils/exec={
- \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform
- \let\@nx\tikz@transform\relax % The next line was set up to fix the classlabelstyle glitch
- \the\sseq@sseqstyle\@nx\the\sseq@sseqstyle@page
- \the\sseq@labelstyle\@nx\the\sseq@labelstyle@page\the\sseq@classlabelstyle\@nx\the\sseq@classlabelstyle@page
- \sseq@theouterclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode}
- % \@nx\iftikz@fullytransformed\@nx
- % \@nx\tikz@fullytransformedtrue
- % \else
- % \@nx{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform}
- % \@nx\fi
- \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save
- }
- ]{\unexpanded\@xp{\@xp\sseq@labeltextfn\@xp{\processedlabel}}};%
- \@nx\fi
- }%
- \else
- \sseq@options@firstpassmode
- \the\sseq@innerclasslabelstyle
- \sseq@options@normalmode
- \sseq@protectedeval{\@nx\pgfqkeys{/sseqpages/class/label}{#2}}%
- \sseq@protected@xdef\sseq@classnodetext{\processedlabel}%
- \xdef\sseq@classnodetextoptions{%
- %\unexpanded{\def\pgfkeysdefaultpath{/sseqpages/class/node texts/}}%
- \sseq@thelabelstyle\sseq@theinnerclasslabelstyle\unexpanded\@xp{\sseq@savedoptioncode}%
- }%
- \fi
- \endpgfscope\endgroup
-}
-
-\def\sseq@handleedgequotes#1#2{% We use this via \let\tikz@quotes@as\sseq@handleedgequotes
- /utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out.
- \endgroup
- \let\sseq@savedoptioncode@save\sseq@savedoptioncode
- \sseq@processoptions{label}{#2}
- \sseq@needstikztrue
- \let\sseq@temp\sseq@savedoptioncode
- \let\sseq@savedoptioncode\sseq@savedoptioncode@save
- \sseq@e@addto@options{
- \@nx\tikzset{
- every to/.append style={
- edge node={
- node [/sseqpages/label,
- /utils/exec={
- \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform
- \let\@nx\tikz@transform\relax
- \@nx\sseq@thelabelstyle\@nx\sseq@theedgelabelstyle
- \unexpanded\@xp{\sseq@temp}
- \ifsseq@rotatelabels\iftikz@fullytransformed\else\@nx\tikz@fullytransformedtrue\@nx\tikz@addtransform{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform}\fi\fi
- \unexpanded\@xp{\sseq@edgeoptionhook} % this is just to make description work
- \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save
- }
- ]{\sseq@labeltextfn{#1}}
- }
- }
- }
- }
- }
-}
\def\sseq@checktransform@error{\sseq@error@nn{illegal-transform}}
@@ -550,6 +513,7 @@
\let\sseq@tikzprimitives@coords@maybeclass\sseq@tikzprimitives@coords@notaclass
\let\sseq@checktransform\@gobbletwo
\let\sseq@tikz@shifttransform\sseq@okayshifttransform
+ % TODO: This needs fixing:
%((((((((((((((((((
\def\class##1){\sseq@setthiscall{\string\class##1)}\sseq@error@x{standard-parse}{\string\class}}%
\def\replaceclass##1){\sseq@setthiscall{\string\replaceclass##1)}\sseq@error@x{standard-parse}{\string\replaceclass}}%
@@ -560,6 +524,7 @@
\def\structlineoptions##1)##2){\sseq@setthiscall{\string\structlineoptions##1)##2)}\sseq@error@x{standard-parse}{\string\structlineoptions}}%
}
+% I don't think this is ever actually used...
\def\sseq@nodeparse{%
\let\sseq@tikzprimitives@coords@maybeclass\sseq@tikzprimitives@coords@maybeclass@save
\let\sseq@tikzprimitives@coords@maybeclass
@@ -596,10 +561,12 @@
background/.sseq @ first pass code={\sseq@error@n{option-tikz-prims-only}{background}}
}
+% Some class options. All of these will make changes local to the current \class command. They are communicated to \class via these commands,
+% which we initialize here as empty.
\def\sseq@class@tag{}
\def\sseq@class@tagprefix{}
\def\sseq@class@name{}
-\def\sseq@namehandler{}%\@xp\sseq@normalizepolynomial\@xp{\sseq@class@name}\let\sseq@class@name\sseq@polynomial}
+\def\sseq@namehandler{}
\def\sseq@currenttag{\sseq@class@tag}% for the user ??
\def\sseq@tooltip{}
\pgfqkeys{/sseqpages/scope}{
@@ -607,14 +574,16 @@
tag prefix/.code={\pgfkeys@spdef\temp{#1}\sseq@e@addto@macro\sseq@class@tagprefix{\unexpanded\@xp{#1}}}
}
+\def\sseq@classinsert{}
\pgfqkeys{/sseqpages/class}{
name/.code={\def\sseq@class@name{#1}\pgfkeysalso{/sseqpages/alias=#1}},
- show name/.code={\def\sseq@class@showname{#1}},
+ show name/.store in=\sseq@class@showname,
page/.code={\sseq@getnumrange\sseq@class@page{#1}},% page & gen are only for \classoptions.
generation/.code={\sseq@getnumrange\sseq@gen{#1}}, % \class tests if \sseq@class@page is set and throw an error if so.
tag/.code={\sseq@d@addto@macro\sseq@class@tag{#1}},
- offset/.code={\def\sseq@tempoffset{#1}},
- tooltip/.sseq @ first pass code={\def\sseq@tooltip{#1}}
+ offset/.store in=\sseq@tempoffset,
+ tooltip/.sseq @ first pass code={\def\sseq@tooltip{#1}},
+ insert/.store in=\sseq@classinsert
}
\pgfqkeys{/sseqpages/struct line}{
@@ -647,8 +616,9 @@
}
\pgfqkeys{/sseqpages}{needs tikz/.code=\sseq@needstikztrue}
+% All of these things need tikz to draw but otherwise require no special handling.
\sseq@needstikzandpass{/sseqpages}{%
- shade, blend mode, pattern, path picture, path fading, decorate, pin, label
+ shade, blend mode, pattern, path picture, path fading, decorate, pin, label % should pin be here?
}
\sseq@needstikzandpass{/sseqpages/differential}{%
@@ -671,8 +641,8 @@
% rectangle split/.code=\sseq@needstikzandpass,
% align/.code=\sseq@needstikzandpass,
-\sseq@addtostorelist\sseq@runoffarrow@start@differential@spec{...}
-\sseq@addtostorelist\sseq@runoffarrow@end@differential@spec{...}
+\sseq@addtostorelist\sseq@runoffarrow@start@differential@spec{}
+\sseq@addtostorelist\sseq@runoffarrow@end@differential@spec{>}
\sseq@addtostorelist\sseq@runoffarrow@start@structline@spec{...}
\sseq@addtostorelist\sseq@runoffarrow@end@structline@spec{...}
\sseq@pgfqkeysdirlist{/sseqpages/global,/sseqpages}{
@@ -704,11 +674,24 @@
%% Add key code to \sseq@savedoptioncode
% #1 -- a list of directories to search
% #2 -- keys
+%
+% This is pretty similar in basic concept to \sseq@processoptions, but instead of using the .unknown handlers to walk up the directory,
+% it just tries the key in each directory in the list. I'm not actually sure anymore why it was important to do it this way, but there probably was a good reason...
+%
% This is a faster and sloppier way of doing:
-%\def\sseq@temp{#1}
-%\pgfqkeys{/sseqpages/alwaysunknown}{#2}
+% \def\sseq@temp{#1}
+% \pgfqkeys{/sseqpages/alwaysunknown}{#2}
% and defining an event handler: alwaysunknown/.unknown/.code={\@xp\sseq@keys@try@addtooptions\@xp{\sseq@temp}{}{\sseq@keys@unknown}
+% That basically takes advantage of the pgfkeys parser but gives me back control over what to do with the parsed things.
+%
+% For some reason I made the probably misguided decision that that approach was too slow, even though this isn't performance
+% critical code. Maybe I had a better reason for doing this that I can't remember. Instead I copied pgfkeys but deleted all the
+% parts that are useless in this context, which is most of it. Occasionally bugs crop up here when it turns out I deleted a little too much.
+%
+% This uses a hook \sseq@addstylecodetooptions@unknown to allow the sseqs style to sift out the nonglobal keys and handle them differently.
+%
% Copied with modification from /pgf/utilities/pfgkeys.code.tex
+
\def\sseq@addstylecodetooptions#1#2{%
\def\sseq@directorylist{#1}%
\sseq@simple@pgfkeys@parse#2,\pgfkeys@mainstop
@@ -733,6 +716,7 @@
\pgfkeys@spdef\pgfkeyscurrentvalue{#2}%
\ifx\pgfkeyscurrentkey\pgfkeys@empty\else
\def\next{\@xp\sseq@keys@try@addtooptions\@xp{\sseq@directorylist}{}{\sseq@addstylecodetooptions@unknown}}%
+ % We deleted the general "first char syntax" handler, so we need to do our own check for the quote.
\sseq@simple@pgfkeys@checkquote#1\sseq@nil{%
\def\pgfkeyscurrentname{handle quote}%
\def\pgfkeyscurrentvalue{#1}%
@@ -747,6 +731,7 @@
\@xp\next
\fi
}
+% This is a hook for the "sseqs" style.
\let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown
\long\def\sseq@simple@pgfkeys@checkquote#1#2\sseq@nil{%
@@ -757,17 +742,42 @@
\fi
}
-\def\sseq@sseqstyle@globalpart{}
-
\def\sseq@stylelist{}
\def\sseq@clearchangestyles{}
+% The basic idea here is we make a tokens list \sseq@structlinestyle and define a key "struct lines" that takes a list of keys
+% and adds the keys to \sseq@structlinestyle. In order to do this, I need some special trick to delete spaces.
+% The macro \sseq@setmacronospaces defined in spectralsequences.sty accomplishes this.
\def\sseq@newstyles#1#2{\def\sseq@temppath{#1}\sseq@newstyles@#2,\sseq@nil}
\def\sseq@newstyles@#1,{\sseq@newsseqstyle{\sseq@trimleadingspaces#1}\@ifnextchar\sseq@nil{\@gobble}{\sseq@newstyles@}}
-\def\sseq@set@newstyle#1{\pgfqkeys{/sseqpages}{#1}\pgfqkeys{/sseqpages/global}{#1}\pgfqkeys{/sseqpages/global/default}{#1}\pgfqkeys{/sseqpages/first pass}{#1}}
+\def\sseq@set@newstyle#1{\pgfqkeys{/sseqpages}{#1}\pgfqkeys{/sseqpages/global}{#1}\pgfqkeys{/sseqpages/global/default}{#1}}
+
+% Here are two useful wrappers around addstylecodetotoks.
+
+% #1 -- token list
+% #2 -- path
+% #3 -- code
+\def\sseq@addstylecodetotoks#1#2#3{%
+ \let\sseq@savedoptioncode@store\sseq@savedoptioncode
+ \edef\sseq@savedoptioncode{\the#1}%
+ \sseq@addstylecodetooptions{#2}{#3}%
+ #1\@xp{\sseq@savedoptioncode}%
+ \let\sseq@savedoptioncode\sseq@savedoptioncode@store
+}
+
+% #1 -- macro
+% #2 -- path
+% #3 -- code
+\def\sseq@addstylecodetomacro#1#2#3{%
+ \let\sseq@savedoptioncode@store\sseq@savedoptioncode
+ \let\sseq@savedoptioncode#1%
+ \sseq@addstylecodetooptions{#2}{#3}%
+ \let#1\sseq@savedoptioncode
+ \let\sseq@savedoptioncode\sseq@savedoptioncode@store
+}
\def\sseq@newsseqstyle#1{%
\sseq@setmacronospaces\sseq@tempcmd{sseq@#1style}%
@@ -780,23 +790,15 @@
\sseq@x@addto@macro\sseq@clearchangestyles{\sseq@tempcmdb{}}%
\sseq@set@newstyle{%
#1s/.ecode={%
- \let\@nx\sseq@savedoptioncode@store\@nx\sseq@savedoptioncode
- \edef\@nx\sseq@savedoptioncode{\@nx\the\sseq@tempcmd}%
- \@nx\sseq@addstylecodetooptions{\sseq@temppath}{##1}%
- \sseq@tempcmd\@nx\@xp{\@nx\sseq@savedoptioncode}%
+ \@nx\sseq@addstylecodetotoks{\sseq@tempcmd}{\sseq@temppath}{##1}
\@nx\ifsseq@inprogress
\@nx\sseq@savedpaths@xadd{\sseq@tempcmd{\@nx\the\sseq@tempcmd}}%
\@nx\fi
- \let\@nx\sseq@savedoptioncode\@nx\sseq@savedoptioncode@store
},%
change #1s/.ecode={%
\@nx\ifsseq@ispageenv\@nx\else\@nx\sseq@error@nn{change-style-data}{#1}{##1}\@nx\fi
\@nx\ifsseq@hasname\@nx\else\@nx\sseq@error@nn{change-style-standalone}{#1}{##1}\@nx\fi
- \let\@nx\sseq@savedoptioncode@store\@nx\sseq@savedoptioncode
- \edef\@nx\sseq@savedoptioncode{\@nx\the\sseq@tempcmdb}%
- \@nx\sseq@addstylecodetooptions{\sseq@temppath}{##1}%
- \sseq@tempcmdb\@nx\@xp{\@nx\sseq@savedoptioncode}%
- \let\@nx\sseq@savedoptioncode\@nx\sseq@savedoptioncode@store
+ \@nx\sseq@addstylecodetotoks{\sseq@tempcmdb}{\sseq@temppath}{##1}
}
}%
}
@@ -808,12 +810,13 @@
% sseqs has to be handled separately, because it must decide whether an option is a global option or not
% and handle them at different times. This makes the code a little trickier.
+\def\sseq@sseqstyle@globalpart{}
\sseq@g@addto@macro\sseq@stylelist{\sseq@sseqstyle{\the\sseq@sseqstyle}}%
\sseq@g@addto@macro\sseq@clearchangestyles{\sseq@sseqstyle@page{}}%
\sseq@set@newstyle{
sseqs/.code={%
- \let\sseq@savedoptioncode@store\sseq@savedoptioncode
- \let\sseq@savedoptioncode\sseq@sseqstyle@globalpart
+ % This will get called on each key that isn't a defined global option. Then we add it to \sseq@sseqstyle to be applied
+ % locally to absolutely everything.
\def\sseq@addstylecodetooptions@unknown{%
\let\sseq@sseqstyle@globalpart\sseq@savedoptioncode
\edef\sseq@savedoptioncode{\the\sseq@sseqstyle}%
@@ -821,32 +824,30 @@
\sseq@sseqstyle\@xp{\sseq@savedoptioncode}%
\let\sseq@savedoptioncode\sseq@sseqstyle@globalpart
}%
- \sseq@addstylecodetooptions{/sseqpages/global}{#1}%
- \let\sseq@sseqstyle@globalpart\sseq@savedoptioncode
+ \sseq@addstylecodetomacro\sseq@sseqstyle@globalpart{/sseqpages/global}{#1}%
\ifsseq@inprogress
\sseq@savedpaths@xadd{\sseq@sseqstyle{\the\sseq@sseqstyle}}%
\fi
+ % Restore hook
\let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown
- \let\sseq@savedoptioncode\sseq@savedoptioncode@store
},%
+ % It's not clear to me that "change sseqs" should even exist as an option.
change sseqs/.code={%
\ifsseq@ispageenv\else\sseq@error@nn{change-style-data}{sseq}{#1}\fi
\ifsseq@hasname\else\sseq@error@nn{change-style-standalone}{sseq}{#1}\fi
- \let\sseq@savedoptioncode@store\sseq@savedoptioncode
- \edef\sseq@savedoptioncode{\the\sseq@sseqstyle@page}%
- \sseq@addstylecodetooptions{\sseq@temppath}{#1}%
- \sseq@sseqstyle@page\@xp{\sseq@savedoptioncode}%
- \let\sseq@savedoptioncode\sseq@savedoptioncode@store
+ \sseq@addstylecodetotoks{\sseq@sseqstyle@page}{\sseq@temppath}{#1}%
}
}
+% sseq needs special handling, so is done by hand above.
%\sseq@newstyles{/sseqpages/}{sseq}% DON'T make this /global/default! Bad things will happen.
\sseq@newstyles{/sseqpages/label,/sseqpages}{edge, label, edge label, differential label, struct line label}
\sseq@newstyles{/sseqpages/class,/sseqpages}{class, permanent cycle, transient cycle, this page cycle}
\sseq@newstyles{/sseqpages/differential,/sseqpages}{differential}
\sseq@newstyles{/sseqpages/struct line,/sseqpages}{struct line, this page struct line}
\sseq@newstyles{/sseqpages/class/label}{class label, inner class label, outer class label}
+\sseq@newstyles{/sseqpages/class/label/pin}{pin}
\sseq@newstyles{/sseqpages/tikz primitives}{tikz primitive}
\sseq@newstyles{/sseqpages/fit}{circle class}
@@ -860,11 +861,6 @@
permanent classes/.code={\pgfkeysalso{permanent cycles={#1}}},
transient classes/.code={\pgfkeysalso{transient cycles={#1}}},
this page classes/.code={\pgfkeysalso{this page cycles={#1}}},
- cycle style/.code={\pgfkeysalso{class style={#1}}},
- permanent class style/.code={\pgfkeysalso{permanent cycle style={#1}}},
- transient class style/.code={\pgfkeysalso{transient cycle style={#1}}},
- this page class style/.code={\pgfkeysalso{this page cycle style={#1}}},
- class label position/.code={\pgfkeysalso{class label positions={#1}}}
}%
\def\sseq@newplotstyle#1{
@@ -874,21 +870,13 @@
\@xp\def\sseq@tempcmdb{}
\pgfqkeys{/sseqpages/global}{%
#1 style/.ecode={
- \unexpanded{\let\sseq@savedoptioncode@store\sseq@savedoptioncode}
- \let\@nx\sseq@savedoptioncode\@xp\@nx\sseq@tempcmd
- \unexpanded{\sseq@addstylecodetooptions{/tikz}}{##1}
- \let\@xp\@nx\sseq@tempcmd\@nx\sseq@savedoptioncode
- \unexpanded{\let\sseq@savedoptioncode\sseq@savedoptioncode@store}
+ \@nx\sseq@addstylecodetomacro{\@xp\@nx\sseq@tempcmd}{/tikz}{##1}
}
}
% Only difference here is \sseq@tempcmdb -- which puts it in the default code -- instead of \sseq@tempcmd
\pgfqkeys{/sseqpages/global/default}{%
#1 style/.ecode={
- \unexpanded{\let\sseq@savedoptioncode@store\sseq@savedoptioncode}
- \let\@nx\sseq@savedoptioncode\@xp\@nx\sseq@tempcmdb
- \unexpanded{\sseq@addstylecodetooptions{/tikz}}{##1}
- \let\@xp\@nx\sseq@tempcmdb\@nx\sseq@savedoptioncode
- \unexpanded{\let\sseq@savedoptioncode\sseq@savedoptioncode@store}
+ \@nx\sseq@addstylecodetomacro{\@xp\@nx\sseq@tempcmdb}{/tikz}{##1}
}
}
}
@@ -896,10 +884,152 @@
\def\sseq@newplotstyles#1{\def\sseq@temppath{#1}\sseq@newplotstyles@#1,\sseq@nil}
\def\sseq@newplotstyles@#1,{\sseq@newplotstyle{\sseq@trimleadingspaces#1}\@ifnextchar\sseq@nil{\@gobble}{\sseq@newplotstyles@}}
-
\sseq@newplotstyles{x tick, y tick}
+%%
+%%
+%% 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.
+%%
+
+
+\def\sseq@featurelist{\\{class}\\{differential}\\{structline}\\{circleclass}\\{tikzprimitive}}
+\def\sseq@mapfeaturelist#1{\def\\##1{#1}\sseq@featurelist}
+
+\def\sseq@familylist{}
+
+\def\sseq@collections@featuretype{}
+\def\sseqnewfamily#1{%
+ % Make five bins associated to the new family, one for each feature type. Add them to storelist with empty defaults.
+ \sseq@mapfeaturelist{
+ \@xp\sseq@setmacronospaces\csname sseq@tempcmd@##1\endcsname{sseq@user@#1@##1@style}
+ \@xp\sseq@setmacronospaces\csname sseq@tempcmd@##1@default\endcsname{sseq@user@#1@##1@style@default}
+ \sseq@eval{\@nx\sseq@addtostorelist\@xptwo\@nx\csname sseq@tempcmd@##1\endcsname{\@xptwo\@nx\csname sseq@tempcmd@##1@default\endcsname}}
+ \@xptwo\def\csname sseq@user@#1@##1@style@default\endcsname{}
+ }
+ % This is for deciding what set of options to apply to a feature
+ \@xp\sseq@setnospaces\csname sseq@tempcmd\endcsname{sseq@user@#1}
+%
+ % A flag to decide whether to draw the family. Set/unset using "draw family" and "no family".
+ \@xp\sseq@addtostorelist\csname sseq@#1@maybedraw\endcsname{}
+ \pgfqkeys{/sseqpages/global}{%
+ #1 style/.ecode={%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@class{/sseqpages/class,/sseqpages/collections/class}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@differential{/sseqpages/differential,/sseqpages/collections/differential}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@structline{/sseqpages/struct line,/sseqpages/collections/struct line}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@circleclass{/sseqpages/fit,/sseqpages/collections/fit}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@tikzprimitive{/sseqpages/tikz primitives,/sseqpages/collections/tikz primitives}{##1}%
+ },
+ draw #1/.ecode = {\def\@xp\@nx\csname sseq@#1@maybedraw\endcsname{\@nx\sseq@drawtrue}},
+ no #1/.ecode = {\def\@xp\@nx\csname sseq@#1@maybedraw\endcsname{\@nx\sseq@drawfalse}}
+ }%
+ \pgfqkeys{/sseqpages/global/default}{%
+ #1 style/.ecode={%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@class@default{/sseqpages/class}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@differential@default{/sseqpages/differential}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@structline@default{/sseqpages/struct line}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@circleclass@default{/sseqpages/fit}{##1}%
+ \@nx\sseq@addstylecodetomacro\@xp\@nx\sseq@tempcmd@tikzprimitive@default{/sseqpages/tikz primitives}{##1}%
+ },
+ draw #1/.ecode = {\def\@xp\@nx\csname sseq@#1@maybedraw@default\endcsname{\@nx\sseq@drawtrue}},
+ no #1/.ecode = {\def\@xp\@nx\csname sseq@#1@maybedraw@default\endcsname{\@nx\sseq@drawfalse}}
+ }%
+%
+ \pgfqkeys{/sseqpages}{
+ #1/.ecode={
+ \@nx\sseq@d@addto@macro\@nx\sseq@familylist{\@nx\csname sseq@#1@maybedraw\endcsname}
+ \@nx\sseq@options@secondpass{
+ \unexpanded\@xp{\@xp\csname\sseq@tempcmd @\sseq@collections@featuretype @style\endcsname}
+ }
+ }
+ }
+}
+
+
+
+
+\def\sseq@collections@classlabels@hook{}
+\def\sseq@collections@innerclasslabels@hook{}
+\def\sseq@collections@outerclasslabels@hook{}
+\def\sseq@collections@pins@hook{}
+
+\def\sseq@collections@labels@hook{}
+\def\sseq@collections@edgelabels@hook{}
+\def\sseq@collections@differentiallabels@hook{}
+\def\sseq@collections@structlinelabels@hook{}
+
+\def\sseq@collections@setempty#1{\sseq@collections@setempty@#1,\sseq@nil}
+\def\sseq@collections@setempty@#1,{
+ \pgfqkeys{/sseqpages/collections}{
+ class/#1/.code={},
+ differential/#1/.code={},
+ struct line/#1/.code={},
+ fit/#1/.code={},
+ tikz primitives/#1/.code={}
+ }
+ \@ifnextchar\sseq@nil{\@gobble}{\sseq@collections@setempty@}
+}
+
+\sseq@collections@setempty{%
+ classes, cycles, permanent classes, permanent cycles, transient classes, transient cycles, this page classes, this page cycles,
+ edges, differentials,struct lines, this page struct lines,circleclasses, tikz primitives,
+ labels, edge labels, differential labels, struct line labels,
+ class labels, inner class labels, outer class labels,pins
+}
+
+% #1 -- path
+% #2 -- hook name
+% #3 -- code
+\def\sseq@collections@addtohook#1#2#3{
+ \sseq@keys@do{
+ \let\sseq@savedoptioncode@store\sseq@savedoptioncode\let\sseq@savedoptioncode\empty
+ \pgfqkeys{#1}{#3}
+ \edef\sseq@savedoptioncode{\unexpanded\@xp{\sseq@savedoptioncode@store}\def\@nx#2{\unexpanded\@xp{\sseq@savedoptioncode}}}
+ }
+}
+
+\pgfqkeys{/sseqpages/collections}{
+ class/classes/.style={/sseqpages/class/.cd,#1},
+ class/cycles/.style={/sseqpages/class/.cd,#1},
+ class/permanent classes/.code={\ifsseq@permanentcycle\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ class/permanent cycles/.code={\ifsseq@permanentcycle\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ class/transient classes/.code={\ifsseq@permanentcycle\else\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ class/transient cycles/.code={\ifsseq@permanentcycle\else\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ class/this page classes/.code={\ifsseq@thispage\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ class/this page cycles/.code={\ifsseq@thispage\pgfkeysalso{/sseqpages/class/.cd,#1}\fi},
+ differential/edges/.style={/sseqpages/differential/.cd,#1},
+ differential/differentials/.style={/sseqpages/differential/.cd,#1},
+ struct line/edges/.style={/sseqpages/struct line/.cd,#1},
+ struct line/struct lines/.style={/sseqpages/struct line/.cd,#1},
+ struct line/this page struct lines/.code={\ifsseq@thispage\pgfkeysalso{/sseqpages/struct line/.cd,#1}\fi},
+ fit/circleclasses/.style={/sseqpages/fit/.cd,#1},
+ tikz primitives/tikz primitives/.style={/sseqpages/tikz primitives/.cd,#1},
+% labels
+ class/class labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/class/label}{\sseq@collections@classlabels@hook}{#1}}},
+ class/inner class labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/class/label}{\sseq@collections@innerclasslabels@hook}{#1}}},
+ class/outer class labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/class/label}{\sseq@collections@outerclasslabels@hook}{#1}}},
+ class/pins/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/class/label/pin}{\sseq@collections@pins@hook}{#1}}},
+%
+ class/labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@labels@hook}{#1}}},
+ differential/labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@labels@hook}{#1}}},
+ struct line/labels/.code/.expanded={\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@labels@hook}{#1}}},
+%
+ differential/edge labels/.code/.expanded=
+ {\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@edgelabels@hook}{#1}}},
+ struct line/edge labels/.code/.expanded=
+ {\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@edgelabels@hook}{#1}}},
+ differential/differential labels/.code/.expanded=
+ {\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@differentiallabels@hook}{#1}}},
+ struct line/struct line labels/.code/.expanded=
+ {\unexpanded\@xp{\sseq@collections@addtohook{/sseqpages/label}{\sseq@collections@structlinelabels@hook}{#1}}},
+}
+
+
+
+
%%% Global keys handlers and infrastructure
\def\sseq@keys@lastpart{%
@@ -909,6 +1039,50 @@
\edef\sseq@temp@ii{\pgfkeyscurrentkey}%
}
+\def\sseq@sanitize@intexpr#1#2{
+ \sseq@ifintexpr{#1}{
+ \edef\sseq@sanitize@output{\the\numexpr#1}
+ }{
+ \sseq@error@xx{invalid-intexpr}{\unexpanded{#2}}{#1}
+ \sseq@break
+ }
+}
+
+\def\sseq@sanitize@positiveintexpr#1#2{
+ \sseq@sanitize@intexpr{#1}{#2}
+ \ifnum\sseq@sanitize@output<1\relax
+ \sseq@error@xx{invalid-positive-intexpr}{\unexpanded{#2}}{#1}
+ \@xp\sseq@break
+ \fi
+}
+
+\def\sseq@sanitize@dimenexpr#1#2{
+ \sseq@ifpgfmathexpr{#1}{
+ \ifpgfmathunitsdeclared\else
+ \sseq@error@xx{invalid-dimenexpr}{\unexpanded{#2}}{#1}
+ \@xp\sseq@break
+ \fi
+ \edef\sseq@sanitize@output{\sseq@mathresult}
+ }{
+ \sseq@error@xx{invalid-dimenexpr}{\unexpanded{#2}}{#1}
+ \sseq@break
+ }
+}
+
+\def\sseq@sanitize@color#1#2{
+ \begingroup
+ \global\sseq@gtempiffalse
+ \def\c@lor@error##1{\global\sseq@gtempiftrue}
+ \color{#1}
+ \endgroup
+ \ifsseq@gtempif
+ \sseq@error@xx{invalid-color}{\unexpanded{#2}}{#1}
+ \@xp\sseq@break
+ \else
+ \def\sseq@sanitize@output{#1}
+ \fi
+}
+
\pgfqkeys{/handlers}{
.sseq store in/.code 2 args={%
\sseq@addtostorelist#1{#2}%
@@ -918,6 +1092,44 @@
/sseqpages/global/default/\sseq@temp/.store in/.expand once=\csname \sseq@macroname#1@default\endcsname
}%
},
+ .sseq store in sanitize/.code n args={3}{%
+ \sseq@addtostorelist#1{#2}%
+ \sseq@keys@lastpart
+ \pgfkeys{%
+ \sseq@temp@ii/.code/.expanded={%
+ \unexpanded{#3{##1}}{\sseq@temp=\unexpanded{##1}}%
+ \unexpanded{\edef#1{\unexpanded\@xp{\sseq@sanitize@output}}}%
+ %\show\@nx#1
+ \sseq@breakpoint
+ },
+ \sseq@temp@ii/.value required,
+ /sseqpages/global/default/\sseq@temp/.code/.expanded={%
+ \unexpanded{#3{##1}}{\sseq@temp=\unexpanded{##1}}%
+ \edef\@xp\@nx\csname \sseq@macroname#1@default\endcsname\unexpanded{{\unexpanded\@xp{\sseq@sanitize@output}}}%
+ \sseq@breakpoint
+ },
+ /sseqpages/global/default/\sseq@temp/.value required
+ }%
+
+ },
+ .sseq store int in/.code 2 args={
+ \sseq@keys@lastpart
+ \pgfkeysalso{%
+ \sseq@temp@ii/.sseq store in sanitize={#1}{#2}\sseq@sanitize@intexpr
+ }
+ },
+ .sseq store positive int in/.code 2 args={
+ \sseq@keys@lastpart
+ \pgfkeysalso{%
+ \sseq@temp@ii/.sseq store in sanitize={#1}{#2}\sseq@sanitize@positiveintexpr
+ }
+ },
+ .sseq store dimen in/.code 2 args={
+ \sseq@keys@lastpart
+ \pgfkeysalso{%
+ \sseq@temp@ii/.sseq store in sanitize={#1}{#2}\sseq@sanitize@dimenexpr
+ }
+ },
.sseq append to style/.code 2 args={%
\sseq@addkeytostorelist{#1}{\pgfkeysalso{#2}}%
\sseq@keys@lastpart
@@ -970,8 +1182,8 @@
\sseq@usedparam\sseq@tempb
\fi
\pgfkeys{%
- /sseqpages/global/\sseq@temp/.ecode={\@nx\pgfkeysalso{\sseq@tempb{x}={##1},\sseq@tempb{y}={##1}}},%
- /sseqpages/global/default/\sseq@temp/.ecode={\@nx\pgfkeysalso{\sseq@tempb{x}={##1},\sseq@tempb{y}={##1}}}%
+ /sseqpages/global/\sseq@temp/.code/.expanded={\@nx\pgfkeysalso{\sseq@tempb{x}=\unexpanded{{##1}},\sseq@tempb{y}=\unexpanded{{##1}}}},%
+ /sseqpages/global/default/\sseq@temp/.code/.expanded={\@nx\pgfkeysalso{\sseq@tempb{x}=\unexpanded{{##1}},\sseq@tempb{y}=\unexpanded{{##1}}}}%
}%
}
}
@@ -987,32 +1199,35 @@
}
}
-\def\sseq@add@tikzkey@to@options@forstylehander#1{\sseq@e@addto@options{\@nx\sseq@options@secondpass{#1}}}
+\def\sseq@patchrepeat#1#2#3{%
+ \patchcmd#1{#2}{#3}{\sseq@patchrepeat{#1}{#2}{#3}}{}%
+}
+
+\def\sseq@stylehandler@processpath#1#2{%
+ \def\sseq@savedoptioncode{}%
+ \sseq@eval{\@nx\sseq@addstylecodetooptions{/sseqpages/#1}{\unexpanded\@xp{\sseq@keybody{*1}}}}%
+ \edef\sseq@savedoptioncode##1{\unexpanded\@xp{\sseq@savedoptioncode}}%
+ \sseq@patchrepeat\sseq@savedoptioncode{*1}{##1}%
+ \sseq@eval{\@nx\pgfqkeys{/sseqpages/#1}{\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode{##1}}}}}%
+}
+
+\def\sseq@add@tikzkey@to@options@forstylehander#1{\sseq@e@addto@options{#1}}
\pgfqkeys{/handlers}{ % defines sseq style, etc
sseq @@ make style handler/.style 2 args={%
.sseq #1/.code={%
+ \def\sseq@keybody####1{##1}%
\sseq@keys@lastpart
\let\sseq@savedoptioncode@store\sseq@savedoptioncode
\def\sseq@keys@unknown@error{}%
- \def\sseq@savedoptioncode{}%
\let\sseq@add@tikzkey@to@options\sseq@add@tikzkey@to@options@forstylehander
- \sseq@addstylecodetooptions{/sseqpages/scope}{##1}%
- \sseq@eval{\@nx\pgfkeys{/sseqpages/scope/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
- \def\sseq@savedoptioncode{}%
- \sseq@addstylecodetooptions{/sseqpages/class}{##1}%
- \sseq@eval{\@nx\pgfkeys{/sseqpages/class/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
- \def\sseq@savedoptioncode{}%
- \sseq@addstylecodetooptions{/sseqpages/differential}{##1}%
- \sseq@eval{\@nx\pgfkeys{/sseqpages/differential/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
- \def\sseq@savedoptioncode{}%
- \sseq@addstylecodetooptions{/sseqpages/struct line}{##1}%
- \sseq@eval{\@nx\pgfkeys{/sseqpages/struct line/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
- \def\sseq@savedoptioncode{}%
- \sseq@addstylecodetooptions{/sseqpages/circle classes}{##1}
- \sseq@eval{\@nx\pgfkeys{/sseqpages/circle classes/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
- \def\sseq@savedoptioncode{}%
- \sseq@addstylecodetooptions{/sseqpages/tikz primitives}{##1}%
- \sseq@eval{\@nx\pgfkeys{/sseqpages/tikz primitives/\sseq@temp/.#2={\unexpanded\@xp{\sseq@savedoptioncode}}}}%
+%
+ \sseq@stylehandler@processpath{scope}{#2}%
+ \sseq@stylehandler@processpath{class}{#2}%
+ \sseq@stylehandler@processpath{differential}{#2}%
+ \sseq@stylehandler@processpath{struct line}{#2}%
+ \sseq@stylehandler@processpath{circle classes}{#2}%
+ \sseq@stylehandler@processpath{tikz primitives}{#2}%
+%
\let\sseq@savedoptioncode\sseq@savedoptioncode@store
\let\sseq@addstylecodetooptions@unknown\sseq@keys@unknown
\let\sseq@keys@unknown@error\sseq@keys@unknown@error@normal
@@ -1036,7 +1251,7 @@
sseq @@ make code handler=code,
sseq @@ make code handler=prefix code,
sseq @@ make code handler=append code,
-%
+% these just are the same as /.style, etc.
.global sseq style/.code={\pgfkeys{\pgfkeyscurrentpath/.code=\pgfkeysalso{#1}}},
.global sseq prefix style/.code={\pgfkeys{\pgfkeyscurrentpath/.add code={\pgfkeysalso{#1}}{}}},
.global sseq append style/.code={\pgfkeys{\pgfkeyscurrentpath/.add code={}{\pgfkeysalso{#1}}}},
@@ -1147,11 +1362,19 @@
name/.sseq default error,
~page/.code={
\ifsseq@hasname
- \sseq@ifintexpr{#1}{
- \def\sseq@thepage{#1}\sseq@thepagecount=#1\relax\let\page\sseq@thepage
- }{
- \sseq@error{invalid-page}{#1}
- }
+ \sseq@getnumrange\sseq@thepage{#1}
+ \sseq@thepagecount=\sseq@thepage\relax
+ \let\page\sseq@thepage
+ \edef\sseq@thepagemm{\the\numexpr\sseq@thepagecount-1\relax}
+ \ifx\sseq@thepagemax\undefined
+ \edef\sseq@thepagemaxpp{\the\numexpr\sseq@thepagecount+1\relax}
+ \else
+ \ifnum\sseq@thepagemax=\z@
+ \let\sseq@thepagemaxpp\sseq@infinity
+ \else
+ \edef\sseq@thepagemaxpp{\the\numexpr\sseq@thepagemax+1\relax}
+ \fi
+ \fi
\else
\sseq@error{page-no-name}
\fi
@@ -1168,6 +1391,11 @@
},
grid/.code={\ifcsname sseq@grid@#1\endcsname\@xp\let\@xp\sseq@grid\csname sseq@grid@#1\endcsname\else\sseq@error@n{unknown-grid}{#1}\fi},
grid/.sseq default code={\ifcsname sseq@grid@#1\endcsname\@xp\let\@xp\sseq@grid@default\csname sseq@grid@#1\endcsname\else\sseq@error@n{unknown-grid}{#1}\fi},
+ grid color/.sseq store in sanitize=\sseq@gridcolor{gray}\sseq@sanitize@color,
+ grid step/.sseq x y alias,
+ grid step/.value required,
+ x grid step/.sseq store positive int in=\sseq@xgridstep{1},
+ y grid step/.sseq store positive int in=\sseq@ygridstep{1},
math nodes/.sseq is if=mathnodes, % TODO: make this locally toggleable
custom clip/.sseq store in=\sseq@customclip{},
clip/.sseq is if=clip,
@@ -1178,7 +1406,7 @@
draw orphan edges/.sseq is if=draworphanedges,
no orphan edges/.sseq is if false={draworphanedges},
class pattern/.sseq store in=\sseq@classpattern{standard},
- class pattern/.append code={\ifcsname sseq@\sseq@classpattern xoffset1/1\endcsname\else\sseq@error{unknown-class-pattern}\fi},
+ class pattern/.add code={\ifcsname sseq@#1xoffset1/1\endcsname\else\sseq@error{unknown-class-pattern}\@xp\sseq@break\fi}{\sseq@breakpoint},
class placement transform/.code={%
\bgroup
\let\tikz@transform\pgfutil@empty
@@ -1218,8 +1446,6 @@
\sseq@addtostorelist\sseq@classplacementtransform{}
-\sseq@addiftostorelist@truedefault{borderxaxis}\sseq@addiftostorelist@truedefault{borderyaxis}
-\sseq@addtostorelist\sseq@xaxisorigin{0}\sseq@addtostorelist\sseq@yaxisorigin{0}
%%% Range keys and commands
\sseq@globalkeys{%
@@ -1249,18 +1475,27 @@
\@xp\sseq@addtostorelist\@xp\sseq@xmaxpp\@xp{\sseq@infinity}
\@xp\sseq@addtostorelist\@xp\sseq@ymaxpp\@xp{\sseq@infinity}
+\sseq@addiftostorelist{specifiedxrange}
+\sseq@addiftostorelist{specifiedyrange}
\def\sseq@xrange#1#2{%
\global\let\sseq@xminmax\@gobbletwo % Don't need to calculate range of nodes if user specifies it
- \gdef\sseq@xmin{#1}%
- \gdef\sseq@xmax{#2}%
+ \global\sseq@specifiedxrangetrue
+ \sseq@sanitize@intexpr{#1}{x range={#1}{#2}}
+ \sseq@sanitize@intexpr{#2}{x range={#1}{#2}}
+ \xdef\sseq@xmin{\the\numexpr#1}%
+ \xdef\sseq@xmax{\the\numexpr#2}%
\let\xmin\sseq@xmin
\let\xmax\sseq@xmax
% Need to know decremented \xmin and incremented \xmax to decide which nodes to print
\sseq@tempcount=#1 \advance\sseq@tempcount-1\xdef\sseq@xminmm{\the\sseq@tempcount}%
\sseq@tempcount=#2 \advance\sseq@tempcount1\xdef\sseq@xmaxpp{\the\sseq@tempcount}%
+ \sseq@breakpoint
}
\def\sseq@yrange#1#2{%
\global\let\sseq@yminmax\@gobbletwo %
+ \sseq@sanitize@intexpr{#1}{x range={#1}{#2}}
+ \sseq@sanitize@intexpr{#2}{x range={#1}{#2}}
+ \global\sseq@specifiedyrangetrue
\gdef\sseq@ymin{#1}%
\gdef\sseq@ymax{#2}%
\let\ymin\sseq@ymin
@@ -1340,6 +1575,7 @@
%%% Axes and Layout options
\sseq@addtostorelist{\sseq@xtickfn}{} % These should initially be the identity macro, but addtostorelist doesn't accept functions as default
\sseq@addtostorelist{\sseq@ytickfn}{} % so the default is instated in begin{sseqdata} / begin{sseqpicture}.
+
\sseq@globalkeys{%
title/.sseq store in=\sseq@title{},
title style/.sseq append to style={/sseqpages/global/every title}{at={(0.5*\xmin+0.5*\xmax,\ymax)}},
@@ -1358,13 +1594,9 @@
no labels/.sseq x y alias=no #1 label,
draw labels/.sseq x y alias=draw #1 label,
%
- no x axis/.sseq is if false={drawxaxis},
- no y axis/.sseq is if false={drawyaxis},
- no axes/.value forbidden,
- no axes/.sseq x y alias=no #1 axis,
- draw x axis/.sseq is if=drawxaxis,
- draw y axis/.sseq is if=drawyaxis,
- draw axes/.sseq x y alias=draw #1 axis,
+ no x axis/.style={x axis type=none},
+ no y axis/.style={y axis type=none},
+ no axes/.style={axes type=none},
rotate labels/.sseq is if=rotatelabels,
%
draw x ticks/.sseq is if=drawxaxisticks,
@@ -1377,62 +1609,135 @@
draw ticks/.default=true,
tick step/.sseq x y alias,
tick step/.value required,
- x tick step/.sseq store in=\sseq@xtickstep{1},
- y tick step/.sseq store in=\sseq@ytickstep{1},
+ x tick step/.sseq store positive int in=\sseq@xtickstep{1},
+ y tick step/.sseq store positive int in=\sseq@ytickstep{1},
+ tick offset/.sseq x y alias,
+ tick offset/.value required,
+ x tick offset/.sseq store int in=\sseq@xtickstepoffset{0},
+ y tick offset/.sseq store int in=\sseq@ytickstepoffset{0},
+ major tick step/.sseq x y alias,
+ x major tick step/.sseq store int in=\sseq@xmajortickstep{0},
+ y major tick step/.sseq store int in=\sseq@ymajortickstep{0},
+ minor tick step/.sseq x y alias,
+ x minor tick step/.sseq store int in=\sseq@xminortickstep{0},
+ y minor tick step/.sseq store int in=\sseq@yminortickstep{0},
x tick handler/.code={\def\sseq@xtickfn##1{#1}},
x tick handler/.sseq default code={\def\sseq@xtickfn@default##1{#1}},
y tick handler/.code={\def\sseq@ytickfn##1{#1}},
y tick handler/.sseq default code={\def\sseq@ytickfn@default##1{#1}},
- class label handler/.code = {\long\def\sseq@classlabeltextfn##1{#1}}, % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...)
- class label handler/.sseq default code={\long\def\sseq@classlabeltextfn@default##1{#1}},
+ class label handler/.code = { % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...)
+ \long\def\sseq@classlabeltextfn##1{#1}
+ \ifx\sseq@classlabeltextfn\@gobble
+ \def\sseq@classlabeltextfn##1{\def\processedlabel{##1}}
+ \else
+ \edef\sseq@tempa{\unexpanded\@xp{\sseq@classlabeltextfn{}}}
+ \edef\sseq@tempb{\unexpanded\@xp{\sseq@classlabeltextfn{blah}}}
+ \ifx\sseq@tempa\sseq@tempb
+ \long\def\sseq@classlabeltextfn##1{#1{##1}}
+ \fi
+ \fi
+ },
+ class label handler/.sseq default code={
+ \long\def\sseq@classlabeltextfn@default##1{#1}
+ \ifx\sseq@classlabeltextfn@default\@gobble
+ \def\sseq@classlabeltextfn@default##1{\def\processedlabel{##1}}
+ \else
+ \edef\sseq@tempa{\unexpanded\@xp{\sseq@classlabeltextfn@default{}}}
+ \edef\sseq@tempb{\unexpanded\@xp{\sseq@classlabeltextfn@default{blah}}}
+ \ifx\sseq@tempa\sseq@tempb
+ \long\def\sseq@classlabeltextfn@default##1{#1{##1}}
+ \fi
+ \fi
+ },
x tick style/.sseq store in=\sseq@xtickstyle{},
y tick style/.sseq store in=\sseq@ytickstyle{},
tick style/.sseq x y alias,
%
- x axis style/.is choice,
- y axis style/.is choice,
- axes style/.sseq x y alias=axis style,
- ~x axis style/border/.code={\sseq@drawxaxistrue\sseq@borderxaxistrue},
- ~y axis style/border/.code={\sseq@drawyaxistrue\sseq@borderyaxistrue},
- ~x axis style/center/.code={
- \sseq@drawxaxistrue\sseq@borderxaxisfalse
- \ifx\sseq@xaxisgap\sseq@xaxisgap@default
- \def\sseq@xaxisgap{0cm}
- \fi
- },
- ~y axis style/center/.code={\sseq@drawyaxistrue\sseq@borderyaxisfalse\ifx\sseq@yaxisgap\sseq@yaxisgap@default\def\sseq@yaxisgap{0cm}\fi},
- ~x axis style/none/.code={\sseq@drawxaxisfalse},
- ~y axis style/none/.code={\sseq@drawyaxisfalse},
- x axis origin/.sseq store in=\sseq@xaxisorigin{0},
- y axis origin/.sseq store in=\sseq@yaxisorigin{0},
+ axes type/.sseq x y alias=axis type,
+ axes type/.add code={\let\sseq@axistypesanitizer\sseq@axistypesanitizerb}{\let\sseq@axistypesanitizer\sseq@axistypesanitizera},
+ axes type/.value required,
+ x axis type/.sseq store in sanitize=\sseq@xaxistype{border}\sseq@axistypesanitizer,
+ x axis type/.value required,
+ y axis type/.sseq store in sanitize=\sseq@yaxistype{border}\sseq@axistypesanitizer,
+ y axis type/.value required,
+ x axis origin/.sseq store int in=\sseq@xaxisorigin@center@{0},
+ y axis origin/.sseq store int in=\sseq@yaxisorigin@center@{0},
axes origin/.sseq x y alias=axis origin,
}
+
+\def\sseq@validaxestypesa{border, center, or none. The value frame only works with the 'axes type' key.}
+\def\sseq@validaxestypesb{border, center, frame, or none.}
+\let\sseq@validaxestypes\sseq@validaxestypesa
+
+\let\sseq@axistypekeya\@firstofone
+\def\sseq@axistypekeyb#1{axes type}
+\let\sseq@axistypekey\sseq@axistypekeya
+
+\def\sseq@uptoequal#1{\sseq@uptoequal@#1\sseq@nil}
+\def\sseq@uptoequal@#1=#2\sseq@nil{#1}
+\def\sseq@axistypesanitizerb#1#2{
+ \let\sseq@validaxestypes\sseq@validaxestypesb
+ \let\sseq@axistypekey\sseq@axistypekeyb
+ \@xp\ifx\csname sseq@leftgridpadding@y#1\endcsname\relax
+ \sseq@error@xx{invalid-axis-type}{#1}{\sseq@uptoequal{#2}}
+ \sseq@breakfi
+ \else
+ \def\sseq@sanitize@output{#1}
+ \fi
+ \let\sseq@validaxestypes\sseq@validaxestypesa
+ \let\sseq@axistypekey\sseq@axistypekeya
+}
+
+\def\sseq@axistype@frame{frame}
+\def\sseq@axistypesanitizera#1#2{
+ \def\temp{#1}
+ \ifx\sseq@axistype@frame\temp
+ \sseq@error@xx{invalid-axis-type}{#1}{\sseq@uptoequal{#2}}
+ \sseq@breakfi
+ \fi
+ \sseq@axistypesanitizerb{#1}{#2}
+}
+\let\sseq@axistypesanitizer\sseq@axistypesanitizera
+
\pgfqkeys{/sseqpages}{%
- class label handler/.code = {\long\def\sseq@classlabeltextfn##1{#1}}
+ class label handler/.code = { % \long so that \ifx\classlabeltextfn\@gobble compares true if this is empty (\@gobble is long...)
+ \long\def\sseq@classlabeltextfn##1{#1}
+ \ifx\sseq@classlabeltextfn\@gobble
+ \def\sseq@classlabeltextfn##1{\def\processedlabel{##1}}
+ \else
+ \edef\sseq@tempa{\unexpanded\@xp{\sseq@classlabeltextfn{}}}
+ \edef\sseq@tempb{\unexpanded\@xp{\sseq@classlabeltextfn{blah}}}
+ \ifx\sseq@tempa\sseq@tempb
+ \long\def\sseq@classlabeltextfn##1{#1{##1}}
+ \fi
+ \fi
+ }
}
\sseq@globalkeys{
axes gap/.sseq x y alias=axis gap,
axes gap/.value required,
- x axis gap/.sseq store in=\sseq@xaxisgap{0.5cm},
- y axis gap/.sseq store in=\sseq@yaxisgap{0.5cm},
+ x axis gap/.sseq store dimen in=\sseq@xaxisgap{0.5cm},
+ y axis gap/.sseq store dimen in=\sseq@yaxisgap{0.5cm},
tick gap/.sseq x y alias,
tick gap/.value required,
- x tick gap/.sseq store in=\sseq@xlabelgap{0.5cm},
- y tick gap/.sseq store in=\sseq@ylabelgap{0.5cm},
- x axis extend start/.sseq store in=\sseq@xaxis@start@extend{0.9cm},
- y axis extend start/.sseq store in=\sseq@yaxis@start@extend{0.9cm},
+ x tick gap/.sseq store dimen in=\sseq@xlabelgap{0.5cm},
+ y tick gap/.sseq store dimen in=\sseq@ylabelgap{0.5cm},
+ x axis tail/.sseq store dimen in=\sseq@xaxis@tail{0.9cm},
+ y axis tail/.sseq store dimen in=\sseq@yaxis@tail{0.9cm},
+ x axis extend start/.sseq store dimen in=\sseq@xaxis@start@extend{0.5cm},
+ y axis extend start/.sseq store dimen in=\sseq@yaxis@start@extend{0.5cm},
axes extend start/.sseq x y alias=axis extend start,
- x axis extend end/.sseq store in=\sseq@xaxis@end@extend{0.5cm},
- y axis extend end/.sseq store in=\sseq@yaxis@end@extend{0.5cm},
+ x axis extend end/.sseq store dimen in=\sseq@xaxis@end@extend{0.5cm},
+ y axis extend end/.sseq store dimen in=\sseq@yaxis@end@extend{0.5cm},
axes extend end/.sseq x y alias=axis extend end,
- x axis clip padding/.sseq store in=\sseq@xclip@axisgap{0.1cm},
- y axis clip padding/.sseq store in=\sseq@yclip@axisgap{0.1cm},
+ x axis clip padding/.sseq store dimen in=\sseq@xclip@axisgap{0.1cm},
+ y axis clip padding/.sseq store dimen in=\sseq@yclip@axisgap{0.1cm},
axes clip padding/.sseq x y alias=axis clip padding,
- right clip padding/.sseq store in=\sseq@clip@padding@right{0.1cm},
- left clip padding/.sseq store in=\sseq@clip@padding@left{0.4cm},
- top clip padding/.sseq store in=\sseq@clip@padding@top{0.1cm},
- bottom clip padding/.sseq store in=\sseq@clip@padding@bottom{0.4cm}
+ right clip padding/.sseq store dimen in=\sseq@clip@padding@right{0.1cm},
+ left clip padding/.sseq store dimen in=\sseq@clip@padding@left{0.1cm},
+ top clip padding/.sseq store dimen in=\sseq@clip@padding@top{0.1cm},
+ bottom clip padding/.sseq store dimen in=\sseq@clip@padding@bottom{0.1cm}
}
%%%
@@ -1445,6 +1750,9 @@
\sseq@addtostorelist\sseq@globalrotatetransform{}
\sseq@addtostorelist\sseq@globalscaletransform{}
+\sseq@addtostorelist\sseq@xscale{1}
+\sseq@addtostorelist\sseq@yscale{1}
+
\def\sseq@globaldetoneoption#1#2{%
\ifsseq@globaldetone\else
\sseq@error@n{det-one-after-scale}{#2}
@@ -1454,7 +1762,7 @@
}
\def\sseq@globalscaleoption#1{%
\sseq@globaldetonefalse
- \@xp\gdef\@xp\sseq@globalscaletransform\@xp{\sseq@globalscaletransform#1}#1%
+ \@xp\gdef\@xp\sseq@globalscaletransform\@xp{\sseq@globalscaletransform#1}%
}
\pgfqkeys{/sseqpages/global}{%
x/.sseq @ illegal,
@@ -1481,28 +1789,44 @@
mirror/.forward to=/sseqpages/global/xmirror,
mirror/.forward to=/sseqpages/global/ymirror,
xscale/.code={%
- \pgfmathparse{int(#1-1)}%
- \ifnum\pgfmathresult<\z@%
+ \sseq@ifpgfmathexpr{int(#1-1)}{}{
+ \sseq@error@nn{invalid-scale}{x}{#1}%
+ \sseq@break
+ }
+ \ifpgfmathunitsdeclared
+ \sseq@error@nn{unit-scale}{x}{#1}%
+ \sseq@break
+ \fi
+ \ifnum\sseq@mathresult<\z@
\sseq@error@nn{negative-scale}{x}{#1}%
+ \sseq@break
\fi
- \sseq@globalscaleoption{\pgftransformxscale{#1}}%
+ \sseq@globalscaleoption{\pgfsetxvec{\pgfpointxy{#1}{0}}}
+ \pgfmathparse{\sseq@xscale*#1}
+ \edef\sseq@xscale{\pgfmathresult}
+ \sseq@breakpoint
},
xscale/.value required,
yscale/.code={%
- \pgfmathparse{int(#1-1)}%
- \ifnum\pgfmathresult<\z@
+ \sseq@ifpgfmathexpr{int(#1-1)}{}{
+ \sseq@error@nn{invalid-scale}{y}{#1}%
+ \sseq@break
+ }
+ \ifpgfmathunitsdeclared
+ \sseq@error@nn{unit-scale}{y}{#1}%
+ \sseq@break
+ \fi
+ \ifnum\sseq@mathresult<\z@
\sseq@error@nn{negative-scale}{y}{#1}%
+ \sseq@break
\fi
- \sseq@globalscaleoption{\pgftransformyscale{#1}}%
+ \sseq@globalscaleoption{\pgfsetyvec{\pgfpointxy{0}{#1}}}
+ \pgfmathparse{\sseq@yscale*#1}
+ \edef\sseq@yscale{\pgfmathresult}
+ \sseq@breakpoint
},
yscale/.value required,
- scale/.code={%
- \pgfmathparse{int(#1-1)}%
- \ifnum\pgfmathresult<\z@
- \sseq@error@nn{negative-scale}{}{#1}%
- \fi
- \sseq@globalscaleoption{\pgftransformscale{#1}}%
- },
+ scale/.sseq x y alias=#1scale,
scale/.value required
}
@@ -1520,11 +1844,11 @@
x/.code={\sseq@error@n{option-illegal}{#1}},
y/.code={\sseq@error@n{option-illegal}{#1}},
z/.code={\sseq@error@n{option-illegal}{#1}},
- xshift/.sseq @ second pass code={\sseq@shifttransform{x}{#1}}, % I don't know why it has to be this way,
- xshift/.sseq @ first pass append code={\sseq@firstpass@shifttransform{x}{#1}}, % but it definitely breaks if I change it...
+ xshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{x}{#1},
+ yshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{y}{#1},
+ xshift/.append code=\sseq@options@scopeshiftsecondpass{\sseq@tikz@shifttransform{x}{#1}},%% Note special scopeshiftsecondpass command
+ yshift/.append code=\sseq@options@scopeshiftsecondpass{\sseq@tikz@shifttransform{y}{#1}},%%
xshift/.value required,
- yshift/.sseq @ second pass code={\sseq@shifttransform{y}{#1}},
- yshift/.sseq @ first pass append code={\sseq@firstpass@shifttransform{y}{#1}},
yshift/.value required,
shift/.sseq @ transform, shift/.value required,
shift only/.sseq @ transform,
@@ -1541,7 +1865,6 @@
transform canvas/.sseq @ transform, transform canvas/.value required
}
-% These two should be exactly the same
\def\sseq@shift@firstpassprocess#1{\sseq@shift@firstpassprocess@#1\sseq@nil}
\def\sseq@shift@firstpassprocess@#1#2\sseq@nil{\ifx#1\pgfpointxy\sseq@shift@firstpassprocess@@#2\else\sseq@standardparse\fi}
\def\sseq@shift@firstpassprocess@@#1#2{
@@ -1556,6 +1879,15 @@
\sseq@tikz@shifttransform{y}{#2}
}
+% special second pass handler for scopes to prevent shifts from causing out of memory style errors,
+% see the longer comment at the definition of sseq@scope in main.code.tex
+\def\sseq@options@scopeshiftsecondpass{\sseq@options@secondpass}
+
+\sseq@pgfqkeysdirlist{/sseqpages/scope,/sseqpages/tikz primitives,/sseqpages,/sseqpages/label,/sseqpages/class/label}{
+ align/.sseq @ second pass code=\tikzset{align/#1},
+ align/.sseq @ first pass append code={\sseq@needstikztrue\def\sseq@classquotes@smugglehook@inner{\sseq@needstikztrue\tikzset{align/#1}}}
+}
+
\sseq@pgfqkeysdirlist{/sseqpages/scope,/sseqpages/tikz primitives}{
shift/.code={
\sseq@options@firstpass{\tikz@scan@one@point\sseq@shift@firstpassprocess#1\relax}
@@ -1563,8 +1895,8 @@
},
xshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{x}{#1},
yshift/.sseq @ first pass code=\sseq@tikz@firstpass@checkshifttransform{y}{#1},
- xshift/.sseq @ second pass append code=\sseq@tikz@shifttransform{x}{#1},
- yshift/.sseq @ second pass append code=\sseq@tikz@shifttransform{y}{#1},
+ xshift/.append code=\sseq@options@scopeshiftsecondpass{\sseq@tikz@shifttransform{x}{#1}},%% Note special scopeshiftsecondpass command
+ yshift/.append code=\sseq@options@scopeshiftsecondpass{\sseq@tikz@shifttransform{y}{#1}},%%
rotate around/.sseq @ second pass code={\sseq@standardparse\sseq@pgfkeysdocommand{rotate}{#1}},
rotate/.sseq @ stdparse do transform, rotate/.value required,
xslant/.sseq @ stdparse do transform, xslant/.value required,
@@ -1589,7 +1921,7 @@
\let\sseq@firstpass@shifttransform\sseq@firstpass@checkshifttransform
\def\sseq@checkshifttransform#1#2{%
- \pgfmathparse{#2}%
+ \pgfmathparse{(#2)}%
\sseq@ifpgfmathresultisunitlessint{%
\@xp\pgfmathint\@xp{\pgfmathresult}%
\@xp\advance\csname sseq@#1\endcsname\pgfmathresult\relax
@@ -1619,7 +1951,7 @@
\sseq@ifpgfmathresultisunitlessint{%
\@xp\pgfmathint\@xp{\pgfmathresult}%
\@xp\advance\csname sseq@\sseq@getfirstchar#1\sseq@nil\endcsname\pgfmathresult\relax
- \sseq@pgfkeysdocommand{#1shift}{#2cm}
+ \sseq@pgfkeysdocommand{#1shift}{#2cm*\csname sseq@#1scale\endcsname}
}{
\sseq@standardparse
\ifpgfmathunitsdeclared
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex
index e86a1baf071..a72988b39dc 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqloadstore.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqloadstore.code.tex
@@ -21,6 +21,7 @@
\sseq@x@addto@macro\sseq@storelist@setdefaults{\global\let\@nx#1\@xp\@nx\csname \sseq@macroname#1@default\endcsname}%
\@xp\gdef\csname\sseq@macroname#1@default\endcsname{#2}%
}
+% TODO: is this used?
\def\sseq@addtostorelistlet#1#2{%
\sseq@g@addto@macro\sseq@storelist{\\#1}%
\sseq@x@addto@macro\sseq@storelist@setdefaults{\global\let\@nx#1\@xp\@nx\csname \sseq@macroname#1@default\endcsname}%
@@ -68,7 +69,6 @@
\global\@xp\let\csname pgfk@#1/.@body\@xp\endcsname\csname pgfk@#1/.@body@@@\sseq@thename\endcsname
}
-
\def\sseq@storecmds{\let\\\sseq@storelist@store\let\sseq@storelistif\sseq@storelistif@store\let\sseq@storelistkey\sseq@storelistkey@store\sseq@storelist}
\def\sseq@getcmds{\let\\\sseq@storelist@get\let\sseq@storelistif\sseq@storelistif@get\let\sseq@storelistkey\sseq@storelistkey@get\sseq@storelist}
@@ -82,18 +82,19 @@
\def\sseq@obj@xdef#1{\@xptwo\xdef\sseq@obj{#1}}
\def\sseq@obj@protectedxdef#1{\@xptwo\sseq@protected@xdef\sseq@obj{#1}}
\def\sseq@obj@xodef#1{\@xp\gdef\csname \sseq@obj@fullname{#1}\@xp\endcsname\@xp}
-\def\sseq@obj@let#1{\@xptwo\let\sseq@obj{#1}}
+\def\sseq@obj@let#1{\@xptwo\let\sseq@obj{#1}} % This shouldn't be used anywhere because all object assignments should be global...
+\def\sseq@obj@glet#1{\global\@xptwo\let\sseq@obj{#1}}
\def\sseq@obj@gletcsname#1#2{\global\@xp\let\csname\sseq@obj@fullname{#1}\@xp\endcsname\csname#2\endcsname}
\def\sseq@obj@gletobj#1#2{\global\@xp\let\csname\sseq@obj@fullname{#1}\@xp\endcsname\csname\sseq@obj@fullname{#2}\endcsname}
-\def\sseq@obj@undef#1{\@xptwo\let\sseq@obj{#1}\relax}
+\def\sseq@obj@undef#1{\global\@xptwo\let\sseq@obj{#1}\relax}
\def\sseq@obj@show#1{\@xptwo\show\sseq@obj{#1}}
\def\sseq@obj@ifundef#1{\@ifundefined{\sseq@obj@fullname{#1}}}
\def\sseq@obj@ifdef#1#2#3{\@ifundefined{\sseq@obj@fullname{#1}}{#3}{#2}}
+\def\sseq@obj@useifdef@else#1#2{\@ifundefined{\sseq@obj@fullname{#1}}{#2}{\sseq@obj{#1}}}
\def\sseq@obj@inc#1{\bgroup\sseq@tempcount\sseq@obj{#1}\relax\advance\sseq@tempcount\@ne\sseq@obj@xdef{#1}{\the\sseq@tempcount}\egroup}
-\def\sseq@obj@gaddto{\@xptwo\sseq@g@addto@macro\sseq@obj}
-\def\sseq@obj@xaddto{\@xptwo\sseq@x@addto@macro\sseq@obj}
-\def\sseq@obj@xaddto{\@xptwo\sseq@x@addto@macro\sseq@obj}
-\def\sseq@obj@xoaddto#1{\@xp\sseq@g@addto@macro\csname \sseq@obj@fullname{#1}\@xp\endcsname\@xp}
+\def\sseq@obj@gaddto#1{\sseq@obj@ifundef{#1}{\sseq@obj@gdef{#1}}{\@xptwo\sseq@g@addto@macro\sseq@obj{#1}}}
+\def\sseq@obj@xaddto#1{\sseq@obj@ifundef{#1}{\sseq@obj@xdef{#1}}{\@xptwo\sseq@x@addto@macro\sseq@obj{#1}}}
+\def\sseq@obj@xoaddto#1{\sseq@obj@ifundef{#1}{\sseq@obj@xodef{#1}}{\@xp\sseq@g@addto@macro\csname \sseq@obj@fullname{#1}\@xp\endcsname\@xp}}
\def\sseq@obj@map#1#2{\def\\##1{#2}\sseq@obj{#1}}
@@ -126,6 +127,7 @@
\def\sseq@savedpaths@addclass@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@class@draw@ifpage{#1}}}
\def\sseq@savedpaths@adddifferential@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@differential@draw@ifpage{#1}}}
\def\sseq@savedpaths@addstructline@standard#1{\sseq@x@addto@macro\sseq@savedpaths{\@nx\sseq@structline@draw@ifpage{#1}}}
+\def\sseq@savedpaths@xaddtikzpath@standard#1{\sseq@x@addto@macro\sseq@savedpaths{#1}}
\def\sseq@savedpaths@add@standard{\sseq@g@addto@macro\sseq@savedpaths}
\def\sseq@savedpaths@xadd@standard{\sseq@x@addto@macro\sseq@savedpaths}
\def\sseq@savedpaths@show@standard{\show\sseq@savedpaths}
@@ -134,6 +136,7 @@
\def\sseq@savedpaths@addclass@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@class@draw@ifpage{#1}}}
\def\sseq@savedpaths@adddifferential@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@differential@draw@ifpage{#1}}}
\def\sseq@savedpaths@addstructline@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{\@nx\sseq@structline@draw@ifpage{#1}}}
+\def\sseq@savedpaths@xaddtikzpath@temporary#1{\sseq@x@addto@macro\sseq@tempsavedpaths{#1}}
\def\sseq@savedpaths@add@temporary{\sseq@g@addto@macro\sseq@tempsavedpaths}
\def\sseq@savedpaths@xadd@temporary{\sseq@x@addto@macro\sseq@tempsavedpaths}
\def\sseq@savedpaths@show@temporary{\show\sseq@tempsavedpaths}
@@ -143,6 +146,7 @@
\def\sseq@savedpaths@addclass@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@addclass}}
\def\sseq@savedpaths@adddifferential@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@adddifferential}}
\def\sseq@savedpaths@addstructline@background#1{\sseq@error@internal@n{illegal-add-background-mode}{\sseq@savedpaths@addstructline}}
+\def\sseq@savedpaths@xaddtikzpath@background#1{\sseq@x@addto@macro\sseq@savedbackgroundpaths{#1}}
\def\sseq@savedpaths@add@background{\sseq@g@addto@macro\sseq@savedbackgroundpaths}
\def\sseq@savedpaths@xadd@background{\sseq@x@addto@macro\sseq@savedbackgroundpaths}
\def\sseq@savedpaths@show@background{\show\sseq@savedbackgroundpaths}
@@ -150,6 +154,7 @@
\def\sseq@savedpaths@addclass@ignore#1{}
\def\sseq@savedpaths@adddifferential@ignore#1{}
\def\sseq@savedpaths@addstructline@ignore#1{}
+\def\sseq@savedpaths@xaddtikzpath@ignore#1{}
\def\sseq@savedpaths@add@ignore#1{}
\def\sseq@savedpaths@xadd@ignore#1{}
\def\sseq@savedpaths@show@ignore#1{}
@@ -159,6 +164,7 @@
\@xp\let\@xp\sseq@savedpaths@addclass \csname sseq@savedpaths@addclass@#1\endcsname
\@xp\let\@xp\sseq@savedpaths@adddifferential\csname sseq@savedpaths@adddifferential@#1\endcsname
\@xp\let\@xp\sseq@savedpaths@addstructline \csname sseq@savedpaths@addstructline@#1\endcsname
+ \@xp\let\@xp\sseq@savedpaths@xaddtikzpath \csname sseq@savedpaths@xaddtikzpath@#1\endcsname
\@xp\let\@xp\sseq@savedpaths@add \csname sseq@savedpaths@add@#1\endcsname
\@xp\let\@xp\sseq@savedpaths@xadd \csname sseq@savedpaths@xadd@#1\endcsname
\pgfutil@ifundefined{sseq@scope@savedpaths@add@#1}{}{%
@@ -167,9 +173,14 @@
}%
}
-\def\sseq@usesavedpaths{%
- \sseq@savedpaths
- \sseq@clearchangestyles
- \sseq@tempsavedpaths
- \gdef\sseq@tempsavedpaths{}%
-} \ No newline at end of file
+% We don't want to add anything to paths except for tikz paths in background mode
+% We need to draw those because they might affect the bounding box.
+\def\sseq@setsavedpaths@draftmode{
+ \sseq@setsavedpaths{ignore} % Don't add stuff to paths
+ % Only add tikzpaths if in background mode (so ignore in standard or temporary)
+ \let\sseq@savedpaths@xaddtikzpath@standard\@gobble
+ \let\sseq@savedpaths@xaddtikzpath@temporary\@gobble
+ % Only update mode for tikzpath
+ \def\sseq@setsavedpaths##1{\@xp\let\@xp\sseq@savedpaths@xaddtikzpath \csname sseq@savedpaths@xaddtikzpath@##1\endcsname}
+}
+
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex
index 1a89dc4b66a..b6ec7c5ec46 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmacromakers.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqmacromakers.code.tex
@@ -25,17 +25,6 @@
%%% Install user commands
% copy commands into user namespace by removing sseq@ prefixes
% given a list of commands, \let\thiscommand\sseq@thiscommand on each one
-
-\def\sseq@recordmacros{\@xp\sseq@recordmacros@\sseq@macrolist\sseq@nil}
-\def\sseq@recordmacros@#1{%
- \ifx#1\sseq@nil\else % if so, that was the last command in the list
- \@xp\def\csname sseq@builtin\sseq@macroname#1\endcsname{}
- \@xp\sseq@recordmacros@
- \fi %
-}
-
-
-
\def\sseq@installmacros{\@xp\sseq@installmacros@\sseq@macrolist\sseq@nil}
\def\sseq@installmacros@#1{%
\ifx#1\sseq@nil\else % if so, that was the last command in the list
@@ -44,28 +33,74 @@
\fi %
}
-
% Capital U argument type is "Until" but puts back the token when it's done.
-\cs_new_protected:Npn \sseq__xparse_add_type_U:w #1
- {
- \__xparse_flush_m_args:
- \__xparse_add_grabber_mandatory:N U
- \tl_put_right:Nn \l__xparse_signature_tl { {#1} }
- \__xparse_prepare_signature:N
- }
-
-\cs_new_protected:Npn \sseq__xparse_grab_U:w #1#2 \l__xparse_args_tl
- { \sseq__xparse_grab_U_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn }
-
-\cs_new_protected:Npn \sseq__xparse_grab_U_aux:nnN #1#2#3
- {
- \exp_after:wN #3 \l__xparse_fn_tl ##1 #1
+
+% So xparse changed a bunch between the copy pushed to CTAN on February 7th and the copy pushed on February 9th
+\@ifpackagelater{xparse}{2017/02/08}{
+ \ifsseq@patchxparseU
+ % NEW CODE
+ \cs_new_protected:Npn \sseq__xparse_grab_U:w #1#2 \__xparse_run_code:
+ { \sseq__xparse_grab_U_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn }
+ \cs_new_protected:Npn \sseq__xparse_grab_U_aux:nnN #1#2#3
+ {
+ \tl_set:Nn \l__xparse_signature_tl {#2}
+ \exp_after:wN #3 \l__xparse_fn_tl ##1 #1
+ { \__xparse_add_arg:n {##1} #1 }
+ \l__xparse_fn_tl
+ }
+ \cs_new_protected:Npn \sseq__xparse_add_type_U:w #1
+ {
+ \__xparse_flush_m_args:
+ \__xparse_add_default:
+ \__xparse_add_grabber_mandatory:N U
+ \tl_put_right:Nn \l__xparse_signature_tl { {#1} }
+ \__xparse_prepare_signature:N
+ }
+ \else
+ % Assumptions failed, so just make U give an error (this isn't such a big deal since we don't use it for \d anymore).
+ \cs_new_protected:Npn \sseq__xparse_add_type_U:w #1
+ {
+ \sseq@error{U-xparse-incompatible}
+ }
+ \fi
+}{
+ % OLD CODE
+ \cs_new_protected:Npn \sseq__xparse_grab_U:w #1#2 \l__xparse_args_tl
+ { \sseq__xparse_grab_U_aux:nnN {#1} {#2} \cs_set_protected_nopar:Npn }
+ \cs_new_protected:Npn \sseq__xparse_grab_U_aux:nnN #1#2#3
+ {
+ \exp_after:wN #3 \l__xparse_fn_tl ##1 #1
+ {
+ \__xparse_add_arg:n {##1}
+ #2\l__xparse_args_tl #1
+ }
+ \l__xparse_fn_tl
+ }
+ \cs_new_protected:Npn \sseq__xparse_add_type_U:w #1
{
- \__xparse_add_arg:n {##1}
- #2\l__xparse_args_tl #1
+ \__xparse_flush_m_args:
+ \__xparse_add_grabber_mandatory:N U
+ \tl_put_right:Nn \l__xparse_signature_tl { {#1} }
+ \__xparse_prepare_signature:N
}
- \l__xparse_fn_tl
- }
+}% END \@ifpackagelater
+
+
+\cs_new_protected:Npn \sseq__xparse_normalize_type_U:w #1 {
+ \quark_if_recursion_tail_stop_do:nn {#1} { \__xparse_bad_arg_spec:wn }
+ \__xparse_normalize_check_lu:N U
+ \__xparse_add_arg_spec:n { U {#1} }
+ \int_incr:N \l__xparse_mandatory_args_int
+ \tl_clear:N \l__xparse_last_delimiters_tl
+ \__xparse_normalize_arg_spec_loop:n
+}
+
+% Expandable commands are a menace to us because they define a bunch of helper commands that we then have to keep track of.
+% We are too lazy to do this, so force \l__xparse_grab_expandably_bool to be false.
+% This is backwards compatible (I think) because \bool_set_false:N just performs a chardef (no existence check)
+% so in old versions, \l__xparse_grab_expandably_bool will be created harmlessly.
+\let\sseq__xparse_prepare_signature:n\__xparse_prepare_signature:n
+\pretocmd\sseq__xparse_prepare_signature:n { \bool_set_false:N \l__xparse_grab_expandably_bool } {}{\error}
% I would like to patch the \__xparse_grab_U:w's in my commands into \sseq__xparse_grab_U:w's but I can't because of -NoValue-.
\def\sseq@install@xparse@Uarggrabber{ \cs_set_eq:NN \__xparse_grab_U:w \sseq__xparse_grab_U:w }
@@ -77,10 +112,15 @@
% so the result is that it defines \sseq@somecommand intended to be \let to \somecommand later.
\cs_new_protected:Npn\sseq@DeclareDocumentCommand#1{%
- \exp_args:Nc \sseq@DeclareDocumentCommandAs { sseq @ \cs_to_str:N #1 }#1
+ \exp_args:Nc \sseq@DeclareDocumentCommandAs@setinputline { sseq @ \cs_to_str:N #1 }#1
+}
+
+\cs_new_protected:Npn\sseq@DeclareDocumentCommandAs@setinputline#1{
+ \protected\edef #1 { \@nx\sseq@setinputline \@xp\@nx\csname \cs_to_str:N #1 @@unique@@ start \endcsname }
+ \exp_args:Nc \sseq@DeclareDocumentCommandAs { \cs_to_str:N #1 @@unique@@ start }
}
-%%% \sseq@DeclareDocumentCommandAS
+%%% \sseq@DeclareDocumentCommandAs
%
% #1 - the command to define
% #2 - the command to use in argument parsing errors
@@ -89,13 +129,12 @@
%
% See my stack exchange question: https://tex.stackexchange.com/questions/350596/control-error-messages-made-by-commands-defined-with-newdocumentcommand
-
-
\cs_new_protected:Npn\sseq@DeclareDocumentCommandAs#1#2#3#4{
\group_begin:
\cs_set_eq:NN \__xparse_add_type_U:w \sseq__xparse_add_type_U:w
- \cs_set_eq:cN { tempsave_ \cs_to_str:N #2 } #2 % Store the original value of #2
- \cs_set_eq:cc { tempsave_ \cs_to_str:N #2 \c_space_tl code } { \cs_to_str:N #2 \c_space_tl code } % Store the original value of #2
+ \cs_set_eq:NN \__xparse_normalize_type_U:w \sseq__xparse_normalize_type_U:w
+ \cs_set_eq:NN \__xparse_prepare_signature:n \sseq__xparse_prepare_signature:n
+ %\cs_set:Npn \__xparse_declare_cmd_code:Nnn {\bool_set_false:N \l__xparse_grab_expandably_bool\__xparse_declare_cmd_code_aux:Nnn}
\sseq@installmsghooks
\def\sseq@error@setup{}
\def\sseq@error@cleanup{\sseq@errortrue}
@@ -109,16 +148,25 @@
\cs_if_exist:cTF{ \cs_to_str:N #2 \c_space_tl code }{
\cs_gset:Npx #1{
\begingroup
+ \exp_not:N \cs_set_eq:NN % force xparse to always ignore spaces!
+ \exp_not:N \peek_meaning:NTF
+ \exp_not:N \peek_meaning_ignore_spaces:NTF
+ \exp_not:N \cs_set_eq:NN % force xparse to always ignore spaces!
+ \exp_not:N \peek_meaning_remove:NTF
+ \exp_not:N \peek_meaning_remove_ignore_spaces:NTF
+ % Not sure why we use set_eq:cc and exp_not:n here but I'm concerned that something will break if I change it...
+ \exp_not:N \cs_set_eq:cc
+ \exp_not:n {{ \cs_to_str:N #2 \c_space_tl code }}
+ \exp_not:n {{ \cs_to_str:N #1 \c_space_tl code }}
\exp_not:N \cs_set_eq:NN
- \exp_not:c { \cs_to_str:N #2 \c_space_tl code }
- \exp_not:c { \cs_to_str:N #1 \c_space_tl code }
+ \exp_not:c { \cs_to_str:N #2 \c_space_tl }
+ \exp_not:c { \cs_to_str:N #1 \c_space_tl }
\exp_not:c { \cs_to_str:N #1 \c_space_tl inner }
}
- \pretocmd:cnnn { \cs_to_str:N #2 \c_space_tl code } { \endgroup } { } { \sseq@error@x { macro-patch-failed } { \string#1 } }
+ \pretocmd:cnnn { \cs_to_str:N #2 \c_space_tl code } { \endgroup{} } { } { \sseq@error@x { macro-patch-failed } { \string#1 } }
\cs_gset_eq:cN { \cs_to_str:N #1 \c_space_tl inner } #2
\cs_gset_eq:cc { \cs_to_str:N #1 \c_space_tl code } { \cs_to_str:N #2 \c_space_tl code }
- \cs_gset_eq:Nc #2 { tempsave _ \cs_to_str:N #2 }
- \cs_gset_eq:cc { \cs_to_str:N #2 \c_space_tl code } { tempsave_ \cs_to_str:N #2 \c_space_tl code }
+ \cs_gset_eq:cc { \cs_to_str:N #1 \c_space_tl }{ \cs_to_str:N #2 \c_space_tl } % sometimes the new version of xparse stores stuff in #2<space>
}{
\cs_gset_eq:NN #1 #2
}
@@ -135,7 +183,8 @@
\cs_new_protected:Npn\NewSseqCommand#1{%
\cs_if_free:cTF { sseq @ usermacro @ \cs_to_str:N #1 } { \DeclareSseqCommand#1 } { \sseq@error@x{usermacro-not-free}{\string#1} \use_none:nn }
}
-
+\let\begingroupa\begingroup
+\let\begingroupb\begingroup
\cs_new_protected:Npn\DeclareSseqCommand#1#2#3{%
\cs_if_exist:cTF { sseq @ builtin @ \cs_to_str:N #1 } {\sseq@error@x{wont-override-system-macro}{\string#1}\sseq@break} {}
\cs_if_free:cT { sseq @ usermacro @ \cs_to_str:N #1 } {
@@ -143,8 +192,10 @@
}
% Make sure \cs_if_exist doesn't pass because there was a previously defined user macro with same name
\cs_undefine:c { sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code }
- \exp_args:Nc \sseq@DeclareDocumentCommandAs { sseq @ usermacro @ \cs_to_str:N #1 } #1 { #2 } {
- #3
+ \exp_args:Nc \sseq@DeclareDocumentCommandAs@setinputline { sseq @ usermacro @ \cs_to_str:N #1 } #1 { #2 } {%
+ \sseq@loadinputline
+ \sseq@atbeginusermacro@msgsetup
+ {}#3{} % prevent space patching space hazards with these {}'s
\endgroup
}%
\ifsseq@error
@@ -155,22 +206,22 @@
% You might think we could skip this patching, and it's probably possible.
% However, this is responsible for turning the #'s of catcode other into #'s of catcode arg. I don't have as good of a way to do that.
% Also, this allows me to use \sseq@parseargspec after defining the command, so I don't have to run any error checking inside of it
- % because if the argspec is invalid, \DeclareDocumentCommand will let me know.
- \cs_if_exist:cTF{ sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code }{
- \patchcmd:cnfnn{ sseq @ usermacro @ \cs_to_str:N #1 \c_space_tl code }{\endgroup}{
+ % because if the argspec is invalid, \DeclareDocumentCommand will let me know.\sseq@temptoks
+ \cs_if_exist:cTF{ sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start \c_space_tl code }{
+ \patchcmd:cnfnn{ sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start \c_space_tl code }{\endgroup{}}{
\@xp\endgroup
- \@xp\begingroup
+ \@xp\begingroupa
\the\sseq@temptoks
- \sseq@atbeginusermacro@msgsetup
- }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}}
+ }{}{\sseq@error@x{usermacro-failed-patch}{\string#1}}
+ \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start \c_space_tl code } { sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start \c_space_tl code}
}{
- \pretocmd:cfnn{ sseq @ usermacro @ \cs_to_str:N #1 }{
- \@xp\begingroup
+ \pretocmd:cfnn{ sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start }{
+ \@xp\begingroupb
\the\sseq@temptoks
- \sseq@atbeginusermacro@msgsetup
- }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}}
+ }{}{\sseq@error@x{usermacro-failed-patch}{\string#1}}
}
\cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #1 } { sseq @ usermacro @ \cs_to_str:N #1 }
+ \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start } { sseq @ usermacro @ \cs_to_str:N #1 @@unique@@ start}
\ifsseq@inprogress
\cs_set_eq:Nc #1 { sseq @ usermacro @ \cs_to_str:N #1 }
\fi
@@ -178,12 +229,6 @@
}
%%% Commands to help the user define "groups" of commands to be reused
-\def\sseqnewgroup@splitcoord#1,#2\sseq@nil{%
- \sseq@eval{
- \@nx\begin{scope}[xshift=#1,yshift=#2,\unexpanded\@xp{\sseq@options}]
- }
-}
-
% #1 -- command
% #2 -- argspec
% #3 -- body of function (long)
@@ -197,8 +242,7 @@
\long\def\DeclareSseqGroup@#1#2#3#4{%
\group_begin:
\let\sseq@parseargspec\@gobbletwo % Get rid of argparse so we can change what gets added for setting up thiscall
- \sseq@temptoks\@xp{\sseq@SseqGroup@argspec} % This gets added to the outer command by DeclareSseqCommand
-%
+% why are we doing these things here?
\sseq@installmsghooks
\def\sseq@error@setup{}
\def\sseq@error@cleanup{\sseq@errortrue}
@@ -206,50 +250,64 @@
%
% undefine so we can tell whether we need to patch \command<space>code or \command
\cs_undefine:c { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }
- \exp_args:Nc \DeclareDocumentCommand { sseq @ usermacro @ \cs_to_str:N #2 @ helper } { #3 } {
- #4
+ \exp_args:Nc \sseq@DeclareDocumentCommandAs { sseq @ usermacro @ \cs_to_str:N #2 @ helper } #2 { #3 } {
+ \sseq@loadinputline
+ \sseq@usermacro@esetthiscall{\the\sseq@groupthiscalltoks}
+ \sseq@atbeginusermacro@msgsetup % the stack push happens in here
+ \sseq@scopecall
+ {}#4{}
\end{scope}
+ \endgroup
}%
\ifsseq@error
\@xp\sseq@break
\fi
+ \sseq@temptoks\@xp{\sseq@SseqGroup@argspec} % This gets added to the command by DeclareSseqCommand
#1#2{od()}{%
+ %can't use \sseq@atbeginusermacro@msgsetup until next spot b/c don't know what the whole call looks like yet
\IfNoValueTF{##1}{\def\sseq@options{}}{\def\sseq@options{##1}}%
\IfNoValueTF{##2}{%
- \sseq@eval{
- \@nx\begin{scope}[\unexpanded\@xp{\sseq@options}]
- }%
+ \edef\sseq@scopecall{\@nx\begin{scope}[\unexpanded\@xp{\sseq@options}]}
}{%
\sseqnewgroup@splitcoord##2\sseq@nil
}%
- \csname sseq @ usermacro @ \sseq@macroname #2 @ helper \@xp\endcsname \@gobble % This gobble eats the endgroup added by sseqDeclareDocumentCommand
+ \csname sseq @ usermacro @ \sseq@macroname #2 @ helper \@xp\endcsname\@gobbletwo % This gobble eats the endgroup added by sseqDeclareDocumentCommand
}%
\sseq@parseargspec@newgroup{#2}{#3}%
% You might think we could skip this patching, and it's probably possible.
- % However, this is responsible for turning the #'s of catcode other into #'s of catcode arg. I don't have as good of a way to do that.
+ % However, this is responsible for turning the #'s of catcode other into #'s of catcode arg. I don't have as good of a way to do that.
\cs_if_exist:cTF{ sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }{
\pretocmd:cfnn { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }{
\the\sseq@temptoks
- \sseq@atbeginusermacro@msgsetup
- }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}}
- \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } % globalize definition
+ }{}{\sseq@error@x{usermacro-failed-patch}{\string#1}}
+ % globalize definition:
+ \cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code } { sseq @ usermacro @ \cs_to_str:N #2 @ helper \c_space_tl code }
}{
\pretocmd:cfnn { sseq @ usermacro @ \cs_to_str:N #2 @ helper }{
\the\sseq@temptoks
- \sseq@atbeginusermacro@msgsetup
- }{}{\error\sseq@error@x{usermacro-failed-patch}{\string#1}}
+ }{}{\sseq@error@x{usermacro-failed-patch}{\string#1}}
}
\cs_gset_eq:cc { sseq @ usermacro @ \cs_to_str:N #2 @ helper } { sseq @ usermacro @ \cs_to_str:N #2 @ helper } % globalize definition
\let\sseq@parseargspec\sseq@parseargspec@normal
\sseq@breakpoint
\group_end:
}
-\let\sseqnewgroup\NewSseqGroup
+
+\def\sseqnewgroup@splitcoord#1,#2\sseq@nil{%
+ \edef\sseq@scopecall{
+ \@nx\begin{scope}[xshift=#1,yshift=#2,\unexpanded\@xp{\sseq@options}]
+ }
+}
+\newtoks\sseq@groupargspectoks
+\newtoks\sseq@groupthiscalltoks
\bgroup\catcode`\#=12\relax
- \gdef\sseq@SseqGroup@argspec{\sseq@eval{\sseq@temptoks{\IfNoValueF{#1}{\unexpanded{[#1]}}\IfNoValueF{#2}{\unexpanded{(#2)}}}}\@gobble}
+ \gdef\sseq@SseqGroup@argspec{
+ \sseq@eval{\global\sseq@groupargspectoks{\IfNoValueF{#1}{\unexpanded{[#1]}}\IfNoValueF{#2}{\unexpanded{(#2)}}}}
+ \@gobbletwo
+ }
\gdef\sseq@thearg{#\the\sseq@tempcount}
\egroup
@@ -271,7 +329,18 @@
\sseq@temptoks{}
\sseq@temptoksii{}%
\sseq@parseargspec@#2\sseq@nil
- \sseq@eval{\sseq@temptoks{\the\sseq@temptoksii\@nx\sseq@usermacro@esetthiscall{\@nx\@nx\@nx#1\@nx\the\sseq@temptoks\the\sseq@temptoks}}}
+ % What's the second temptoks for?
+ \sseq@eval{
+ \sseq@temptoks{
+ \the\sseq@temptoksii
+ \@nx\sseq@esetthiscall{
+ \@nx\@nx\@nx#1
+ \@nx\the\sseq@groupargspectoks
+ \the\sseq@temptoks
+ }
+ \global\sseq@groupthiscalltoks\@nx\@xp{\@nx\the\sseq@thiscalltoks}
+ }
+ }
}
@@ -308,6 +377,8 @@
}
}
+% v, E, and e are illegal
+
% Mandatory
\def\sseq@parseargspec@m{%
\sseq@e@addto@temptoks{{\@nx\unexpanded{\sseq@thearg}}}
@@ -360,7 +431,7 @@
\sseq@parseargspec@
}
-
+% Optional with default
\def\sseq@parseargspec@O#1{
\sseq@parseargspec@setargdefault{#1}%
@@ -383,7 +454,6 @@
\sseq@parseargspec@
}
-
\ExplSyntaxOff
-%
+% \ No newline at end of file
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex
index edc87c5d2b0..b7dea7f4149 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmain.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqmain.code.tex
@@ -16,14 +16,21 @@
%%% Environment definitions
%%%
%%%%%%%
+\def\sseq@usesavedpaths{%
+ \sseq@savedpaths
+ \sseq@clearchangestyles
+ \sseq@tempsavedpaths
+ \gdef\sseq@tempsavedpaths{}%
+}
\sseq@addtostorelist\sseq@savedbackgroundpaths{}
\sseq@addtostorelist\sseq@restorestyles{}
-\def\sseqdata{\@ifnextchar[{\sseqdata@}{\sseqdata@[]}}%}
-
\def\sseq@page{\protect\sseq@thepage}
+
+\def\sseqdata{\@ifnextchar[{\sseqdata@}{\sseqdata@[]}}%}
+
\def\sseqdata@[#1]{%
\edef\sseq@restorefont{\font@name}
\selectfont\nullfont % Avoid space hazards!
@@ -91,14 +98,18 @@
}
\sseq@savedpaths@xadd{\sseq@stylelist}
\sseq@savedpaths@add{\begingroup} % prevent some of the two-pass user macros horrors
+ \let\sseq@error@setup\sseq@error@setup@withinfo
}
% Just store all the settings
\def\endsseqdata{
+ \let\sseq@error@setup\sseq@error@setup@noinfo
+ \sseq@checkend{sseqdata}
\sseq@savedpaths@add{\endgroup} % prevent some of the two-pass user macros horrors
\xdef\sseq@restorestyles{\sseq@stylelist}
\sseq@storecmds
\ignorespacesafterend
+ \sseq@breakpoint
}
\def\sseqpage{\@ifnextchar[{\sseqpage@}{\sseqpage@[]}} %]
@@ -118,11 +129,9 @@
\sseq@ispageenvtrue
\def\sseq@sseqsetdirectory{/sseqpages}
%
- \let\sseq@xminmax\sseq@xminmax@active
- \let\sseq@yminmax\sseq@yminmax@active
- \ifsseq@mathnodes
- \let\sseq@maybemathswitch=$\@gobble$
- \fi
+% \ifsseq@mathnodes
+% \let\sseq@maybemathswitch=$\@gobble$
+% \fi
%
% Copy commands into user namespace
\sseq@installmacros
@@ -176,28 +185,88 @@
\@xp\@nx\csname pgfk@/sseqpages/global/{\sseq@currentoptionpath} options/.@cmd\endcsname
}
\fi
+%
+ \ifsseq@specifiedxrange
+ \let\sseq@xminmax\@gobbletwo
+ \else
+ \let\sseq@xminmax\sseq@xminmax@active
+ \fi
+ \ifsseq@specifiedyrange
+ \let\sseq@yminmax\@gobbletwo
+ \else
+ \let\sseq@yminmax\sseq@yminmax@active
+ \fi
+%
\sseq@savedpaths@xadd{\sseq@stylelist}
\sseq@savedpaths@add{\begingroup} % prevent some of the two-pass user macros horrors
\ifx\sseq@targetx\pgfutil@empty\else
\sseq@hasdegreetrue
\fi
+ \let\sseq@error@setup\sseq@error@setup@withinfo
}
% Here we do all of the work to actually print the page
\def\endsseqpage{
+ \let\sseq@error@setup\sseq@error@setup@noinfo
+ \sseq@checkend{sseqpage}
\sseq@savedpaths@add{\endgroup} % prevent some of the two-pass user macros horrors
+%
+ \sseq@xscalecm=\sseq@xscale cm
+ \sseq@yscalecm=\sseq@yscale cm
+%
+% check that range is okay
+%
\ifx\sseq@xmin\sseq@infinity\sseq@error{no-range}\def\sseq@xmin{0}\def\sseq@xmax{0}\@xp\sseq@break\fi % could be warning
\ifx\sseq@ymin\sseq@infinity\sseq@error{no-range}\def\sseq@ymin{0}\def\sseq@ymax{0}\@xp\sseq@break\fi
%
+ \ifnum\numexpr\sseq@xmax-\sseq@xmin\relax>\numexpr\maxdimen/\dimexpr1pt\relax-1\relax
+ \sseq@error@xx{range-super-overflow}{x}
+ {from \sseq@xmin\space to \sseq@xmax\space (xmax - xmin = \the\numexpr\sseq@xmax-\sseq@xmin)}
+ \@xp\sseq@break
+ \fi
+ \ifnum\numexpr\sseq@ymax-\sseq@ymin\relax>\numexpr\maxdimen/\dimexpr1pt\relax-1\relax
+ \sseq@error@xx{range-super-overflow}{y}
+ {from \sseq@ymin\space to \sseq@ymax\space (ymax - ymin = \the\numexpr\sseq@ymax-\sseq@ymin)}
+ \@xp\sseq@break
+ \fi
+%
+ \sseq@tempdimen = \dimexpr \textwidth -\sseq@clip@padding@right - \sseq@xaxis@end@extend - \sseq@xaxis@start@extend - \sseq@yaxisgap \relax
+ \sseq@tempcount = \numexpr \sseq@tempdimen /\sseq@xscalecm \relax
+ \ifnum \numexpr\sseq@xmax-\sseq@xmin + 1 > \sseq@tempcount
+ \pgfmathparse{\sseq@tempdimen/1cm/(\sseq@xmax-\sseq@xmin+1)}
+ \sseq@error@xxxx{range-overflow}{x}
+ {from \sseq@xmin\space to \sseq@xmax\space (xmax - xmin = \the\numexpr\sseq@xmax-\sseq@xmin)}
+ {\the\sseq@tempcount}% max x range
+ {\pgfmathresult}% max xscale
+ \@xp\sseq@break
+ \fi
+%
+ \sseq@tempdimen = \dimexpr \textheight - \sseq@clip@padding@top - \sseq@yaxis@end@extend - \sseq@yaxis@start@extend - \sseq@xaxisgap \relax
+ \sseq@tempcount = \numexpr \sseq@tempdimen /\sseq@yscalecm \relax
+ \ifnum \numexpr\sseq@ymax-\sseq@ymin +1 > \sseq@tempcount
+ \pgfmathparse{\sseq@tempdimen/1cm/(\sseq@ymax-\sseq@ymin+1)}
+ \sseq@error@xxxx{range-overflow}{y}
+ {from \sseq@ymin\space to \sseq@ymax\space (ymax - ymin = \the\numexpr\sseq@ymax-\sseq@ymin)}
+ {\the\sseq@tempcount}% max x range
+ {\pgfmathresult}% max xscale
+ \@xp\sseq@break
+ \fi
+%
+ % Really this could be anything between -\sseq@xmin and -\sseq@xmax and it wouldn't matter. We'll split the difference.
+ \sseq@xoffset=\numexpr\sseq@intdivceiling{\numexpr-\sseq@xmin-\sseq@xmax\relax}{\numexpr4*\sseq@xgridstep\relax}*(2*\sseq@xgridstep)\relax
+ \sseq@yoffset=\numexpr\sseq@intdivceiling{\numexpr-\sseq@ymin-\sseq@ymax\relax}{\numexpr4*\sseq@ygridstep\relax}*(2*\sseq@ygridstep)\relax
+%
+%
\tikzset{
z=0pt,
every path/.style={},
every node/.style={}
}
\let\errmessage\sseq@errmessage@std
+ \sseq@setlayoutparameters
\begin{tikzpicture}[/sseqpages/global/{default} options,\ifsseq@hasname/sseqpages/global/{\sseq@thename} options\fi,/sseqpages/global/{this page} options]%
\sseq@sseqstyle@globalpart
- \pgftransformreset
+ %\pgftransformreset
\sseq@globaldetonetransform
\sseq@globalscaletransform
%
@@ -205,32 +274,49 @@
\let\sseq@shifttransform\sseq@checkshifttransform % Allow shifts as long as they are by integers and have no units.
%
\sseq@setupclip
+%
+ \sseq@patchtikzcoords
+%
\pgfonlayer{background}%
% Axes labels only occur once per page, so the cost of typesetting them with tikz doesn't matter ... THANK GOD
\ifx\sseq@title\pgfutil@empty\else
\ifsseq@drawtitle
- \sseq@eval{\unexpanded{\path (0.5*\xmin+0.5*\xmax,\ymax) node[
+ \sseq@eval{\@nx\path (0,-\sseq@yoffset) node[
/sseqpages/global/every title,
- above=\sseq@clip@padding@top+\sseq@yaxis@end@extend+10pt
- ]} {\unexpanded\expandafter{\sseq@title}};}
+ above=\sseq@topclippadding+5pt
+ ] {\unexpanded\expandafter{\sseq@title}};
+ }
\fi
\fi
% Don't touch the shifts -- they are very persnickety.
\ifx\sseq@xaxislabel\pgfutil@empty\else\ifsseq@drawxaxislabel
- \sseq@eval{\noexpand\node[/sseqpages/global/every x axis label, yshift=-\sseq@xaxisgap-\sseq@yaxis@start@extend-10pt] {\unexpanded\expandafter{\sseq@xaxislabel}};}
+ \sseq@eval{\noexpand\node[
+ align=center,
+ /sseqpages/global/every x axis label,
+ below,
+ shift={\sseq@xlabelposition},
+ ] {\unexpanded\expandafter{\sseq@xaxislabel}};}
\fi\fi
\ifx\sseq@yaxislabel\pgfutil@empty\else\ifsseq@drawyaxislabel
- \sseq@eval{\noexpand\node[/sseqpages/global/every y axis label,rotate=90,yshift=\sseq@yaxisgap+\sseq@xaxis@start@extend+10pt] {\unexpanded\expandafter{\sseq@yaxislabel}};}
+ \sseq@eval{\noexpand\node[
+ align=center,
+ /sseqpages/global/every y axis label,
+ above,
+ rotate=90,
+ shift={\sseq@ylabelposition},
+ ] {\unexpanded\expandafter{\sseq@yaxislabel}};}
\fi\fi
+%
+ \sseq@grid
\sseq@handlexaxis % Draw the axis with pgf primitives. These are defined in sseqdrawing.code.tex
\sseq@handleyaxis
- \sseq@grid
\endpgfonlayer
%
\ifsseq@mathnodes
\tikzset{execute at begin node=$,execute at end node=$}%
\fi
%\let\sseq@error@setup\sseq@error@setup@withinfo
+%
\begingroup
\sseq@savedbackgroundpaths
\endgroup
@@ -267,11 +353,18 @@
%%% Scope
\newcount\sseq@scope@savestackid
+\def\sseq@scope@secondpasstoks{}
\def\sseq@scope{\@ifnextchar[{\sseq@scope@}{\sseq@scope@[]}}%]
\def\sseq@scope@[#1]{%
\sseq@scope@savedpaths@add{\begin{scope}}%
+ % 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@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.
+ % Anyways, to avoid this excessive storage demand, we don't put the shifts into the scope toks and apply them tons of times, we just do them once.
+ \let\sseq@options@scopeshiftsecondpass\sseq@scope@savedpaths@add
\sseq@processoptions{scope}{#1}% outputs into \sseq@savedoptioncode
- \sseq@eval{\@nx\sseq@scope@savedpaths@add{\sseq@scope@toks{\unexpanded\@xp{\sseq@savedoptioncode\tikz@options}}}}%
+ \edef\sseq@scope@secondpasstoks{\unexpanded\@xp{\sseq@scope@secondpasstoks}\unexpanded\@xp{\sseq@savedoptioncode}}
+ \sseq@eval{\@nx\sseq@scope@savedpaths@add{\sseq@scope@toks{\unexpanded\@xp{\sseq@scope@secondpasstoks}}}}%
%\advance\sseq@scope@savestackid\@ne
%\sseq@savestack@name{scope@save\the\sseq@scope@savestackid}
}
@@ -284,25 +377,13 @@
\ifsseq@draftmode % Okay, have to dummy out all the main commands.
- \sseq@setsavedpaths{ignore} % Don't add stuff to paths
- \let\sseq@setsavedpaths\@gobble % and dummy out the normal mechanism that would change this
-
- % We don't really want to add anything to the saved paths, but the whole tikz parser is already loaded in parsers and we want to dummy a bit of it out.
- % It's good to have the parser itself though, because it is responsible for sanity checking the structure of the input. Just get rid of the hard tasks
- % the parser does once it's parsed the stuff.
- \def\sseq@defer@tikzcommand@option[#1]{%
- \sseq@g@addto@macro\sseq@whattheusersaid{[#1]}%
- \sseq@defer@tikzcommand@
- } % These are the two expensive handlers, redefine them to do nothing.
- \def\sseq@defer@tikzcommand@coord(#1){%
- \sseq@g@addto@macro\sseq@whattheusersaid{(#1)}%
- \sseq@defer@tikzcommand@
- }
-
-
+ % Only add tikz background paths to the savedpaths. We need to draw background paths because they might change the bounding box!
+ \sseq@setsavedpaths@draftmode
+%
% All we want to do here is record the range. Have to process options in order to figure out where it is.
\sseq@DeclareDocumentCommand\class{or()}{%
\begingroup
+ \sseq@loadinputline
\IfNoValueT{#2}{\sseq@break}%
\sseq@xsetthiscall{\string\class\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}%
\sseq@options@firstpassmode
@@ -317,13 +398,10 @@
\sseq@yminmax{\xcoord}{\ycoord}%
\sseq@pushstack@\coord % also need the class stack to calculate other \class commands.
\sseq@cleanup@obj{partcoord.(\partialcoord).numnodes}%
- \sseq@cleanup@obj{partcoord.(\partialcoord).numnodespp}%
\ifnum\nodenum=\@ne
\sseq@obj@gdef{partcoord.(\partialcoord).numnodes}{0}%
- \sseq@obj@gdef{partcoord.(\partialcoord).numnodespp}{1}%
\fi
\sseq@obj@xdef{partcoord.(\partialcoord).numnodes}{\nodenum}%
- \sseq@obj@xdef{partcoord.(\partialcoord).numnodespp}{\the\numexpr\nodenum+1}%
\edef\classname{class.\coord[0]}%
\ifx\sseq@class@tag\pgfutil@empty\else
\sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{%
@@ -344,12 +422,11 @@
}
% Now the rest of these can be no-ops
- \sseq@DeclareDocumentCommand\classoptions{or()}{}
- \sseq@DeclareDocumentCommand\replaceclass{or()}{}
- \sseq@DeclareDocumentCommand\d{oU(r()d()}{}
- \sseq@DeclareDocumentCommand\doptions{oU(r()d()}{}
- \sseq@DeclareDocumentCommand\structline{or()r()}{}
- \sseq@DeclareDocumentCommand\structlineoptions{or()r()}{}
+ \sseq@DeclareDocumentCommand\classoptions{od()}{}
+ \sseq@DeclareDocumentCommand\replaceclass{od()}{}
+ \def\sseq@d@main#1#2#3#4#5{} % makes both \d and \doptions do nothing
+ \sseq@DeclareDocumentCommand\structline{od()d()}{}
+ \sseq@DeclareDocumentCommand\structlineoptions{od()d()}{}
\sseq@DeclareDocumentCommand\circleclasses{or()r()}{}
\endinput
\fi
@@ -365,6 +442,7 @@
%%% \class, \classoptions, \replaceclass
\sseq@DeclareDocumentCommand\class{or()}{%
\begingroup
+ \sseq@loadinputline
\IfNoValueT{#2}{\sseq@break}
\sseq@xsetthiscall{\string\class\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}%
\sseq@options@firstpassmode
@@ -384,18 +462,33 @@
\sseq@error@xxxx{classpattern-too-many-classes}{(\partialcoord)}{\nodenum}{\sseq@classpattern}{\@xp\the\csname sseq@\sseq@classpattern @maxclasses\endcsname}
\sseq@breakfi
\fi
- \sseq@processlabels
+%%%% No more breaks after this point
+%
+ \ifx\sseq@classinsert\empty
+ % by default, just insert to the right of previous classes
+ \edef\sseq@classinsert{\nodenum}
+ \else
+ \ifnum\sseq@classinsert<\z@
+ % negative 1 is where we would normally insert things
+ \edef\sseq@classinsert{\the\numexpr\nodenum+\sseq@classinsert+1}
+ \fi
+ \ifnum\sseq@classinsert<\@ne
+ \def\sseq@classinsert{1}
+ \fi
+ \ifnum\sseq@classinsert>\nodenum\relax
+ \edef\sseq@classinsert{\nodenum}
+ \fi
+ \ifnum\nodenum>\@ne
+ \@xp\sseq@class@adjustclasses\@xp{\partialcoord} % Adjust all of the indices of the classes to the right of the one we're inserting
+ \fi
+ \fi
+%
+ \sseq@processlabels % This sets up the label nodes, now that we know the position of the class (I think that's what we needed?)
%
\sseq@xminmax{\xcoord}{\ycoord}%
\sseq@yminmax{\xcoord}{\ycoord}%
\sseq@cleanup@obj{partcoord.(\partialcoord).numnodes}%
- \sseq@cleanup@obj{partcoord.(\partialcoord).numnodespp}%
- \ifnum\nodenum=\@ne
- \sseq@obj@gdef{partcoord.(\partialcoord).numnodes}{0}%
- \sseq@obj@gdef{partcoord.(\partialcoord).numnodespp}{1}%
- \fi
\sseq@obj@xdef{partcoord.(\partialcoord).numnodes}{\nodenum}%
- \sseq@obj@xdef{partcoord.(\partialcoord).numnodespp}{\the\numexpr\nodenum+1}%
\edef\classname{class.\coord[0]}%
\ifx\sseq@class@tag\pgfutil@empty\else
\sseq@obj@ifdef{partcoord.(\partialcoord).tag.\sseq@class@tagprefix\sseq@class@tag}{
@@ -421,14 +514,25 @@
%
\sseq@obj@gdef{class.\coord.num}{0}% For \replaceclass
\sseq@obj@xdef{\classname.page}{\sseq@infinity}%
- \sseq@obj@xodef{\classname.options}{\sseq@savedoptioncode}%
- \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext}%
- \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions}%
- \sseq@obj@xodef{\classname.labelnodes}{\sseq@classlabelnodes}%
- \sseq@obj@xdef{class.\coord.x}{\xcoord}%
- \sseq@obj@xdef{class.\coord.y}{\ycoord}%
- \sseq@obj@gdef{\classname.dependencies}{}%
- \sseq@obj@xdef{\classname.needstikz}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi}%
+ \sseq@obj@xdef{class.\coord.n}{\sseq@classinsert}
+ \ifx\sseq@familylist\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.familylist}{\sseq@familylist}
+ \fi
+ \ifx\sseq@savedoptioncode\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.options}{\sseq@savedoptioncode}%
+ \fi
+ \ifx\sseq@classnodetext\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext}
+ \fi
+ \ifx\sseq@classnodetextoptions\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions}
+ \fi
+ \ifx\sseq@classlabelnodes\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.labelnodes}{\sseq@classlabelnodes}%
+ \fi
+ \ifsseq@needstikz
+ \sseq@obj@xdef{\classname.needstikz}{\sseq@needstikztrue}%
+ \fi
\@ifundefined{sseq@tempoffset}{}{%
\tikz@scan@one@point\sseq@setoffset\sseq@tempoffset
}%
@@ -437,17 +541,31 @@
\fi
%
\sseq@savedpaths@addclass{class.\coord}%
- \sseq@obj@gdef{class.\coord.style}{}%
\sseq@breakpoint
\endgroup
}
\def\sseq@setoffset#1{\sseq@obj@gdef{\classname.offset}{\pgftransformshift{#1}}}
-\sseq@DeclareDocumentCommand\classoptions{or()}{%
+% 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@classinsert.
+\def\sseq@class@adjustclasses#1{
+ \sseq@tempcount=\z@
+ \sseq@tempcountb=\sseq@obj{partcoord.(#1).numnodes}
+ \loop
+ \advance\sseq@tempcount\@ne
+ \ifnum\sseq@obj{class.(#1,\the\sseq@tempcount).n}<\sseq@classinsert\relax\else
+ \sseq@cleanup@obj{class.(#1,\the\sseq@tempcount).n}
+ \sseq@eval{\@nx\sseq@obj@inc{class.(#1,\the\sseq@tempcount).n}} % unfortunately, \sseq@obj@inc uses \sseq@tempcount so we need this eval
+ \fi
+ \ifnum\sseq@tempcount<\sseq@tempcountb\repeat
+
+}
+
+\sseq@DeclareDocumentCommand\classoptions{od()}{%
\begingroup
- \sseq@xsetthiscall{\classoptions\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}%
+ \sseq@loadinputline
+ \sseq@xsetthiscall{\string\classoptions\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}%
\IfNoValueT{#1}{\sseq@error@x{cmdoptions-without-options}{\string\classoptions}\sseq@break}% could be warning
- \IfNoValueT{#2}{\sseq@break}%
\sseq@options@firstpassmode
\the\sseq@sseqstyle
\the\sseq@classstyle
@@ -456,25 +574,31 @@
\let\sseq@processlabels\sseq@processlabels@default % Don't double dip on labels from the scope or classstyle
\sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode
%
- \sseq@parsecoord\coord{#2}{\string\classoptions}%
+ \IfNoValueTF{#2}{
+ \def\sseq@coord{\lastclass0}
+ }{
+ \def\sseq@coord{#2}
+ }
+ \sseq@parsecoord\coord{\sseq@coord}{\string\classoptions}%
%
\sseq@processlabels
%
\let\partialcoord\coord@partial
+ \edef\sseq@classnum{\sseq@obj@ifdef{class.\coord.num}{\sseq@obj{class.\coord.num}}{0}}
\@ifundefined{sseq@class@page}{%
\@ifundefined{sseq@gen}{
\@ifundefined{sseq@thepage}{
- \edef\sseq@gen{\sseq@obj{class.\coord.num}}
+ \let\sseq@gen\sseq@classnum
}{
\sseq@obj@pagetogen{class.\coord}{\sseq@thepage} % stores in \sseq@gen
}
\let\sseq@genmax\sseq@gen
}{
\ifnum\sseq@gen<\z@
- \edef\sseq@gen{\the\numexpr\sseq@obj{class.\coord.num}+\sseq@gen+1}
+ \edef\sseq@gen{\the\numexpr\sseq@classnum+\sseq@gen+1}
\fi
\@ifundefined{sseq@genmax}{\let\sseq@genmax\sseq@gen}{
- \edef\sseq@genmax{\the\numexpr\sseq@obj{class.\coord.num}+\sseq@genmax+1}
+ \edef\sseq@genmax{\the\numexpr\sseq@classnum+\sseq@genmax+1}
}
}
}{
@@ -482,7 +606,7 @@
\sseq@class@getgen{\sseq@class@page}
\@ifundefined{sseq@class@pagemax}{
% If no max is present, apply options to all pages starting at specified minimum
- \edef\sseq@genmax{\sseq@obj{class.\coord.num}}%
+ \let\sseq@genmax\sseq@classnum%
\let\sseq@class@pagemax\sseq@infinity % ensure if "page" is defined, "pagemax" is defined too
}{
\let\sseq@genmin\sseq@gen
@@ -494,7 +618,7 @@
\edef\sseq@class@pagemax{\the\numexpr\sseq@class@pagemax+\@ne}
}
\ifnum\sseq@gen=\m@ne
- \edef\sseq@gen{\sseq@obj{class.\coord.num}}
+ \let\sseq@gen\sseq@classnum
\fi
\edef\classname{class.\coord[\sseq@gen]}
\ifsseq@keepchanges\else
@@ -552,6 +676,10 @@
\sseq@cleanup@obj{\classname.labelnodes}
\sseq@classoptions@obj@addto@withpagerange{\classname.labelnodes}{\sseq@classlabelnodes}
\fi
+ \ifx\sseq@familylist\pgfutil@empty\else
+ \sseq@cleanup@obj{\classname.familylist}
+ \sseq@classoptions@obj@addto@withpagerange{\classname.familylist}{\sseq@familylist}
+ \fi
\@ifundefined{sseq@tempoffset}{}{
\sseq@cleanup@obj{\classname.offset}
\tikz@scan@one@point\sseq@setoffset\sseq@tempoffset
@@ -586,7 +714,7 @@
}
\def\sseq@class@getgen#1{
\bgroup
- \ifnum\sseq@obj{class.\coord.num}>\z@
+ \ifnum\sseq@classnum>\z@
\sseq@eval{\unexpanded{\sseq@obj@pagetogen{class.\coord}}{#1}} % stores in \sseq@gen
\else
\def\sseq@gen{0}
@@ -594,8 +722,9 @@
\sseq@smuggle@macro\sseq@gen
\egroup
}
-\sseq@DeclareDocumentCommand\replaceclass{or()}{%
+\sseq@DeclareDocumentCommand\replaceclass{od()}{%
\begingroup
+ \sseq@loadinputline
\sseq@xsetthiscall{\string\replaceclass\IfNoValueF{#1}{[\unexpanded{#1}]}\unexpanded{(#2)}}
\sseq@options@firstpassmode
\the\sseq@sseqstyle
@@ -606,10 +735,15 @@
\sseq@processoptions{class}{#1}% Outputs result into \sseq@savedoptioncode
}%
%
- \sseq@parsecoord\coord{#2}{\string\replaceclass}
+ \IfNoValueTF{#2}{
+ \def\sseq@coord{\lastclass0}
+ }{
+ \def\sseq@coord{#2}
+ }
+ \sseq@parsecoord\coord{\sseq@coord}{\string\classoptions}%
\sseq@processlabels
%
- \sseq@ifundefcoord\coord{\sseq@error@x{replaceclass-no-class}{\coordname}\sseq@break}{}
+ \sseq@obj@ifundef{class.\coord.num}{\sseq@error@x{replaceclass-no-class}{\coordname}\sseq@break}{}
\sseq@ifdead\coord{}{\sseq@error@x{replaceclass-not-dead-yet}{\coordname}\sseq@break}
\ifsseq@keepchanges\else
\ifnum\the\numexpr\sseq@obj{class.\coord[\sseq@obj{class.\coord.num}].page}<\sseq@thepagecount\else
@@ -647,13 +781,20 @@
\fi
\edef\classname{class.\coord[\sseq@obj{class.\coord.num}]}
%
+ \sseq@obj@xodef{\classname.familylist}{\sseq@familylist}
\sseq@obj@xdef{\classname.page}{\sseq@infinity}
\sseq@obj@xodef{\classname.options}{\sseq@savedoptioncode}
- \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext}
- \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions}
+ \ifx\sseq@classnodetext\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.nodetext}{\sseq@classnodetext}
+ \fi
+ \ifx\sseq@classnodetextoptions\pgfutil@empty\else
+ \sseq@obj@xodef{\classname.nodetext.options}{\sseq@classnodetextoptions}
+ \fi
\sseq@obj@xodef{\classname.labelnodes}{\sseq@classlabelnodes}
\sseq@obj@gdef{\classname.dependencies}{}
- \sseq@obj@xdef{\classname.needstikz}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi}
+ \ifsseq@needstikz
+ \sseq@obj@xdef{\classname.needstikz}{\sseq@needstikztrue}
+ \fi
\@ifundefined{sseq@tempoffset}{}{\tikz@scan@one@point\sseq@setoffset\sseq@tempoffset}
%
\sseq@breakpoint
@@ -666,8 +807,12 @@
\ifnum\sseq@obj{#1[\sseq@gen].page}=\sseq@thepagecount
\sseq@thispagetrue
\fi
- \sseq@gsetthiscall{class #1}
- \sseq@class@drawnode{#1[\sseq@gen]}
+ \sseq@drawtrue
+ \sseq@obj{#1[\sseq@gen].familylist}
+ \ifsseq@draw
+ \sseq@gsetthiscall{class #1}
+ \sseq@class@drawnode{#1[\sseq@gen]}
+ \fi
\fi
\egroup
}
@@ -690,25 +835,76 @@
\egroup
}
%%%
-%%% \d and \doptions
+%%% \kill, \d and \doptions
%%%
-\sseq@DeclareDocumentCommand\d{oU(r()d()}{%
- \sseq@d@{d}{#1}{#2}{#3}{#4}%
-}
-\sseq@DeclareDocumentCommand\doptions{oU(r()d()}{%
+% Because \kill doesn't take options, there's no need to use \sseq@DeclareDocumentCommand for the outer command.
+% Rather than use \sseq@DeclareDocumentCommand with no arguments, we just do the normal stuff that \sseq@DeclareDocumentCommand would do,
+% Then call \sseq@d@grabpage, the command that is responsible for handling the strange syntax of the page argument for \d.
+\protected\def\sseq@kill{%
\begingroup
- \IfNoValueT{#1}{
- \sseq@xsetthiscall{\@xp\string\csname#1\endcsname\unexpanded{#2(#3)}\IfNoValueF{#4}{\unexpanded{(#4)}}}%
- \sseq@error@x{cmdoptions-without-options}{\string\doptions}\sseq@break % could be warning
- }
- \sseq@d@{doptions}{#1}{#2}{#3}{#4}%
+ \sseq@setinputline % These two lines normally would happen inside of \sseq@DeclareDocumentCommand.
+ \sseq@loadinputline
+ \sseq@d@grabpage\sseq@kill@
+}
+
+% Now we need to parse a potential coordinate.
+\sseq@DeclareDocumentCommandAs\sseq@kill@\kill {d()} {
+ \sseq@xsetthiscall{\string\kill\unexpanded\@xp{\sseq@dpage}\IfNoValueF{#1}{(#1)}}%
+ \sseq@parsecoord\coordinate{\IfNoValueTF{#1}{\lastclass}{#1}}{}%
+ \sseq@ifintexpr{\sseq@dpage}{%
+ \sseq@tempcount=\numexpr\sseq@dpage\relax % this is a convenient way to get rid of spaces because #3 has to be a number
+ }{%
+ \sseq@error@x{d-invalid-page}{\unexpanded\@xp{\sseq@dpage}}\sseq@break%
+ }%
+ \sseq@d@setpageminrec{class.\coordinate}{\the\sseq@tempcount}{coordinate}% automatically handles \sseq@cleanup@obj
\sseq@breakpoint
\endgroup
}
-\def\sseq@d@#1#2#3#4#5{%
+
+% \sseq@d@grabpage is defined in sseqparsers.
+\sseq@DeclareDocumentCommand\d{o}{%
+ \begingroup
+ \sseq@loadinputline
+ \def\sseq@dtype{d}
+ \def\sseq@d@theoptions{#1}
+ \sseq@d@grabpage\sseq@d@
+}
+
+\sseq@DeclareDocumentCommand\doptions{o}{%
\begingroup
+ \sseq@loadinputline
+ \def\sseq@dtype{doptions}
+ \def\sseq@d@theoptions{#1}
+ \sseq@d@grabpage\sseq@d@
+}
+
+\def\sseq@d@{
+ \ifsseq@tempif
+ \csname sseq@\sseq@dtype @grabcoord\@xp\endcsname
+ \else
+ \sseq@eval{\@nx\sseq@d@main{\sseq@dtype}{\unexpanded\@xp{\sseq@d@theoptions}}{\sseq@dpage}{\sseq@NoValue}{\sseq@NoValue}}
+ \sseq@breakpoint
+ \endgroup
+ \fi
+}
+
+\sseq@DeclareDocumentCommandAs\sseq@d@grabcoord\d{d()d()}{
+ \sseq@eval{\@nx\sseq@d@main{\sseq@dtype}{\unexpanded\@xp{\sseq@d@theoptions}}{\sseq@dpage}}{#1}{#2}
+ \sseq@breakpoint
+ \endgroup
+}
+
+\sseq@DeclareDocumentCommandAs\sseq@doptions@grabcoord\doptions{d()d()}{
+ \sseq@eval{\@nx\sseq@d@main{\sseq@dtype}{\unexpanded\@xp{\sseq@d@theoptions}}{\sseq@dpage}}{#1}{#2}
+ \sseq@breakpoint
+ \endgroup
+}
+
+
+\def\sseq@d@main#1#2#3#4#5{%
\sseq@options@firstpassmode
+ \def\sseq@edgetype{differential}
\the\sseq@sseqstyle
\the\sseq@edgestyle
\the\sseq@differentialstyle
@@ -717,16 +913,15 @@
\IfNoValueF{#2}{
\sseq@processoptions{differential}{#2}% Outputs result into \sseq@savedoptioncode
}
- \sseq@xsetthiscall{\@xp\string\csname#1\endcsname\IfNoValueF{#2}{\unexpanded{[#2]}}\unexpanded{#3(#4)}\IfNoValueF{#5}{\unexpanded{(#5)}}}%
+ \sseq@xsetthiscall{\@xp\string\csname#1\endcsname\IfNoValueF{#2}{\unexpanded{[#2]}}\unexpanded{#3}\IfNoValueF{#4}{\unexpanded{(#4)}}\IfNoValueF{#5}{\unexpanded{(#5)}}}%
\sseq@ifintexpr{#3}{%
\sseq@tempcount=\numexpr#3\relax % this is a convenient way to get rid of spaces because #3 has to be a number
}{%
\sseq@error@n{d-invalid-page}{#3}\sseq@break%
}%
- \@xp\sseq@dparsecoord\@xp{\the\sseq@tempcount}{#4}{#5}%
+ \sseq@eval{\@nx\sseq@dparsecoord{\the\sseq@tempcount}{\IfNoValueTF{#4}{\lastclass0}{\unexpanded{#4}}}{\unexpanded{#5}}}
\sseq@eval{\unexpanded{\csname sseq@d@#1\endcsname{#2}}{\the\sseq@tempcount}}%
\sseq@breakpoint
- \endgroup
}
% #1 -- options
@@ -736,9 +931,9 @@
\sseq@d@setpageminrec{class.\source}{#2}{source}% automatically handles \sseq@cleanup@obj
\sseq@d@setpageminrec{class.\target}{#2}{target}
%
- \ifsseq@drawdifferential
+ \ifsseq@drawdifferential % TODO: probably should get rid of invisible now that we have \kill...
+ \sseq@obj@xodef{d.#2\source\target.familylist}{\sseq@familylist}
\sseq@obj@gdef{d.#2\source\target.page}{#2}
- \sseq@obj@gdef{d.#2\source\target.style}{}%
\sseq@obj@xdef{d.#2\source\target.source}{\source}
\sseq@obj@xdef{d.#2\source\target.target}{\target}
\sseq@obj@xdef{d.#2\source\target.options}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi\unexpanded\@xp{\sseq@savedoptioncode}}
@@ -759,6 +954,8 @@
}%
\fi
%
+ \sseq@cleanup@obj{d.#2\source\target.familylist}
+ \sseq@obj@xoaddto{d.#2\source\target.familylist}{\sseq@familylist}
\sseq@cleanup@obj{d.#2\source\target.options}
\sseq@obj@xoaddto{d.#2\source\target.options}{\sseq@savedoptioncode}
}
@@ -823,9 +1020,9 @@
\let\sseq@possibleperiod\empty
\let\sseq@possibleperiodb\empty
\sseq@obj@xdef{\sseq@classgenname.deathlocation}{%
- on input line \the\inputlineno\sseq@error@inforeachloop
+ on input line \sseq@inputline\sseq@error@inforeachloop
}
- \sseq@obj@xdef{\sseq@classgenname.deathline}{\the\inputlineno}
+ \sseq@obj@xdef{\sseq@classgenname.deathline}{\sseq@inputline}
\sseq@tempiffalse
\edef\sseq@temp{\the\sseq@foreachcall}
\ifx\sseq@temp\pgfutil@empty\else\sseq@tempiftrue\fi
@@ -843,7 +1040,7 @@
\def\sseq@preparestacktrace{
\def\foreach{\@nx\foreach}
\edef\sseq@temp@i{\unexpanded\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathline}}}
- \edef\sseq@temp@ii{\the\inputlineno}
+ \edef\sseq@temp@ii{\sseq@inputline}
\ifx\sseq@temp@i\sseq@temp@ii
\sseq@temptoks\@xpthree{\sseq@obj{\sseq@deadclass@genname.deathinfo} (in the same \foreach loop)}
\else
@@ -860,11 +1057,17 @@
\fi
}
\def\sseq@differential@draw@ifpage#1{
- \ifnum\sseq@thepagecount=\z@
- \sseq@drawdifferential{#1}
- \else
- \ifnum\sseq@obj{#1.page}=\sseq@thepagecount\relax
+ \sseq@drawtrue
+ \sseq@obj{#1.familylist}
+ \ifsseq@draw
+ \ifnum\sseq@thepagecount=\z@
\sseq@drawdifferential{#1}
+ \else
+ \ifnum\sseq@obj{#1.page}>\sseq@thepagemm\relax
+ \ifnum\sseq@obj{#1.page}<\sseq@thepagemaxpp\relax
+ \sseq@drawdifferential{#1}
+ \fi
+ \fi
\fi
\fi
}
@@ -880,19 +1083,39 @@
%%%
%%% \structline and \structlineoptions
%%%
-\sseq@DeclareDocumentCommand\structline{or()r()}{%
+
+\sseq@DeclareDocumentCommand\structline{od()}{%
\begingroup
- \sseq@xsetthiscall{\string\structline\IfNoValueF{#1}{\unexpanded{[#1]}}\unexpanded{(#2)(#3)}}%
- \sseq@structline@main{structline}{#1}{#2}{#3}%
+ \sseq@loadinputline
+ \IfNoValueTF{#2}{
+ \sseq@structline@main{structline}{#1}{#2}{#2}
+ }{
+ \def\next{\sseq@structline@@{structline}{#1}{#2}}%
+ \@xptwo\next\sseq@trimleadingspaces
+ }
}
-\sseq@DeclareDocumentCommand\structlineoptions{or()r()}{%
+\sseq@DeclareDocumentCommand\structlineoptions{od()}{%
\begingroup
- \sseq@xsetthiscall{\string\structlineoptions\IfNoValueF{#1}{\unexpanded{[#1]}}\unexpanded{(#2)(#3)}}%
- \IfNoValueT{#1}{\sseq@error@x{cmdoptions-without-options}{\string\structlineoptions}\sseq@break@withcleanup}
- \sseq@structline@main{structlineoptions}{#1}{#2}{#3}%
- \sseq@breakpoint\@gobble\endgroup
+ \sseq@loadinputline
+ \IfNoValueTF{#2}{
+ \sseq@structline@main{structlineoptions}{#1}{#2}{#2}
+ }{
+ \def\next{\sseq@structlineoptions@@{structlineoptions}{#1}{#2}}%
+ \@xptwo\next\sseq@trimleadingspaces
+ }
+}
+
+\sseq@DeclareDocumentCommandAs\sseq@structline@@\structline{mmmd()}{%
+ \sseq@structline@main{#1}{#2}{#3}{#4}
}
-\def\sseq@structline@main#1#2#3#4{%
+
+\sseq@DeclareDocumentCommandAs\sseq@structlineoptions@@\structlineoptions{mmmd()}{%
+ \sseq@structline@main{#1}{#2}{#3}{#4}
+}
+
+\def\sseq@structline@main#1#2#3#4{
+ \sseq@xsetthiscall{\string\structline\IfNoValueF{#2}{\unexpanded{[#2]}}\IfNoValueF{#3}{\unexpanded{(#3)}\IfNoValueF{#4}{\unexpanded{(#4)}}}}%
+ \def\sseq@edgetype{structline}
\sseq@options@firstpassmode
\the\sseq@sseqstyle
\the\sseq@edgestyle
@@ -902,8 +1125,38 @@
\IfNoValueF{#2}{%
\sseq@processoptions{struct line}{#2}% Outputs result into \sseq@savedoptioncode
}%
- \sseq@parsecoord\source{#3}{source of structure line}%
- \sseq@parsecoord\target{#4}{target of structure line}%
+ \def\sourcename{#3}%
+ \def\targetname{#4}%
+ \IfNoValueTF{#3}{%
+ \def\sourcename{\lastclass1}%
+ \def\targetname{\lastclass}%
+ }{%
+ \IfNoValueT{#4}{%
+ \def\targetname{\lastclass}%
+ }%
+ }%
+ \sseq@parsecoord\source{\sourcename}{source of structure line}%
+ \sseq@parsecoord\target{\targetname}{target of structure line}%
+ \ifnum\xsource>\xtarget\relax
+ \sseq@parsedcoords@swap\source\target
+ \else
+ \ifnum\xsource=\xtarget\relax
+ \ifnum\ysource>\ytarget\relax
+ \sseq@parsedcoords@swap\source\target
+ \else
+ \ifnum\ysource=\ytarget\relax
+ \ifnum\nsource>\ntarget\relax
+ \sseq@parsedcoords@swap\source\target
+ \else
+ \ifnum\nsource=\ntarget\relax
+ \sseq@error{structline-source-target-equal}%
+ \@xp\sseq@break\romannumeral-`0
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
\@ifundefined{sseq@structline@page}{%this is repeated in circleclasses
\def\sseq@pagemin{0}
\ifnum\sseq@obj{class.\source.num}>\z@
@@ -938,17 +1191,22 @@
\sseq@cleanup@obj{structline.\source\target.num}
\sseq@obj@inc{structline.\source\target.num}
}{
+ \sseq@cleanup@obj{structline.\source\target.num}
\sseq@obj@gdef{structline.\source\target.num}{0}
\sseq@savedpaths@addstructline{structline.\source\target}
}
\edef\sseq@structlinename{structline.\source\target[\sseq@obj{structline.\source\target.num}]}
+ % The following cleanup call is needed to prevent a glitch where if a \structline is made inside of a temporary sseqpage environment, then later attempts
+ % to put a structline throw a "structline already exists" error
+ \sseq@cleanup@obj{\sseq@structlinename.page}
\sseq@obj@xdef{\sseq@structlinename.page}{\sseq@infinity}
\sseq@obj@xdef{\sseq@structlinename.pagemin}{\sseq@pagemin}
\sseq@obj@xdef{\sseq@structlinename.source}{\source}
\sseq@obj@xdef{\sseq@structlinename.target}{\target}
- \sseq@cleanup@obj{structline.\source\target.num}
\sseq@class@adddependence{class.\source}{\sseq@structlinename}% If the source or target is already dead, this will set structlinename.page
\sseq@class@adddependence{class.\target}{\sseq@structlinename}
+ \sseq@obj@xodef{\sseq@structlinename.familylist}{\sseq@familylist}
+ \sseq@cleanup@obj{\sseq@structlinename.options}
\sseq@obj@xdef{\sseq@structlinename.options}{\ifsseq@needstikz\@nx\sseq@needstikztrue\fi\unexpanded\@xp{\sseq@savedoptioncode}}
}
\def\sseq@structline@structlineoptions{
@@ -980,20 +1238,24 @@
\advance\sseq@tempcount\@ne
\edef\sseq@structlinename{structline.\source\target[\the\sseq@tempcount]}
\sseq@cleanup@obj{\sseq@structlinename.options}
+ \sseq@cleanup@obj{\sseq@structlinename.familylist}
\ifsseq@needstikz
\sseq@obj@gaddto{\sseq@structlinename.options}{\sseq@needstikztrue}
\fi
\ifnum\sseq@tempcount=\sseq@gen\relax
\@ifundefined{sseq@structline@page}{}{
\edef\sseq@savedoptioncode{\@nx\ifnum\sseq@thepagecount>\sseq@structline@page\relax\unexpanded\@xp{\sseq@savedoptioncode}\@nx\fi}
+ \edef\sseq@familylist{\@nx\ifnum\sseq@thepagecount>\sseq@structline@page\relax\unexpanded\@xp{\sseq@familylist}\@nx\fi}
}
\fi
\ifnum\sseq@tempcount=\sseq@genmax\relax
\@ifundefined{sseq@structline@pagemax}{}{
\edef\sseq@savedoptioncode{\@nx\ifnum\sseq@thepagecount<\sseq@structline@pagemax\relax\unexpanded\@xp{\sseq@savedoptioncode}\@nx\fi}
+ \edef\sseq@familylist{\@nx\ifnum\sseq@thepagecount<\sseq@structline@pagemax\relax\unexpanded\@xp{\sseq@familylist}\@nx\fi}
}
\fi
\sseq@obj@xoaddto{\sseq@structlinename.options}{\sseq@savedoptioncode}
+ \sseq@obj@xoaddto{\sseq@structlinename.familylist}{\sseq@familylist}
\ifnum\sseq@tempcount<\sseq@genmax\repeat
}
\def\sseq@structline@getgen#1{
@@ -1032,7 +1294,11 @@
\bgroup
\ifnum\sseq@thepagecount=\z@
\ifnum\sseq@obj{#1[0].pagemin}=\z@
- \sseq@structline@draw{#1[0]}
+ \sseq@drawtrue
+ \sseq@obj{#1[0].familylist}
+ \ifsseq@draw
+ \sseq@structline@draw{#1[0]}
+ \fi
\fi
\else
\sseq@obj@pagetogen{#1}{\sseq@thepage} % sets \sseq@gen
@@ -1041,7 +1307,11 @@
\sseq@thispagetrue
\fi
\ifnum\sseq@obj{#1[\sseq@gen].pagemin}<\sseq@thepagecount
- \sseq@structline@draw{#1[\sseq@gen]}
+ \sseq@drawtrue
+ \sseq@obj{#1[\sseq@gen].familylist}
+ \ifsseq@draw
+ \sseq@structline@draw{#1[\sseq@gen]}
+ \fi
\fi
\fi
\fi
@@ -1052,11 +1322,10 @@
-
-
\newcount\sseq@circleclassuid
\sseq@DeclareDocumentCommand\circleclasses{or()r()}{
\begingroup
+ \sseq@loadinputline
\def\sseq@keysfortikzprim{}
\IfNoValueF{#1}{
\sseq@processoptions{fit}{#1}
@@ -1089,6 +1358,7 @@
%
%
\sseq@obj@xodef{\circleclassobjname.options}{\sseq@savedoptioncode}
+ \sseq@obj@xodef{\circleclassobjname.familylist}{\sseq@familylist}
\sseq@obj@xodef{\circleclassobjname.tikzprimoptions}{\sseq@keysfortikzprim}
\sseq@obj@xdef{\circleclassobjname.fitnodes}{\@nx\tikz@lib@fit{(sseq{\coordanopar})(sseq{\coordbnopar})\sseq@fitalso}}
%\edef\temp{\@nx\sseq@circleclass@draw{\coorda@internalname}{\coordb@internalname}{\unexpanded\@xp{\sseq@savedoptioncode}}}
@@ -1112,12 +1382,115 @@
\fi
\def\sseq@circleclass@draw@ifpage#1#2#3{
- \ifnum\sseq@thepagecount<\numexpr\sseq@obj{#1.page}+\@ne
- \ifnum\sseq@obj{#1.page}=\sseq@thepagecount
- \sseq@thispagetrue
- \fi
- \ifnum\sseq@obj{#1.pagemin}<\sseq@thepagecount
- \sseq@circleclass@draw{#1}{#2}{#3}
+ \sseq@drawtrue
+ \sseq@obj{#1.familylist}
+ \ifsseq@draw
+ \ifnum\sseq@thepagecount<\numexpr\sseq@obj{#1.page}+\@ne
+ \ifnum\sseq@obj{#1.page}=\sseq@thepagecount
+ \sseq@thispagetrue
+ \fi
+ \ifnum\sseq@obj{#1.pagemin}<\sseq@thepagecount
+ \sseq@circleclass@draw{#1}{#2}{#3}
+ \fi
\fi
\fi
-} \ No newline at end of file
+}
+
+%%
+%% Labels
+%%
+%% This code is called from the key value handler, but it has more to do with the code in this file so I am putting it here. Search in sseqkeys.code.tex for "Labels"
+%%
+
+\def\sseq@processlabels@default{%
+ \global\let\sseq@classnodetext\pgfutil@empty
+ \global\let\sseq@classnodetextoptions\pgfutil@empty
+ \global\let\sseq@classlabelnodes\pgfutil@empty
+}
+\let\sseq@processlabels\sseq@processlabels@default
+
+% I can't remember why we need to defer this. If at some point I figure this out, I should explain why here and in the definition of \class...
+\def\sseq@handleclassquotes@inner#1#2{%
+ \begingroup\pgfscope
+ \def\sseq@classquotes@smugglehook{}
+ \def\sseq@classquotes@smugglehook@inner{}
+ \sseq@options@firstpassmode
+ \sseq@thesseqstyle
+ \sseq@thelabelstyle
+ \sseq@theclasslabelstyle
+ \the\sseq@scope@toks
+ \sseq@options@normalmode
+ \sseq@processoptions{class/label}{#2}%
+ \sseq@classlabeltextfn{#1}% labeltextfn is a private handler, classlabeltextfn is exposed via "class label handler"
+ \ifsseq@classlabel
+ \sseq@options@firstpassmode
+ \the\sseq@outerclasslabelstyle
+ \sseq@x@addto@macro\sseq@classlabelnodes{%
+ \@nx\sseq@drawlabel{%
+ \sseq@maybemathswitch\unexpanded\@xp{\processedlabel}\sseq@maybemathswitch}%
+ {% This is setup to prevent a bug where \classoptions and class label style don't work correctly together
+ \the\sseq@sseqstyle\@nx\the\sseq@sseqstyle@page
+ \the\sseq@labelstyle\@nx\the\sseq@labelstyle@page
+ \the\sseq@classlabelstyle\@nx\the\sseq@classlabelstyle@page
+ \sseq@theouterclasslabelstyle
+ \@nx\sseq@collections@labels@hook
+ \@nx\sseq@collections@classlabels@hook
+ \@nx\sseq@collections@outerclasslabels@hook
+ \unexpanded\@xp{\sseq@savedoptioncode}%
+ }%
+ }%
+ \else
+ \let\sseq@classquotes@smugglehook\sseq@classquotes@smugglehook@inner
+ \sseq@options@firstpassmode
+ \the\sseq@innerclasslabelstyle
+ \sseq@options@normalmode
+ \sseq@protectedeval{\@nx\pgfqkeys{/sseqpages/class/label}{#2}}%
+ \sseq@protected@xdef\sseq@classnodetext{\sseq@maybemathswitch\processedlabel\sseq@maybemathswitch}%
+ \xdef\sseq@classnodetextoptions{%
+ %\unexpanded{\def\pgfkeysdefaultpath{/sseqpages/class/node texts/}}%
+ \sseq@thelabelstyle\sseq@theclasslabelstyle\sseq@theinnerclasslabelstyle
+ \@nx\sseq@collections@labels@hook
+ \@nx\sseq@collections@classlabels@hook
+ \@nx\sseq@collections@innerclasslabels@hook
+ \unexpanded\@xp{\sseq@savedoptioncode}%
+ }%
+ \fi
+ \@xp\endpgfscope\@xp\endgroup
+ \sseq@classquotes@smugglehook
+}
+
+\def\sseq@handleedgequotes#1#2{% We use this via \let\tikz@quotes@as\sseq@handleedgequotes
+ /utils/exec={% so it's called inside \pgfkeysalso{stuff}. Need to surround with /utils/exec={} to get out.
+ \let\sseq@savedoptioncode@save\sseq@savedoptioncode
+ \sseq@processoptions{label}{#2}
+ \sseq@needstikztrue
+ \let\sseq@temp\sseq@savedoptioncode
+ \let\sseq@savedoptioncode\sseq@savedoptioncode@save
+ \sseq@e@addto@options{
+ \@nx\tikzset{
+ every to/.append style={
+ edge node={
+ node [/sseqpages/label,
+ /utils/exec={
+ \let\@nx\sseq@tikz@transform@save\@nx\tikz@transform
+ \let\@nx\tikz@transform\relax
+ \@nx\sseq@thelabelstyle
+ \@nx\sseq@collections@labels@hook
+ \@nx\sseq@theedgelabelstyle
+ \@nx\sseq@collections@edgelabels@hook
+ \@xp\@nx\csname sseq@the\sseq@edgetype labelstyle\endcsname
+ \@xp\@nx\csname sseq@collections@\sseq@edgetype labels@hook\endcsname
+ \unexpanded\@xp{\sseq@temp}
+ \ifsseq@rotatelabels\iftikz@fullytransformed\else\@nx\tikz@fullytransformedtrue\@nx\tikz@addtransform{\@nx\pgftransformresetnontranslations\@nx\sseq@globalrotatetransform}\fi\fi
+ \unexpanded\@xp{\sseq@edgeoptionhook} % this is just to make description work
+ \let\@nx\tikz@transform\@nx\sseq@tikz@transform@save
+ }
+ ]{\sseq@labeltextfn{#1}}
+ }
+ }
+ }
+ }
+ }
+}
+
+
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex
index c8fbbb1eb75..899a425a3c4 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqmessages.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqmessages.code.tex
@@ -43,7 +43,7 @@
%%
%% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%% !
-%% ! sseqpages error: "index-too-large"
+%% ! spectralsequences error: "index-too-large"
%% !
%% ! Index '-3' provided for target of structure line is too large -- only 1
%% ! classes exist at position (32,8).
@@ -55,7 +55,7 @@
%% ! \towergroupb (8*\n ,4*\n ) % Produced by \sseq@printstacktrace
%% ! \foreach \n in {2,3,4}
%% !
-%% ! See the sseqpages documentation for further information.
+%% ! See the spectralsequences documentation for further information.
%% !
%% ! Type <return> to continue.
%% !...............................................
@@ -66,6 +66,16 @@
% Stack, thiscall, foreachcall.
% Here we record what the user has said (as best we can tell)
\newtoks\sseq@thiscalltoks
+
+% These guys are set up because I want \sseq@DeclareDocumentCommandAs@setinputline to work
+% but I want the definition of \sseq@inputline to be local, and it would be really bad to
+% open a group inside of sseq@DeclareDocumentCommandAs that has to be closed in the code.
+% So what I do is globally put it into \sseq@globalinputline using \sseq@setinputline
+% and then after starting the group at the beginning of the actual macro body,
+% call \sseq@loadinputline
+\def\sseq@setinputline{\xdef\sseq@globalinputline{\the\inputlineno}}
+\def\sseq@loadinputline{\let\sseq@inputline\sseq@globalinputline}
+
\def\sseq@thiscall{\the\sseq@thiscalltoks}
\def\sseq@setthiscall#1{\sseq@seterrorannotation{call}\sseq@thiscalltoks{#1}}
\def\sseq@esetthiscall#1{\sseq@seterrorannotation{call}\sseq@eval{\sseq@thiscalltoks{#1}}}
@@ -85,7 +95,9 @@
\ifx\sseq@temp\pgfutil@empty\else
\edef\sseq@restofstacktrace{\unexpanded{\\\ \ \ }\@nx\sseq@stack@unexpanded{\the\sseq@topofstacktrace}\unexpanded\@xp{\sseq@restofstacktrace}}
\fi
- \sseq@topofstacktrace{#1}
+ \sseq@eval{\sseq@topofstacktrace{\unexpanded{#1}\sseq@possibleoninputlinedash}}
+ \let\sseq@possibleoninputlinedash\empty
+ \let\sseq@possibleoninputlinepar\empty
}
\def\sseq@opushstacktrace#1{\@xp\sseq@pushstacktrace\@xp{#1}}
\def\sseq@stack@unexpanded#1{\@nx\sseq@stack@unexpanded\unexpanded{{#1}}}
@@ -116,11 +128,14 @@
\sseq@seterrorannotation{aftercall}
-
-\def\sseq@error@inforeachloop{\sseq@possibleperiod}
-\def\sseq@error@inforeachloop@active{\sseq@possiblecomma in \foreach block with variable values:\sseq@for@printvars\sseq@possibleperiodb}
+\def\sseq@inputline{\the\inputlineno}
+\def\sseq@error@inforeachloop{\sseq@possibleoninputlinepar\sseq@possibleperiod}
+\def\sseq@error@inforeachloop@active{\sseq@possiblecomma in loop with variable values:\sseq@for@printvars\sseq@possibleperiodb}
\def\sseq@error@setup@errorinfo{}% Changed during \foreach and user commands
+\def\sseq@possibleoninputlinepar{ (on input line \sseq@inputline)} % let this to a no-op at beginning of usermacros
+\def\sseq@possibleoninputlinedash{ -- on input line \sseq@inputline}
+
\def\sseq@possiblecomma{,\space}
\def\sseq@possibleperiod{.}
\def\sseq@possibleperiodb{.}
@@ -151,7 +166,7 @@
\sseq@error@hook
}
-\def\sseq@error@setup@noinfo {\bgroup\def\foreach{\@nx\foreach}\let\sseq@stack@unexpanded\unexpanded\def\sseq@error@annotation{}\sseq@error@hook}
+\def\sseq@error@setup@noinfo{\bgroup\def\foreach{\@nx\foreach}\let\sseq@stack@unexpanded\unexpanded\def\sseq@error@annotation{}\sseq@error@hook}
\let\sseq@error@setup\sseq@error@setup@noinfo
\def\sseq@error@cleanup{\egroup\sseq@errortrue} % If the error was thrown in NewDocumentCommand, we need to process it. Just used in sseqmacromakers.
@@ -195,10 +210,11 @@
\def\sseq@atbeginforeach@msgsetup{%
\let\protect\empty % prevent issues if protected variables like \xmax are used as the loop max
+ \let\sseq@error@setup@errorinfo\sseq@error@setup@errorinfo@active
\let\sseq@error@build@foreachvarsinfo\sseq@error@build@foreachvarsinfo@active % Install stack annotation
\let\sseq@error@inforeachloop\sseq@error@inforeachloop@active % install message indicating foreach variable values
\let\sseq@error@setup\sseq@error@setup@withinfo
- \sseq@foreachcall{\foreach} % Stack gets pushed at the beginning of the body of the foreach loop once we know what the call looks like
+ \sseq@foreachcall\@xp{\string\foreach} % Stack gets pushed at the beginning of the body of the foreach loop once we know what the call looks like
}
@@ -219,6 +235,18 @@
\fi
}
+%%
+%% \sseq@checkend
+%%
+\def\sseq@checkend#1{
+ \def\sseq@tempa{#1}
+ \ifx\sseq@tempa\@currenvir\else % mismatch
+ \sseq@error@n{endenv-mismatch}{#1}
+ \csname end\@currenvir\endcsname % run the \end code for the correct environment
+ \def\@currenvir{#1} % Prevent \@checkend from throwing a second redundant error
+ \@xp\sseq@break % don't run the code \end for this environment
+ \fi
+}
@@ -232,21 +260,21 @@
\ExplSyntaxOn
\char_set_catcode_space:N\ % Needed to make pretocmd work -- there are always spaces after every command, and they need to be retokenized as spaces
-\def\sseqerrortowarning#1{ \msg_redirect_name:nnn { sseqpages } { #1 } { warning } }
-
-\def\sseq@error {\msg_error:nn {sseqpages}}
-\def\sseq@error@n {\msg_error:nnn {sseqpages}}
-\def\sseq@error@nn {\msg_error:nnnn {sseqpages}}
-\def\sseq@error@nnn {\msg_error:nnnnn {sseqpages}}
-\def\sseq@error@nnnn{\msg_error:nnnnnn{sseqpages}}
-\def\sseq@error@x {\msg_error:nnx {sseqpages}}
-\def\sseq@error@xx {\msg_error:nnxx {sseqpages}}
-\def\sseq@error@xxx {\msg_error:nnxxx {sseqpages}}
-\def\sseq@error@xxxx{\msg_error:nnxxxx{sseqpages}}
-\def\sseq@warning {\msg_warning:nn{sseqpages}}
-
-\def\sseq@newerror#1#2{\msg_new:nnn{sseqpages}{#1}{#2}}
-\def\sseq@newerror@internal#1#2{\msg_new:nnn{sseqpages}{#1}{Internal error: #2 \sseq@contactpackageauthor}}
+\def\sseqerrortowarning#1{ \msg_redirect_name:nnn { spectralsequences } { #1 } { warning } }
+
+\def\sseq@error {\msg_error:nn {spectralsequences}}
+\def\sseq@error@n {\msg_error:nnn {spectralsequences}}
+\def\sseq@error@nn {\msg_error:nnnn {spectralsequences}}
+\def\sseq@error@nnn {\msg_error:nnnnn {spectralsequences}}
+\def\sseq@error@nnnn{\msg_error:nnnnnn{spectralsequences}}
+\def\sseq@error@x {\msg_error:nnx {spectralsequences}}
+\def\sseq@error@xx {\msg_error:nnxx {spectralsequences}}
+\def\sseq@error@xxx {\msg_error:nnxxx {spectralsequences}}
+\def\sseq@error@xxxx{\msg_error:nnxxxx{spectralsequences}}
+\def\sseq@warning {\msg_warning:nn{spectralsequences}}
+
+\def\sseq@newerror#1#2{\msg_new:nnn{spectralsequences}{#1}{#2}}
+\def\sseq@newerror@internal#1#2{\msg_new:nnn{spectralsequences}{#1}{Internal error: #2 \sseq@contactpackageauthor}}
\edef\sseq@contactpackageauthor{Contact package author \sseq@authorname\space at \sseq@authoremail.}
@@ -269,7 +297,7 @@
\sseq@newerror@internal{msg-patch-failed}{Failed to patch the latex 3 message system. The errors will not be as expressive.}
\def\sseq@msgpatchfailed{
- \msg_error:nn{sseqpages}{msg-patch-failed}
+ \msg_error:nn{spectralsequences}{msg-patch-failed}
\def\sseq@installmsghooks{}
\sseq@break
}
@@ -307,20 +335,20 @@
%%
%%
\@ifpackagelater{tikz}{2015/07/08}{
- \sseq@newerror@internal{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with core features.}
- \sseq@newerror@internal{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with \string\circleclasses.}
- \sseq@newerror@internal{foreach-patch-failed}{Failed to patch \string\foreach. The errors sseqpages provides will be less comprehensive. Your copy of tikz is newer than the version sseqpages was designed for and seems to be incompatible with parts of the error handling system.}
+ \sseq@newerror@internal{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is newer than the version spectralsequences was designed for and seems to be incompatible with core features.}
+ \sseq@newerror@internal{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is newer than the version spectralsequences was designed for and seems to be incompatible with \string\circleclasses.}
+ \sseq@newerror@internal{foreach-patch-failed}{Failed to patch \string\foreach. The errors spectralsequences provides will be less comprehensive. Your copy of tikz is newer than the version spectralsequences was designed for and seems to be incompatible with parts of the error handling system.}
\sseq@newerror@internal{circleclasses-not-provided}{\@nx\circleclasses won't work because your copy of tikz is too new. Instead I'm doing nothing.}
}{
- \sseq@newerror{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with core features. Update tikz!}
- \sseq@newerror{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with \string\circleclasses. Update tikz!}
- \sseq@newerror{foreach-patch-failed}{Failed to patch \string\foreach. The errors sseqpages provides will be less comprehensive. Your copy of tikz is older than the version sseqpages was designed for and seems to be incompatible with parts of the error handling system.}
+ \sseq@newerror{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is older than the version spectralsequences was designed for and seems to be incompatible with core features. Update tikz!}
+ \sseq@newerror{fit-patch-failed}{Failed to patch fit. \@nx\circleclasses won't work. Your copy of tikz is older than the version spectralsequences was designed for and seems to be incompatible with \string\circleclasses. Update tikz!}
+ \sseq@newerror{foreach-patch-failed}{Failed to patch \string\foreach. The errors spectralsequences provides will be less comprehensive. Your copy of tikz is older than the version spectralsequences was designed for and seems to be incompatible with parts of the error handling system.}
\sseq@newerror{circleclasses-not-provided}{\@nx\circleclasses won't work because your copy of tikz is too old. Instead I'm doing nothing. Update tikz!}
}
\def\sseq@pgfkeyspatchfailed {
- \msg_critical:nn { sseqpages } { pgfkeys-patch-failed }
+ \msg_critical:nn { spectralsequences } { pgfkeys-patch-failed }
}
@@ -332,10 +360,20 @@
%%
%%
+%% loadstore
+%%
+%%
+\sseq@newerror@internal{illegal-add-background-mode}{\string#1 occurred in background mode.}
+
+
+
+%%
+%%
%% macromakers
%%
%%
-\sseq@newerror{won't-override-builtin}{Macro '#1' is a sseqpages builtin and I won't override it. Try a different name.}
+\sseq@newerror@internal{U-xparse-incompatible}{The 'U' argument type is incompatible with the current version of xparse.}
+\sseq@newerror{won't-override-builtin}{Macro '#1' is a spectralsequences builtin and I won't override it. Try a different name.}
\sseq@newerror{usermacro-not-free}{Macro '#1' has already been defined using \string\DeclareSseqCommand, \string\NewSseqCommand, \string\DeclareSseqGroup, or \string\NewSseqGroup. I am overriding it. If this is what you intended, you should either use \@nx\DeclareSseqGroup or \string\DeclareSseqCommand, which won't complain.}
\sseq@newerror{macro-patch-failed}{Failed to patch macro '#1'. This is probably some annoying catcode issue. Try \@nx\tracingpatches to see more information about why the patch failed.}
@@ -357,10 +395,10 @@
If you need to have this many classes in this position, you can make your own class pattern with \string\sseqnewclasspattern, but you might want to consider alternatives like using one class to represent multiple generators in some way -- it is hard to make a diagram look good with large numbers of classes in one position.%
}
-\sseq@newerror{invalid-coordinate}{Invalid #1coordinate\sseq@printerrortype.}
-\sseq@newerror{no-classes}{No classes yet exist in #1.}
-\sseq@newerror{index-too-large}{Index '#1' provided\sseq@printerrortype\ is too large -- only #2 classes exist at position #3.}
-\sseq@newerror{undefined-tag}{Index '#1' provided\sseq@printerrortype\ is not a valid integer expression or known tag in position #2.}
+\sseq@newerror{invalid-coordinate}{Invalid #1coordinate\sseq@printforerrortype.}
+\sseq@newerror{no-classes}{No classes yet exist in #1\sseq@printerrortype{, the }.}
+\sseq@newerror{index-too-large}{Index '#1' provided\sseq@printforerrortype\ is too large -- only #2 classes exist at position #3.}
+\sseq@newerror{undefined-tag}{Index '#1' provided\sseq@printforerrortype\ is not a valid integer expression or known tag in position #2.}
\sseq@newerror{class-no-tag}{The class #1 has no tag so I cannot get it.}
\sseq@newerror{class-extra-coords}{Too many coordinates. Ignoring the extra ones.}
@@ -378,13 +416,17 @@
\sseq@newerror{anchor-ignored} {The coordinate #1 is not a class, but it has an anchor '#3'. Ignoring the anchor and treating it as the literal position #2.}
\sseq@newerror{invalid-tikz-coord}{The coordinate #1 does not refer to a tikz class but its #2 coordinate is not valid \string\pgfmathparse\ input.}
-
%%
%%
-%% loadstore
+%% foreach
%%
%%
-\sseq@newerror{illegal-add-background-mode}{\string#1 occurred in background mode.} % Should be impossible to trigger
+\sseq@newerror{DoUntil-no-bound}{You used #1 but specified neither an x range nor a y range.}
+\sseq@newerror{DoUntil-no-progress}{You used #1 but the loop body you provided seems to be making no progress towards the boundary.}
+\sseq@newerror{Do-invalid-int-expr}{Argument "#2" to #1 is not a valid integer expression.}
+
+
+
%%
%%
@@ -416,12 +458,20 @@
You can only use '#1' as an option for tikz primitives, not for \@nx\class, \@nx\replaceclass, \@nx\classoptions, \@nx\d, \@nx\doptions, \@nx\structline, or \@nx\structlineoptions.%
}
+\sseq@newerror{invalid-intexpr}{The value '#2' provided for key '#1' is not a valid integer expression.}
+\sseq@newerror{invalid-positive-intexpr}{The value '#2' provided for key '#1' does not evaluate to a positive integer.}
+\sseq@newerror{invalid-dimenexpr}{The value '#2' provided for key '#1' is not a valid dimension expression.}
+\sseq@newerror{invalid-color}{The value '#2' provided for key '#1' is not a valid color or color expression.}
+\sseq@newerror{invalid-axis-type}{The value '#1' provided for '\sseq@axistypekey{#2}' is not valid. Valid values for '\sseq@axistypekey{#2}' are: \sseq@validaxestypes}
+
\sseq@newerror{det-one-after-scale}{You cannot use the option '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi' as a global option after using 'xscale', 'yscale', or 'scale'. Please move '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi' before any scaling options.}
+\sseq@newerror{invalid-scale}{You said '#1scale=#2' as a global option, but '#2' is not a valid pgf math expression.}
+\sseq@newerror{unit-scale}{You said '#1scale=#2' as a global option, but '#2' is not a scalar.}
\sseq@newerror{negative-scale}{You said '#1scale=#2' as a global option, but scaling by negative numbers is not allowed as a global option. Instead, please use the option '#1mirror', and then scale by the absolute value.}
\sseq@newerror{illegal-transform}{%
You said '#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi', but
- no coordinate transforms are allowed in the body of sseqpages or sseqdata other than shifts by unit-free integers
+ no coordinate transforms are allowed in the body of sseqpage or sseqdata other than shifts by unit-free integers
except as options for tikz primitives or for scopes that only contain tikz primitives. If you need a coordinate transformation,
first use the option 'standard parse'.%
}
@@ -451,6 +501,7 @@
%%
%%
+\sseq@newerror{endenv-mismatch}{\string\begin {\@currenvir }\@currenvline \space ended by \string\end {#1}. I'm going to run the code for \string\end{\@currenvir} instead.}
\sseq@newerror{env-inside-tikz}{#1 environment started inside tikz.}
\sseq@newerror{env-inside-sseq}{#1 environment started inside other sseq environment.}
\sseq@newerror{env-data-no-name}{Every 'sseqdata' environment must have a name. Specify one by saying 'name=your sseq name'.}
@@ -462,7 +513,10 @@
\sseq@newerror{no-range}{Empty spectral sequence. For every spectral sequence you must either specify both the "x range" and "y range" or include at least one
\string\class.} % maybe warning?
-\sseq@newerror{index-larger-than-stack}{Index #1 is larger than the current stack depth #2.}
+\sseq@newerror{range-overflow}{The #1 range #2 is too large. The maximum #1 range to fit on the page with the current #1scale and plot options is #1max - #1min = #3. The maximum #1scale possible with the current #1range is #4. Either change the scale or the range as appropriate.}
+\sseq@newerror{range-super-overflow}{The #1 range #2 is too large. The maximum range possible is #1max - #1min = 16383 because of internal limitations of etex. }
+
+\sseq@newerror{index-out-of-bounds}{Index #1 is greater than or equal to the current stack depth #2. Valid indices must be strictly less than the stack depth.}
\sseq@newerror{incomplete-tikz}{Incomplete tikz expression. What I have so far is #1 and I am stopping because I ran into #2. You probably forgot a semicolon.}
@@ -477,7 +531,6 @@
\sseq@newerror{doptions-invisible}{Cannot add options to invisible differential.}
\sseq@newerror{doptions-no-effect-on-this-page}{Adding an option to a differential on page #1 when the current page is \sseq@thepage\ and the 'keep changes' option is not present has no effect.}
-
\sseq@newerror{class-tag-already-defined}{A class with tag '#1' is already defined in position #2. Overwriting it.} % warning
\sseq@newerror{replaceclass-not-dead-yet}{I cannot replace the class at #1 because it seems to be alive and well.}
@@ -503,6 +556,7 @@
\sseq@newerror{structline-no-page-max}{You cannot provide \@nx\structline with the option "page=min--max", only with "page=min".} %warning
\sseq@newerror{structline-already-exists}{Cannot add a structline from #1 to #2 because such a structline already exists.}
\sseq@newerror{structline-stillborn}{Structline dies before it is born. Perhaps you meant to specify a different source or target?}
+\sseq@newerror{structline-source-target-equal}{The source and target of a \@nx\structline cannot be equal.}
\ExplSyntaxOff
diff --git a/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex b/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex
index cbce7c25492..f1804243fe5 100644
--- a/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex
+++ b/Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex
@@ -1,8 +1,8 @@
%%
-%% Package: spectralsequences.sty version 1.0
+%% Package: spectralsequences v1.1.0
%% Author: Hood Chatham
%% Email: hood@mit.edu
-%% Date: 2017-06-18
+%% Date: 2017-08-02
%% License: Latex Project Public License
%%
%% File: sseqparsers.code.tex
@@ -11,11 +11,32 @@
%% ExplSyntaxOn for this whole file!
\ExplSyntaxOn
+\let\sseq@NoValue\c__xparse_no_value_tl
+\protected\def\sseqparseint#1#2{
+ \sseq@ifintexpr{#2+0}{ % +0 here to prevent \lastx from freaking out if it's at the end of #2.
+ \edef#1{\the\numexpr#2\relax}
+ }{
+ \sseq@error{invalid-int-expr}
+ }
+}
+
+% WARNING: doesn't work =(
+\def\sseq@ifint#1{
+ \ifcat$\romannumeral0#1$
+ \prg_return_true:
+ \else
+ \ifcat$\romannumeral-0#1$
+ \prg_return_true:
+ \else
+ \prg_return_false:
+ \fi
+ \fi
+}
% Prevent \protect from causing trouble for \pgfmathparse
\let\sseq@pgfmathparse@orig\pgfmathparse
-\def\sseq@pgfmathparse#1{\let\@@protect\protect\def\protect{}\sseq@pgfmathparse@orig{#1}\restore@protect}
+\protected\def\sseq@pgfmathparse#1{\let\@@protect\protect\def\protect{}\sseq@pgfmathparse@orig{#1}\restore@protect}
%%% ifpgfmathexpr
@@ -24,17 +45,20 @@
% #3 -- false case
% This tests true if \pgfmathparse{#1} throws an error or not. Luckily, \pgfmathparse pipes its errors through \pgfmath@error so this is easy.
\def\sseq@ifpgfmathexpr#1{
- \bgroup
+ \begingroup
\let\protect\pgfutil@empty
\global\sseq@gtempiftrue
- \def\pgfmath@error##1##2{\global\sseq@gtempiffalse}
+ \def\pgfmath@error##1##2{\global\sseq@gtempiffalse\sseq@closegroups\sseq@break}
+ \def\sseq@groupflag{}
\pgfmathparse{#1}
+ \global\let\ifpgfmathunitsdeclared\ifpgfmathunitsdeclared
\ifpgfmathunitsdeclared
\xdef\sseq@mathresult{\pgfmathresult pt}
\else
\xdef\sseq@mathresult{\pgfmathresult}
\fi
- \egroup
+ \endgroup
+ \sseq@breakpoint
\ifsseq@gtempif
\@xp\@firstoftwo
\else
@@ -42,6 +66,8 @@
\fi
}
+\def\sseq@closegroups{\ifx\sseq@groupflag\empty\endgroup\@xp\sseq@closegroups\fi}
+
% Test if single token input is a digit
\def\sseq@ifdigit#1{
@@ -75,21 +101,13 @@
% so we make spaces into catcode other and use \scantokens
\def\sseq@ifintexpr#1{%
\bgroup
- \char_set_catcode_other:N \ %
\sseq@tempcount\z@
- \makeatletter
- \scantokens{\sseq@ifintexpr@first{needsint}#1\sseq@nil}%
+ \sseq@ifintexpr@{needsint}#1\sseq@nil%
\@xp\egroup\next
}
-\@xp\let\@xp\sseq@otherspace\c_catcode_other_space_tl % This has to be a let, no idea why
-%\def\sseq@ifintexpr#1{\@firstoftwo}
-
-% Gobble the space of catcode other that scantokens inserts after \sseq@ifintexpr@first
-\def\sseq@ifintexpr@first#1#2{\sseq@ifintexpr@{#2}}
% We need to use \futurelet so that we can detect open braces even when they only surround one token like {1}
-% so we have to store the state in \sseq@ifintexpr@state
-
+% also we use it to detect spaces. Store the state in \sseq@ifintexpr@state first.
\def\sseq@ifintexpr@#1{\def\sseq@ifintexpr@state{#1}\futurelet\testtok\sseq@ifintexpr@@}
\def\sseq@ifintexpr@@{%
\ifx\testtok\bgroup%
@@ -98,12 +116,10 @@
\ifx\testtok\sseq@nil
\@xp\let\@xp\next\csname sseq@ifintexpr@@\sseq@ifintexpr@state @done\endcsname
\else
- % Even though I \let \sseq@otherspace to a space of catcode other up there,
- % I still need this freaking expandafter here. God only knows why. Figured this out by trial and error.
% We need to check here for a space because \string<space> produces NO OUTPUT regardless of the catcode of the space.
- % This fucks over \sseq@ifintexpr@@@ real hard because it doesn't expect \string#1 to produce no characters.
- \@xp\ifx\sseq@otherspace\testtok
- \def\next{\sseq@ifintexpr@next{~}\@xp\next\@gobble}
+ % This messes up \sseq@ifintexpr@@@ because it doesn't expect \string#1 to produce no characters.
+ \@xp\ifx\space\testtok
+ \def\next{\sseq@ifintexpr@next{\space}\@xp\next\romannumeral-`0}
\else
\let\next\sseq@ifintexpr@@@
\fi
@@ -116,28 +132,24 @@
\ifcat$\@xp\@gobble\string#1$%
\@xp\sseq@ifintexpr@@@@\@xp#1
\else
- % scantokens puts an extra space character after control sequences, so to give them the best shot at working, eat that space character
+ % This is a macro, so fexpand it
% Then use f expansion.
- \@xp\@xp\@xp\sseq@ifintexpr@@@fexpcs\@xp\@xp\@xp#1\@xp\@gobble
+ \@xp\sseq@ifintexpr@@@fexpcs\@xp#1
\fi
}
-% Unfortunately, if we have a macro that takes an argument inside another macro that takes an argument, this will fail (the inside macro will get a space) but such is life.
\def\sseq@ifintexpr@@@fexpcs{\exp_last_unbraced:Nf\sseq@ifintexpr@@@fexpcs@}
\def\sseq@ifintexpr@@@fexpcs@{\futurelet\testtok\sseq@ifintexpr@@@fexpcs@@}
\def\sseq@ifintexpr@@@fexpcs@@{
\ifx\testtok\bgroup
- \@xp\sseq@ifintexpr@false
+ \@xp\sseq@ifintexpr@false % We already tested for groups above, so we need to check if this expanded to a group
\else
- \@xp\sseq@ifintexpr@@@@
+ \@xp\sseq@ifintexpr@@@@ % If it's still a control sequence, then this will fail in the \pgfutil@ifundefined step
\fi
}
-%\exp_last_unbraced:Nf\sseq@ifintexpr@@
-
-
% We can't just use \futurelet because "\let\testtok(" makes \testtok unexpandable
% (I guess that makes sense, but why is it that I need \@xp\ifx\otherspace above if I've also \let\otherspace to a character? Mysterious...),
% so then "\csname hello\testtok\endcsname" is an error. This indexes into our state machine,
@@ -161,7 +173,9 @@
\ifx#1/%
\sseq@ifintexpr@next{*/}
\else
- \pgfutil@ifundefined{sseq@ifintexpr@@\sseq@ifintexpr@state @#1}%
+ % This extra \string here is so that if a control sequence fexpanded and still gave a control sequence,
+ % we don't get a missing \endcsname error here, it just returns false
+ \pgfutil@ifundefined{sseq@ifintexpr@@\sseq@ifintexpr@state @\string#1}%
{\let\next\sseq@ifintexpr@false}%
{\sseq@ifintexpr@next{#1}}%
\fi
@@ -173,11 +187,9 @@
\next
}
-% This has to eat the space
-%\bgroup\lccode`\*=`\ \lowercase{\egroup
- \def\sseq@ifintexpr@true#1\sseq@nil{\ifnum\sseq@tempcount=\z@ \let\next\@firstoftwo\else\let\next\@secondoftwo\fi}
- \def\sseq@ifintexpr@false#1\sseq@nil{\let\next\@secondoftwo}
-%}
+\def\sseq@ifintexpr@true#1\sseq@nil{\ifnum\sseq@tempcount=\z@ \let\next\@firstoftwo\else\let\next\@secondoftwo\fi}
+\def\sseq@ifintexpr@false#1\sseq@nil{\let\next\@secondoftwo}
+
\def\sseq@makeifint#1#2#3{\@xp\def\csname sseq@ifintexpr@@#1@#2\endcsname{#3}}
\def\sseq@ifintexpr@next#1{\@xp\let\@xp\next\csname sseq@ifintexpr@@\sseq@ifintexpr@state @#1\endcsname}
@@ -220,6 +232,95 @@
\sseq@makeifint{nointallowed}{\space}{\sseq@ifintexpr@{nointallowed}}
%%
+%% This parser defines the syntax for the page argument of \d.
+%%
+\def\sseq@d@grabpage#1{
+ \let\sseq@grabdpage@return#1
+ \futurelet\testtok\sseq@grabdpage@
+}
+
+\def\sseq@grabdpage@{
+ \sseq@tempiftrue
+ \ifx\testtok\bgroup
+ \let\next\sseq@grabdpage@group
+ \else
+ \def\sseq@dpage{}
+ \let\next\sseq@grabdpage@norm
+ \fi
+ \next
+}
+
+\def\sseq@grabdpage@group#1{\def\sseq@dpage{#1}\sseq@grabdpage@return}
+
+\def\sseq@grabdpage@norm{
+ \futurelet\testtok\sseq@grabdpage@norm@
+}
+
+\def\sseq@grabdpage@norm@{
+ \let\next\sseq@grabdpage@token
+ \ifx\testtok\bgroup
+ \sseq@tempiffalse
+ \let\next\sseq@grabdpage@return
+ \else
+ \ifx\testtok\par
+ \sseq@tempiffalse
+ \let\next\sseq@grabdpage@return
+ \else
+ \ifx\testtok(
+ \let\next\sseq@grabdpage@return
+ \else
+ \@xp\ifx\space\testtok
+ \let\next\sseq@grabdpage@space
+ \fi
+ \fi
+ \fi
+ \fi
+ \next
+}
+
+\def\sseq@grabdpage@space{\sseq@d@addto@macro\sseq@dpage{~}\@xp\sseq@grabdpage@norm\romannumeral-`0}
+
+\def\sseq@grabdpage@token#1{
+ \ifcat$\@xp\@gobble\string#1$%
+ \sseq@d@addto@macro\sseq@dpage{#1}
+ \@xp\sseq@grabdpage@norm
+ \else
+ \ifx#1\end
+ \sseq@tempiffalse
+ \@xp\sseq@grabdpage@return\@xp#1\romannumeral-`0
+ \else
+ \ifx#1\begin
+ \sseq@tempiffalse
+ \@xp\sseq@grabdpage@return\@xp#1\romannumeral-`0
+ \else
+ \@xp\sseq@grabdpage@token@fexpcs\@xp#1\romannumeral-`0
+ \fi
+ \fi
+ \fi
+}
+
+\def\sseq@grabdpage@token@fexpcs{\exp_last_unbraced:Nf\sseq@grabdpage@token@fexpcs@}
+\def\sseq@grabdpage@token@fexpcs@{\futurelet\testtok\sseq@grabdpage@token@fexpcs@@}
+\def\sseq@grabdpage@token@fexpcs@@{
+ \ifx\testtok\bgroup
+ \sseq@tempiffalse
+ \@xp\sseq@grabdpage@return
+ \else
+ \@xp\sseq@grabdpage@token@fexpcs@@@
+ \fi
+}
+\def\sseq@grabdpage@token@fexpcs@@@#1{
+ \ifcat$\@xp\@gobble\string#1$%
+ \sseq@d@addto@macro\sseq@dpage{#1}
+ \@xp\sseq@grabdpage@norm
+ \else
+ \sseq@tempiffalse
+ \@xp\sseq@grabdpage@return
+ \fi
+}
+
+
+%%
%%
%% New Class Pattern
%%
@@ -354,11 +455,6 @@
%% %%
%%%%%% %%%%%%
-% Only works for full coordinates. Used for error checking in \replaceclass and \d.
-\def\sseq@ifundefcoord{\@xp\sseq@ifundefcoord@}
-\def\sseq@ifundefcoord@(#1){%
- \sseq@obj@ifundef{class.(#1).num}%
-}
\def\sseq@ifdead#1{\ifnum\sseq@obj{class.#1[\sseq@obj{class.#1.num}].page}<\sseq@infinitycount\@xp\@firstoftwo\else\@xp\@secondoftwo\fi}
@@ -378,7 +474,8 @@
% inside of an hbox.
\def\sseq@errortype{}
-\def\sseq@printerrortype{\@xp\sseq@ifempty\@xp{\sseq@errortype}{}{~ for ~ \sseq@errortype}}
+\def\sseq@printerrortype#1{\@xp\sseq@ifempty\@xp{\sseq@errortype}{}{#1 \sseq@errortype}}
+\def\sseq@printforerrortype{\sseq@printerrortype{~for~}}
%% Pulls off x,y and evaluates them, puts n or empty into a separate variable.
% #1 -- a coordinate of the form {x,y} or {x,y,stuff}
@@ -390,7 +487,7 @@
\pgfutil@in@ \sseq@protecterror { #1 }
\ifpgfutil@in@
\bgroup
- \sseq@restorefont
+ \sseq@restorefont % This prevents "Missing character" stuff from being written to the log.
\let\sseq@protecterror\relax
\setbox0=\hbox{#1} % Trigger the error message
\egroup
@@ -498,8 +595,11 @@
\ifx\sseq@index\pgfutil@empty
\@xp\sseq@parsecoord@index
\fi
+ % TODO: clean this up a bit? it's pretty ad-hoc.
+ % Whenever you update this, make sure to update sseq@paredcoords@swap below too.
\@xp\let\csname x\sseq@macroname#1\endcsname\sseq@xcoord
\@xp\let\csname y\sseq@macroname#1\endcsname\sseq@ycoord
+ \@xp\let\csname n\sseq@macroname#1\endcsname\sseq@index
\@xp\let\csname \sseq@macroname#1@partial\endcsname\sseq@xycoord
\edef#1{(\sseq@xycoord,\sseq@index)}%
\@xp\edef\csname\sseq@macroname#1nopar\endcsname{\sseq@xycoord,\sseq@index}
@@ -508,6 +608,26 @@
\@xp\edef\csname\sseq@macroname#1@internalname\endcsname{sseq{\sseq@xycoord,\sseq@index}}%
}
+% #1 & #2 -- the two base commands that were handed to \sseq@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@temp#1 \let#1#2 \let#2\sseq@temp
+}
+\cs_generate_variant:Nn \sseq_swapmacros:NN { cc }
+
+\def\sseq@parsedcoords@swap#1#2{
+ \sseq_swapmacros:cc { x\sseq@macroname#1 } { x\sseq@macroname#2 }
+ \sseq_swapmacros:cc { y\sseq@macroname#1 } { y\sseq@macroname#2 }
+ \sseq_swapmacros:cc { n\sseq@macroname#1 } { n\sseq@macroname#2 }
+ \sseq_swapmacros:cc { \sseq@macroname#1@partial } { \sseq@macroname#2@partial }
+ \sseq_swapmacros:NN #1 #2
+ \sseq_swapmacros:cc { \sseq@macroname#1nopar } { \sseq@macroname#2nopar }
+ \sseq_swapmacros:cc { \sseq@macroname#1name } { \sseq@macroname#2name }
+ \sseq_swapmacros:cc { \sseq@macroname#1nameunbraced } { \sseq@macroname#2nameunbraced }
+ \sseq_swapmacros:cc { \sseq@macroname#1@internalname } { \sseq@macroname#2@internalname }
+}
+
% EXPOSE: a wrapper around \sseq@parsecoord. Use full name of coordinate to avoid name class with sseq@parsecoord.
\sseq@DeclareDocumentCommand \parsecoordinate { m r() }{%
\sseq@parsecoord{#1}{#2}{call of \string\parsecoord}%
@@ -522,7 +642,7 @@
\let\partialcoord\sseq@xycoord
\let\xcoord\sseq@xcoord
\let\ycoord\sseq@ycoord
- \edef\nodenum{\sseq@obj@ifundef{partcoord.(\partialcoord).numnodespp}{1}{\sseq@obj{partcoord.(\partialcoord).numnodespp}}}%
+ \edef\nodenum{\sseq@obj@ifundef{partcoord.(\partialcoord).numnodes}{1}{\the\numexpr\sseq@obj{partcoord.(\partialcoord).numnodes}+1}}%
\edef\coordnopar{\xcoord,\ycoord,\nodenum}
\edef\coord{(\coordnopar)}%
}
@@ -540,7 +660,7 @@
\@xp\pgfkeys@spdef\@xp\sseq@rawsindex\@xp{\sseq@rawsindex}
\edef\sseq@rawtindex{\@xp\sseq@dparsecoord@getyindex\@xp{\sseq@restcoord}}%
\@xp\pgfkeys@spdef\@xp\sseq@rawtindex\@xp{\sseq@rawtindex}
- %
+%
\let\sseq@rawindex\sseq@rawsindex
\def\sseq@errortype{source ~ of ~ differential}
\@xp\sseq@parsecoord@index % the \@xp is needed so that \sseq@break inside of parsecoordindex works properly.
@@ -553,6 +673,11 @@
\fi
\fi
\let\sourcecoord\sseq@xycoord
+%
+ \let\xsource\sseq@xcoord
+ \let\ysource\sseq@ycoord
+ \let\nsource\sseq@index
+%
\edef\source{(\sseq@xycoord,\sseq@index)}%
\ifx\sourcename\undefined
\edef\sourcename{(\sseq@xycoord\ifx\sseq@rawindex\pgfutil@empty\else,\sseq@rawindex\fi)}
@@ -565,6 +690,9 @@
\sseq@parsecoord@index
\let\targetcoord\sseq@xycoord
\edef\target{(\sseq@xycoord,\sseq@index)}%
+ \let\xtarget\sseq@xcoord
+ \let\ytarget\sseq@ycoord
+ \let\ntarget\sseq@index
\edef\targetname{(\sseq@xycoord\ifx\sseq@rawindex\pgfutil@empty\else,\sseq@rawindex\fi)}
}{
\ifx\sseq@rawtindex\pgfutil@empty\else
@@ -587,7 +715,7 @@
\def\sseq@differential@gettarget@#1#2,#3\sseq@nil{\the\numexpr#2+\sseq@targetx{#1}\relax,\the\numexpr#3+\sseq@targety{#1}\relax}
\def\sseq@getfirsttwoelts#1,#2,#3\sseq@nil{#1,#2}
-\def\sseq@getdtarget#1#2#3{\sseq@eval{\edef\@nx#1{\@nx\sseq@differential@gettarget{#2}{\sseq@getfirsttwoelts#3,,\sseq@nil}}}}
+\protected\def\sseq@getdtarget#1#2#3{\sseq@eval{\edef\@nx#1{\@nx\sseq@differential@gettarget{#2}{\sseq@getfirsttwoelts#3,,\sseq@nil}}}}
% Takes a comma separated list that can be empty, have one element, or two elements, returns first element (or empty if list is empty).
\def\sseq@dparsecoord@getxindex#1{\sseq@dparsecoord@getxindex@#1,\sseq@nil}
@@ -600,14 +728,15 @@
}%
}
-\def\sseq@parsecoordinate#1#2{%
+% EXPOSE: a wrapper around \sseq@parsecoord.
+\sseq@DeclareDocumentCommand\parsecoordinate { m r() }{%
\sseq@parsecoord{#1}{#2}{call of \string\parsecoord}%
}
-% EXPOSE: a wrapper around \sseq@parsecoord. Use full name of coordinate to avoid name class with sseq@parsecoord.
-\sseq@DeclareDocumentCommand \parsedifferential { m r() }{%
- \sseq@dparsecoord{#1}{#2}{call of \string\parsecoord}%
+% EXPOSE: a wrapper around \sseq@dparsecoord.
+\sseq@DeclareDocumentCommand \parsedifferential { m r() d() }{%
+ \sseq@dparsecoord{#1}{#2}{#3}%
}
% Expandable coordinate parsing for \isalive.
@@ -659,29 +788,32 @@
%%% The Stack
%%%
-\sseq@addtostorelistlet\sseq@stacktop\relax
-\def\sseq@stackitem#1#2#3{\csname sseq.\sseq@thename.stack.#1.#3\endcsname} % gobble #2 which we added in for the error message
-\def\sseq@getstackentry#1{
- \exp_args:No\sseq@getstackentry@{\sseq@stacktop}{#1}{#1} % Second copy of #1 for error message
+% This maybe should be moved into sseqmain.code.tex...
+\sseq@addtostorelist\sseq@stacktop{}
+\def\sseq@stackitem#1#2{\csname sseq.\sseq@thename.stack.#1.#2\endcsname} % gobble #2 which we added in for the error message
+\def\sseq@getstackentry#1#2{
+ \ifnum#1<\sseq@stackdepth
+ \exp_args:No\sseq@getstackentry@{\sseq@stacktop}{#1}{#2}
+ \else
+ \sseq@protecterror{\sseq@error@xx{index-out-of-bounds}{#1}{\the\sseq@stackdepth}}
+ \fi
}
\def\sseq@getstackentry@#1#2{
\ifnum#2=\z@\@xp\@firstoftwo\else\@xp\@secondoftwo\fi
- {\sseq@stackitem{#1}}
- {\@ifundefined{sseq.\sseq@thename.stack.#1.next}{\sseq@getstackentry@indextoolarge}{
- \exp_args:Nf\sseq@getstackentry@{\csname sseq.\sseq@thename.stack.#1.next\@xp\endcsname\@xp}\@xp{\the\numexpr#2-1}
- }}
+ { \sseq@stackitem{#1} }
+ { \exp_args:Nco\sseq@getstackentry@ { sseq.\sseq@thename.stack.#1.next } { \the\numexpr#2-1 } }
}
-\def\sseq@getstackentry@indextoolarge#1{\sseq@protecterror{\sseq@error@xx{index-larger-than-stack}{#1}{\the\sseq@stackdepth}}}
-\def\sseq@pushstack(#1){
+\protected\def\sseq@pushstack(#1){
\bgroup
\sseq@parsecoord\temp{#1}{}
\sseq@pushstack@\temp
\egroup
}
+% Note that \class directly calls pushstack@ to avoid reparsing the coordinate
\def\sseq@pushstack@{\@xp\sseq@pushstack@@}
\def\sseq@pushstack@@(#1,#2,#3){
@@ -696,11 +828,11 @@
\newcount\sseq@userstacksavecount
-\def\sseq@savestack{
+\protected\def\sseq@savestack{
\global\advance\sseq@userstacksavecount\@ne
\sseq@savestack@name{usersave@\the\sseq@userstacksavecount}
}
-\def\sseq@restorestack{
+\protected\def\sseq@restorestack{
\sseq@restorestack@name{usersave@\the\sseq@userstacksavecount}
\global\advance\sseq@userstacksavecount\m@ne
}
@@ -714,17 +846,19 @@
% if #1 consists of a single nonnegative integer then -0#1 will be turned into some nonpositive integer
% and romannumeral produces no output when handed a nonpositive integer, so the result will be empty.
% If #1 has any nonnumerical tokens or is negative, there will be left over stuff.
+ %
+ % We also have to subtract off \sseq@x so that this behaves correctly inside of a scope (the \lastx value should be unshifted)
\@xp\sseq@ifempty\@xp{\romannumeral-0#1}{
- \sseq@getstackentry{#1}{lastx}
+ \the\numexpr\sseq@getstackentry{#1}{lastx}-\sseq@x\relax
}{
- \sseq@getstackentry{0}{lastx}#1 % #1 isn't a number so put it back
+ \the\numexpr\sseq@getstackentry{0}{lastx}-\sseq@x\relax#1 % #1 isn't a number so put it back
}
}
\def\sseq@lasty#1{
\@xp\sseq@ifempty\@xp{\romannumeral-0#1}{
- \sseq@getstackentry{#1}{lasty}
+ \the\numexpr\sseq@getstackentry{#1}{lasty}-\sseq@y\relax
}{
- \sseq@getstackentry{0}{lasty}#1 % #1 isn't a number so put it back
+ \the\numexpr\sseq@getstackentry{0}{lasty}-\sseq@y\relax#1 % #1 isn't a number so put it back
}
}
@@ -737,16 +871,22 @@
}
-\def\sseq@nameclass#1(#2){
+\sseq@DeclareDocumentCommand\nameclass {mr()} {
\bgroup
+ \sseq@setthiscall{\sseq@nameclass#1(#2)}
+ \let\sseq@possibleoninputlinepar\empty
\sseq@parsecoord\coord{#2}{}
\sseq@cleanup@obj{class.namedclass.#1}
\sseq@obj@xdef{class.namedclass.#1}{\coordnopar}
+ \sseq@breakpoint
\egroup
}
-\def\sseq@tagclass#1(#2){%
+\sseq@DeclareDocumentCommand\tagclass{mr()}{
\bgroup
+ \sseq@setthiscall{\tagclass#1(#2)}
+ \let\sseq@possibleoninputlinepar\empty
+ \def\sseq@class@tag{#1}
\sseq@parsecoord\coord{#2}{}%
\sseq@obj@ifdef{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}{%
\sseq@error@nn{class-tag-already-defined}{\sseq@class@tagprefix\sseq@class@tag}{(\sseq@xycoord)}% could be warning
@@ -755,23 +895,59 @@
\sseq@obj@xdef{class.\coord.tag}{\sseq@class@tagprefix\sseq@class@tag}%
\sseq@cleanup@obj{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}%
\sseq@obj@xdef{partcoord.(\sseq@xycoord).tag.\sseq@class@tagprefix\sseq@class@tag}{\sseq@index}%
+ \sseq@breakpoint
\egroup
}
-\def\sseq@gettag#1(#2){
+\sseq@DeclareDocumentCommand\gettag{mr()}{
\bgroup
+ \sseq@setthiscall{\gettag#1(#2)}
+ \let\sseq@possibleoninputlinepar\empty
\sseq@parsecoord\coord{#2}{}
\sseq@obj@ifdef{class.\coord.tag}{
\xdef#1{\sseq@obj{class.\coord.tag}}
}{
\sseq@error@n{class-no-tag}{(#2)}
}
+ \sseq@breakpoint
\egroup
}
+\prg_new_conditional:Npnn \sseq_if_out_of_bounds:n #1 { T , F , TF } {
+ \bgroup
+ \sseq@tempiftrue
+ \sseq@parsecoord\coord{#1}{}
+ \@gobbletwo\sseq@breakpoint\sseq@tempiffalse % this executes \sseq@tempiffalse if we broke, otherwise it gets gobbled
+ \ifsseq@tempif
+ \sseq_if_out_of_bounds_noparse:nnTF { \xcoord } { \ycoord }{\egroup\prg_return_true:}{\egroup\prg_return_false:}
+ \else
+ \egroup
+ \prg_return_false
+ \fi
+}
+% For internal use b/c it's faster not to call \sseq@parsecoord
+% There's no noticeable performance boost though... =(
+\prg_new_conditional:Npnn \sseq_if_out_of_bounds_noparse:nn #1#2 {TF} {
+ \sseq@tempiftrue
+ \ifnum#1<\sseq@xmaxpp\relax\ifnum#1>\sseq@xminmm\relax\ifnum#2<\sseq@ymaxpp\relax\ifnum#2>\sseq@yminmm\relax
+ \sseq@tempiffalse
+ \fi\fi\fi\fi
+ \ifsseq@tempif
+ \prg_return_true:
+ \else
+ \prg_return_false:
+ \fi
+}
+\sseq@DeclareDocumentCommand \IfOutOfBoundsTF { r() } { \sseq_if_out_of_bounds:nTF { #1 } }
+\sseq@DeclareDocumentCommand \IfOutOfBoundsT { r() } { \sseq_if_out_of_bounds:nT { #1 } }
+\sseq@DeclareDocumentCommand \IfOutOfBoundsF { r() } { \sseq_if_out_of_bounds:nF { #1 } }
+\sseq@DeclareDocumentCommand \IfInBoundsTF { r() mm } { \sseq_if_out_of_bounds:nTF { #1 } { #3 } { #2 } }
+\sseq@DeclareDocumentCommand \IfInBoundsT { r() } { \sseq_if_out_of_bounds:nF { #1 } }
+\sseq@DeclareDocumentCommand \IfInBoundsF { r() } { \sseq_if_out_of_bounds:nT { #1 } }
+
%%%%%%
%%%
@@ -788,7 +964,7 @@
}
\def\sseq@modtikzcommands@#1{%
\ifx#1\sseq@nil\else
- \edef#1{\@xp\@nx\csname\sseq@macroname#1\space\endcsname\@nx#1}%
+ \protected\edef#1{\@xp\@nx\csname\sseq@macroname#1\space\endcsname\@nx#1}%
\@xp\let\csname\sseq@macroname#1\space\endcsname\sseq@defer@tikzcommand % This is just for error reporting so that it will say "Paragraph ended before \draw was complete"
\@xp\sseq@modtikzcommands@
\fi
@@ -797,6 +973,8 @@
\def\sseq@defer@tikzcommand#1{%
\begingroup
\let\sseq@isaliveprotect\sseq@isaliveprotect@protect
+ \sseq@setinputline
+ \sseq@loadinputline
\sseq@callas{#1}%
\gdef\sseq@thepathsofar{#1[/utils/exec={\sseq@thesseqstyle\sseq@thetikzprimitivestyle\the\sseq@scope@toks\sseq@savedoptioncode}]}%
\xdef\sseq@whattheusersaid{\string#1}
@@ -836,7 +1014,7 @@
\def\sseq@defer@tikzcommand@option[#1]{%
\sseq@processoptions{tikz ~ primitives}{#1}%
\ifx\sseq@savedoptioncode\pgfutil@empty\else
- \sseq@x@addto@macro\sseq@thepathsofar{[/utils/exec={\unexpanded\@xp{\sseq@savedoptioncode}}]}%
+ \sseq@x@addto@macro\sseq@thepathsofar{[/utils/exec={\unexpanded\@xp{\@xp\sseq@options@bothpassmode\sseq@savedoptioncode}}]}%
\fi
\sseq@g@addto@macro\sseq@whattheusersaid{[#1]}
\sseq@defer@tikzcommand@
@@ -927,14 +1105,14 @@
\sseq@defer@tikzcommand@finish@
}
-% If the expression was incomplete, we'll jump here
+% If the expression was incomplete, we'll jump here to avoid adding the semicolon to the error printout
\def\sseq@defer@tikzcommand@finish@{
\sseq@g@addto@macro\sseq@thepathsofar{;}
\global\sseq@thiscalltoks\@xp{\sseq@whattheusersaid}
\ifx\sseq@pageconstraint\sseq@pageconstraint@true
- \sseq@savedpaths@xadd{\unexpanded\@xp{\sseq@thepathsofar}}%
+ \sseq@savedpaths@xaddtikzpath{\unexpanded\@xp{\sseq@thepathsofar}}%
\else
- \sseq@savedpaths@xadd{%
+ \sseq@savedpaths@xaddtikzpath{%
\@nx\sseq@tikzcommand@conditionaldraw{\unexpanded\@xp{\sseq@thepathsofar}}{\unexpanded\@xp{\sseq@pageconstraint}}
}%
\fi
@@ -1151,7 +1329,6 @@
}
-%TODO: fix this...
\def\sseq@updatepageconstraintrange{%
\sseq@protected@edef\sseq@pageconstraint{%
(\unexpanded\@xp{\sseq@pageconstraint})&&(\temp<=\page \ifx\tempmax\empty\else&&\page<=\tempmax\fi)%
@@ -1262,17 +1439,6 @@
\sseqnormalizemonomial@testend
}
-% This is supposed to take a space out of the input stream. For some reason \futurelet grabs it even though it's not supposed to...
-% Make sure braces go around argument, except that if they go around \sseq@nil, \futurelet will grab the the open brace and not see
-% the \sseq@nil. So we use a full expansion and don't put braces around \sseq@nil if that's our argument.
-% MOTHERFUCKING SPACES.
-\def\sseqnormalizemonomial@id#1{
- \ifx\sseq@nil#1
- \@xp\@firstoftwo
- \else
- \@xp\@secondoftwo
- \fi{\@nx\sseq@nil}{{#1}}
-}
\def\sseqnormalizemonomial@testend{
\ifx\testtok\sseq@nil
@@ -1281,12 +1447,8 @@
\egroup
\let\next\@gobble
\else
- \@xp\ifx\space\testtok % not sure why I have to test for spaces like this -- figured it out with trial and error, like in \ifintexpr
- % I'm not really sure why a space can show up here, but it crashes the macro and we don't care about spaces.
- % I can't \@gobble the space because it will ignore it and take the next argument. What I can do is \@firstofone it away, but that deletes braces
- % and in our case it's safe to put in extra braces but not to delete them. So I have \sseqnormalizemonomial@id...
- % LaTeX is really really weird.
- \def\next{\@xp\futurelet\@xp\testtok\@xp\sseqnormalizemonomial@testend\romannumeral-`0\sseqnormalizemonomial@id}
+ \@xp\ifx\space\testtok
+ \def\next{\@xp\futurelet\@xp\testtok\@xp\sseqnormalizemonomial@testend\romannumeral-`0}
\else
\let\next\sseqnormalizemonomial@
\fi