6

Using commands within tabular definition result in error ! Missing $ inserted. In this case, it is the \, that causes problems when calling the custom command. Same commands work fine outside tabular definition, so how do I use commands in the parameter?

MWE:

\documentclass{article}

\usepackage{calc}
\usepackage{array}

\newcommand{\comtest}[1]{
\begin{tabular}{p{\widthof{#1}}}
#1
\end{tabular}
}

\begin{document}

\setlength\fboxsep{0pt}
\setlength\fboxrule{0.5pt}

\fbox{\comtest{Text\,}}

\end{document}

EDIT: I need to use the width measurement for the paragraph width within the tabular so I can specify to vertically center multiple cells. Below is a less-contrived example. Padding modifiers removed for brevity.

\documentclass{article}

\usepackage{calc}
\usepackage{array}

%produces an image and following text vertically centered
% [image command, image width, text]
\newcommand{\vcenteredimagetext}[3]{{
\begin{tabular}{@{}>{\centering}m{#2}@{}@{\ }>{\centering\arraybackslash}m{\widthof{#3}}@{}}
#1&#3\\
\end{tabular}
}}

\begin{document}

\vcenteredimagetext{\rule{0.5in}{0.5in}}{0.5in}{\bf{Text}}
\bf{Text}

\end{document}

EDIT #2: Decided to go with \raisebox option here instead of pursuing fixes to this method further.

David Carlisle
  • 757,742
TomH57
  • 327
  • 2
  • 8
  • Can you give a more meaningful example? For this one, a c column would be sufficient. – egreg Aug 21 '13 at 15:35
  • 2
    note \bf has been deprecated sine latex2e was released, but if you do use it its syntax is {\bf Text} not \bf{Text} The whole construction is weird, if you want to vertically centre something, you could use a tabular, or more directly use \raisebox{-.5\height}{Text} – David Carlisle Aug 21 '13 at 17:14
  • I just used the \bf as an example command. Feel free to modify it if you wish. – TomH57 Aug 21 '13 at 17:33
  • Also, I'm not sure how you would center an image that is a different height than the text? Ideally I'd like to center an image of any height at the center of the text height above the baseline, where the text may be anything. I'd need to intersperse several of these images within a single line of text, and still have the baselines of all the text line-up. – TomH57 Aug 21 '13 at 17:48
  • @TomH57 the \raisebox command I suggest above does that, there is no need for a table at all. – David Carlisle Aug 21 '13 at 20:41
  • Looks like \raisebox might work after all if I can get a few things worked out. New question posted here.

    Make a response recommending \raisebox and I'll mark it as the answer if I can get the lengths figured out. Thanks!

    – TomH57 Aug 21 '13 at 20:55

1 Answers1

7

Interesting....

You don't really want to do that as it would calculate the width for every row of the table (your example only had one row but...) You can do

\documentclass{article}

\usepackage{calc}
\usepackage{array}
\newlength\zz
\newcommand{\comtest}[1]{
\setlength{\zz}{\widthof{#1}}
\begin{tabular}{p{\zz}}
#1
\end{tabular}
}

\begin{document}

\setlength\fboxsep{0pt}
\setlength\fboxrule{0.5pt}


\fbox{\comtest{Text\,}}

\end{document}

which avoids that, and works.

However arguably what you had should work, \, is declared as a robust command but it is being expanded at a place where \protect code is not being activated, so it takes the wrong (math mode) choice.


To make the original code work:

\documentclass{article}

\usepackage{calc}
\usepackage{array}

\makeatletter
\def\zzz#1{#1}
\def\@classz{\@classx
   \@tempcnta \count@
   \prepnext@tok
  \def\zzz##1{\unexpanded{\zzz}{\unexpanded{##1}}}%
   \@addtopreamble{\ifcase \@chnum
      \hfil
      \d@llarbegin
      \insert@column
      \d@llarend \hfil \or
      \hskip1sp\d@llarbegin \insert@column \d@llarend \hfil \or
      \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend \or
   $\vcenter
   \@startpbox{\expandafter\zzz\expandafter{\@nextchar}}\insert@column \@endpbox $\or
   \vtop \@startpbox{\expandafter\zzz\expandafter{\@nextchar}}\insert@column \@endpbox \or
   \vbox \@startpbox{\expandafter\zzz\expandafter{\@nextchar}}\insert@column \@endpbox
  \fi}%
\prepnext@tok}

\makeatother


\newcommand{\comtest}[1]{
\begin{tabular}{p{\widthof{#1}}}
#1
\end{tabular}
}

\begin{document}

\setlength\fboxsep{0pt}
\setlength\fboxrule{0.5pt}

%\tracingall
\fbox{\comtest{Text\,}}

\end{document}
David Carlisle
  • 757,742
  • I'm not sure how this is different from my first sample, other than you store the length in a temporary variable before using it. I need to know the width of text so that I can specify it when using a vertically centered m{}. – TomH57 Aug 21 '13 at 16:22
  • @TomH57 That is the only difference in the original answer. – David Carlisle Aug 21 '13 at 16:59
  • @TomH57 It is a very odd thing to do, to use a parbox that is the width of the text, are you sure you want to do that? – David Carlisle Aug 21 '13 at 17:00
  • Unless I'm mistaken there's no other way to ensure the table is no wider than the content while still using vertical centering. – TomH57 Aug 21 '13 at 17:35
  • @TomH57 there are lots of ways, there is no point at all using a table just to get an mcolumn around a single cell. Especially m column with text isn't usually what you want as it destroys baseline alignment, to verntically centre an image you can use \raisebox or perhaps simpl the adjustbox package gives a nicer suntax. – David Carlisle Aug 21 '13 at 20:40