我怎样才能通过多层 \edef 来抑制扩张?

我怎样才能通过多层 \edef 来抑制扩张?

我正在使用基于以下定义的宏一些建议这里可以自动创建表。

例如

\newcommand{\clearrows}{\let\matrixcontent\empty}
\newcommand{\actionsrow}[3]{%
  \foreach \i in #3 {%
    \pgfmathparse{#1[\i-1]}
    \let\c\pgfmathresult
    \pgfmathparse{#2[\i-1]}
    \let\s\pgfmathresult
    \begingroup\edef\x{\endgroup
       \noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\c}; \&}}\x
    }%
  \gappto\matrixcontent{\\}%
}

让我只需几行代码就能轻松创建所需的表格。例如,

\newcommand{\rowhv}[1]{
    \actionsrow{{"$e$","$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}

\begin{tikzpicture}
    \matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}

生产

enter image description here

这看起来可能不是什么了不起的成就,但我需要建立相当大的表格,而且要建立很多表格,所以这些宏至关重要。

我需要能够在单元格中放置任意内容,范围从任意格式(例如\textsf{..})到导入的图像(例如使用\includegraphics)或我定义的其他宏来绘制节点内容。但上面的代码仅适用于纯文本的单元格内容。如果我在第一个参数中的项目中提供纯文本以外的任何内容(\actionsrow用于\c循环中),我会收到错误,

\reserved@a 的参数有一个额外的}。

尽管此类内容对于节点而言完全有效。我怀疑我的(窃取的)宏解析方式出了问题\c,但我甚至不知道从哪里开始追踪。

我如何修改我的\actionsrow宏以便我可以将任意 LaTeX 指定为我的节点的内容?


\documentclass[]{article}

\usepackage{etoolbox}
\usepackage{tikz}
\usetikzlibrary{matrix}


\begin{document}

% See -- https://tex.stackexchange.com/a/47649/7844
\newcommand{\clearrows}{\let\matrixcontent\empty}
\newcommand{\actionsrow}[3]{%
  \foreach \i in #3 {%
    \pgfmathparse{#1[\i-1]} % See -- https://tex.stackexchange.com/a/56838/7844; note \let vs \def
    \let\c\pgfmathresult
    \pgfmathparse{#2[\i-1]}
    \let\s\pgfmathresult
    \begingroup\edef\x{\endgroup
       \noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\c}; \&}}\x
    }%
  \gappto\matrixcontent{\\}%
}

% This works fine
\newcommand{\rowhv}[1]{
    \actionsrow{{"$e$","$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}

\begin{center}
\begin{tikzpicture}
  \matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}
\end{center}

% Here, arbitrary specifications work for the nodes, if done manually
\begin{center}
\begin{tikzpicture}
\matrix [nodes={minimum size=7mm}]
{
    \node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!67]{$v$}; & \node[fill=gray!100]{$hv$}; \\
    \node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!100]{$hv$}; & \node[fill=gray!67]{$v$}; \\
    \node[fill=gray!67]{$v$}; & \node[fill=gray!100]{$hv$}; & \node[fill=gray!3]{\texttt{e}}; & \node[fill=gray!33]{\color{red}$h$}; \\
    \node[fill=gray!100]{$hv$}; & \node[fill=gray!67]{$v$}; & \node[fill=gray!33]{\color{red}$h$}; & \node[fill=gray!3]{\texttt{e}}; \\
 };
\end{tikzpicture}
\end{center}

% But this fails
\renewcommand{\rowhv}[1]{
    \actionsrow{{"\texttt{e}","\color{red}$h$","$v$","$hv$"}}{{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}{#1} }
\clearrows
\rowhv{{1,2,3,4}} \rowhv{{2,1,4,3}} \rowhv{{3,4,1,2}} \rowhv{{4,3,2,1}}

\begin{center}
\begin{tikzpicture}
  \matrix[ampersand replacement=\&,nodes={minimum size=7mm}]{\matrixcontent};
\end{tikzpicture}
\end{center}

\end{document}

答案1

您有两个问题,都与有关\edef。第二个问题实际上是与您的有关,因为任何进入\edef的宏都会被扩展并造成混乱。第一个问题是与有关,因为根据手册,数学表达式中的所有内容都会完全展开,因此,您需要对应该的内容进行额外的保护#1\c\x\pgfmathparse不是需要扩展。我发现有两种方法可以解决这个问题:

  1. 手动将\unexpanded每个项目放在数组的周围#1,并将其放在数组的\expandonce前面(因此它被展开,但其内容没有展开)。这很麻烦,但可以解决问题。\c\edef

  2. 在继续执行当前的主体之前,先用 进行初步循环以\foreach放入这些s 。由于让双引号与此很好地交互会很麻烦,我建议您为其第一个参数制作语法,\unexpanded\actionsrow{$a$, $\mathbf{b}$, \includegraphics{c.pdf}, ...}没有引号,并添加\foreach\unexpanded引号。另外,不要忘记\expandonce\c\edef和前面一样。

以下是我实施选项 2 的方法:

\newcommand{\actionsrow}[3]{%
  %%%
  % NEW STUFF
  %%%
  \let\comma=\empty
  \let\b=\empty
  \foreach \a in {#1} {%
   \xappto\b{\comma"\noexpand\unexpanded{\expandonce\a}"}%
   \gdef\comma{,}%
  }%
  \foreach \i in #3 {%
    %%% CHANGED #1 -> \b
    \pgfmathparse{{\b}[\i-1]}%
    \let\c\pgfmathresult
    \pgfmathparse{#2[\i-1]}%
    \let\s\pgfmathresult
    \begingroup\edef\x{\endgroup
       %%% ADDED \expandonce\c
       \noexpand\gappto\noexpand\matrixcontent{\noexpand\node[\s]{\expandonce\c}; \&}}\x
    }%
  \gappto\matrixcontent{\\}%
}

\newcommand{\rowhv}[1]{
 \actionsrow
  %%% NEW SYNTAX: first arg is a pure CSV list
  {$\mathbf{e}$,$h$,$v$,$hv$}
  {{{"fill=gray!3"},{"fill=gray!33"},{"fill=gray!67"},{"fill=gray!100"}}}
  {#1}%
}

相关内容