31

Is there something I can add to the preamble of my document such that multiple letters without spacing in a Math environment (such as $NP$) do not have extra spacing between them and are not considered multiple distinct variables? Right now, I have to use $\mathit{NP}$ to prevent any extra spacing, but I feel that it is more natural to add a space between the letters if they are a different variable ($N P$).

For example, if I want the multi-letter variable NP, I want to be able to say $NP$ which would automatically be replaced by $\mathit{NP}$. If I want N and P to have the proper inter-variable spacing, I want to do that only when they are separated by a space, like so: $N P$.

Is there a way to achieve this? Would it break something that I'm unaware of?

Edit:

Here's a screenshot that shows what I mean:

enter image description here

So basically, is it possible for line 1 to automatically give me line 3 and for line 2 to give me line 2?

13
  • If you want spacing, you could do $A$ $B$. You dont need to have then in one inline math delimiter.
    – dustin
    Aug 21, 2013 at 14:03
  • 2
    I'm not sure I understand what you mean. If I'm typesetting Math, is it possible for $A B$ to imply, for example, multiplication and get the extra spacing, but for $AB$ to denote a multi-letter variable and not get the extra spacing, without having to use $\mathit{AB}$? I'd prefer to get the spacing only when there is a space between the symbols.
    – sudosensei
    Aug 21, 2013 at 14:06
  • In math mode, there is no spacing. That is $A B$ is the same as $AB$. If you want spacing, you either have to force a space with a slash or you can do $A$ $B$.
    – dustin
    Aug 21, 2013 at 14:09
  • 1
    @sudosensei I recommend using \cs{letters}, where \cs should be a meaningful command name. Slightly less comfortable for typing, surely better to maintain information about your content.
    – egreg
    Aug 21, 2013 at 15:32
  • 4
    Note it is not really spacing that is different between $NP$ and $\mathit{NP}$ It is a different font altogether and the fact that the spacing is larger is an effect of the of the math italic font being optimised for single letter variables whereas \mathit uses the text italic font which is designed for words, but as far as TeX is concerned no extra space is added between the letters. Aug 21, 2013 at 21:29

5 Answers 5

32

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}

enter image description here

3
  • Thank you, egreg. I'll mark this as the accepted answer in case someone is looking for a way to do this this without changing the default behaviour.
    – sudosensei
    Aug 22, 2013 at 13:59
  • Do you know an alternative math markup language which supports clusters of letters as multiletter identifiers by default? I tend to use multiletter identifiers a lot, and typesetting that with LaTEX is quite inconvenient.
    – matj1
    Feb 7 at 12:53
  • @matj1 It's possible, but it requires code that cannot be explained in a comment. Please, open a new question with the details and some examples of what you plan to do.
    – egreg
    Feb 7 at 13:41
26

Here the solution for "egreg's exercise for the reader". The following example makes the letters "math active" with the following features:

  • The letters are collected until a non-letter is reached. Single letters are passed to macro \mprintsingle, multiple letters are passed to macro \mprintmulti. Both macros have two arguments. The first is intended to output the result in math mode, the second can be used for text mode.
  • Also the result is put into a subformula using \bgroup and \egroup. This allows putting multiple letters into indexes and subscripts without curly braces, e.g. F_strong.

Two applications:

  • The OP would use something like:

    \renewcommand*{\mprintsingle}[2]{#1}% the default
    \renewcommand*{\mprintmulti}[2]{\mathit{#1}}
    

Usually multiple letters are text words and not variables and should be printed upright. This can be achieved by:

    \usepackage{amstext}
    \renewcommand*{\mprintsingle}[2]{#1}% the default
    \renewcommand*{\mprintmulti}[2]{\text{#2}}

The full example file showing both applications:

\documentclass[fleqn]{article}

\makeatletter
\usepackage{etexcmds}
\newtoks\m@toks@math
\newtoks\m@toks@text

\edef\m@tmp@restore{%
  \lccode\number`\X=\the\lccode`\X\relax
  \lccode\number`\~=\the\lccode`\~\relax
}

\newcommand*{\m@activate}{}
\newcommand*{\m@check@letter}{}
\newcommand*{\m@check@fi}{}

\newif\ifm@single

\let\m@start\relax
\def\m@loop{%
  \lccode`\X=\count@
  \lccode`\~=\count@
  \lowercase{%
    \expandafter\mathchardef\csname m@code@X\endcsname=\mathcode\count@
    \edef\m@activate{%
      \etex@unexpanded\expandafter{\m@activate}%
      \mathcode\the\count@="8000\relax
      \def\noexpand~{\m@start\csname m@code@X\endcsname X}%
    }%
    \g@addto@macro\m@check@letter{%
      \ifx\@let@token X\else
    }%
  }%
  \g@addto@macro\m@check@fi{\fi}%
  \advance\count@\@ne
}
% A-Z
\count@=`\A\relax
\@whilenum\count@<\numexpr`\Z+1\relax\do{\m@loop}
% a-z
\count@=`\a\relax
\@whilenum\count@<\numexpr`\z+1\relax\do{\m@loop}

\newcommand*{\m@start}[2]{%
  \bgroup
  \m@toks@math{#1}%
  \m@toks@text{#2}%
  \m@singletrue
  \futurelet\@let@token\m@check
}
\edef\m@check{%
  \etex@unexpanded{%
    \let\m@next\m@add
    \ifx\@let@token\space
      \let\m@next\m@finish
    \else
      \ifx\@let@token\egroup
        \let\m@next\m@finish
      \else
  }%
  \etex@unexpanded\expandafter{%
        \m@check@letter
  }%
  \etex@unexpanded{%
          \let\m@next\m@finish
  }%
  \etex@unexpanded\expandafter{%
        \m@check@fi
  }%
  \etex@unexpanded{%
      \fi
    \fi
    \m@next
  }%
}

\newcommand*{\m@add}[1]{%
  \m@singlefalse
  \m@toks@math\expandafter{%
    \the\expandafter\m@toks@math
    \csname m@code@#1\endcsname
  }%
  \m@toks@text\expandafter{%
    \the\m@toks@text
    #1%
  }%
  \futurelet\@let@token\m@check
}

\newcommand*{\m@finish}{%
  \ifm@single
    \expandafter\mprintsingle\expandafter{%
      \the\expandafter\m@toks@math\expandafter
    }\expandafter{%
      \the\expandafter\m@toks@text\expandafter
    }%
  \else
    \expandafter\mprintmulti\expandafter{%
      \the\expandafter\m@toks@math\expandafter
    }\expandafter{%
      \the\expandafter\m@toks@text\expandafter
    }%
  \fi
  \egroup
}
\let\mprintsingle\@firstoftwo
\let\mprintmulti\@firstoftwo

\everymath{\m@activate}
\everydisplay{\m@activate}

\m@tmp@restore
\makeatother

\usepackage{color}
\usepackage{amstext}

\begin{document}
\textcolor{blue}{Single letters are set in blue},
\textcolor{red}{multiple letters in red}.
\begin{itemize}
\item Multiple letters are put in \verb|\mathit|:
  \renewcommand*{\mprintsingle}[2]{{\color{blue}#1}}%
  \renewcommand*{\mprintmulti}[2]{\mathit{\color{red}#1}}%
  \[ NP \neq N P \]

\item Multiple letters are put in \verb|\text|:
  \renewcommand*{\mprintsingle}[2]{{\color{blue}#1}}%
  \renewcommand*{\mprintmulti}[2]{\text{\color{red}#2}}%
  \[ NP\ (text) \neq N P\ (two\ variables) \]
  \[ F_force = m_mass * a_acceleration \]
\end{itemize}
\end{document}

Result

1
  • This is amazing. I always thought that this should have been the default behaviour in Math mode. But I guess Knuth knows better. ;-) I wish I could accept two answers...
    – sudosensei
    Aug 22, 2013 at 13:57
8

Asked in comments to expand on my comment about fonts.

TeX does not control the space between letters in math mode, the apparent space appears because usually math italic fonts have wider sidebearings and inter-letter kerning (and often the characters themselves are wider) than a text italic.

\documentclass{article}

\begin{document}

\showoutput

\textit{NP ffiv} $NP ffiv$ $\mathit{NP ffiv}$

\end{document}

Produces

enter image description here

and in the log:

...\hbox(6.94444+1.94444)x345.0, glue set 224.80687fil
....\hbox(0.0+0.0)x15.0
....\OT1/cmr/m/it/10 N
....\OT1/cmr/m/it/10 P
....\glue 3.57774 plus 1.53178 minus 1.02322
....\OT1/cmr/m/it/10 ^^N (ligature ffi)
....\OT1/cmr/m/it/10 v
....\kern 1.07637
....\glue 3.33333 plus 1.66666 minus 1.11111
....\mathon
....\OML/cmm/m/it/10 N
....\kern1.09026
....\OML/cmm/m/it/10 P
....\kern1.3889
....\OML/cmm/m/it/10 f
....\kern1.0764
....\OML/cmm/m/it/10 f
....\kern1.0764
....\OML/cmm/m/it/10 i
....\OML/cmm/m/it/10 v
....\kern0.35878
....\mathoff
....\glue 3.33333 plus 1.66666 minus 1.11111
....\mathon
....\hbox(6.94444+1.94444)x28.70953
.....\OT1/cmr/m/it/10 N
.....\OT1/cmr/m/it/10 P
.....\OT1/cmr/m/it/10 ^^N
.....\OT1/cmr/m/it/10 v
.....\kern1.07637
....\mathoff
....\penalty 10000

Looking at the log you see that the third example uses the same font, .\OT1/cmr/m/it/10 as the first (this is a choice of the default computer modern font setup, other font packages may differ in whether they make \mathit use the same font as \textit or a font chosen to match the main math font).

The fact that there is kern of 1.09026pt between N and P (and the fact that there is no ffi ligature) in the middle example is not under the control of TeX (or visible from TeX macros except in luatex), it is a property of the font metrics. It is not just the kerning and sidebearings that differ, the letter shapes are different as well: most noticeable in v in this example. Of course if the font package changes the text fonts to be other than computer modern, but leaves the math fonts untouched, the difference between \mathit and \textit would be more pronounced.

5
  • This is really interesting. Thank you for taking the time to explain this, David. I guess the question is whether using $\mathit{NP}$ for multi-letter identifiers could ever cause typographical nightmares (inconsistencies etc.).
    – sudosensei
    Aug 22, 2013 at 20:46
  • there's some understandable confusion on account of the naming of the fonts. "\mathit" is really the text italic font, cmi, while "math italic" is the font designed for use as math variables, cmmi. the widths of a single letter in cmmi is slightly wider than that of the same letter in cmi, on purpose so that, for example, the variable a in an italic theorem environment can be distinguished from the article a in the same text. (it's subtle, but possible; see the v in david's example.) this is unique to the computer modern fonts. Feb 15, 2015 at 3:29
  • Is it not rather the f that stands out?
    – Jost
    Jun 8, 2016 at 12:53
  • @Jost not sure what you mean exactly but it is not so much the f itself as the lack of ff-ligatures that makes math italic ff look different to text italic ff Jun 8, 2016 at 13:03
  • Oh, you are right. I tested it by displaying the fs separately, i.e., $\mathit{f} \mathit{f}$ vs $\mathit{ff}. I always assumed the ligature only stretches the horizontal bar, but it actually also lengthens the 'head' of the f.
    – Jost
    Jun 8, 2016 at 13:17
2

I found this question while I was looking for the same problem.

Contrary to the complex latex definitions in the other answers, that modify the letter parsing and insert, I found an alternative solution using an existing package that solves most of requirements from the question, if one is willing to slightly compromise.

Namely, we can use the package mathastext to change the default font of the math mode, and the package option italic will let the math font stay italic. This removes spaces between single letters, making multiple letters read as a single variable and we get the results displayed below. Still, all space letters remain ignored, so we need to use explicit spaces when we want them (e.g., ~ \; \,).

I think this can be considered an acceptible compromise, as when you write equations with multi-letter variables (for example to model computer programs), it is much less effort to be explicit in all uses of spaces, than it it to be explicit on every use of a multi-letter variable.

See also the documentation of the mathastext package.

\documentclass{article}
\usepackage{listings}
\usepackage[italic]{mathastext}

\begin{document}

\begin{tabular}{ll}
latex                                     & rendered \\
\lstinline!$NP$!                          & $NP$ \\
\lstinline!$N P$!                         & $N P$ \\
\lstinline!$\mathit{NP}$!                 & $\mathit{NP}$ \\
\lstinline!$\mathit{N P}$!                & $\mathit{N P}$ \\
\lstinline!$N~P$!                         & $N~P$ \\
\lstinline!$(if~(a == 1)~then~b~else~c)$! & $(if~(speed > acceleration)~then~fast~else~slow)$ \\
\end{tabular}

\end{document}

enter image description here

0

The unicode-math package distinguishes between words in math mode (\mathit, \mathbfit, etc.) and consecutive math symbols (\symit, \symbfit, etc.) You set the former with \setmathrm and the usual BoldFont=, UprightFont= options, but it defaults to the main text font. You set the latter with the range= option to \setmathfont.

2
  • If you want this to happen automatically -- without entering \mathit, \symit, etc., the letters have to be added as exactly the unicode characters, which probably supposes a special keyboard overlay or some such mechanism. There's no easy way where you can just type the letters and have the "right thing" happen. May 1, 2020 at 18:41
  • @barbarabeeton True. There are package options that help, including math-style=literal and making e.g. \mathbf the default instead of \symbf.
    – Davislor
    May 2, 2020 at 0:55

You must log in to answer this question.

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