# Forcing equal width columns in an array environment with a custom command

I've defined a custom command tractorQ that takes four arguments and typesets them in a matrix-like notation using the array environment:

\newcommand{\tractorQ}[4]{
\def\arraystretch{1.2}
\left(
\begin{array}{ccc}
\multicolumn{3}{c}{#4} \\
{#2} & | & {#3} \\
\multicolumn{3}{c}{#1}
\end{array}
\right)
}


The input

\tractorQ{A}{BCDEFG}{H}{I}


produces the output

but I'd like to center the pipe horizontally, that is, force the first and third columns of the array environment to have the same width. I know that I can achieve this for any instance of this notation either manually or using the array package and defining a custom column environment that uses a custom width. This requires setting the custom width separately for each instance of this notation, however, as the arguments of \tractorQ vary widely in width across instances. Is there a way to write a command that achieves this automatically?

A simple solution with the eqparbox package. It requires the name of the box in columns 1 and 3 as an optional argument (W by default):

 \documentclass{article}
\usepackage{amsmath}
\usepackage{eqparbox}
\newcommand{\tractorQ}[5][W]{
\def\arraystretch{1.2}
\begin{pmatrix}
\multicolumn{3}{c}{#5} \\
\eqmakebox[#1]{$#3$} & | & \eqmakebox[#1]{$#4$} \\
\multicolumn{3}{c}{#2}
\end{pmatrix}
}

\begin{document}

$\tractorQ{A}{BCDEFG}{H}{I}$

$\tractorQ[X]{A}{BCD}{H}{I}$

\end{document}


• This is quite a nice solution, thank you! (+1) Mar 31 '16 at 19:10
• This code also has the (to me) undesirable consequence that all the widths of the middle row cells, i.e., across all instances of \tractorQ in the document share a common width. So, if I add to the above code \tractorQ{J}{K}{L}{M}, the K and L cells are as wide as the BCDEFG cell in the existing instance. Is there a way to avoid this? I tried adding a fifth argument to tractorQ and replacing the relevant line with \eqmakebox[#5]{$#2$} & | & \eqmakebox[#5]{$#3$} \\ so that in each instance of tractorQ I could use a dummy argument unique to that instance, but this generates an error. Apr 7 '16 at 18:27
• Is there a way to resolve this issue? I looked through the package documentation, but couldn't find anything relevant. Apr 7 '16 at 18:28
• Actually, I've found that using a counter resolves this issue. Apr 7 '16 at 18:32
• @Travis: Yours is another nice solution (+1). Apr 7 '16 at 18:53

The \fixTABwidth{T} macro of the tabstackengine package forces all columns to be equal width, if that works for you. EDITED to place rows 1 and 3 in zero-width boxes, so as to avoid them influencing column width.

In this MWE, the intercolumn gap is set to 0ex and the interrow baselineskip is set to 14pt.

\documentclass{memoir}
\usepackage{tabstackengine}
\setstacktabbedgap{0ex}
\setstackgap{L}{14pt}
\newcommand\tractorQ[4]{\fixTABwidth{T}\parenMatrixstack{%
&\makebox[0pt]{#1}&\\#2&|&#3\\&\makebox[0pt]{$#4$}&}
}
\begin{document}
$\tractorQ{A}{BCDEFG}{H}{I}$
$\tractorQ{A}{BCD}{H}{IJKLM}$
\end{document}


• Thank you for this. This doesn't quite fit my needs, as $A$ and $I$ are in some instances rather wide, and in those instances it leaves good deal of awkward space on either side of the pipe. Mar 31 '16 at 18:55
• @Travis Give me a second...I have an idea. Mar 31 '16 at 19:01
• @Travis Please see if revision is any better for your needs. Mar 31 '16 at 19:04
• Yes, this suits my needs nicely, thank you! (And +1 earlier, b.t.w.) Mar 31 '16 at 19:10

A different approach based on the w column type provided by array and the calc package.

\documentclass{article}
\usepackage{amsmath}
\usepackage{calc,array}

\newcommand{\tractorQ}[4]{%
\left(
\renewcommand{\arraystretch}{1.2}
\begin{array}{
@{}
>{$}w{c}{\maxof{\widthof{$#2$}}{\widthof{$#3$}}}<{$}
|
>{$}w{c}{\maxof{\widthof{$#2$}}{\widthof{$#3$}}}<{$}
@{}
}
\multicolumn{2}{c}{#4} \\
#2 & #3 \\
\multicolumn{2}{c}{#1} \\
\end{array}\right)
}

\begin{document}

$\tractorQ{A}{BCDEFG}{H}{I} \qquad \tractorQ{A}{B}{H}{I} \qquad \tractorQ{A}{\begin{array}{@{}c@{}}XYZ\\W\end{array}}{H}{I}$

\end{document}


You can also do that with nicematrix. It's easy to program but you will need two compilations.

\documentclass{article}
\usepackage{amsmath}
\usepackage{nicematrix}

\NewDocumentCommand {\tractorQ} { m m m m }
{
\begin{pNiceArray}{C|C}[columns-width=auto]
\multicolumn{2}{C}{#4} \\
#2 & #3 \\
\multicolumn{2}{C}{#1} \\
\end{pNiceArray}
}

\begin{document}

$\tractorQ{A}{BCDEFG}{H}{I} \qquad \tractorQ{A}{B}{H}{I} \qquad \tractorQ{A}{\begin{array}{@{}c@{}}XYZ\\W\end{array}}{H}{I}$

\end{document}


This answer is just to record a modification of the code in Bernard's helpful answer that produces behavior that I desired but which the original code does not entail. Replacing the \begin{document} ... \end{document} code there with

\begin{document}

$\tractorQ{A}{BCDEFG}{H}{I} , \tractorQ{J}{K}{L}{M}$

\end{document}


so that more than one instance of tractorQ is called, produces the output

In particular, the argument W, which functions as a label that tells the compiler which cells to equalize in width, is applied to every instance of tractorQ in the document. The result is that the cells containing the arguments K and L are wider than necessary.

One can modify this behavior by introducing a dedicated counter, using it as the argument of \eqmakebox in both instances, and incrementing it every time tractorQ is called:

\documentclass{article}
\usepackage{amsmath}
\usepackage{eqparbox}

\newcounter{tractorQcounter}

\newcommand{\tractorQ}[4]{
\def\arraystretch{1.2}
\begin{pmatrix}
\multicolumn{3}{c}{#4} \\
\eqmakebox[\thetractorQcounter]{$#2$} & | & \eqmakebox[\thetractorQcounter]{$#3$} \\
\multicolumn{3}{c}{#1}
\end{pmatrix}
\stepcounter{tractorQcounter}
}

\begin{document}

$\tractorQ{A}{BCDEFG}{H}{I} , \tractorQ{J}{K}{L}{M}$

\end{document}


This produces the output