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.

This is a followup question from one asked by Andrew Howard. After some discussion, it became clear that colortbl has some issues with the names that can be used for a \newcolumntype. The result of the discussion digressed far enough that it seems like a new, more general, question may be asked.

Let's suppose that we want to define new columns without using \newcolumntype, which is limited in that names may only be a single character. The tabular environment can take more complex input. For example, without defining a \newcolumntype we can do this

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}

\begin{document}
\begin{tabular}{|>{\columncolor{blue!10}}c|>{\columncolor{red!10}}c|}
Something  & Something else\\
\end{tabular}
\end{document}

which is not particularly reusable. What we can't do is this

\newcommand{\colone}{>{\columncolor{blue!10}}c}
\newcommand{\coltwo}{>{\columncolor{red!10}}c}

\begin{tabular}{|\colone|\coltwo|}
Something  & Something else\\
\end{tabular}

The array package provides \newcolumntype to get around this, but allows only single character names, which is not very satisfactory.

How can I force LaTeX to expand \colone and \coltwo before tabular gets them? Defining a new environment would be fine for this. In general how does one force expansion in a particular order using a new environment?

share|improve this question
    
\newcolumntype is provided by array. Additionally, the array package mentions (p 4 in the array documentation) that "[it] takes care not to expand the [tabular/array] preamble", and therefore control sequences in the column specification does not work in the current scheme (it does without the array package - the "old scheme"). –  Werner Nov 14 '11 at 6:24
    
Oops. That was careless of me. I'll correct the question. とにかく... with or without the array package, is there a way to force this expansion? More semantic names are desirable. It is clear that some of the issues can be mitigated with optional arguments to newcolumntype. i.e. \newcolumntype{C}[1]{>{\columncolor{#1}}c} allows a simpler way to choose the colour and leave the rest the same. I'd still like to see some examples on how to apply expandafter on new environments. –  qubyte Nov 14 '11 at 8:50
    
Does tex.stackexchange.com/q/12234/2707 help? –  Bruno Le Floch Nov 14 '11 at 15:25
    
Interesting. It means that I can do this, but a command would probably have to include the definition of all columns. Anyway, it's the demonstration of expandafter I was looking for, and it allows me to construct a new environment too. Feel free to put an answer in and I'll mark it as accepted. Otherwise I'll put one in tomorrow. –  qubyte Nov 14 '11 at 15:35
    
@MarkS.Everitt: How about writing an answer? –  lockstep Dec 5 '11 at 23:01

3 Answers 3

up vote 13 down vote accepted

For what it's worth, most of \newcolumntype doesn't actually require that the column name to be a single character, just that it be a single token. So this works, for example

\newcolumntype{\fooa}[1]{>{\color{#1}}c}
\newcolumntype{\foob}{|l|}
\begin{tabular}{\fooa{red}\fooa{blue}\foob}
a b c & a b c & a b c \\
1&2&3
\end{tabular}

It's not really supported though, and \showcols fails in this usage, although that could presumably be fixed, but it's probably simpler to stick to single letters, even after avoiding special characters there are over 200 of them in an 8-bit TeX, which ought to be enough column types. :-)

share|improve this answer
8  
Welcome to TeX.sx, David! –  Werner Dec 21 '11 at 0:28
    
Agreed on a single character being simpler, and personally I would do that. The question that prompted this demanded a lot of work for not a lot of reward and raised this question (I made your point in the comments of my answer). The whole thing was very very irritating. I favour imperfect but simple in general, so this answer wins! thanks! :) –  qubyte Dec 21 '11 at 12:43
    
The David Carlisle of "The LaTeX Companion" ???? –  Justin Bailey Dec 21 '11 at 19:40
    
amongst other things, yes:-) more to the point, \newcolumntype was my idea (a lifetime ago....) –  David Carlisle Dec 21 '11 at 22:27

An improvement of Justin's idea:

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}
\newenvironment{tabularex}[2][c]
  {\begingroup\edef\x{\endgroup\noexpand\tabular[#1]{#2}}\x}
  {\endtabular}
\newcommand{\newcolumntypeex}[2]{\newcommand#1{\unexpanded{#2}}}
\newcolumntypeex{\colone}{>{\columncolor{blue!10}}c}
\newcolumntypeex{\coltwo}{>{\columncolor{red!10}}c}

\begin{document}

\begin{tabularex}{\colone\coltwo}
Something & else\\
\end{tabularex}
\end{document}

It has many limitations with respect to the usual tabular environment: for example, something like >{\raggedright}p{3cm} won't work (which is precisely the reason why array doesn't expand the tokens in the argument of tabular). One has to put \protect in front of every token of this kind.

All considered, I don't think it's particularly useful. The problem at hand may be solved by

\newcolumntype{Z}[1]{>{\columncolor{#1}}c}

and

\begin{tabular}{Z{blue!10}Z{red!10}}

Recall that the definitions performed by \newcolumntype are local, so one given inside a table environment will disappear after it.

share|improve this answer

The definition of tabularex below works for one column, and it could be generalized to any number of columns separated by |. Its not in general for any environment but it works for tabular:

\documentclass[10pt]{article}
\usepackage[table,dvipsnames]{xcolor}
\usepackage{array}
\usepackage{colortbl}
\def\tabularex#1{\toks0=\expandafter{#1}%%
  \edef\go{\toks2={\noexpand\begin{tabular}{\the\toks0}}}%%
  \go\the\toks2}

\begin{document}
\newcommand{\colone}{>{\columncolor{blue!10}}c}
\newcommand{\coltwo}{>{\columncolor{red!10}}c}

\tabularex{\colone}
Something \\
\end{tabular}
\end{document}

The key element is the use of \expandafter in the token assignment: \toks0=\expandafter{#1}. Because colone takes no arguments, this only does one level of expansion. I learned this trick from the TeXBook - the answer to Exercise 20.15 shows you how write a macro that expands another only one level, and the discussion of the \asts macro at the beginning of Appendix D ("Dirty Tricks") shows how to use \expandafter with a token assignment.

share|improve this answer
    
You can set only the first column with a newly defined column type. –  egreg Dec 20 '11 at 18:19

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.