6

I'm trying to define a macro for table headers but unfortunately I'm far from a TeX expert. I should split a list that is delimited with ampersands, format the entries and concatenate it again with ampersands. Splitting the list works but I can't concatenate it with ampersands.

\documentclass{article}
\usepackage{xstring}

\newcommand{\DLbase}[1]% #1 = comma delimited keywords
{{\saveexpandmode\expandarg%
\StrCut{\noexpand#1}{&}\DLleft\DLright%
\loop% extract keywords from list
\StrCut{\DLright}{&}\DLnext\DLright%
\textbf\DLleft\DLsep%
\edef\DLleft{\DLnext}%
\if\DLright\relax\else\repeat%
\textbf{\DLleft}%
\restoreexpandmode}}

\newcommand{\tabhead}[1]{\def\DLsep{&}\DLbase{#1}\\}

\begin{document}

\begin{table}[ht]
  \begin{center}
    \caption{Command / Purposes}
    \begin{tabular}{|p{0.3\textwidth}|p{0.6\textwidth}|}
      \hline
      \tabhead{Command & Purpose}
      \hline
      cd & change directory \\
      rm & remove files 
      \hline
    \end{tabular}
  \end{center}
\end{table}
\end{document}

I copied most of the code from here and here.

How do I have to define \DLbase and \DLsep that this works?

1

2 Answers 2

5

The problem is always to output all the row before TeX “sees” &. It's easy with expl3, with \seq_use:Nn, that delivers its result “at once”.

The \tabhead command has an optional argument for the formatting command, default \bfseries. It splits its argument at &, then adds the optional argument before items, separating them with &, with a trailing \\.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\tabhead}{ O{\bfseries} m }
 {
  \seq_set_split:Nnn \l_tmpa_seq { & } { #2 }
  #1 \seq_use:Nn \l_tmpa_seq { & #1 } \\
 }
\ExplSyntaxOff

\begin{document}

\begin{table}[htp]
\centering
\caption{Command / Purposes}

\begin{tabular}{|p{0.3\textwidth}|p{0.6\textwidth}|}
\hline
\tabhead{Command & Purpose}
\hline
cd & change directory \\
rm & remove files \\
\hline
\end{tabular}

\bigskip

\begin{tabular}{|p{0.3\textwidth}|p{0.6\textwidth}|}
\hline
\tabhead[\itshape]{Command & Purpose}
\hline
cd & change directory \\
rm & remove files \\
\hline
\end{tabular}

\end{table}

\end{document}

enter image description here

0
3

Rather than using xstring I recommend using the dedicated commands in the xparse package such as \SplitList or \SplitArgument to do this. As these commands don't appear to play well with ampersands (I'm sure this could be fixed by playing with the category codes), I have changed \tabhead to expect a command separated list:

\documentclass{article}
\usepackage{xparse}

% typeset an entry of the header
\newcommand\MakeEntry[1]{\headersep#1\def\headersep{&}}

\DeclareDocumentCommand\tabhead{ > { \SplitList{,}} m }
   {\let\headersep\relax% no & needed for first column
    \ProcessList{#1}{\MakeEntry}\relax\\%
   }

\begin{document}

    \begin{tabular}{|p{0.3\textwidth}|p{0.6\textwidth}|}
      \hline
      \tabhead{Command, Purpose}
      \hline
      cd & change directory \\
      rm & remove files\\
      \hline
    \end{tabular}

\end{document}

I've dropped the center and table environments as they are not necessary for the MWE. This produces the expected output:

enter image description here

In the definition of \tabhead the > causes the "input" to be treated as a comma separated list, the entries of which are then passed to \MakeEntry by \ProcessList. The \headersep macro is use to add a & separator before every header item except the first.

1
  • Thank you for your solution which works fine when one uses a different delimiter than the ampersand. I couldn't figure out where I should change the catcode. Luckily I don't have to anymore due to egregs solution.
    – CrisX
    Nov 14, 2016 at 18:31

You must log in to answer this question.

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