4

If one is in a tabular environment, how can one make sure, that the previous line has ended (with \\)?

One might want to add an \hline or do some other stuff only at the beginning of a new line.

If one adds \\ before, that might add an unwanted, additional empty line.

So the question is, in comparison to \clearpage vs. \newpage, if there is a likewise command for tabular \??? vs. \\?

1
  • 3
    This question looks like an “X-Y” problem (ask about Y when you are actually trying to achieve X), so I’m not going to answer it; but as a hint, recall that immediately after a \\ TeX is in vertical mode, and this condition can be tested with \ifvmode.
    – GuM
    Commented Jul 5, 2017 at 18:15

3 Answers 3

4

The following introduces a tabular newline macro \tnl which checks whether it's followed by \tnl using \@ifnextchar. Since \@ifnextchar leaves the "peeked token" in the input stream, concatenated called to \tnl are all ignored, except for the last one:

enter image description here

\documentclass{article}

\makeatletter
\newcommand{\tnl}{\@ifnextchar\tnl{}{\\}}
\makeatother

\begin{document}

\begin{tabular}{ l }
  one \\ two
\end{tabular}\quad
\begin{tabular}{ l }
  one \tnl two
\end{tabular}

\bigskip

\begin{tabular}[t]{ l }
  one \\ \\ two
\end{tabular}\quad
\begin{tabular}[t]{ l }
  one \tnl \tnl two
\end{tabular}

\bigskip

\begin{tabular}[t]{ l }
  one \\ \\ \\ two
\end{tabular}\quad
\begin{tabular}[t]{ l }
  one \tnl \tnl \tnl two
\end{tabular}

\end{document}

This does remove the optional argument specification that accompanies \\. Not sure whether that's needed.

1
  • This command \tnl seems to do the same a \crcr in David Carlisle's answer (as far as I can see). And it yields the same result in my other question ( tex.stackexchange.com/questions/378324/… ).
    – Toscho
    Commented Jul 5, 2017 at 17:59
3

Just to illustrate the suggestion I made in a comment:

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\newcommand*{\ensureLineHasEnded}{\ifvmode \else \expandafter \\\fi}
\newcommand*{\NLhline}{\ensureLineHasEnded\hline}



\begin{document}

\noindent
\begin{tabular}{|l|}
    \hline
    A one-column \texttt{tabular}, just for demo purposes.  \\
    \NLhline
    It uses both vertical and horizontal rules (arrggh\ldots!).  \\
    \NLhline
    But some of the \verb|\\|~commands are missing\ldots
    \NLhline
    \ldots yet the horizontal rules are typeset normally.  \\*[6pt]
    \NLhline
    The \verb|\ensureLineHasEnded| can take the same optional arguments\ldots
    \ensureLineHasEnded*[6pt]\hline
    \ldots as the \verb|\\|~command.
    \NLhline
    Moreover, it works as expected when used at the end of the \texttt{tabular}.
    \ensureLineHasEnded[9pt]
\end{tabular}\par

\end{document}

Edit: As David Carlisle has remarked, the \ifvmode test does not work if p-type columns are used, because TeX is in vertical mode in these columns too. Note that, more precisely, TeX is internal vertical mode both inside p-type columns and between the lines of an alignment (The TeXbook, p. 282), so a supplementary \ifinner test wouldn’t help either. A distinction that does work in simple situations is based on the current group level, which can be enquired about by means of the e-TeX primitive \currentgrouplevel.

The following code is just a proof of concept: there’s little point in refining it unless you know the precise context into which it’s going to be used.

% My standard header for TeX.SX answers:
\documentclass[a4paper]{article} % To avoid confusion, let us explicitly 
                                 % declare the paper format.

\usepackage[T1]{fontenc}         % Not always necessary, but recommended.
% End of standard header.  What follows pertains to the problem at hand.

\makeatletter

\@ifdefinable\@tabular@group@level{\newcount\@tabular@group@level}
\newcommand*\ensureLineHasEnded{%
    \ifnum \currentgrouplevel>\@tabular@group@level
        % % Diagnostics:
        % \count@ \currentgrouplevel
        % \typeout{Inserting \protect\\ at line \number\inputlineno,
        %     since \number\count@\space > \number\@tabular@group@level}%
        \expandafter \\%
    \fi
}
\newcommand*\saltAwayLevel{%
    \noalign{%
        \global \@tabular@group@level
            \numexpr \currentgrouplevel -\@ne \relax
        % % Diagnostics:
        % \typeout{\number\@tabular@group@level}
    }%
}

\makeatother

\newcommand*{\NLhline}{\ensureLineHasEnded\hline}



\begin{document}

With \texttt{l}~columns:
\begin{center}
    \begin{tabular}{|l|}
        \saltAwayLevel
        \hline
        A one-column \texttt{tabular}, just for demo purposes.  \\%
        \NLhline
        It uses both vertical and horizontal rules (arrggh\ldots!).  \\
        \NLhline
        But some of the \verb|\\|~commands are missing\ldots
        % \typeout{\number\currentgrouplevel}%
        \NLhline
        \ldots yet the horizontal rules are typeset normally.  \\*[6pt]
        \NLhline
        The \verb|\ensureLineHasEnded| can take the same optional arguments\ldots
        \ensureLineHasEnded*[6pt]\hline
        \ldots as the \verb|\\|~command.  \\
        \NLhline
        Moreover, it works as expected when used at the end of the \texttt{tabular}.
        \ensureLineHasEnded[9pt]
    \end{tabular}\par
\end{center}

\bigbreak

With \texttt{p}~columns:
\begin{center}
    \begin{tabular}{|p{.9\linewidth}|}
        \saltAwayLevel
        \hline
        A one-column \texttt{tabular}, just for demo purposes.  \\%
        \NLhline
        It uses both vertical and horizontal rules (arrggh\ldots!).  \\
        \NLhline
        But some of the \verb|\\|~commands are missing\ldots
        % \typeout{\number\currentgrouplevel}%
        \NLhline
        \ldots yet the horizontal rules are typeset normally.  \\*[6pt]
        \NLhline
        The \verb|\ensureLineHasEnded| can take the same optional arguments\ldots
        \ensureLineHasEnded*[6pt]\hline
        \ldots as the \verb|\\|~command.  \\
        \NLhline
        Moreover, it works as expected when used at the end of the \texttt{tabular}.
        \ensureLineHasEnded[9pt]
    \end{tabular}\par
\end{center}

\end{document}

You can uncomment the diagnostic commands to get additional information on what is going on.

4
  • 2
    yes I wondered about suggesting that but that only works if the otherwise bad \hline is in an l column, if it would be in a p column the vmode test would (or at least could) show as true anyway Commented Jul 5, 2017 at 19:03
  • 1
    Thank you for the answer, but it still doesn't work, if I use it in a \DTLforeach from datatool-package, that produces one line ending with \` per iteration. It seems, that \DTLforeach` does something, which breaks all these checks, before going through the iterated code, although it doesn't print something.
    – Toscho
    Commented Jul 5, 2017 at 19:47
  • 1
    @Toscho: Indeed, as D.C. has remarked the test is not robust enough. I intend to remove this answer after the usual grace period of 48 hours that I apply, by policy, to all my pieces of nonsense. :-)
    – GuM
    Commented Jul 5, 2017 at 19:54
  • @GuM: would you consider leaving the answer up? As you say, it’s a slightly flawed answer, but (a) it still works for some use-cases, so may be useful to some readers; (b) other answerers may be able to build on the idea and improve it to something more robust; and (c) having it here together with the explanation of its limitations is useful to anyone else who thinks of using this approach. Commented Jul 5, 2017 at 20:17
3

Mostly you can use the TeX primitive \crcr to achieve this. \crcr acts like \cr unless the previous command was \cr in which case it does nothing.

This is the heart of the reason that latex can ignore a \\ at the end of the final row.

the only wrinkle is that if you end the previous row with \crcr then it as if it was ended with \cr rather than \\ but in most cases this comes to the same thing.

2
  • Thx for the hint on \crcr, but this does not work as I expect it in my other question ( tex.stackexchange.com/questions/378324/… ). If I add \crcr before the \hline in the commented line, the code compiles without erros, but adds an empty line.
    – Toscho
    Commented Jul 5, 2017 at 17:57
  • @Toscho well that's not surprising:-) \crcr only does nothing if there are no non-expandable commands since the last \cr the chance that that's the case in the middle of that loop is small. You would be better to put either \\ or \\\hline at the beginning of each row, at the point you can test \bar Commented Jul 5, 2017 at 18:04

You must log in to answer this question.

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