tocloft 包中的 \newlistof 的扩展问题

tocloft 包中的 \newlistof 的扩展问题

我尝试编写宏,比如说,它自动为一些生成的宏\foo提供计数器和类似的命令,使用包方法对生成的命令进行微调。 \listofsomethingxkeyval

我使用该tocloft包进行计数器和生成(尽管我认为我可以自己\listofsomething定义一些类似的方法)\@starttoc

但是,我发现了扩展问题,并且下面的\expandafterfor组合不起作用\newlistof(我省略了\expandafterMWE 中的语句)。

代码没有抱怨,但是输出是错误的,因为使用generator\foo进行另一个宏定义将提供“正确”的\listofsomething命令,但是\listofname从最后定义的命令开始使用,并且所有条目都进入同一个列表,这是不想要的。

(当然,真正的代码有很多功能(或将有很多)),但我将其归结为最低限度。例如,如果没有明确给出键值,则包含的宏\listofname将从第二个参数自动生成,但我在这里省略了这一点)\foo

  • 我并不怀疑xkeyval这应该归咎于此(因为使用它之外的关键宏并将它们重新定义为其他内容只会提供最新的内容,而不是以前的内容。
  • \begingroup...\endgroup有助于保持命名空间在 中的整洁\foo,但\listofsomething定义的宏在\newlistof之外无法使用\foo
  • 此处定义的宏的输出格式\foo并不重要。目前它只是一个用于测试的小“标题”。
  • \foo命令是为了\@onlypreamble使用而设计的,但为了简单起见,我在这里省略了此功能。

这个问题的可能解决方案是什么?或者之后有没有办法使用\global\listofsomething,以便在内部使用分组\foo(也许一些\let等等?)


\documentclass{article}


\usepackage{tocloft}
\usepackage{xkeyval}

\makeatletter
\define@key{foo}{listofname}{%
  \def\foolistofname{#1}%
}

\define@key{foo}{countername}{%
  \def\foocountername{#1}%
}

\define@key{foo}{listext}{%
  \def\foolistext{#1}%
}


\makeatother

\newcommand{\foo}[2][]{%
\setkeys{foo}{#1}
\newlistof{\foocountername}{\foolistext}{\foolistofname}
\expandafter\newcommand\csname #2\endcsname[1]{%
  \refstepcounter{\foocountername}%
  \addcontentsline{\foolistext}{section}{\csname the\foocountername\endcsname~ ##1}
  {\vspace*{50pt}\noindent\bfseries \large \csname the\foocountername\endcsname~ ##1\normalsize\normalfont}
}
}

\newcommand{\listofmarxbrothersname}{List of Marx Brothers}
\newcommand{\listofstoogesname}{List of the Stooges}

% Define the command \marxbrothers and its \listof...
\foo[listofname={\listofmarxbrothersname},listext=mb,countername={mb}]{marxbrothers}
% Define the command \stooges and its \listof...

\foo[listofname=\expandafter{\listofstoogesname},listext=st,countername={stooges}]{stooges}


\def\foocountername{monty}
\def\foolistext{monty}
\def\foolistofname{List of Monty Pythons}


\newlistof{\foocountername}{\foolistext}{\foolistofname}


\begin{document}
\listofstooges
\listofmb%
\marxbrothers{Groucho}
\marxbrothers{Zeppo}
\marxbrothers{Harpo}
\marxbrothers{Chico}
\marxbrothers{Gummo}


\stooges{Curly}
\stooges{Moe}
\stooges{Larry}



\end{document}

快照显示所有条目都进入了同一份列表,使用了错误的计数器和错误的List of ....标题。应该有两个列表。

在此处输入图片描述

答案1

你用什么

\foo[listofname={\listofmarxbrothersname},listext=mb,countername={mb}]{marxbrothers}

本质上

\newlistof{\foocountername}{\foolistext}{\foolistofname}
\newcommand\marxbrothers[1]{%
   \addcontentsline{\foolistext}{section}{\csname the\foocountername\endcsname~##1}%
  ...%
}

这当然不是你想要的,因为\marxbrothers将使用当前的的值\foocountername等等。

你需要一个巨大的\begingroup\edef\x{\endgroup...}\x技巧,写起来很麻烦,\expandafter而且\noexpand涉及很多关键位置。我不想这么做。

这是一个更加简单的实现expl3

\documentclass{article}

\usepackage{tocloft}
\usepackage{xparse}

\ExplSyntaxOn
\keys_define:nn { christian/foo }
 {
  listofname .tl_set:N = \l_foo_listofname_tl,
  countername .tl_set:N = \l_foo_countername_tl,
  listext .tl_set:N = \l_foo_listext_tl,
 }

\NewDocumentCommand{\foo}{O{}m}
 {
  \keys_set:nn { christian/foo } { #1 }
  \__foo_create_commands:nVVV {#2} \l_foo_countername_tl \l_foo_listext_tl \l_foo_listofname_tl
 }

\cs_new_protected:Nn \__foo_create_commands:nnnn
 {
  \newlistof{#2}{#3}{#4}
  \cs_new_protected:cpn { #1 } ##1
   {
    \refstepcounter{#2}
    \addcontentsline{#3}{section}{\use:c{the#2}~##1}
    \group_begin:
    \par
    \vspace*{20pt}
    \noindent\large\bfseries\use:c{the#2}~##1\par
    \group_end:
   }
 }
\cs_generate_variant:Nn \__foo_create_commands:nnnn { nVVV }
\ExplSyntaxOff

\newcommand{\listofmarxbrothersname}{List of Marx Brothers}
\newcommand{\listofstoogesname}{List of the Stooges}

% Define the command \marxbrothers and its \listof...
\foo[listofname={\listofmarxbrothersname},listext=mb,countername={mb}]{marxbrothers}
% Define the command \stooges and its \listof...
\foo[listofname=\listofstoogesname,listext=st,countername={stooges}]{stooges}

\begin{document}

\listofstooges
\listofmb

\marxbrothers{Groucho}
\marxbrothers{Zeppo}
\marxbrothers{Harpo}
\marxbrothers{Chico}
\marxbrothers{Gummo}

\stooges{Curly}
\stooges{Moe}
\stooges{Larry}

\end{document}

在此处输入图片描述

在我看来,\foo应该有两个强制参数,并且可能应该将键标记为必需,因为当您使用新命令定​​义新列表时,需要所有这三个。

相关内容