summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/eqnnumwarn/eqnnumwarn.sty
blob: e88098daf2c5c00f1d88d7d45e61f8339a29367b (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
% Copyright (c) 2017 by Jonathan Gleason <jgleason@math.berkeley.edu>
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% This work consists of the file eqnnumwarn.sty.
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{eqnnumwarn}[2017/10/09 v1.0 Warnings for displaced equation numbers]

\RequirePackage{etoolbox}
\RequirePackage{xparse}
\RequirePackage{calc}
\RequirePackage{environ}
\RequirePackage{mathtools}
\RequirePackage{tikz}
\usetikzlibrary{cd}
\tikzcdset{ampersand replacement=\&} % This makes it so that "\&", not "&", is treated as the column separator in tikzcd environments.  (We do this so that it these environments can be passed as arguments (via "\BODY") to our redefinition of the equation environment.)  (See https://tex.stackexchange.com/questions/15093/.)
\let\old@tikzcd\tikzcd % So that we don't have to manually write "\&", we update the "tikzcd" environment so that it automatically replaces the "&"s with "\&"s.
\let\old@endtikzcd\endtikzcd
\RenewEnviron{tikzcd}[1][]{%
	\xpatchcmd*{\BODY}{&}{\&}{}{}% For compatibility with tikz.  (Also see \tikzcdset{ampersand replacement=\&} above.)
	\old@tikzcd[#1]%
	\BODY%
	\old@endtikzcd%
}

\NewDocumentCommand\intomargin{}{\def\enw@intomargin{1}}% Use this command if you would like to possibly shift the equation into the margin in order to avoid displacing the equation number.  Should place *before* environment.
\NewDocumentCommand\noeqnnumwarn{}{\def\enw@noeqnnumwarm{1}}% Use this command if you want to suppress the warning for a particular equation.  Should place *before* environment.

\newbox\temp@box
\newdimen\stest
\newdimen\smin
\newdimen\smax
\def\enw@find#1#2#3{% Used for \enw@getstretch and \enw@getshrink below.  (From https://tex.stackexchange.com/questions/191140/measure-total-glue-in-a-box)
	\let\old@hbadness\hbadness% Need to temporarily redefine \hbadness and \hfuzz so don't get a ridiculously number of warnings as we test for stretchability/shrinkability.
	\hbadness=1000000%
	\let\old@hfuzz\hfuzz%
	\hfuzz=\maxdimen%
	\smin = -\maxdimen
	\smax = \maxdimen
	\loop
	\stest = \smin
	\advance \stest by \smax
	\divide \stest by 2 % now \stest=(\smin+\smax)/2 truncated to 0
	\ifdim \stest = \smax
	\advance \stest by -1sp % ensure that \smin<=\stest<\smax.
	\fi
	\setbox 0 = \hbox spread #2 1sp {%
		\unhcopy\temp@box
		\hskip 0pt #3-\stest
	}%
	\ifnum \badness > 100 % (shrink/stretch in \temp@box) <= \stest
	\smax = \stest
	\else
	\smin = \stest
	\advance \smin by 1sp
	% since ">\stest" implies ">=\stest+1sp"
	\fi
	% In both cases, the interval [\smin,\smax] becomes smaller.
	\ifdim\smin<\smax
	\repeat
	\ifdim\smin>\smax\BOOM\fi% cannot happen, I think
	\hfuzz=\old@hfuzz%
	\hbadness=\old@hbadness%
}
\def\enw@getstretch#1{% Returns the amount of stretchable glue in the \smin register.
	\setbox\temp@box\hbox{#1}%
	\enw@find{stretch}{}{plus}%
}
\def\enw@getshrink#1{% Returns the amount of shrinkable glue in the \smin register.
	\setbox\temp@box\hbox{#1}%
	\enw@find{shrink}{-}{minus}%	
}

\ifdef{\mathindent}{}{\newlength{\mathindent}}% In case \mathindent hasn't been defined, define it. (Will be used in redefinition of equation environment.)
% Modifies "equation" environment to test if equation number has been displaced.
\newlength{\enw@widthofequation}
\newlength{\enw@widthofnumber}
\newlength{\enw@shrinkability}
\newlength{\enw@tagsep}
\def\enw@initializelengthsdisplaced{%
	\setlength{\enw@tagsep}{\mintagsep}% See the definition of \calc@shift@gather in amsmath.sty.  Note the line "\multiply\dimen@\tw@" (previously \dimen@ is defined to be \mintagsep), which is only done if fleqn is *not* activated.
	\if@fleqn\else\setlength{\enw@tagsep}{2\enw@tagsep}\fi% Thus, we have to multiply \enw@tagsep by 2 in this case.
	\enw@getshrink{\ensuremath{\BODY}}% Stores shrink in \smin.
	\setlength{\enw@shrinkability}{\smin}%
	\setlength{\enw@widthofequation}{\widthof{\ensuremath{\displaystyle\BODY}}}%
	\setlength{\enw@widthofnumber}{\widthof{\normalfont\normalcolor \tagform@\theequation}}% See definition of \@eqnum in amsmath.sty.
}

\newlength{\enw@tagdisplaced}
\def\enw@settagdisplaced{%
	\enw@initializelengthsdisplaced%
	\setlength{\enw@tagdisplaced}{%
		\enw@widthofequation -\enw@shrinkability +\enw@widthofnumber +\enw@tagsep -\displaywidth}% Should be displaced if this is greater than 0.
	\ifdimcomp{\enw@tagdisplaced}{<}{0pt}{%
		\setlength{\enw@tagdisplaced}{0pt}}{}%
	\ifx\print@eqnum\@empty% Don't actually issue the warning if an equation number was not to be displayed.
	\def\enw@tagdisplaced{0}%
	\fi%
}

\let\old@equation\equation
\let\old@endequation\endequation
\RenewEnviron{equation}{%
	\old@equation% Start equation environment.
	\gdef\enw@isequation{1}% Used as a flag so we know if other commands need to be redefined accordingly.
	%
	\ifdef{\enw@noeqnnumwarm}{}{\def\enw@noeqnnumwarm{0}}%
	\if1\enw@noeqnnumwarm%
	\BODY%
	\else%
	% Don't want to "label" twice, so we disable labeling here (will be "label"ed below when defining \@tempequationlength, and need the label to appear there because we want it to be measured when it comes to the legnth).
	\let\old@label\label%
	\renewcommand{\label}[1]{}%
	\let\old@footnote\footnote% Similarly for footnotes.
	\renewcommand{\footnote}[1]{}%
	% Actually test if the equation number has been displaced, and if so, give a warning.
	\enw@settagdisplaced%
	% Restore \footnote and \label commands.
	\let\footnote\old@footnote%
	\let\label\old@label%
	\ifdef{\enw@intomargin}{%
		\iftagsleft@%
		\setlength{\enw@tagdisplaced}{\enw@tagdisplaced+1sp}%
		\appto{\BODY}{\hspace*{-\enw@tagdisplaced}}% This allows the equation to shift to the right before displacing the equation number.
		\else%
		\setlength{\enw@tagdisplaced}{\enw@tagdisplaced+1sp}%
		\preto{\BODY}{\hspace*{-\enw@tagdisplaced}}%
		%\preto{\BODY}{\hspace{0pt minus \temp@smin}}% This allows the equation to shift to the left before displacing the equation number.
		\fi%
	}{}%
	\BODY% Display actual equation.
	\ifdef{\enw@intomargin}{\setlength{\enw@tagdisplaced}{0pt}}{}% So don't throw warning.
	\global\undef{\enw@intomargin}%
	\ifdimcomp{\enw@tagdisplaced}{>}{0pt}{%
		\PackageWarning{eqnnumwarn}{Equation number (\theequation ) has been displaced}}{}%
	\fi%
	\global\undef\enw@noeqnnumwarm%
	%
	\global\undef\enw@isequation%
	\old@endequation% Close equation environment.
}

% Credit goes to David Carlisle for these ideas.
\pretocmd{\place@tag@gather}{%`
	\ifshifttag@%
	\ifdef{\enw@noeqnnumwarm}{}{\def\enw@noeqnnumwarm{0}}%
	\if1\enw@noeqnnumwarm%
	\else%
	\PackageWarning{eqnnumwarn}{Equation number (\theequation ) has been displaced}%
	\fi%
	\fi%
}{}{}

\apptocmd{\place@tag}{%`
	\if1\shift@tag\row@%
	\ifdef{\enw@noeqnnumwarm}{}{\def\enw@noeqnnumwarm{0}}%
	\if1\enw@noeqnnumwarm%
	\else%
	\PackageWarning{eqnnumwarn}{Equation number (\theequation ) has been displaced}%
	\fi%
	\fi%
}{}{}

\AfterEndEnvironment{multline}{%
	\ifshifttag@%
	\ifdef{\enw@noeqnnumwarm}{}{\def\enw@noeqnnumwarm{0}}%
	\if1\enw@noeqnnumwarm%
	\else%
	\PackageWarning{eqnnumwarn}{Equation number (\theequation ) has been displaced}%
	\fi%
	\fi%
}

\endinput