summaryrefslogtreecommitdiff
path: root/graphics/pgf/contrib/spectralsequences/src/sseqmessages.code.tex
blob: 7677949e9c43e8ed63c288e0f2d8aa273de00415 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
%%
%% Package: spectralsequences v1.3.2 2022-02-19
%% Author: Hood Chatham
%% Email: hood@mit.edu
%% Date: 2022-02-19
%% License: Latex Project Public License
%%
%% File: sseqmessages.code.tex
%% Exposes: Error message redirects?
%%
%%   Set up fancy error messages
%%



%% The error handling system is build on top of l3msg. l3msg produces errors like:
%%
%%    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%%    !
%%    ! LaTeX error: "<package>/<error-name>"
%%    !
%%    ! <error message text>
%%    !
%%    ! See the <package> documentation for further information. % produced by \msg_see_documentation_text:n{<package>}
%%    !...............................................
%%
%% The user will see underneath it l.<line number> <text on line>
%%
%% Unfortunately, if the error is in a \foreach statement, the user will only see the final line of the foreach loop, often just the close brace.
%% It's impossible to tell from this where in the \foreach the error occurred. Similar problems occur if the command is inside a user command.
%%
%% We're going to modify this file to improve the situation.
%%
%% If the command is in a forloop or a user command I want to:
%%   -- annotate the error with the command that caused it, or the previous command if the error occurred before I can know what the current command looks like.
%%   -- present a stack trace to inform the user where exactly the problem occurred
%%
%%
%% We automatically print the annotation and stack trace at the end of all l3msg messages by hooking into \msg_see_documentation_text:n.
%% The annotation and stack trace are prepared by a command \sseq@error@setup which we hook into the beginning of the latex3 message processing code.
%%
%% Here's an example of the result:
%%
%%    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
%%    !
%%    ! spectralsequences error: "index-too-large"
%%    !
%%    ! Index '-3' provided for target of structure line is too large -- only 1
%%    ! classes exist at position (32,8).
%%    !
%%    ! (Error occurred during call "\structline(16,-1,-1)(16,0,-3)", in the    % This is the annotation
%%    ! \foreach block that ends on line 158, with variable values: \n = 2.)    % it's stored in \sseq@error@annotation
%%    !
%%    ! Stack trace:                                                            % This is the stack trace
%%    !    \towergroupb (8*\n ,4*\n )                                           % Produced by \sseq@printstacktrace
%%    !    \foreach \n in {2,3,4}
%%    !
%%    ! See the spectralsequences documentation for further information.
%%    !
%%    ! Type <return> to continue.
%%    !...............................................


\def\sseq@protecterror#1{\@nx\sseq@protecterror\unexpanded{{#1}}}

% Stack, thiscall, foreachcall.
% Here we record what the user has said (as best we can tell)
\newtoks\sseq@thiscalltoks

% 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}}}
\def\sseq@gsetthiscall{\sseq@seterrorannotation{call}\global\sseq@thiscalltoks}
\def\sseq@xsetthiscall#1{\sseq@eval{\@nx\sseq@gsetthiscall{#1}}}
\def\sseq@xsetlastcall#1{\sseq@eval{\global\sseq@thiscalltoks{#1}}}

\def\sseq@usermacro@esetthiscall#1{\sseq@eval{\sseq@thiscalltoks{#1}}} % Don't set \sseq@error@annotation@call

\newtoks\sseq@foreachcall
\newtoks\sseq@topofstacktrace
\sseq@topofstacktrace{}
\def\sseq@restofstacktrace{}

\def\sseq@pushstacktrace#1{
    \edef\sseq@temp{\the\sseq@topofstacktrace}
    \ifx\sseq@temp\pgfutil@empty\else
        \edef\sseq@restofstacktrace{\unexpanded{\\\ \ \ }\@nx\sseq@stack@unexpanded{\the\sseq@topofstacktrace}\unexpanded\@xp{\sseq@restofstacktrace}}
    \fi
    \sseq@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}}}



% Positional information about the error:
% Lengths are five more than the correct length to account for the fact that the line starts with !<space> and to accommodate two quote characters and a comma.
\def\sseq@error@annotation@aftercall{\\\\Error occurred after call\sseq@printthiscall\sseq@error@inforeachloop}
\chardef\sseq@error@annotation@length@aftercall=34
\def\sseq@error@annotation@call{\\\\Error occurred during call\sseq@printthiscall\sseq@error@inforeachloop}
\chardef\sseq@error@annotation@length@call=33
\def\sseq@error@annotation@atbeginforeach{\\\\Error occurred at the beginning of \string\foreach\ statement\sseq@printthiscall\sseq@error@inforeachloop}
\chardef\sseq@error@annotation@length@atbeginforeach=60
\def\sseq@error@annotation@atbeginusercmd{\\\\Error occurred at the beginning of user command\sseq@printthiscall\sseq@error@inforeachloop}
\chardef\sseq@error@annotation@length@atbeginusercmd=54

\def\sseq@seterrorannotation@drawing#1#2#3#4#5{%
    \def\sseq@error@annotation{\\\\Error occurred while drawing class (#2,#3,#4)\ifnum#5>0 \space which has been replaced #5 time\ifnum#5>1s\fi\fi.
    Look for a \ifnum#5>0\string\replaceclass\else\string\class\fi\space command that makes a class at that position.
    Also make sure to check any \@nx\classoptions commands that could be the culprit.}%
}

\def\sseq@seterrorannotation#1{%
    \@xp\let\@xp\sseq@error@annotation\csname sseq@error@annotation@#1\endcsname
    \@xp\let\@xp\sseq@error@annotation@length\csname sseq@error@annotation@length@#1\endcsname
}

\sseq@seterrorannotation{aftercall}

\def\sseq@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{.}


\def\sseq@error@announcestacktrace{\\\\Stack trace:}
\def\sseq@printstacktrace{ % Only prints rest of stack trace because top element is mentioned in annotation.
    \ifx\sseq@restofstacktrace\pgfutil@empty\else
        \sseq@error@announcestacktrace\sseq@restofstacktrace
    \fi
}

% \sseq@error@setup happens before the error is reported, \sseq@error@cleanup at the end.

\ExplSyntaxOn

\def\sseq@error@setup@withinfo{
    \bgroup
    \def\foreach{\@nx\foreach}
    \sseq@countthiscall
    \ifnum\sseq@thiscallnumchars>\numexpr\l_iow_line_count_int-\sseq@error@annotation@length\relax
        \def\sseq@printthiscall{:\\\@xp\iow_indent:n\@xp{\the\sseq@thiscalltoks}\\}
        \let\sseq@possiblecomma\empty
        \let\sseq@possibleperiod\empty
    \fi
    \let\sseq@stack@unexpanded\unexpanded
    \sseq@error@setup@errorinfo
    \sseq@error@hook
}

\def\sseq@error@setup@noinfo{\bgroup\def\foreach{\@nx\foreach}\let\sseq@stack@unexpanded\unexpanded\def\sseq@error@annotation{}\sseq@error@hook}
\let\sseq@error@setup\sseq@error@setup@noinfo
\def\sseq@error@cleanup{\egroup\sseq@errortrue} % If the error was thrown in NewDocumentCommand, we need to process it. Just used in sseqmacromakers.


\def\sseq@printthiscall{\ "\the\sseq@thiscalltoks"}
% make \exp_args:NNNf:
\let \sseq_dummy:NNn \empty
\cs_generate_variant:Nn \sseq_dummy:NNn {NNf}


% Count the chars in thiscall
% Detokenize handles the control words, but keeps the spaces as spaces. To count them properly, we lowercase them into 0's (any nonspace character would do just fine).
\def\sseq@countthiscall{
    \bgroup\lccode`\ =`\0\relax
    \edef\temp{\detokenize\@xp{\the\sseq@thiscalltoks}}
    \exp_args:Nf\lowercase{
        \exp_args:NNNf\egroup
        \edef\sseq@thiscallnumchars{
            \exp_args:NNo\@nx\tl_count:n{\temp}
        }
    }
}

\ExplSyntaxOff


\def\sseq@error@hook{} % \sseq@error@hook is just used once in the isalive error handling to set \protect to relax. Probably a better way to do that...
\def\sseq@errorinfo{%
    \sseq@error@annotation
    \sseq@printstacktrace
}



\def\sseq@atbeginusermacro@msgsetup{%
    \let\protect\empty % prevent issues if protected variables like \xmax are used as the loop max
    \let\sseq@error@setup@errorinfo\sseq@error@setup@errorinfo@active % Install foreach error annotations
    \let\sseq@error@setup\sseq@error@setup@withinfo
    \sseq@opushstacktrace{\the\sseq@thiscalltoks}
}

\def\sseq@atbeginforeach@msgsetup{%
    \let\protect\empty % prevent issues if protected variables like \xmax are used as the loop max
    \let\sseq@error@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\@xp{\string\foreach} % Stack gets pushed at the beginning of the body of the foreach loop once we know what the call looks like
}


\def\sseq@error@setup@errorinfo@active{%
    \edef\tempa{\the\sseq@thiscalltoks}\edef\tempb{\the\sseq@foreachcall}
    \ifx\tempa\tempb % We're at the beginning of a for loop
        \sseq@seterrorannotation{atbeginforeach}
    \else
        \edef\tempb{\the\sseq@topofstacktrace}
        \ifx\tempa\tempb % we're at the beginning of a user macro
            \sseq@seterrorannotation{atbeginusercmd}
        \else
            % The top of the stack trace doesn't get included in the stack trace because it is assumed to be
            % mentioned in the annotation. Since we aren't at the beginning of the foreach or usercmd,
            % that means it won't be mentioned. Push an empty thing onto the stack so the innermost \foreach or usercommand is mentioned.
            \sseq@pushstacktrace{}
        \fi
    \fi
}

%%
%%  \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
}





%%%
%%% Set up l3msg Hooks
%%%


\ExplSyntaxOn
\char_set_catcode_space:N\ % Needed to make pretocmd work -- there are always spaces after every command, and they need to be retokenized as spaces

\def\SseqErrorToWarning#1{\msg_redirect_name:nnn{spectralsequences}{#1}{warning}}
\let\sseqerrortowarning\SseqErrorToWarning
\def\sseq@quieterror#1{\msg_redirect_name:nnn{spectralsequences}{#1}{none}}

\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\sseq@errorinfo}}
\def\sseq@newerror@internal#1#2{\msg_new:nnn{spectralsequences}{#1}{Internal error: #2 \sseq@openagithubissue}}
\edef\sseq@openagithubissue{Please report this on the github issue tracker which is at the following url: \sseq@issuetracker}


\cs_new_eq:NN \__sseq_hooked_msg_see_documentation_text:n \msg_see_documentation_text:n
\cs_new_eq:NN \__sseq_hooked_msg_fatal_code:nnnnnn   \__msg_fatal_code:nnnnnn
\cs_new_eq:NN \__sseq_hooked_msg_error_code:nnnnnn   \__msg_error_code:nnnnnn
\cs_new_eq:NN \__sseq_hooked_msg_warning_code:nnnnnn \__msg_warning_code:nnnnnn
\cs_new_eq:NN \__sseq_hooked_msg_info_code:nnnnnn    \__msg_info_code:nnnnnn
\cs_new_eq:NN \__sseq_hooked_interupt_wrap:nnn \__msg_interrupt_wrap:nnn


\cs_new:Npn \sseq@installmsghooks {%
    \cs_set_eq:NN \errmessage \sseq@errmessage
    \cs_set_eq:NN \msg_see_documentation_text:n \__sseq_hooked_msg_see_documentation_text:n
    \cs_set_eq:NN \__msg_fatal_code:nnnnnn      \__sseq_hooked_msg_fatal_code:nnnnnn
    \cs_set_eq:NN \__msg_error_code:nnnnnn      \__sseq_hooked_msg_error_code:nnnnnn
    \cs_set_eq:NN \__msg_warning_code:nnnnnn    \__sseq_hooked_msg_warning_code:nnnnnn
    \cs_set_eq:NN \__msg_info_code:nnnnnn       \__sseq_hooked_msg_info_code:nnnnnn
    \cs_set_eq:NN \__msg_interrupt_wrap:nnn       \__sseq_hooked_interupt_wrap:nnn
}

\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_warning:nn{spectralsequences}{msg-patch-failed}
    \def\sseq@installmsghooks{}
    \sseq@break
}

\let\sseq@errmessage@std\errmessage
\def\sseq@errmessage#1{\sseq@error@setup\let\\\iow_newline:\sseq@errmessage@std{#1\sseq@error@annotation}\sseq@error@cleanup}

\pretocmd\__sseq_hooked_msg_see_documentation_text:n{\sseq@errorinfo}{}{\sseq@msgpatchfailed}


\pretocmd\__sseq_hooked_msg_fatal_code:nnnnnn  {\sseq@error@setup}  {}{\sseq@msgpatchfailed}
\pretocmd\__sseq_hooked_msg_error_code:nnnnnn  {\sseq@error@setup}  {}{\sseq@msgpatchfailed}
%\pretocmd\__sseq_hooked_msg_warning_code:nnnnnn{\sseq@msg@setup}  {}{\sseq@msgpatchfailed}
%\pretocmd\__sseq_hooked_msg_info_code:nnnnnn   {\sseq@msg@setup}  {}{\sseq@msgpatchfailed}
\apptocmd\__sseq_hooked_msg_fatal_code:nnnnnn  {\sseq@error@cleanup}{}{\sseq@msgpatchfailed}
\apptocmd\__sseq_hooked_msg_error_code:nnnnnn  {\sseq@error@cleanup}{}{\sseq@msgpatchfailed}
%\apptocmd\__sseq_hooked_msg_warning_code:nnnnnn{\sseq@error@cleanup}{}{\sseq@msgpatchfailed}
%\apptocmd\__sseq_hooked_msg_info_code:nnnnnn   {\sseq@error@cleanup}{}{\sseq@msgpatchfailed}
\patchcmd \__sseq_hooked_interupt_wrap:nnn {\str_count:N\l__msg_text_str-\str_count:N\l__msg_name_str +2} {2} {}{\sseq@msgpatchfailed}

\sseq@breakpoint



%%%%
%%%%
%%%% Error message definitions
%%%%
%%%%


%%
%%
%% checkdefinitions -- patch-failed errors
%%
%%
\@ifpackagelater{tikz}{2015/07/08}{
    \sseq@newerror@internal{pgfkeys-patch-failed}{Failed to patch the key value system. Setting all commands to do nothing and quitting. Your copy of tikz is newer than the version 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 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 {spectralsequences} {pgfkeys-patch-failed}
}

\sseq@newerror@internal{expl3-incompatibility}{Since this version of spectralsequences, the expl3 definition of #1 was updated in an incompatible way.}

\sseq@newerror@internal{this-shouldnt-happen}{This branch of the code should be unreachable. Something really weird has happened. Error occurred in #1.}

% Convexity thing
\sseq@newerror{clip-not-convex}{The clip you provided to the "clip" option was not convex and the current edge intersects it more than two times. I'm not going to draw it.}


%%
%%
%% loadstore
%%
%%
\sseq@newerror@internal{illegal-add-background-mode}{\string#1 occurred in background mode.}



%%
%%
%% macromakers
%%
%%
\sseq@newerror@internal{U-xparse-incompatible}{The 'U' argument type is incompatible with the current version of xparse.}
\sseq@newerror{wont-override-builtin}{Macro '#1' is a spectralsequences built in and I won't override it. Try a different name.}
\sseq@newerror{usermacro-not-free}{Macro '#1' has already been defined using \string\DeclareSseqCommand, \string\NewSseqCommand, \string\DeclareSseqGroup, or \string\NewSseqGroup. I am overriding it. If this is what you intended, you should either use \@nx\DeclareSseqGroup or \string\DeclareSseqCommand, which won't complain.}

\sseq@newerror{macro-patch-failed}{Failed to patch macro '#1'. This is probably some annoying catcode issue. Try \@nx\tracingpatches to see more information about why the patch failed.}
\sseq@newerror{usermacro-unsupported-argument-type}{Unsupported argument type '#1'. All argument types in the 2017/05/29 release of xparse are supported except for v, e, and E.}

%%
%%
%% parsers
%%
%%
\sseq@newerror{classpattern-already-defined}{Class pattern '#1' already defined. Overwriting it.}
\sseq@newerror{classpattern-invalid-math-expression}{Expression '#1' encountered in class pattern definition is not a valid math expression. Skipping the definition.}
\sseq@newerror{classpattern-unexpected-token}{Unexpected token '#1' in class pattern definition. Skipping the definition.}
\sseq@newerror{classpattern-missing-tokens}{Incomplete class pattern definition. Skipping the definition.}
\sseq@newerror{classpattern-extra-coord-ignored}{Extra coordinate '#1' ignored in row #2. You probably forgot a semicolon.}
\sseq@newerror{classpattern-too-few-coords}{Too few coordinates in row #1.}

\sseq@newerror{classpattern-too-many-classes}{%
    Too many classes in position #1. You are trying to add a #2th class, but the current class pattern is "#3" which only defines offset patterns for up to #4 classes.
    If you need to have this many classes in this position, you can make your own class pattern with \string\sseqnewclasspattern, but you might want to consider alternatives like using one class to represent multiple generators in some way -- it is hard to make a diagram look good with large numbers of classes in one position.%
}

\sseq@newerror{invalid-coordinate}{Invalid #1coordinate\sseq@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.}
\sseq@newerror{named-coordinate-class}{You can't pass a named coordinate to \string\class.}

\sseq@newerror{d-no-degree}{%
    If you want to use the differential command \string\d\ you must either specify the grading of the differential or explicitly provide a target coordinate for the differential.
    Specify the degree by providing 'degree={f(\#1)}{g(\#1)}' as an option to '\string\begin{sseqdata}',
    where f(\#1) and g(\#1) are formulas for the x and y degree of the \#1th page differential. Alternatively, you may say e.g., '\string\d2(source)(target)'%
}
\sseq@newerror{d-named-coord-two-indexes}{You provided a named class and two indexes, but the named class already comes with an index so you can only provide one more for the target. Ignoring the second index.}% should be a warning
\sseq@newerror{d-target-index-target-coord}{You provided both a target index and a target coordinate, but this overdetermines the differential. Ignoring the target index.}
\sseq@newerror{d-wrong-degree}{Differential does not respect grading. The target should be in position #1 but instead it is #2 in position #3.}

\sseq@newerror{index-ignored}     {The coordinate #1 is not a class, but it has an index '#3'. Ignoring the index and treating it as the literal position #2.}
\sseq@newerror{anchor-ignored}    {The coordinate #1 is not a class, but it has an anchor '#3'. Ignoring the anchor and treating it as the literal position #2.}
\sseq@newerror{invalid-tikz-coord}{The coordinate #1 does not refer to a tikz class but its #2 coordinate is not valid \string\pgfmathparse\ input.}

% handlers
\sseq@newerror{NormalizeMonomial-invalid-exponent}{The exponent #1 of the variable #2 in the monomial #3 is not a valid integer expression. Giving up on processing this monomial -- I will leave it alone and hope for the best.}
\sseq@newerror{AHSSNameHandler-missing-cell}{The name #1 has no cell (an integer expression surrounded by brackets). Giving up on processing it and returning my input in \string\result.}
\sseq@newerror{AHSSNameHandler-invalid-integer}{The cell degree #1 of #2 is not a valid integer expression. I am leaving it alone, but I processed the monomial.}



%%
%%
%% foreach
%%
%%
\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.}




%%
%%
%% keys
%%
%%

\def\sseq@possiblecurrentvalue{\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi}
\def\sseq@possiblecurrentvaluemean{\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else={\@xp\sseq@macrogobble\meaning\pgfkeyscurrentvalue}\fi}

\sseq@newerror{option-illegal}{%
    You said '#1\sseq@possiblecurrentvalue', but the option '#1' is
    illegal in the sseqdata and sseqpage environments#3.%
}
\sseq@newerror{option-illegal-as-global}{%
    You passed '#1\sseq@possiblecurrentvalue' as a global option, but option '#1' is illegal as a global option.%
}
\sseq@newerror{option-global-only}{%
    You said '#1\sseq@possiblecurrentvaluemean', but the option '#1' is
    only allowed as a global option (as in '\string\begin{sseqdata}[#1\sseq@possiblecurrentvaluemean]'
    or '\string\begin{sseqpage}[#1\sseq@possiblecurrentvaluemean]').%
}


% Applies to name and page. Saying "sseqs={name=somename}" is a bad idea.
\sseq@newerror{option-no-default-allowed}{%
    You cannot set a default value for '#1'.% Try \@nx\sseqset{sseqs={#1\ifx\pgfkeyscurrentvalue\pgfkeysnovalue@text\else=\pgfkeyscurrentvalue\fi}}.%
}
\sseq@newerror{option-tikz-prims-only}{%
    You can only use '#1' as an option for tikz primitives, not for \@nx\class, \@nx\replaceclass, \@nx\classoptions, \@nx\d, \@nx\doptions, \@nx\structline, or \@nx\structlineoptions.%
}

\sseq@newerror{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 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'.%
}

\sseq@newerror{unknown-key}{I do not know the key "\pgfkeyscurrentname".}
\sseq@newerror{unknown-global}{Undefined global option '\pgfkeyscurrentname\@xp\ifx\pgfkeyscurrentvalue\pgfkeysnovalue\else=\pgfkeyscurrentvalue\fi'.}

\sseq@newerror{scope-quotes}{Quotes are not allowed as options to a scope.}
\sseq@newerror{tikz-edge-quotes}{If you want to use quotes on a tikz edge, please provide it directly to the 'to' command e.g., \@nx\draw (0,0) to["hi"] (1,0);}

\sseq@newerror{change-style-data}{It's pointless to use 'change #1s' in the sseqdata environment. Try '#1s={##1}' instead.}
\sseq@newerror{change-style-standalone}{It's pointless to use 'change #1s' in a standalone sseqpage environment. Try '#1s={##1}' instead.}
\sseq@newerror{page-update-existing}{Option 'update existing' is only for the sseqdata environment.}
\sseq@newerror{page-no-name}{You can't specify a page but no name.}
\sseq@newerror{keep-changes-no-name}{Option 'keep changes' is only for named spectral sequences.}
\sseq@newerror{only-for-sseqpages}{Option '#1' is only for the sseqpage environment.}
\sseq@newerror{unknown-grid}{Undefined grid style '#1'.}
\sseq@newerror{unknown-class-pattern}{Unknown class pattern '\sseq@classpattern'.}
\sseq@newerror{class-placement-shift}{Shifts are illegal in the transformations applied in "class placement" key. If you want to shift your nodes, use \string\sseqnewclasspattern.} % #1 <- x shift, #2 <- shift amount
\sseq@newerror@internal{do-command-failed}{\string\sseq@pgfkeysdocommand{#1}{#2} failed.}

\sseq@newerror{standard-parse}{You cannot use \string#1 inside a scope that has either the background key or coordinate transformations other than integer shifts.}

\sseq@newerror{no-tooltip}{You cannot use the 'tooltip' option without either using the 'tooltips' package option or giving your own definition for '\string\sseqtooltip'.
    Tooltips aren't enabled by default because they use the 'pdfcomment' package which creates two extra auxiliary files.%
}

%%
%%
%% main
%%
%%

\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'.}
\sseq@newerror{env-data-already-exist}{A spectral sequence with the name '#1' already exists; updating it. If you want to add to an already existing spectral sequence, please pass the option 'update existing'.} % warning
\sseq@newerror{env-page-not-exist}{No spectral sequence named '#1' exists. Making a new one.} % warning


\sseq@newerror{is-alive-illegal-here}{You can't use \@nx\isalive outside of a page constraint for a tikz primitive.}

\sseq@newerror{no-range}{Empty spectral sequence. For every spectral sequence you must either specify both the "x range" and "y range" or include at least one
\string\class.} % maybe warning?
\sseq@newerror{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.}


\sseq@newerror{cmdoptions-only}{You can only use the '#1' option with #2, not with #3.} % warning
\sseq@newerror{cmdoptions-without-options}{There is no reason to use \string#1 without giving options.} % warning
\sseq@newerror{cmdoptions-feature-doesn't-exist}{There is no #1 of the form '\sseq@thiscall' so I can't add options to it.}

\sseq@newerror{classoptions-already-dead}{Generation #1 of the class #2 perished on page #3 so there is no reason to add an option to it on page \sseq@thepage.}
\sseq@newerror{classoptions-not-yet-born}{Generation #1 of the class #2 is not yet present on page \sseq@thepage\ so there is no reason to add an option to it.}
\sseq@newerror{classoptions-page-gen}{Don't use both "page" and "generation" for the same \@nx\classoption command.} % warning
\sseq@newerror{classoptions-class-already-named}{The class \coord\ already is named '\sseq@obj{class.\classname.name}'. Overwriting it. Use \@nx\nameclass if you want to give it a second name.}%warning
\sseq@newerror{doptions-invisible}{Cannot add options to invisible differential.}
\sseq@newerror{doptions-no-effect-on-this-page}{Adding an option to a differential on page #1 when the current page is \sseq@thepage\ and the 'keep changes' option is not present has no effect.}

\sseq@newerror{class-tag-already-defined}{A class with tag '#1' is already defined in position #2. Overwriting it.} % warning

\sseq@newerror{replaceclass-not-dead-yet}{I cannot replace the class at #1 because it seems to be alive and well.}
\sseq@newerror{replaceclass-no-effect-on-this-page}{The class at #1 died on page #2 so replacing it only affects pages after #3, but the current page is \sseq@thepage.} % warning
\sseq@newerror{replacestructlines-class-not-replaced}{I cannot replace the structlines on #1 because it has not been replaced.}


\sseq@newerror{d-invalid-page}{Invalid page '#1'.}
\sseq@newerror{d-class-already-hit}{% #1 <-#3, #2 <-\csname #3name\endcsname, #3 <- #2, #4 <- \unexpanded\@xpthree{\sseq@obj{\sseq@temp.deathinfo}}
    The #1 #2 of differential \sseq@thiscall\ on page #3 has already been the #4.
    Use \string\replaceclass#2 before \sseq@thiscall.%
}
\sseq@newerror{d-class-has-extension}{The #1 #2 of differential \sseq@thiscall\ on page #3 has already been involved in an extension. If you are planning to replace it, move the \string\extension\ after the call to \string\replaceclass.}
\sseq@newerror{d-hit-same-page-replaceclass}{%#1 <- #3, #2 <- \csname #3name\endcsname, #3 <- #2, #3 <-\sseq@obj{#1[\the\sseq@tempcount].deathinfo},
    The #1 #2 of differential \sseq@thiscall\ was the #3.
    If multiple differentials touch a class on the same page, they cannot be separated by a \@nx\replaceclass command.%
}
\sseq@newerror{d-hit-wrong-order}{%
    The #1 #2 of differential \sseq@thiscall\ on page #3 has already been the #4.
    First use the shorter differential, then \string\replaceclass#2, then the longer differential.%
}


\sseq@newerror{structline-no-page-max}{You cannot provide \@nx\structline with the option "page=min--max", only with "page=min".} %warning
\sseq@newerror{structline-already-exists}{Cannot add a structline from #1 to #2 because such a structline already exists.}
\sseq@newerror{structline-stillborn}{#1 dies before it is born. Perhaps you meant to specify a different source or target?}
\sseq@newerror{extension-stillborn}{Either the source or target of extension is not currently alive. Perhaps you meant to specify a different source or target? Perhaps you forgot a call to \@nx\replaceclass?}
\sseq@newerror{edge-source-target-equal}{The source and target of a #1 cannot be equal.}


\protected\def\sseq@quiet{\msg_redirect_module:nnn{spectralsequences}{error}{info}}
\protected\def\sseq@endquiet{}

\ExplSyntaxOff