diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/spectralsequences/sseqparsers.code.tex | 344 |
1 files changed, 253 insertions, 91 deletions
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 |