My eventual goal is to create my own tabular-like environment in which all entries are in math-mode by default, let's call it fancytable
. (One requirement is that the first column be separated from the others by a line, but that shouldn't be the main problem.)
In Math mode in tabular without having to use $…$ everywhere I found how to approach the problem:
\documentclass{article}
\usepackage{array}
\usepackage{tabularx}
\begin{document}
\begin{tabular}{ >{$}c<{$} | >{$}c<{$} >{$}c<{$} }
x & x^2 & x^3\\
y & y^2 & y^4
\end{tabular}
\end{document}
but this is not what I'm looking for. (Note I am including tabularx
because I need it for other purposes, I think it is relevant to mention.) The tabular may become large (say 15 columns) so writing >{$}c<{$}
every time would be tedious. Also, some day I might change my mind and choose another lay-out, and changing all tables isn't really a thing I'm looking forward to. That's why I try to make it an environment.
Recently I asked how to copy and print a string a few times, in A command which concatenates a string an arbitrary number of times. So currently I have a command \repeatstring
available and I expect to need it as in \repeatstring{5}{>{$}c<{$}}
. (I have included its current definition below)
The first thing I tried is something like
\documentclass{article}
\usepackage{array}
\usepackage{tabularx}
% definition of \repeatstring left out, see below
\newenvironment{fancytable}[1]%
{\begin{tabular}{ >{$}c<{$} | \repeatstring{#1}{>{$}c<{$}} } }
{\end{tabular}}
\begin{document}
\begin{fancytable}{2} % the argument of fancytable is 1 less than the desired number of columns
x & x^2 & x^3\\
y & y^2 & y^4
\end{fancytable}
\end{document}
but tabular
does not accept arbitrary commands in its header. I read trough How do I expand a macro into a tabular head? and tried to adapt the answers given there. Meanwhile I figured out that I should somehow expand \repeatstring
before tabular
sees what's going on in its head. I think defining a new columntype
every time a fancytable
is created is not a good thing to do (I fail to do it anyway, getting the same error as with the above approach). Some tries:
\documentclass{article}
\usepackage{array}
\usepackage{tabularx}
% definition of \repeatstring left out, see below
\newcommand\buildtabularhead{}
\newenvironment{fancytable}[1]%
{%
\renewcommand\buildtabularhead{ >{$}c<{$} | \repeatstring{#1}{>{$}c<{$}} }%
\expandafter\tabular\expandafter{\buildtabularhead}}
{\endtabular}
\begin{document}
\begin{fancytable}{2}
x & x^2 & x^3\\
y & y^2 & y^4
\end{fancytable}
\end{document}
(based on Matthew Leingang's answer) but I keep getting
Package array Error: Illegal pream-token (\repeatstring): `c' used.
as usual. The same with Bruno Le Floch's answer:
\documentclass{article}
\usepackage{array}
\usepackage{tabularx}
% definition of \repeatstring left out, see below
\makeatletter
\newcolumntype{\expand}{}
\long\@namedef{NC@rewrite@\string\expand}{\expandafter\NC@find}
\makeatother
\newcommand\mypream{}
\newenvironment{fancytable}[1]%
{%
\renewcommand\mypream{ >{$}c<{$} | \repeatstring{#1}{>{$}c<{$}} }%
\begin{tabular}{\expand\mypream}}
{\endtabular}
\begin{document}
\begin{fancytable}{2}
x & x^2 & x^3\\
y & y^2 & y^4
\end{fancytable}
\end{document}
I really don't know what to do. I read When to use \edef, \noexpand, and \expandafter? but didn't achieve to use \expandafter
of \edef
in the right way. I always and up with
Package array Error: Illegal pream-token (\repeatstring or \edef or \expandafter or \setcounter): `c' used.
\setcounter
comes from my current definition of \repeatstring
when I expand it:
\usepackage{etoolbox}
\newcounter{countdown}
\newcommand\concathere{}
\newcommand\repeatstring[2]{
\setcounter{countdown}{#1}
\renewcommand\concathere{}
\whileboolexpr{test {\ifnumcomp{\thecountdown}{>}{0}}}{
\addtocounter{countdown}{-1}
\appto\concathere{#2}
}
\concathere
}
Best Answer
The best solution to a simply 'repeat n-times' in a
tabular
preamble is indeed to use the*
syntax as in barto's answer. However, if you do want to use a macro containing the preamble for some reason, using Bruno's solution to How do I expand a macro into a tabular head?, then the important thing to do is to make sure it contains exactly the preamble text. That requires a definition of\repeatstring
which is expandable and the use of an\edef
-like expansion of the codeIn the above, I've used an
expl3
based expandable repeat function to define\repeatstring
(much the same as egeg's solution to A command which concatenates a string an arbitrary number of times), which means that when\protected@edef
is applied\mypream
ends up with definition>{$}c<{$} | >{$}c<{$}>{$}c<{$}
, i.e. exactly what is needed in thetabular
preamble.All of this is needed as
array
avoids any expansion of thetabular
preamble. Thus if you dowhat
array
sees is exactly that: not a string of repeated>{$}c<{$}
entries but the token\repeatstring
, which is does not know (and so raises an error).