0

I am trying to define some options for an environment using a macro.

\usepackage{tabularray}

....

% previous parameter definition, does not scale
\def\cellax{1}
\def\cellay{2}
\def\cellaw{4}

\def\cellbx{2}
\def\cellby{3}
\def\cellbw{5}

% want to use a macro taking arguments
\newcommand{\newcell}[3]{
    hline{#2-{#2+1}}={#1-{#1 + #3 - 1}}{solid},
    vline{#1,#1+#3}={#2}{solid},
    cell{#2}{#1}={c=#3}{c},
}
\begin{table}[!ht]
    \ttfamily
    \centering
    $\begin{tblr}{
        hline{1}={1-Z}{solid},
        hline{2}={1-Z}{solid},
        vline{1}={1}{solid},
        vline{2-11}={1}{dashed},
        %
        hline{\cellay-{\cellay+1}}={\cellax-{\cellax + \cellaw - 1}}{solid},
        vline{\cellax,\cellax+\cellaw}={\cellay}{solid},
        cell{\cellay}{\cellax}={c=\cellaw}{c},
        %
        hline{\cellby-{\cellby+1}}={\cellbx-{\cellbx + \cellbw - 1}}{solid},
        vline{\cellbx,\cellbx+\cellbw}={\cellby}{solid},
        cell{\cellby}{\cellbx}={c=\cellbw}{c},
        % Want to use it here ....
        \newcell{4, 4, 4},
        %
        hspan = even,
    }
    x_1&x_2&x_3&x_4&x_5&x_6&x_7&x_8&x_9&x_{10}&\ldots\\
    n_1&\\
    &n_2  \\ 
    &&n_3  \\ 
    &&&&\ddots  \\ 
    \end{tblr}$
\end{table}

Essentially I am trying to replace the definitions using \cellax ("cell A, x coordinate"), \cellbx, etc. with a macro taking 3 arguments and expanding to the definition of a few hlines and vlines and a cell. These are all options for the tblr environment from the tabularray package, as far as I am aware.

This code produces the error "You can't use macro parameter character # in horizontal mode" in the newcommand, but even when I insert concrete values into the macro definition it doesn't seem to work. No new cell is created.

enter image description here

  1. how do I correctly expand a macro in the options of an environment?
  2. how do I use arguments in a macro expanding to a list of options?
1
  • 1
    Not the issue at its core but: In TeX, a macro defined as \newcommand\foo[3]{<stuff>} should be used as \foo{a}{b}{c}, not as \foo{a, b, c}.
    – Skillmon
    Sep 18 at 18:55

2 Answers 2

2

If all your key=value contents can be subject to full expansion you could use \expanded to expand it before the tblr-environment reads it. You should then protect the \begin from expanding (using either \noexpand as in the code below, or \unexpanded{<stuff>} with <stuff> replaced with whatever shouldn't expand further).

As already pointed out in my comment, arguments in TeX are separate sets of braces, so it would be \newcell{4}{4}{4} instead of \newcell{4, 4, 4}. Additionally the number of arguments for \newcommand is given in brackets, not braces, as that's an optional argument: \newcommand{\newcell}[3]{<replacement text>}.

With these things applied your code becomes the following:

\documentclass[preview]{standalone}

\usepackage{tabularray}

% previous parameter definition, does not scale
\def\cellax{1}
\def\cellay{2}
\def\cellaw{4}

\def\cellbx{2}
\def\cellby{3}
\def\cellbw{5}

% want to use a macro taking arguments
\newcommand{\newcell}[3]{
    hline{#2-{#2+1}}={#1-{#1 + #3 - 1}}{solid},
    vline{#1,#1+#3}={#2}{solid},
    cell{#2}{#1}={c=#3}{c},
}

\begin{document}
\begin{table}[!ht]
    \ttfamily
    \centering
    $\expanded{\noexpand\begin{tblr}{
        hline{1}={1-Z}{solid},
        hline{2}={1-Z}{solid},
        vline{1}={1}{solid},
        vline{2-11}={1}{dashed},
        %
        hline{\cellay-{\cellay+1}}={\cellax-{\cellax + \cellaw - 1}}{solid},
        vline{\cellax,\cellax+\cellaw}={\cellay}{solid},
        cell{\cellay}{\cellax}={c=\cellaw}{c},
        %
        hline{\cellby-{\cellby+1}}={\cellbx-{\cellbx + \cellbw - 1}}{solid},
        vline{\cellbx,\cellbx+\cellbw}={\cellby}{solid},
        cell{\cellby}{\cellbx}={c=\cellbw}{c},
        % Want to use it here ....
        \newcell{4}{4}{4},
        %
        hspan = even,
    }}
    x_1&x_2&x_3&x_4&x_5&x_6&x_7&x_8&x_9&x_{10}&\ldots\\
    n_1&\\
    &n_2  \\ 
    &&n_3  \\ 
    &&&&\ddots  \\ 
    \end{tblr}$
\end{table}
\end{document}

enter image description here


An alternative that gives more control could be to use expkv1 and its key=value-expansion syntax. In the following the V: in front of \newcell tells expkv to expand the following once (if it had a = it'd expand the value instead of the key). Everything else is forwarded untouched (or at least almost untouched, one set of outer braces around a key-name would be stripped -- something not present in your MWE).

To simplify the job of wrapping your key-list in expkv just for the expansion mechanism I wrote a short helper macro \keyexpander. If you need explanations for it just ask.

\documentclass[preview]{standalone}

\usepackage{tabularray}
\usepackage{expkv-cs}

\newcommand*\keyexpander{\ekvoptarg\keyexpanderKV{}}
\ekvcSplitAndForward\keyexpanderKV\keyexpanderDO
  {
     pre = {}
    ,post = {}
    ,keyProc  = \keyexpanderKEY
    ,pairProc = \keyexpanderPAIR
  }
\ekvcSecondaryKeys\keyexpanderKV
  {
     nmeta oarg = { pre = [, post = ] }
    ,nmeta brace-keys =
      { keyProc = \keyexpanderKEYBR, pairProc = \keyexpanderPAIRBR }
    ,nmeta plain-keys =
      { keyProc = \keyexpanderKEY, pairProc = \keyexpanderPAIR }
  }
\newcommand\keyexpanderDO[6]
  {%
    \expanded
      {%
        \unexpanded{#5#1}%
        {%
          \IfBlankF{#6}
            {%
              \unexpanded\expandafter\expandafter\expandafter
                {%
                  \expandafter\keyexpanderCOMMA\expanded
                    {\expanded{\ekvparse{#3}{#4}{#6}}}%
                }%
            }%
        }%
      }%
    #2%
  }
\def\keyexpanderCOMMA, {}
\newcommand\keyexpanderKEY[1]{, \unexpanded{#1}}
\newcommand\keyexpanderPAIR[2]{, \unexpanded{#1}= {\unexpanded{#2}}}
\newcommand\keyexpanderKEYBR[1]{, {\unexpanded{#1}}}
\newcommand\keyexpanderPAIRBR[2]{, {\unexpanded{#1}}= {\unexpanded{#2}}}

% previous parameter definition, does not scale
\def\cellax{1}
\def\cellay{2}
\def\cellaw{4}

\def\cellbx{2}
\def\cellby{3}
\def\cellbw{5}

% want to use a macro taking arguments
\newcommand{\newcell}[3]{
    hline{#2-{#2+1}}={#1-{#1 + #3 - 1}}{solid},
    vline{#1,#1+#3}={#2}{solid},
    cell{#2}{#1}={c=#3}{c},
}

\begin{document}
\begin{table}[!ht]
    \ttfamily
    \centering
    $\keyexpander{\begin{tblr}}{
        hline{1}={1-Z}{solid},
        hline{2}={1-Z}{solid},
        vline{1}={1}{solid},
        vline{2-11}={1}{dashed},
        %
        hline{\cellay-{\cellay+1}}={\cellax-{\cellax + \cellaw - 1}}{solid},
        vline{\cellax,\cellax+\cellaw}={\cellay}{solid},
        cell{\cellay}{\cellax}={c=\cellaw}{c},
        %
        hline{\cellby-{\cellby+1}}={\cellbx-{\cellbx + \cellbw - 1}}{solid},
        vline{\cellbx,\cellbx+\cellbw}={\cellby}{solid},
        cell{\cellby}{\cellbx}={c=\cellbw}{c},
        % Want to use it here ....
        V: \newcell{4}{4}{4},
        %
        hspan = even,
      }
    x_1&x_2&x_3&x_4&x_5&x_6&x_7&x_8&x_9&x_{10}&\ldots\\
    n_1&\\
    &n_2  \\ 
    &&n_3  \\ 
    &&&&\ddots  \\ 
    \end{tblr}$
\end{table}
\end{document}

Output like above.

1Disclaimer: I'm the author of expkv.

5
  • Amazing. Thank you so much.. Unfortunately it is difficult to find such tricks by simply googling. Hopefully this helps others in the future.
    – stimulate
    Sep 18 at 19:27
  • @stimulate I have yet another (more complicated) approach... I'll edit (for your use case, at least as given in the question, this first code should suffice, the other variant gives more control).
    – Skillmon
    Sep 18 at 19:38
  • Could you maybe elaborate on why the second example is more flexible or do you have an example how to use it?
    – stimulate
    Sep 18 at 22:07
  • @stimulate in the first code block \cellax etc. are expanded as well. If their state would change during the key=value processing that wouldn't be reflected later on. Using expkv you get a notation to selectively expand single keys without affecting anything else. For instance o: expands once, e: expands fully in \expanded, V: expands once and reinserts the list as additional key=value input.
    – Skillmon
    Sep 19 at 7:17
  • Okay, I think I see what you mean, though I think I am not deep enough in Latex and Macro expansion yet to imagine all of the possible use cases.. your first answer completely suffices for now :)
    – stimulate
    Sep 19 at 13:23
1

The same diagram can be achieved using TeX primitives only. Creating such macros is much more fun.

\newdimen\bw  \bw=1.8em

\def\dashrule{\lower4pt\vbox to15pt{%
   \cleaders\vbox{\kern.5pt\hrule height2pt width.4pt\kern.5pt}\vfil}%
}
\def\xcells#1{\ifx\relax#1\else 
   \hbox to\bw{\hfil$x_{#1}$\hfil \dashrule}%
   \expandafter\xcells\fi
}
\def\boxik#1#2#3{
   \moveright#1\bw\vbox{\kern-.4pt
      \hrule
      \hbox to#2\bw{\vrule height 11pt depth4pt \hfil$#3$\hfil\vrule}
      \hrule
   }
}

\vbox{\offinterlineskip
   \hrule
   \hbox{\vrule\kern-.4pt \xcells 123456789{10}\relax \kern2pt\dots\kern2pt}
   \hrule
   \boxik 0 4 {n_1}
   \boxik 1 5 {n_2}
   \boxik 2 5 {n_3}
   \moveright 4.5\bw\hbox{$\ddots$}
}

You must log in to answer this question.

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