15

I have the following MNWE and don't understand why this fails.

\documentclass{article}
\usepackage{amsmath}
\begin{document}
$\dots \left. \right.$
\end{document}

Understanding the relevant code in amsmath proves to be rather difficult and I can't find a mention anywhere that this is somehow not OK to do. Of course I can use some of the more specialized dot commands to get rid of the guessing \dots does. I would be extra grateful for an explanation of what the trick with \uppercase in all the helper definitions(\striplong@...) and using \meaning in \mdots is.

4
  • 1
    it's a bug, hang on I'll see what it's doing.... May 8, 2016 at 20:47
  • Who's planted it? ;-) It works with TL2014.
    – egreg
    May 8, 2016 at 20:53
  • @egreg yes but long macros (like amsmath defined arrows don't work in 2014:-) May 8, 2016 at 20:57
  • Another reason not to use \left/\right... May 11, 2016 at 7:10

1 Answer 1

16

UPDATE this is fixed in release 2.15d (sent to ctan today, 2016-06-28, so will be reaching distributions is a few days.)


This is a bug (sorry ask @egreg who did it:-) until a fix is made available you can use

 $\dots\relax \left. a \right.$

Rather than change the document, you can fix the definition of \striplong@ as follows

\documentclass{article}
\usepackage{amsmath}
{\catcode`\@=11 \uccode`9=`\l \uccode`8=`\o %
 \uppercase{\gdef\striplong@#1#2#3#4\relax{%
  \ifx9#2\ifx8#3\@xp\@xp\@xp\@xp\@xp\@xp\@xp\zap@to@space\fi\fi}}}

\begin{document}
a$x$

$\dots \left. a \right)$
\end{document}

UPDATE

There are other cases that can trigger the same error (probably less likely to occur except in test files) basically any primitive starting with l so I think this is a better fix. It looks complicated as it is patching a largeish macro but the actual suggested change here is a singe space character being added (. ......... instead of ..........)

\documentclass{article}
\usepackage{amsmath}

\makeatletter
\def\mdots@@{\gdef\thedots@{\dotso@}%
 \ifx\@let@token\boldsymbol 
   \gdef\thedots@\boldsymbol{\boldsymboldots@}%
 \else
   \ifx,\@let@token \gdef\thedots@{\dotsc}%
   \else
     \ifx\not\@let@token
       \gdef\thedots@{\dotsb@}%
     \else
       \keybin@
       \ifgtest@ % if \keybin@ test
         \gdef\thedots@{\dotsb@}%
       \else
%    \end{macrocode}
% The space below ensures that |\zap@to@space| never gets a runaway argument.
% (If |\meaning@| is |\left|, |\long|, |\looseness| in which case later tests will see |.|
% and choose |\ldots| as required.)
%    \begin{macrocode}
         \xdef\meaning@{\meaning\@let@token. .........}%
%    \end{macrocode}
% In previous versions \verb|\long| macros were not seen.
% Bad as this file uses \verb|\(re)newcommand| for \verb|\implies| etc.
%    \begin{macrocode}
         \xdef\meaning@@{\@xp\striplong@\meaning@\relax\meaning@}%
%    \end{macrocode}
%    \begin{macrocode}
         \@xp\math@\meaning@\math@
         \ifgtest@ % if \mathxxx test
           \@xp\mathch@\meaning@\mathch@
           \ifgtest@ % if \mathchar
             \@xp\getmathch@\meaning@\getmathch@
           \fi % end if \mathchar
         \else  % \not \mathxxx
%    \end{macrocode}
% Test for \verb|\Umathchar| added.
%    \begin{macrocode}
             \@xp\Umathch@\meaning@"0"\Umathch@
             \ifgtest@ % if \Umathchar
             \else % else not \Umathcar
%    \end{macrocode}
%    \begin{macrocode}
           \@xp\macro@\meaning@@\macro@
           \ifgtest@ % if macro test
             \@xp\not@\meaning@\not@
             \ifgtest@ % if macro starts \not test
               \gdef\thedots@{\dotsb@}%
             \else% else not \not
               \@xp\DOTS@\meaning@\DOTS@
               \ifgtest@ % \if DOTS
                 \ifcase\number\DOTSCASE@ %ifcase dots
                   \gdef\thedots@{\dotsb@}%
                 \or\gdef\thedots@{\dotsi}\else
                 \fi % endifcase dots
               \else % not macro starts \DOTS
                 \@xp\math@\meaning@\math@
                 \ifgtest@ % \if macro starts \mathxxxx
                   \@xp\mathbin@\meaning@\mathbin@
                   \ifgtest@ % if macro starts \mathbin
                     \gdef\thedots@{\dotsb@}%
                   \else % not macro starting \mathbin
                     \@xp\mathrel@\meaning@\mathrel@
                     \ifgtest@ % if macro starts \mathrel
                       \gdef\thedots@{\dotsb@}%
                     \fi % endif macro starts \mathrel (no else)
                   \fi % endif macro starts \mathbin
                 \fi % endif macro starts with \mathxxx (no else)
               \fi % endif macro starts \DOTS else
             \fi % end macro  starting \not \ifgtest@ test (no else)
%    \end{macrocode}
% Additional test for a catcode 12 character.
%    \begin{macrocode}
             \else
               \@xp\thecharacter@\meaning@\thecharacter@
%    \end{macrocode}
%    \begin{macrocode}
             \fi % end macro \ifgtest@ test (no else)
           \fi % end if \Umathchar test
         \fi % end \math@   \ifgtest@ 
       \fi % end \keybin@ \ifgtest@ test (no else)
     \fi % end if \not (no else)
   \fi % end if comma (no else)
 \fi % end if boldsymbol (no else)
 \thedots@}
\makeatother

\begin{document}
a$x$

$.\dots \left. a \right)$


$.\dots \long\def\zzz{} x$


$.\dots \looseness=1 x$

$.\dots \longrightarrow x$


$.\dots + x$


\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .