Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

How can I easily tell Latex to prevent line-breaks inside a part of an inline formula, without affecting inter-word spacing?


Writing something like $ab(c+d)$ in Latex is bad: Latex might put a line break after +. But I do not want to disable line breaks after a + globally; it is perfectly fine to have a line break in $abc+def$. Therefore I have followed the approach mentioned in this thread: simply add extra braces.

In principle, this is great. I can write things like ${ab(c+d)}$ and $abc+{de(f+g)}$ to control which parts of an inline equation are "atomic" in the sense that Latex must not add line breaks inside them.

Unfortunately, there seems to be an unwanted side effect: Latex typesets ${a+b}$ and $a+b$ in the middle of a fully-justified line of text in different ways. If I write $a+b$, Latex seems to add "flexible" spaces around +: just like regular inter-word spaces, Latex can slightly adjust the spacing so that a fully-justified paragraph looks good. However, if I write ${a+b}$, Latex seems to use fixed-width spaces around +.

This answer mentions that one possible approach is to write something like $a+\nobreak b$, but this gets tedious and error-prone, even with some macros. I would like to "mark" a certain part of an inline equation as a "nobreak-zone". How can I do that, with the least amount of extra code?

Ideally, I would like to write something like $abc + \x{de(f+g)}$, where \x is a macro that prevents line breaks but allows flexible spacing.


An example:

\documentclass[a4paper]{article}

\begin{document}
    Foobar $aaaa+bbbb+cccc+dddd+eeee+ffff+gggg$ foobar foobar foobar foobar
    foobar $aaaa+bbbb+cccc+dddd+eeee+ffff+gggg$ foobar foobar foobar.

    Foobar ${aaaa+bbbb+cccc+dddd+eeee+ffff+gggg}$ foobar foobar foobar foobar
    foobar ${aaaa+bbbb+cccc+dddd+eeee+ffff+gggg}$ foobar foobar foobar.

\end{document}

Produces:

example

share|improve this question
3  
${a+b}$ and $a+b$ is typeset in the same way, except that the first one cannot have a linebreak inside –  Herbert May 15 '11 at 19:34
    
@Herbert: See the edit. –  Jukka Suomela May 15 '11 at 20:14
4  
@Herbert: In ${a+b}$ the space is "frozen"; as the TeXbook says, a subformula in braces is typeset without stretching or shrinking. –  egreg May 15 '11 at 20:45
    
@egreg: sure, but you can set \thinmuskip to the fixed length of 2mu inside ${a+b}$ –  Herbert May 16 '11 at 9:04
3  
@Herbert: the OP wants the space to remain flexible; enclosing a subformula in braces makes the spacing in the subformula rigid. So, in general, $a+b$ and ${a+b}$ are typeset differently, unless spaces are not stretched or shrinked in the former formula, which is unlikely in a normal paragraph. Around binary operators TeX uses \medmuskip, which usually has stretch and shrink components (that are ignored in a braced subformula). –  egreg May 16 '11 at 9:22
show 1 more comment

4 Answers

up vote 11 down vote accepted
+200

I would say

\newcommand{\x}[1]{%
  {}$% get out of math
  \kern-2\mathsurround % in case it's non zero
  $% reenter math
  \binoppenalty10000 \relpenalty10000 #1% typeset the subformula
  {}$% get out of math
  \kern-2\mathsurround % in case it's non zero
  $% reenter math for the rest of the formula
}

TeX breaks formulas only after binary operators or relation symbols, the desirability of such breaks is measured by the two mentioned parameters. However the values used the penalties are those valid at the end of the formula, so simply enclosing #1 in \begingroup...\endgroup and setting the values wouldn't do anything.

Of course this can work only if used in suitable places of the formula, for example $a+\x{b+c}$ would have the right spacing after the first + (because of the empty subformula); the last empty subformula does nothing.

My opinion is still that bad breaks must be solved with suitably placed \nobreak commands.

Some examples:

\documentclass[a4paper,draft]{book}

\newcommand{\x}[1]{{}$\kern-2\mathsurround${}
  \binoppenalty10000 \relpenalty10000 #1{}$\kern-2\mathsurround${}}
\begin{document}
\parbox{5cm}{

A formula \(a+\x{c+d}\)\break showing that spaces are right

A new formula \(a+\x{c+d}\) showing that spaces are right

A brand new formula x \(a+\x{c+d}\) showing that spaces are right

A brand new formula xx \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxx \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c+d}\) showing that spaces are right

Another brand new formula \(a+\x{c+d}\) showing that spaces are right

Right: $\sin(\x{a+b})$

Wrong: $\sin\x{(a+b)}$


\mathsurround=30pt
A formula xxxxxxx \(a+\x{c+d}\) showing mathsurround

A formula xxxxxxx \(a+c+d\) showing mathsurround
}
\end{document}

Addition about usage
The \x macro (possibly with a more descriptive name) should be used in specific places. Its contents must

(1) start with an ordinary symbol or be preceded by an ordinary symbol;
(2) end with an ordinary symbol or be followed by one.

It doesn't support the style declarations \displaystyle, \textstyle, \scriptstyle, or \scriptscriptstyle; it may make sense to carry a \displaystyle declaration, this might be done with a *-variant.

It doesn't support \left or \right: it's not allowed something like

$...\left(\x{a+b}\right)...$

but this is not a problem, as no formula can be split at relation or operation symbols between \left and \right and the spaces around these symbols never participates to stretching or shrinking.

share|improve this answer
    
I have a little bit uneasy feeling about this approach; I wonder if leaving and re-entering math mode has any surprising side effects? –  Jukka Suomela May 17 '11 at 22:48
    
@Jukka: You have to choose carefully where to put the \x command, because it adds to empty ordinary atoms. So it can go wherever an ordinary atom is expected at both ends. For example, $\sin(\x{a+b})$ and not $\sin\x{(a+b)}$. TeX won't break at this "out and in". –  egreg May 17 '11 at 23:02
    
Thanks, the examples are pretty convincing! But let's wait and see if there are other approaches. –  Jukka Suomela May 17 '11 at 23:54
    
@Jukka There's another (obvious) limitation: explicit style declarations cannot be carried over, but this should not be a problem. –  egreg May 18 '11 at 14:37
    
I'm sorry I don't have any solutions to suggest, which is why I only ad this as a comment, but I suggest you set up some test cases for all the scenarios you can think of to try all the solutions you get from other people on. Like Donald Knuth said: "Beware of bugs in the above code; I have only proved it correct, not tried it" –  Pete May 19 '11 at 13:43
add comment

Based on the same idea as Philippe (replacing + by +\nobreak), it is possible to have a more robust solution. This uses the poorly known feature of TeX that normal letters or characters (with category code letter, 11, or other, 12) can be made to behave as active characters when executed in math mode. To do them, assign these characters the mathcode 32768, i.e., "8000 in hexadecimal.

For this application, we can define the active character + to expand to +\nobreak... but this will fail: the resulting +, which now has mathcode "8000 is seen as active, and will expand, etc. Using \let as we would for control sequences would not work: it sould simply build an implicit character, which at execution time behaves identically to the other +, i.e., expands to +\nobreak, etc. The correct solution is to use \mathchar<integer> with the correct integer: \the\mathcode`\+. An \edef is needed to get the value of \mathcode`\+ before it is assigned "8000.

The solution would be simpler if \x was defined with a group, namely by

\newcommand{\x}[1]{\begingroup\defineplusminus #1\endgroup}

But I found it nicer not to use a group. In principle it is slightly more versatile, since one could imagine \defineplusminus a + \mathrm{b + c \undefineplusminus - d}... However, the absence of group means that the active + and - are redefined in the process. So maybe it is a bad idea. Then simply remove all occurrences of \undefineplusminus, and define \x as above.

\documentclass{article}

\makeatletter
\begingroup
\catcode`\+ = \active
\catcode`\- = \active
\@firstofone{\endgroup
  \newcommand{\defineplusminus}
    {%
      \edef\undefineplusminus{%
        \mathcode`\noexpand\+=\the\mathcode`\+
        \mathcode`\noexpand\-=\the\mathcode`\-
      }%
      \edef+{\mathchar\the\mathcode`\+\nobreak}%
      \mathcode`\+="8000\relax
      \edef-{\mathchar\the\mathcode`\-\nobreak}%
      \mathcode`\-="8000\relax
    }
}
\newcommand{\undefineplusminus}{}% just declare it.

\newcommand{\x}[1]{%
  \defineplusminus
  #1%
  \undefineplusminus
}

%% Test document taken from Philippe Goutet
\begin{document}

\parindent=0cm
\hsize=5cm

A formula \(a+\x{c+d}\)\break showing that spaces are right

A new formula \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c+d}\) showing that spaces are right

Right: $\sin\x{(a+b)}$

A formula \(a+\x{c-d}\)\break showing that spaces are right

A new formula \(a+\x{c-d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c-d}\) showing that spaces are right

Right: $\sin\x{(a-b)}$

\end{document}
share|improve this answer
    
That's a good idea (I was considering posting something like that too). You might want to indicate how the process would work for an operator defined by a macro, like \oplus, \otimes, etc. –  Philippe Goutet May 19 '11 at 13:10
add comment

This is completely different from my previous approach, so it warrants a separate answer. Simply go through the argument, and place \nobreak wherever it is needed. Brace groups are detected using \@ifnextchar\bgroup, and copied without modification to the result (in \nobr@toks), since they typically don't need \nobreak inserted within. For single tokens, \nobr@next@N@do checks if they are in a given list (here +-=\cdot\times, but it can be extended). If they are, then \nobreak is added. Otherwise, just put the token in the result.

This method allows \displaystyle and friends, and it allows to use \x anywhere (i.e., not necessarily as an atom). However, it doesn't expand the argument, so won't work with things like \def\PP{c-d} and \x{\PP} won't work (as egreg pointed out in some comments).

I only changed the first of egreg's examples below to show the additional features.

\documentclass[a4paper,draft]{book}

\makeatletter
\newtoks\nobr@toks
\long\def\nobr@put@right#1{\nobr@toks\expandafter{\the\nobr@toks#1}}
\long\def\nobr@next
  {\@ifnextchar\bgroup \nobr@next@bgroup \nobr@next@N }
\long\def\nobr@next@bgroup#1{\nobr@put@right{{#1}}\nobr@next}
\long\def\nobr@next@N#1%
  {%
    \ifx\nobr@end #1%
      \expandafter\@gobbletwo
    \fi
    \nobr@next@N@do #1%
  }%
\long\def\nobr@next@N@do#1%
  {%
    \nobr@put@right{#1}%
    \in@{#1}{+-=\cdot\times}% extensible list.
    \ifin@\nobr@put@right{\nobreak}\fi
    \nobr@next
  }
\def\nobr@end\nobr@end{\nobr@end}
\newcommand{\x}[1]{%
  \nobr@toks={}%
  \nobr@next #1\nobr@end
  \ifnobr@show\showthe\nobr@toks\fi
  \the\nobr@toks
}
\newif\ifnobr@show
% \nobr@showtrue to show the result each time.
\makeatother

\begin{document}
\parbox{5cm}{

A formula \(\displaystyle a \x{ + c^{2+3} + \sum d} \)\break showing that spaces are right

A new formula \(a+\x{c+d}\) showing that spaces are right

A brand new formula x \(a+\x{c+d}\) showing that spaces are right

A brand new formula xx \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxx \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c+d}\) showing that spaces are right

Another brand new formula \(a+\x{c+d}\) showing that spaces are right

Right: $\sin(\x{a+b})$

Wrong: $\sin\x{(a+b)}$


\mathsurround=30pt
A formula xxxxxxx \(a+\x{c+d}\) showing mathsurround

A formula xxxxxxx \(a+c+d\) showing mathsurround
}
\end{document}
share|improve this answer
    
...too bad I didn't have this idea some days ago... ;-) –  Bruno Le Floch May 24 '11 at 0:04
add comment

A wasteful solution (it reads the formula multiple times) but which does not disrupt spacing or style declarations is to make string substitutions of + into +\nobreak, of - into -\nobreak, etc. This can be done with the xstring package :

\documentclass{article}

\usepackage{xstring}

\newcommand{\x}[1]{%
  \begingroup
    \expandarg
    \def\result{#1}
    \StrSubstitute{\result}{+}{+\nobreak }[\result]%
    \StrSubstitute{\result}{-}{-\nobreak }[\result]%
    \result
  \endgroup
}

\begin{document}

\parindent=0cm
\hsize=5cm

A formula \(a+\x{c+d}\)\break showing that spaces are right

A new formula \(a+\x{c+d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c+d}\) showing that spaces are right

Right: $\sin\x{(a+b)}$

A formula \(a+\x{c-d}\)\break showing that spaces are right

A new formula \(a+\x{c-d}\) showing that spaces are right

A brand new formula xxxx \(a+\x{c-d}\) showing that spaces are right

Right: $\sin\x{(a-b)}$

\end{document}

The drawback of this method is that only the symbols specified in the code of the macro \x are changed (I only dealt with + and - in the previous example, but it's easy to expand the code). You must manually add all those you're going to use (if you want a generic solution, you could add the most common ones from the comprehensive LaTeX Symbol List).

share|improve this answer
    
What if one says \def\PP{c-d} and $a+\x{\PP}$? ;-) –  egreg May 18 '11 at 21:45
1  
@egreg: it will work ;-) (xstring expands completely its argument by default). What won't work (and cause an error) is something like \def\PP{c-\mathbf{d}}; I will edit my answer to correct this (with the xstring \expandarg macro), but then your example will indeed not work. –  Philippe Goutet May 19 '11 at 7:05
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.