# Automate correct spacing after ! in math mode

$(2n)!/\bigl(n!\,(n+1)!\bigr)$
$${52!\over13!\,13!\,26!} + 33!! - y$$
$(2n)!/\bigl(n!(n+1)!\bigr)$
$${52!\over13!13!26!} + 33!! - y$$\bye


How could we automate the spacing after !? As explained in the TeXBook, ! requires manual handling of spacing after it. I would like to see what ideas do you have that would lead to correct spacing (first two lines) with input similar to the usual (last two lines).

I added the case of !! which should have no space in between, the rest is from the TeXBook. It's a plainTeX because of that, but any solution would be nice.

You can try the macro \mathexclam:

\def\mathexclam{\futurelet\next\mathexclamA}
\def\mathexclamA{%
\expandafter\ifx\space\next
\def\next{\afterassignment\mathexclam\let\next= }\expandafter\next
\else \edef\tmpb{\meaning\next}\let\tmpa=\mathpunct
\expandafter\expandafter\expandafter\mathexclamB\expandafter\tmpb\string\mathchar\end
\iftrue \expandafter\mathexclamC\tmpb\end
\else \mathexclamD !+-*/=<>,.)]\}\bigr\biggr\Bigr\Biggr\right\over\egroup$\relax \fi \tmpa{\mathchar!}% \ifx\tmpa\mathpunct \mathchoice{}{}{\,}{\,}\fi \fi } \expandafter\def\expandafter\mathexclamB\expandafter#\expandafter1\string\mathchar#2\end#3{% \ifx^#1^% } \def\mathexclamC#1"#2#3\end{% \ifnum#2=1 \let\tmpa=\mathord \fi % Big OP \ifnum#2=2 \let\tmpa=\mathord \fi % Bin \ifnum#2=3 \let\tmpa=\mathord \fi % Rel \ifnum#2=5 \let\tmpa=\mathord \fi % Close \ifnum#2=6 \let\tmpa=\mathord \fi % Punct } \def\mathexclamD#1{\ifx#1\relax \else \ifx#1\next \let\tmpa=\mathord\fi \expandafter\mathexclamD \fi } {\catcode!=13 \global\let!=\mathexclam} \mathcode!="8000$(2n)!/\bigl(n!(n+1)!\bigr)$,$1\over 2!3!$. $${52!\over13!13!26!} + 33!! - y$$ \bye  This macro first ignores the spaces after !. The spaces are non-significant in math mode. Then the \mathexclamB does a test if the next token is deflared as \mathchardef (for example \le). If it is true then \mathexclamC is processed. Else the explicit list of exceptions is processed by \mathexclamD. The ! is typeset as \mathpunct by defualt. But if the next token is Op, Bin, Rel Close or Punct (declared by \mathchadef) then ! is typeset as \mathord. Moreover, if next token is one from the list of exceptions used after \mathexclamD then ! is typeset as mathord too. • Nice. Note, however, that \mathpunct doesn't add the thin space in scriptstyle, so the output in $1\over 2!3!\$ will not be as expected. So probably the macros should add \, explicitly when needed, not relying on \mathpunct. – egreg Feb 11 '15 at 10:51
• Thanks, I added a little code in order to tread spaces in scriptstyle. But I know that the macro cannot be universal or general. There are many exceptions... – wipet Feb 11 '15 at 12:16
• Yes, my impression is that it's easier to remember adding \, when typing. The thirteen kinds of atoms are not really sufficient for completely automatic typesetting. There should be a Factorial atom for this application and also a Slash atom for the fraction slash, rather than considering it an ordinary atom. – egreg Feb 11 '15 at 12:37
• This is acceptable nice, in this case it's not about remembering adding \, but implementing this correct spacing in an already written two hundred pages document. Besides it would be nice to have it automated. @egreg That last comment of yours, since it's not possible to “create new atoms” with TeX macros, would it be possible to implement a new system based on a \count which each math symbol sets to a number, and then the next one adds certain space based on the value of that \count? – Manuel Feb 11 '15 at 14:30
• @Manuel The problem is that you can't know what follows until the math list is fully built. How many expansion steps will you perform? What if you have \newcommand\npi{(n+1)} and \npi` is buried in another macro? – egreg Feb 11 '15 at 15:42