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.

I want to fill a cells of a table with only a \item command, and the \begin{itemize} should be automatically inserted. The following code works :

\newenvironment{matable}[0]{%
\begin{tabular}{l|p{5cm}}
theme & sujets \\ \hline\hline }
{\end{tabular}}

\newcommand{\messujets}[1]{ & \begin{itemize} #1 \end{itemize}\\ \hline}

\begin{matable}
\messujets{\item subject 1 \item subject 2}
\end{matable}

With the command \messujets I start a new line in the table, and I fill the second cell with my \item. But if the argument of \messujets happens to be empty, LaTeX complains about a missing \item. To avoid this, I want to have an \ifthenelse test in the cell. My attempt is to replace:

\begin{itemize} #1 \end{itemize}

by

\ifthenelse{\equal{#1}{}}{\begin{itemize} #1 \end{itemize}}

So, it would be :

\newcommand{\messujets}[1]{ & \ifthenelse{\equal{#1}{}}{}{\begin{itemize} #1 \end{itemize}}\\ \hline}

But this produces an error use of \@item does not match its definition which I do not understand...

Any idea?

share|improve this question

4 Answers 4

The reason for the problem is that the \equal argument is a so called moving argument. That means it will break if it contains in its argument commands that are fragile and not protected by \protect. And because of the optional argument \item is fragile.

In short using \ifthenelse here makes your life unnecessarily complicated as you would need to write something like

\messujets{\protect\item subject 1 \protect\item subject 2}

For that reason a better approach is to use a lowlevel solution where you test for the argument being empty in a way that nothing is getting expanded and breaks. There are a number of ways to do this, e.g.,

\ifx\foo#1\foo ...\else ... \fi

This will work as long as the argument #1doesn't start with \foo so by selecting some internal command for \foo you can make sure that this is the case.

share|improve this answer
\documentclass{article}
\newenvironment{matable}
  {\tabular{l|p{5cm}} theme & sujets \\ \hline\hline }
  {\endtabular}
\newcommand\messujets[1]{ & \ifx\relax#1\relax\else\itemize#1\enditemize\fi\\ \hline}   
\begin{document}

\begin{matable}
  \messujets{\item subject 1 \item subject 2}
  \messujets{}
  \messujets{\item subject 3 \item subject 4}
\end{matable}

\end{document}
share|improve this answer
1  
Care to explain that? It also seems like a duplicate of Ian's. –  Martin Schröder Dec 20 '11 at 14:37
1  
see my answer. Herbert uses \ifx which works (as long as the arg doesn't start with \relax) while Ian uses \ifwhich expands arguments and therefore is much more dangerous (and not quite correct as applied). –  Frank Mittelbach Dec 20 '11 at 15:47
    
Thanks a lot ! I often have problems when using ifthenelse, i think the reason is the same. –  nicolas roy Dec 21 '11 at 8:22
    
By the way : how should i do if i want a slightly more complicated test : If #1 empty or #1 = somestring then nothing else itemize like before ? –  nicolas roy Dec 21 '11 at 20:02

This seems to work, but I must be honest and admit that I don't really understand why.

\documentclass{article}
\newenvironment{matable}[0]{%
\begin{tabular}{l|p{5cm}}
theme & sujets \\ \hline\hline }
{\end{tabular}}
\newcommand{\messujets}[1]{&\if\noexpand#1\relax\else \begin{itemize}#1\end{itemize}\fi\\ \hline}
%
\begin{document}
\begin{matable}
\messujets{\item subject 1 \item subject 2}
\messujets{}
\messujets{\item subject 3 \item subject 4}
\end{matable}
\end{document}
share|improve this answer
    
This is quite risky: \item \textbf{x} would result in a disaster. Moreover the case in which #1 is empty works because \if compares \relax to a special kind of \relax that's different from it: \if\relax\else is an incomplete conditional that TeX normalizes in a funny way. –  egreg Dec 20 '11 at 15:11
    
Thanks egreg. The case where #1 is empty was the part I didn't understand. Where can I read more about this special kind of \relax? –  Ian Thompson Dec 20 '11 at 21:02
    
I think there's something about it in TeX by Topic. See also this discussion –  egreg Dec 20 '11 at 21:13

Rather than use \item you should consider a scheme like the second of the following, or use the multirow package. \ifthenelse will not work in this case. I had a look at the trace file and saw where the problem lies. The first of the following stands a better chance, but may still fail in some cases:

First case:

\documentclass{article}
\makeatletter
\def\ifnotnull#1{%
  \ifcat$\detokenize{#1}$\expandafter\@gobble\else\expandafter\@iden\fi
}
\newenvironment{mytable}
  {\tabular{l|p{5cm}} theme & subjects \\ \hline\hline }
  {\endtabular}
\newcommand\subjects[1]{ & \ifnotnull{#1}{\itemize#1\enditemize}\\ \hline}
\makeatother

\begin{document}
\begin{mytable}
  \subjects{\item subject 1 \item subject 2}
  \subjects{}
  \subjects{\item subject 3 \item subject 4}
\end{mytable}
\end{document}

Second case:

\documentclass{article}
\usepackage{ltxtools}[2011/12/10]
\newcount\colnum
\newcommand\generaterow[1]{%
  \colnum0
  \ltswhileexpr{\ifnum\colnum<#1\relax}{%
    &\global\advance\colnum by1 \the\colnum\relax
  }%
}

\begin{document}
\begin{tabular}{|*{4}{c|}}
  \hline
  x\generaterow{3}\\\hline
\end{tabular}
\end{document}
share|improve this answer

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.