\ldots
is using \mathellipsis
for the dots. It could be redefined to use the text version, but the mixup of text and math fonts might not always a good idea.
\mathellipsis
itself uses three dots as punctuation characters. That means, there is additional thin space between the dots. This can be changed by putting them into a subformula, then they are treated as \mathord
atoms without additional space.
\documentclass[12pt]{article}
\usepackage{amsmath}
\renewcommand*{\mathellipsis}{%
\mathinner{{\ldotp}{\ldotp}{\ldotp}}%
}
\begin{document}
$1,2,\ldots,3$
$(1,2,\ldots)$
\end{document}
Smaller spaces
Usually thin space is the smallest space in math mode, but to some degree \ldots
can be adopted to smaller spaces:
\documentclass[12pt]{article}
\usepackage{amsmath}
\usepackage{letltxmacro}
\renewcommand*{\mathellipsis}{%
\mathinner{{\ldotp}{\ldotp}{\ldotp}}%
}
\makeatletter
\@ifdefinable{\org@ldots}{%
\LetLtxMacro\org@ldots\ldots
\DeclareRobustCommand*{\ldots}{%
\ifmmode
\expandafter\my@ldots
\else
\expandafter\textellipsis
\fi
}%
}
\newcommand*{\neghalfmskip}{%
\nonscript\mskip-.5\muexpr\thinmuskip\relax%
}
\newcommand*{\my@ldots}{%
\mathellipsis
\@ifnextchar,\neghalfmskip{%
\@ifnextchar:\neghalfmskip{%
\@ifnextchar;\neghalfmskip{%
\@ifnextchar.\neghalfmskip{%
\@ifnextchar!\neghalfmskip{%
\@ifnextchar?\neghalfmskip{%
\@ifnextchar){\mskip-.5\muexpr\thinmuskip\relax}{% negative kerning
}}}}}}}%
}
\makeatother
\begin{document}
\noindent
$1,2,\ldots,3_{1,2,\ldots,3}$ (ldots)\\
$1,2,\mathellipsis,3_{1,2,\mathellipsis,3}$ (mathellipsis)\\
$(1,2,\ldots)_{(1,2,\ldots)}$ (ldots)\\
$(1,2,\mathellipsis)_{(1,2,\mathellipsis)}$ (mathellipsis)
\end{document}
TeX sets a thin space between inner atoms and punctuation chars in display and text style only, therefore the use of \nonscript
. There is no space in case of the closing )
, but because of the character shape, you probably want to have a negative kerning, this is applied in all math styles.
More generalized detection of a closing delimiter
The example uses Andrew's hint of \rightdelim@
:
\documentclass[12pt]{article}
\usepackage{amsmath}
\usepackage{letltxmacro}
\renewcommand*{\mathellipsis}{%
\mathinner{{\ldotp}{\ldotp}{\ldotp}}%
}
\makeatletter
\@ifdefinable{\org@ldots}{%
\LetLtxMacro\org@ldots\ldots
\DeclareRobustCommand*{\ldots}{%
\ifmmode
\expandafter\my@ldots
\else
\expandafter\textellipsis
\fi
}%
}
\newcommand*{\neghalfmskip}{%
\nonscript\mskip-.5\muexpr\thinmuskip\relax%
}
\newcommand*{\my@ldots}{%
\mathellipsis
\@ifnextchar,\neghalfmskip{%
\@ifnextchar:\neghalfmskip{%
\@ifnextchar;\neghalfmskip{%
\@ifnextchar.\neghalfmskip{%
\@ifnextchar!\neghalfmskip{%
\@ifnextchar?\neghalfmskip{%
\rightdelim@
\ifgtest@
\mskip-.5\muexpr\thinmuskip\relax% negative kerning
\fi
}}}}}}%
}
\makeatother
\begin{document}
\noindent
$1,2,\ldots,3_{1,2,\ldots,3}$ (ldots)\\
$1,2,\mathellipsis,3_{1,2,\mathellipsis,3}$ (mathellipsis)\\
$(\neghalfmskip\ldots)_{(\neghalfmskip\ldots)}$ (neghalfmskip + ldots)\\
$(\ldots)_{(\ldots)}$ (ldots)\\
$(\mathellipsis)_{(\mathellipsis)}$ (mathellipsis)\\
$\{\ldots\}_{\{\ldots\}}$ (ldots)\\
$\{\mathellipsis\}_{\{\mathellipsis\}}$ (mathellipsis)
\end{document}
But for the detection of an opening delimiter before I do not see a way. There isn't a "\lastmathatom
". Manually the space correction can be applied as the example file shows with \neghalfmskip
.
It's theoretically possible to make LaTeX recognize clusters of letters and typeset them as if they were input as argument to \mathit
, but it would be deadly slow: each alphabetic character should be turned into a “math active” one, which checks whether the following item is an alphabetic character; if it is it should typeset itself, starting \mathit
if it's the first one, and then pass the same control to the next character; if not followed by an alphabetic character it should end \mathit
.
It's instead better to do something like
\newcommand{\mli}[1]{\mathit{#1}}
where \mli
stands for MultiLetter Identifier; use any control sequence name. Then you'd input
$\mli{P}=\mli{NP}$
that has a good deal of advantages, but mainly keeps information about the input.
Note: I have a nice proof of the above statement, but unfortunately there are length limitations for posts on this site.
Heiko's solution in expl3
.
\documentclass[fleqn]{article}
\usepackage{xcolor}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
% 1. Define an equivalent for each letter
\cs_new_protected:Nn \__egreg_letter_loop:nn
{
\int_step_inline:nnn { `#1 } { `#2 }
{
\exp_args:Nc \mathchardef
{ __egreg_letter_code_##1: } % generate the old code
=
\mathcode##1 % the old code
\scan_stop:
\cs_new_protected:cx { __egreg_letter_act_##1: }
{
\exp_not:N \__egreg_letter_scan:nw { ##1 }
}
\char_set_active_eq:nc { ##1 } { __egreg_letter_act_##1: }
}
}
\__egreg_letter_loop:nn { A } { Z }
\__egreg_letter_loop:nn { a } { z }
% 2. Define the main macro that does the scanning
\tl_new:N \l__egreg_letter_scanned_tl
\cs_new_protected:Npn \__egreg_letter_scan:nw #1
{
\tl_if_empty:NT \l__egreg_letter_scanned_tl { \c_group_begin_token } % to be closed later
\tl_put_right:Nx \l__egreg_letter_scanned_tl { \exp_not:c { __egreg_letter_code_#1: } }
\peek_catcode:NF A
{% next char is not a letter
\__egreg_letter_deliver:V \l__egreg_letter_scanned_tl
}
}
\cs_new_protected:Nn \__egreg_letter_deliver:n
{
\tl_if_single:nTF { #1 }
{
\__egreg_letter_single:n { #1 }
}
{
\__egreg_letter_group:n { #1 }
}
\c_group_end_token % finish the group
}
\cs_generate_variant:Nn \__egreg_letter_deliver:n { V }
% 3. The interface for defining the actions
\NewDocumentCommand{\definelettersingle}{m}
{
\cs_set_protected:Nn \__egreg_letter_single:n { { #1 } }
}
\NewDocumentCommand{\definelettergroup}{m}
{
\cs_set_protected:Nn \__egreg_letter_group:n { { #1 } }
}
% 4. Make all letters math active
\int_step_inline:nnn { `A } { `Z } { \mathcode#1="8000 }
\int_step_inline:nnn { `a } { `z } { \mathcode#1="8000 }
\ExplSyntaxOff
% initialize
\definelettersingle{#1}
\definelettergroup{\mathit{#1}}
\begin{document}
First a standard formula $NP\ne N P$
\bigskip
Now \textcolor{blue}{single letters are set in blue},
\textcolor{red}{multiple letters in red}.
\begin{itemize}
\item Multiple letters are put in \verb|\mathit|:
\definelettersingle{{\color{blue}#1}}%
\definelettergroup{\mathit{\color{red}#1}}%
\[ NP \neq N P \]
\item Multiple letters are put in \verb|\mathrm|:
\definelettersingle{{\color{blue}#1}}%
\definelettergroup{\mathrm{\color{red}#1}}%
\[ NP\ (text) \neq N P\ (two\ variables) \]
\[ F_force = m_mass a_acceleration \]
\end{itemize}
\end{document}
Best Answer
It's incorrect to detach the
!
meaning “factorial” from the symbol preceding it, because it's a modifier similar to a prime or a subscript and is not a punctuation symbol.In case you have a factorial followed by an ordinary symbol (not a relation or operation symbol), it's good practice to add a thin space after it:
I've also shown what would happen when detaching the factorial symbol, in order to demonstrate it would be wrong.