建立和加入“内部”名单

建立和加入“内部”名单

如何附加到 pgfkeys 样式的逗号分隔列表?或者,如何定义宏以使用分隔符连接 etoolbox 列表?

对于我正在设计的环境,我想将主体中的定义累积到一个列表中,并将它们输出到环境的结束代码中,并与分隔符连接。我插入分隔符的方法是在每个项目之前插入一个宏(最初它是空白的,然后在循环期间重新分配)。

我尝试了两种存储列表的方法,一种是使用 pgfkeys,另一种是使用 etoolbox。对于 pgfkeys 版本,我有一个似乎运行良好的列表连接宏,但我不知道如何附加到列表中。使用 etoolbox,我可以逐步建立列表,但我的连接列表的宏不起作用。不幸的是,列表表示不兼容(所以我不能同时使用这两种方法)。

\documentclass{article}

\usepackage{pgfkeys,pgffor}
\usepackage{etoolbox}

\makeatletter
\def\listdelimiter{, }  % default delimiter

% pgfkeys list
\pgfkeys{
  /list/.code={\@delim#1\edef\@delim{\@nextdelim}} % delim reassigned after first item
}
\newcommand\pgflistjoin[2][\listdelimiter]{%
  \edef\@nextdelim{#1}%
  \edef\@delim{}%
  \expandafter\@pgflistjoin\expandafter{#2}
}
\newcommand\@pgflistjoin[1]{%  helper macro for expanding the list
  \pgfkeys{/list/.list={#1}}%
}

% etoolbox list
\newcommand\listjoin[2][\listdelimiter]{%
  \edef\@nextdelim{#1}%
  \edef\@delim{}%
  \begingroup % so #1 below is for \do (?)
  \renewcommand*\do[1]{\@delim#1\edef\@delim{\@nextdelim}}%
  \endgroup%
  \dolistloop{#2}%
}
\makeatother

\begin{document}
\pgflistjoin[;]{1,{2 3},4} % bare list; works

\def\alist{1,{2 3},4}
\pgflistjoin[;]{\alist} % macro list; works

\listadd\blist{a}
\listadd\blist{b c}
\listadd\blist{d}

\listjoin[;]{\blist}  % no delimiters (whole list treated as one item?)

\makeatletter  % try manually
\def\@nextdelim{;}
\def\@delim{}
\renewcommand*\do[1]{\@delim#1\edef\@delim{\@nextdelim}}
\dolistloop{\blist}  % this works
\makeatother

\end{document}

对于 etoolbox 版本,我怀疑问题出在 附近\begingroup。但是如果没有它,#1就是来自外部宏的分隔符。

最后,除了这两个包裹之外,我宁愿不带其他包裹。

答案1

我将使用etoolbox: 在您的定义中\listjoin存在两个问题: 不能使用组来访问\do #1,为此您必须#通过将其加倍来逃避 。 因此您得到

...
\renewcommand*\do[1]{\@delim##1\edef\@delim{\@nextdelim}}
...

-确实会产生影响:对于组而言,它是本地的,因此在之后不再可见。这解释了\begingroup为什么您看不到任何分隔符:您的定义不再可见,因此将改用默认定义。这就像一个 noop。\endgroup\renewcommand*\do\endgroup\do\noexpand

因此我们不需要在这里使用组。相反,可以使用组来包围整个宏,以阻止其他宏看到我们对\do\delim、 ... 的更改。

这导致

\newcommand\listjoin[2][\listdelimiter]{%
  \begingroup%
  \edef\@nextdelim{#1}%
  \edef\@delim{}%
  \renewcommand*\do[1]{\@delim##1\edef\@delim{\@nextdelim}}%
  \dolistloop{#2}%
  \endgroup%
}

相关内容