7

edit: changed the MWE to show the problem with french babel

So, I was wondering about in TeX.sx and came upon this question How do magic \dots work in amsmath?, I wanted to do the same thing (have a \dots-aware macro).

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{xparse}
\usepackage[french]{babel}

\renewcommand*{\to}{%
    \DOTSB
    \myto
}
\NewDocumentCommand{\myto}{o}{%
    \IfValueTF{#1}{%
        \xrightarrow{#1}%
    }{%
        % default latex \to
        \mathchar"3221
    }%
}

\begin{document}
\(t\to[s]\dots\to[b]a\)
\end{document}

but the dots don't adapt. I did:

texdef -t latex -p amsmath DOTSB

and apparently \DOTSB is \relax, and the amsmath.sty file confirm this. Does anyone have a solution for this?

edit: I went with @egreg solution, because the other two conflicted with the split environment of amsmath.

2
  • That is because texdef is (like TeX itself) case sensitive: texdef -t latex -p amsmath dotsb yields \dotsb: macro:->\protect \cdots Mar 22, 2014 at 20:30
  • \dotsb is a semantic macro for 'dots for binary operator', I was talking about \DOTSB wich is (if I understood right) a macro used in amsmath.sty to define commands wich make \dots behave like \cdots
    – Zii8roZi
    Mar 22, 2014 at 20:35

3 Answers 3

3

There's a bug in the french module of babel. The \dots command is redefined to be

\relax\csname\ifmmode M\else T\fi dots@\endcsname

so in math mode \Mdots@ is executed, which expands to \@xp\mdots@, which is wrong: it should simply be \mdots@. Indeed, patching \dots gives the expected result:

\documentclass{article}

\usepackage{amsmath}
\usepackage{xparse}
\usepackage[french]{babel}
\usepackage{xpatch}

% the redefinition of \dots happens at begin document
% we simply remove one step: instead of the faulty
% \Mdots@ we do \mdots@
\AtBeginDocument{\xpatchcmd{\dots}{M}{m}{}{}}

\renewcommand*{\to}{%
    \DOTSB
    \myto
}
\NewDocumentCommand{\myto}{o}{%
    \IfValueTF{#1}{%
        \xrightarrow{#1}%
    }{%
        % default latex \to
        \rightarrow
    }%
}

\begin{document}
\(t\to[s]\dots\to[b]a\)
\end{document}

enter image description here

1
  • If it's a bug I expect a bug report to Jazos :-)
    – Joseph Wright
    Mar 22, 2014 at 21:52
4

\dots of amsmath checks the next token and also checks the meaning of the next macro if necessary, if it starts with \DOTSB. The parsing for an optional argument prevents this detection, because it is implemented by more than one macro (mainly because of \futurelet). Therefore \dots does not see \DOTSB, the marker used by \dots. The example splits the macro in an expandable part for \DOTSB and the other part for the arrow and the optional argument:

\documentclass{minimal}

\usepackage{amsmath}
\usepackage{xparse}

\renewcommand*{\to}{%
    \DOTSB
    \myto
}
\NewDocumentCommand{\myto}{o}{%
    \IfValueTF{#1}{%
        \xrightarrow{#1}%
    }{%
        % default latex \to
        \mathchar"3221
    }%
}

\begin{document}
\(t\to[s]\dots\to[b]a\)
\end{document}

Result

\usepackage[french]{babel}

This does not work for frenchb.ldf, because it redefines \dots and the definition of amsmath is gone.

The following example restores the \dots macro of amsmath inside math mode:

\documentclass{minimal}

\usepackage{letltxmacro}
\usepackage{amsmath}
\LetLtxMacro\amsmathdots\dots

\usepackage{xparse}
\usepackage[french]{babel}

\AtBeginDocument{%
  \LetLtxMacro\frenchdots\dots
  \everymath{\LetLtxMacro\dots\amsmathdots}%
  \everydisplay{\LetLtxMacro\dots\amsmathdots}%
}

\renewcommand*{\to}{%
    \DOTSB
    \myto
}
\NewDocumentCommand{\myto}{o}{%
    \IfValueTF{#1}{%
        \xrightarrow{#1}%
    }{%
        % default latex \to
        \mathchar"3221
    }%
}

\begin{document}
\(t\to[s]\dots\to[b]a\)
\end{document}
4
  • Your solution worked perfectly with the MWE, but when I tried it with the acctual document, it didn't. Apparently, there is a conflict with french babel, do you have any idea on how to fix it?
    – Zii8roZi
    Mar 22, 2014 at 20:52
  • Also, I would really love to understand why the texdef command returns \relax.
    – Zii8roZi
    Mar 22, 2014 at 20:53
  • @shilluc: Make a minimal example that shows the problem. Mar 22, 2014 at 20:53
  • 1
    @shilluc: \DOTSB is just used as marker for the previous \dots command. It does not need to do anything just sitting at the begin of the macro. Mar 22, 2014 at 20:54
3

A solution without xparse:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{letltxmacro,amsmath}
\LetLtxMacro\amsdots\dots
\usepackage[french]{babel}
\AtBeginDocument{%
  \LetLtxMacro\frenchdots\dots
  \everymath{\LetLtxMacro\dots\amsdots}%
  \everydisplay{\LetLtxMacro\dots\amsdots}%
}
\renewcommand*\to{\DOTSB\myto}
\newcommand*\myto[1][]{\if$#1$\dots\else\xrightarrow{#1}\fi}

\begin{document}
\( t\to[s]\dots\to[b]a \to\)
\end{document}

enter image description here

You must log in to answer this question.

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