I'm reading source2e.pdf and I have problems in understanding the sense of the definition of LaTeX 2ε's \@esphack
:
Commands like \label{...}
, which themselves do not/shall not produce any visible output, might in the source/in the .tex-input-file be surrounded by spaces. If so, you don't want two space-tokens as this would double the horizontal glue.
If I got it right, \@bsphack
and \@esphack
are there for avoiding the coming into being of a space-token after tokenizing and processing the command in case there already came one into being before tokenizing and processing the command.
So let's look at the definition of \@bsphack
:
> \@bsphack=macro:
->\relax \ifhmode \@savsk \lastskip \@savsf \spacefactor \fi .
l.1 \show\@bsphack
In words:
When in horizontal mode or in restricted horizontal mode, then save the value of \lastskip
to \@savsk
and save the value of \spacefactor
to \@savsf
.
Now let's look at the definition of \@esphack
:
> \@esphack=macro:
->\relax \ifhmode \spacefactor \@savsf \ifdim \@savsk >\z@ \ifdim \lastskip =\z
@ \nobreak \hskip \z@skip \fi \ignorespaces \fi \fi .
l.2 \show\@esphack
In words:
When in horizontal mode or in restricted horizontal mode, then:
- restore the value of
\spacefactor
to the value saved as\savsf
. - In case
\@savsk
is larger than zero, i.e., in case there was some horizontal glue before carrying out the command which at its start called\@bsphack
, then do
\ifdim \lastskip =\z@ \nobreak \hskip \z@skip \fi \ignorespaces
.
I understand that \ignorespaces
will make sense as there was already some horizontal glue before carrying out the command which at its start called \@bsphack
.
But I don't understand what the
\ifdim \lastskip =\z@ \nobreak \hskip \z@skip \fi
-part is good for.
What is the sense of this?
In the situation where this is carried out, the saved value in \@savsk
is larger than \z@
, thus one can conclude that something from within the command which at its start called \@bsphack
did change the value of \lastskip
to \z@
.
But doing something like \nobreak\hskip\z@skip
will not revert that change/will not restore \lastskip
to its previous value.
Thus: What is the gist/sense/benefit of performing that \hskip
of zero-width?
If you wish \lastskip
to be restored, shouldn't it then be something like:
\def\@esphack{%
\relax
\ifhmode
\spacefactor\@savsf
\ifdim\@savsk>\z@
\ifdim\lastskip=\z@
\nobreak
\hskip-\@savsk
\nobreak
\hskip\@savsk
% the total skip is zero and \lastskip is restored.
\fi
\ignorespaces
\fi
\fi
}%
Or perhaps just
\def\@esphack{%
\relax
\ifhmode
\spacefactor\@savsf %now \spacefactor is restored.
\nobreak
\hskip-\@savsk
\nobreak
\hskip\@savsk
% the total skip is zero and \lastskip is restored.
\ifdim\@savsk>\z@
\ignorespaces
\fi
\fi
}%
Is it possible that in some previous release, it was done this way and in later releases somebody erroneously "optimized" the
\nobreak\hskip-\@savsk\nobreak\hskip\@savsk
to \nobreak\hskip\z@skip
, overlooking that this won't restore \lastskip
any more?
If I understand correctly, you need to restore \lastskip
correctly as otherwise things with consecutive sequences of \@bsphack..\@esphack
, e.g., \label{foo}\label{bar}
won't work correctly:
If by now you do something like
A \label{foo} \label{bar} A
or
A \label{foo}\label{bar} A
, \lastskip
will in any case be 0 after \label{foo}
which affects the behavior of \label{bar}
because with \label{bar}
\@savsk
will not be larger than \z@
any more so that \ignorespaces
won't get carried out although it should be carried out!
With the example below you can see a subtle difference when redefining \@esphack
so that it restores \lastskip
:
\documentclass{article}
\newsavebox\mybox
\begin{document}
\par\noindent\begin{lrbox}{\mybox}
\verb*|A\label{1}B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A\label{1}B
\par\noindent\begin{lrbox}{\mybox}
\verb*|A \label{2} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{2} B
\par\noindent\begin{lrbox}{\mybox}
\verb*|A \label{3}\label{4} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{3}\label{4} B
\par\noindent\begin{lrbox}{\mybox}
\verb*| \label{5} \label{6} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{5} \label{6} B
\makeatletter
\def\@esphack{%
\relax
\ifhmode
\spacefactor\@savsf
\ifdim\@savsk>\z@
\ifdim\lastskip=\z@
\nobreak
\hskip-\@savsk
\nobreak
\hskip\@savsk
% the total skip is zero and \lastskip is restored.
\fi
\ignorespaces
\fi
\fi
}%
\makeatother
\noindent\null\hrulefill\null
\par\noindent\begin{lrbox}{\mybox}
\verb*|A\label{a}B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A\label{a}B
\par\noindent\begin{lrbox}{\mybox}
\verb*|A \label{b} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{b} B
\par\noindent\begin{lrbox}{\mybox}
\verb*|A \label{c}\label{d} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{c}\label{d} B
\par\noindent\begin{lrbox}{\mybox}
\verb*|A \label{e} \label{f} B|:
\end{lrbox}\hbox to 4.5cm{\usebox\mybox\hfil} A \label{e} \label{f} B
\end{document}
Does my modification of \@esphack
have drawbacks?
Am I overlooking some caveat/something relevant?