%% %% Package: spectralsequences v1.3.3 2023-01-28 %% Author: Hood Chatham %% Email: hood@mit.edu %% Date: 2023-01-28 %% License: Latex Project Public License %% %% A package for drawing spectral sequences %% % TODO: % Try catch blocks % Make an argument type for the \d page argument. % deal with xmin, xmax, etc (was there actually a problem we were trying to fix?) % % Redo sseqerrortest and set up regression test script as part of build (damn I didn't realize we'd lost anything imporant with that find -d disaster) % Maybe we should add some other regression tests too % % Lower priority: % error messages that should be warnings by default? % \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{spectralsequences}[2023/01/28 v1.3.3] \RequirePackage{tikz} \RequirePackage{etoolbox} \RequirePackage{xparse} \RequirePackage{verbatim} \usetikzlibrary{quotes} \usetikzlibrary{fit} \usetikzlibrary{positioning} \usetikzlibrary{intersections} \usetikzlibrary{backgrounds} \usepgflibrary{arrows.meta} \usetikzlibrary{shapes} %\usetikzlibrary{patterns} %\usetikzlibrary{profiler} \newif\ifsseq@draftmode \newif\ifsseq@tooltip \DeclareOption{draft}{\sseq@draftmodetrue} \DeclareOption{tooltips}{\sseq@tooltiptrue} \ProcessOptions\relax \ifsseq@tooltip \RequirePackage{pdfcomment} \else \let\ulp@afterend\relax % So that removing the tooltip option doesn't cause the aux file to have an error. \fi \def\sseq@authorname{Hood Chatham} \def\sseq@authoremail{hood@mit.edu} \def\sseq@issuetracker{https://github.com/SpectralSequences/latex/issues/new} % Commands we are going to expose just inside of environments \def\sseq@macrolist{% \xcoord\ycoord\page %\xmin\xmax\ymin\ymax % these just get protected % Defined in sseqmessages: \quiet\endquiet % These are defined in sseqmain: \class\classoptions\replaceclass\replacesource\replacetarget \replacestructlines \d\doptions\kill\structline\structlineoptions\extension\extensionoptions\circleclasses \lastlabel % The following are defined in sseqparsers: \pgfmathparse\isalive\lastx\lasty\lastclass\savestack\restorestack\pushstack\nameclass\tagclass \parsecoordinate\parsedifferential\getdtarget\gettag \IfOutOfBoundsTF\IfOutOfBoundsT\IfOutOfBoundsF\IfInBoundsTF\IfInBoundsT\IfInBoundsF \IfExistsTF\IfExistsT\IfExistsF\IfAliveTF\IfAliveT\IfAliveF \IfValidDifferentialTF\IfValidDifferentialT\IfValidDifferentialF \DrawIfValidDifferentialTF\DrawIfValidDifferentialT\DrawIfValidDifferentialF\DrawIfValidDifferential % sseqforeach \Do\DoUntilOutOfBounds\DoUntilOutOfBoundsThenNMore } % 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 } %%%%%% %%%%%% %% %% %% 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@draw \newif\ifsseq@drawedge \newif\ifsseq@tikzprims@integershift \newif\ifsseq@anchor \newif\ifsseq@rangecheck \newif\ifsseq@rangecheck@sideways \sseq@drawedgetrue \sseq@tikzprims@integershifttrue \newif\ifsseq@patchforeach \newif\ifsseq@patchfit \newif\ifsseq@patchxparseU \newif\ifsseq@tempif \newif\ifsseq@gtempif \newif\ifsseq@error \newtoks\sseq@temptoks \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@xoffset % We add these to everything to avoid overflow errors as much as possible \newcount\sseq@yoffset \newcount\sseq@stackdepth \newdimen\sseq@tempdimen \newdimen\sseq@tempxdimen \newdimen\sseq@tempydimen \newdimen\sseq@xscalecm \newdimen\sseq@yscalecm \newdimen\sseq@clip@xcenter \newdimen\sseq@clip@ycenter \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. % Set the catcode of space to ignore, and then reparse the characters in #2. \def\sseq@setmacronospaces#1#2{% \bgroup\catcode`\ =9\relax \makeatletter \scantokens{\expandafter\egroup\expandafter\def\expandafter#1\expandafter{\csname #2\endcsname}}% } \def\sseq@setnospaces#1#2{% \bgroup\catcode`\ =9\relax \makeatletter \scantokens{\expandafter\egroup\expandafter\def\expandafter#1\expandafter{\@firstofone{#2}}}% } \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 \let\sseq@breakpointfinally\@gobble \long\def\sseq@break#1\sseq@breakpoint{} \def\sseq@fbreak{\@xp\sseq@break\romannumeral-`0} \long\def\sseq@break@finally#1\sseq@breakpoint#2{#2} \long\def\sseq@breakfi{\fi\sseq@break} \long\def\sseq@breakfifi{\fi\fi\sseq@break} \long\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 } \newif\ifsseq@insidewaysenv \sseq@insidewaysenvfalse \def\SseqOrientationNormal{\sseq@insidewaysenvfalse} \def\SseqOrientationSideways{\sseq@insidewaysenvtrue} \def\SseqOrientationToggle{\ifsseq@insidewaysenv\sseq@insidewaysenvfalse\else\sseq@insidewaysenvtrue\fi} \AtBeginEnvironment{sideways}{\SseqOrientationToggle} \input sseqmessages.code.tex % Exposes directly: \sseqerrortowarning \input sseqcheckdefinitions.code.tex \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, \sseqparseint \ifsseq@patchforeach \input sseqforeach.code.tex \else \def\sseq@patchfor{} \fi \input sseqkeys.code.tex % Exposes directly: \sseqset, \sseqnewfamily \input sseqmain.code.tex % Defines all the main commands. Exposes directly: the environments, \xmin, \xmax, etc, \SseqCopyPage \input sseqdrawing.code.tex % Give standard definitions for savedpaths wrappers \def\sseq@beginscope@object{\begin{scope}} \def\sseq@endscope@object{\end{scope}} \let\sseq@scope@object\@firstofone \let\sseq@style@object\@firstofone \let\sseq@class@object\sseq@class@draw@ifpage \let\sseq@differential@object\sseq@differential@draw@ifpage \let\sseq@structline@object\sseq@structline@draw@ifpage \let\sseq@extension@object\sseq@extension@draw@ifpage \let\sseq@circleclass@object\sseq@circleclass@draw@ifpage \let\sseq@tikzpath@object\@firstofone %%% 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=->, pins=help lines } \ifsseq@tooltip \let\sseqtooltip\sseq@tooltip@wrapper \fi % Extra commands to expose: \let\sseqifempty\sseq@ifempty \let\SseqParseInt\sseqparseint \let\SseqNewFamily\sseqnewfamily \def\sseqpower#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{1}} \def\sseqpowerempty#1#2{\@xp\sseqtypesetpower@\@xp{\the\numexpr#2}{#1}{}} \def\sseqtypesetpower@#1#2#3{\ifnum#1=\z@#3\else\ifnum#1=\@ne#2\else#2^{#1}\fi\fi}