4

I am trying to design a custom tabular-like environment with (among others) the following features:
- there is an automatic \hline between all tabular rows;
- the user is provided with a command, say \nohline, that when input at the beginning of a row, prevents the above \hline from being input.

So for example

\begin{mytabular}
a & b \\ c & d \\ \nohline e & f
\end{mytabular}

should be equivalent to

\begin{tabular}
\hline a & b \\ \hline c & d \\ e & f
\end{tabular}

(Note that I really want the macro \nohline to operate in this way, for reasons that are not to be discussed here - essentially: compatibility with already-written code, and substituability of stylesheets. Also, I know that this is hard to do, which is why I come to TeX.SX in the first place - if it were only a matter of “use such and such packages” then I could manage myself! So please, if all you can say is “I don't like this question”, then move on to the next one. Thanks.)

I tried playing a bit with \noalign and \everycr: my basic idea was something like

\def\everycr{\futurelet\token\oneline}
\def\oneline{\ifx\token\nohline\else\hline\fi}
\def\nohline{}

The problem with this is that the \noalign (found in the expansion of \hline) must immediately follow \cr at the lexical level, thus the \futurelet is not discarded and this raises a “misplaced \noalign” error.

Is there any other way to make the contents of the \noalign{...} block depend on the presence of the \nohline macro?

4
  • 4
    That's not a good design to do and undo successively. Instead you should not do anything by default and make things on demand including drawing every row. For example having a counter and checking whether given numbers match the row number etc.
    – percusse
    Aug 16, 2016 at 14:54
  • 3
    Making a very easy task automatic by hard means and working on a more hard solution to drop out of the automation. Just leave it. A good table has a few lines as possible.
    – Johannes_B
    Aug 17, 2016 at 6:22
  • 1
    Which TeX engine do you use -- pdfTeX, XeTeX, or LuaTeX?
    – Mico
    Aug 17, 2016 at 9:13
  • pdfTeX 3.1415926-2.4-1.40.13 (TeX Live 2012). (I know it's old, but I am not the sysadmin). I think there is a LuaTeX inside this, however I'm not familiar at all with this. Aug 17, 2016 at 9:26

2 Answers 2

2

Here is a way of doing it using the array package.

\documentclass{article}
\usepackage{array}

\makeatletter
\let\realarraycr\@arraycr% save original
\newcommand\mytabularnewline{\realarraycr\myhline\global\let\myhline\hline}
\newcommand\nohline{\global\let\myhline\relax}% \myhline does nothing
\newenvironment{mytabular}[1]{%
   \let\@arraycr\mytabularnewline% hijack \@arraycr
   \let\myhline\hline% 
   \tabular{#1}\myhline% start a tabular environment
   }{\endtabular}
\makeatother

\begin{document}

  \begin{mytabular}{cc}
    a & b \\  \nohline c & d \\ e & f \\
  \end{mytabular}

\end{document}

The array package calls \@arrayr at the end of each row of a tabular, or array, environment. The idea is to hijack \@arraycr and change it so that \myhline is used at the end of each line. By default, \myhline is the same as \hline but \nohline changes it to \relax.

Here's the output:

enter image description here

As I am using a tabular environment behind the scenes the mytabular environment takes an argument which specifies the number of columns and their alignment.

It is probably no harder doing something similar without loading the array package.

1
  • This seems cleaner than my solution (which is, however, now implemented in production, and seems to work fine so far). Thanks for the reply! Nov 22, 2016 at 11:03
1

Answering my own question here. One solution (dirty) is to:

  • first scan for tokens at beginning of line,
  • once this is done, if we must draw a \hline, then we reissue a new \cr to return to beginning of line, and add a new \noalign to insert some negative vertical glue to return to the previous position (I think that -\normalbaselineskip is the right amount here).

Here is a sample code that works for me. Note that since the colortbl package is loaded (I must have it), this makes a few slight changes: namely \CT@everycr replaces \everycr, and I must also preserve \CT@row@color.

\documentclass{article}
\usepackage{colortbl,booktabs,lipsum}

\makeatletter
\def\fakenoalign#1{%
  \global\CT@everycr{}%
  \cr\noalign{\vskip-\normalbaselineskip}#1%
  \global\CT@everycr{\futurenonspacelet\token\oneline}%
}
\def\oneline{%
  \ifx\token\merge\relax\else
  \ifx\token\header\fakenoalign\toprule \else
  \ifx\token\end\fakenoalign{\bottomrule\noalign{\vskip-\normalbaselineskip}} 
  \else
  \fakenoalign\midrule\fi\fi\fi
\ignorespaces}
\def\makeunique#1{\def#1{\let#1#1\ignorespaces}\ignorespaces}

\newenvironment{tableau}{%
  \let\CT@row@color\relax
  \makeunique\header
  \makeunique\merge
  \global\CT@everycr{\futurenonspacelet\token\oneline}%
  \begin{tabular}%
}{\global\CT@everycr{}\end{tabular}%
  \CT@everycr{\noalign{\global\let\CT@row@color\relax}\the\everycr}%
}
\makeatother


\begin{document}

\lipsum[1]
\begin{tableau}{ll}
\header 1&2\\ a&b\\\merge c&d\\
\end{tableau}
\lipsum[1]
\begin{tabular}{ll}
\toprule 1 & 2\\ \midrule a & b\\ c & d\\\bottomrule
\end{tabular}
\lipsum[1]
\end{document}

You must log in to answer this question.

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