10

I have a table like this:

\documentclass{article}
\begin{document}

\begin{tabular}{rp{1cm}}%
  1&\nobreak\hfill\rlap{9}\\
  1&a\nobreak\hfill\rlap{9}
\end{tabular}

\end{document}

which compiles to this:

enter image description here

Why does this happen if I explicitly add the \nobreak?

My first idea was that maybe, somehow, when starting the table cell TeX was in vertical mode then the \nobreak had a different effect, but then I tried this:

\documentclass{article}
\begin{document}

\begin{tabular}{rp{1cm}}%
  1&\ifvmode v\else h\fi\nobreak\hfill\rlap{9}\\
  1&a\nobreak\hfill\rlap{9}
\end{tabular}

\end{document}

which compiles to:

enter image description here

Which shows that TeX is horizontal mode. Or is horizontal mode triggered by typesetting the h (I know it doesn't make sense). Or maybe TeX is in Schrödinger mode :)

  • 1
    Funny enough, if I move the if-else to after the \nobreak, the first line prints 'v', the 2nd, 'h', – remco Apr 13 '18 at 15:13
  • @remco Interesting :) Looks like \nobreak is somehow triggering vertical mode which, again, doesn't make any sense (for me at least). – Phelype Oleinik Apr 13 '18 at 15:16
  • 2
    Any \penalty at the same position has the same effect. – Andrew Swann Apr 13 '18 at 15:26
10

At the start of a p column tex is in vertical mode so \nobreak (which is really plain tex not to be used in latex) will add a penalty to the vertical list preventing a break (if you had used \nolinebreak the behaviour would be different)

The \ifvmode test at the start of a cell does not do what you expect as you would get the same value for l or p cells or array math cells as the expansion happens while tex is looking for \omit (\multicolumn) so it gives the same answer for all cells before tex decide to insert the implict parbox for p column. (to see this compare &\ifvmode with &\relax\ifvmode where the relax triggers the insertion of the column template and so then you can distinguish an h mode c column from a vmode p column.

The vertical offset that you see is because at the start of a p column there is an \everypar setting that adds a \strut (with the height but not depth of a normal tabular strut) so this works well if the paragraph is started via normal paragraph material such as your a but less will if you use a tex primitive box such as \rlap which does not start a paragraph.

  • Very interesting :) That's why using \leavevmode makes it work with \nobreak. One last quick question: when I need to prevent line break I should always use \nolinebreak instead of plain \nobreak? – Phelype Oleinik Apr 13 '18 at 15:50
  • 1
    @PhelypeOleinik any non expandable command (even \relax which does nothing) will trigger the insertion of the column template so put a p column in v mode. so \leavevmode is seen, it triggers the insertion so puts tex in vmode, then it is seen again after the template has been inserted and so leaves v mode. – David Carlisle Apr 13 '18 at 15:56
  • 1
    @PhelypeOleinik \nobreak is OK if you know which mode you are in, it acts as \linebreak` or \pagebreak depending, but at the start of a table cell knowing which mode you are in is a black art:-) – David Carlisle Apr 13 '18 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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