使用 expl3 在键值中嵌入键值

使用 expl3 在键值中嵌入键值

我正在尝试在调用中将键值嵌入到键值中,如下所示:

\showchapter{
    title=My chapter,
    authors={
        {name=Peter,affiliation=MIT},
        {name=Mary,affiliation=UCLA},
    },
}

得到这个输出

My chapter
    Peter, MIT
    Mary, UCLA

但我无法访问嵌入的键值authors

\seq_map_indexed_function:NN \authors \callshowauthorx:nn对in的调用\showauthors没有按预期进行。

在下面的例子中,我只想输出参数和嵌入的参数:

\documentclass{book}

\ExplSyntaxOn

\keys_define:nn { authorkeys }
  {
    name .tl_set:N = \name,
    affiliation .tl_set:N = \affiliation,
  }
\NewDocumentCommand{\showauthor}{m}
  {
    \textbf{showauthor:~} 
    \keys_set:nn { authorkeys } { #1 }
    ( \name { ,~ } \affiliation )
  }
\seq_new:N \myseqx
\NewDocumentCommand \showauthors { m }
  {
    \textbf{showauthors:~} 
    \seq_set_from_clist:Nn \myseqx { #1 }
    \seq_map_indexed_function:NN \myseqx \callshowauthorx:nn
  }
\cs_new:Nn \callshowauthorx:nn
  { \par \showauthor{#2} }
\keys_define:nn { chapterkeys }
  {
    title .tl_set:N = \title,
    authors .clist_set:N = \authors,
  }
\seq_new:N \myseqy
\NewDocumentCommand{\showchapter}{m}
  {
    \keys_set:nn { chapterkeys } { #1 }
    \par\textbf{showchapter-title:~}
    \title
    \par\textbf{showchapter-authors:~}
    % next line seems not to work as expected
    \seq_map_indexed_function:NN \authors \callshowauthorx:nn
  }

\ExplSyntaxOff
\begin{document}

\showauthor{name=Peter,affiliation=MIT}

\showauthors{
    {name=Peter,affiliation=MIT},
    {name=Mary,affiliation=UCLA},
}

\showchapter{
    title=My chapter,
    authors={
        {name=Peter,affiliation=MIT},
        {name=Mary,affiliation=UCLA},
    },
}

\end{document}

答案1

我怀疑你真的想要所有这些机器。我认为其中一些是用于测试/开发。

我整理了代码(一点点),并修改了它,让它可以做我想让你做的事情。也许这会有所帮助,你可以对它进行微调。

我会坚持使用clists,而不是使用序列 ( seq)。后者有优势,而且对于某些事情来说它们是必要的,但是当您试图掌握时,它们会增加一层复杂性,您可以使用s 和标记列表 ( s )expl3做任何您想做的事情。它们也更接近用户输入,我只是认为在您熟悉语法之前,从较少类型的东西开始更容易。clisttl

在您的原始代码中,您似乎混淆了clistand seq/or tl。命名约定的一个优点是它使这样做变得更加困难并且更容易发现。

如果你说

\tl_new:N <blah>

你正在制作一个 token 列表,<blah>应该结束_tl。同样

\clist_new:N <blah>_clist

对于其他变量也是如此(即不是命令,而是序列和其余部分)。

变量应始终以\l_\g_和 常量开头\c_。通常,您需要\l_局部变量或\g_全局变量。我通常使用局部变量,除非我需要全局变量。

我们还需要一个模块名称。我使用了wolfrevo。然后,局部变量名称的形式基本上是

\l_wolfrevo_<description>_<type>

要处理嵌入的作者,您需要设置两组密钥。最直接的方法就是authors从章节开始传递内容并设置下一级密钥。

\NewDocumentCommand{\showchapter}{m}
{
  \keys_set:nn { wolfrevo / chapterkeys } { #1 }

我们将 的值放入、authors中,并将标题放入标记列表 ( )、 中。clist\l_wolfrevo_authors_clisttl\g_wolfrevo_title_tl

  \par\textbf{showchapter-title:~}
  \g_wolfrevo_title_tl

我们想要的只是排版标题,所以我们就这么做。

  \par\textbf{showchapter-authors:~}

我们不想直接使用作者。相反,我们希望将 clist 的内容本身视为一组键,这次将它们传递给东西authorkeys进行处理。我们可以将 clist 映射到另一个内部函数来实现此目的。

  \clist_map_inline:Nn \l_wolfrevo_authors_clist
  {
    \wolfrevo_showauthor:n { ##1 }
  }
}

\wolfrevo_showauthor:n然后设置键并排版每个作者的姓名和所属机构。

我没有尝试对输入进行合理性检查,因此如果您向命令传递任何意外内容,您将收到奇怪的错误。如果您与其他人(包括后来的您)共享代码,您可能希望在其中建立一些有意义的反馈。

\documentclass{book}

\ExplSyntaxOn

\keys_define:nn { wolfrevo / authorkeys }
{
  name .tl_set:N = \l_wolfrevo_name_tl,
  name .initial:n = {Bilbo ~ Baggins},
  affiliation .tl_set:N = \l_wolfrevo_affiliation_tl,
  affiliation .initial:n = {Hobbinton ~ College ~ of ~ Further ~ Education, ~ The ~ Shire},
}
\keys_define:nn { wolfrevo / chapterkeys }
{
  title .tl_gset:N = \g_wolfrevo_title_tl,
  title .initial:V = \c_empty_tl,
  authors .clist_set:N = \l_wolfrevo_authors_clist,
  authors .initial:n = {},
}
\clist_new:N \l_wolfrevo_tmpa_clist

\cs_new_protected:Nn \wolfrevo_showauthor:nn
{
  \textbf{showauthor:~} (#1 , ~ #2)
}
\cs_generate_variant:Nn \wolfrevo_showauthor:nn { VV } 
\cs_new_protected:Nn \wolfrevo_showauthor:n
{
  \keys_set:nn { wolfrevo / authorkeys } { #1 }
  \wolfrevo_showauthor:VV \l_wolfrevo_name_tl \l_wolfrevo_affiliation_tl
  \par  
}
\NewDocumentCommand{\showchapter}{m}
{
  \group_begin:
    \keys_set:nn { wolfrevo / chapterkeys } { #1 }
    \par
    \textbf{showchapter-title:~} \g_wolfrevo_title_tl
    \par
    \textbf{showchapter-authors:~}
    \par
    \clist_map_inline:Nn \l_wolfrevo_authors_clist
    {
      \wolfrevo_showauthor:n { ##1 }
    }
  \group_end:
}

\ExplSyntaxOff
\begin{document}
  
\showchapter{%
  title=Prequel,
}

\showchapter{
  title=My chapter,
  authors={
    {name=Peter,affiliation=MIT},
    {name=Mary,affiliation=UCLA},
  },
}

\showchapter{%
  title=Sequel,
}

\end{document}

希望以下内容与您的目标类似。

两键排版

编辑

我通常会使用组来保持本地更改。这样,如果未指定任何内容,您始终会获得键的初始值。这不是您在每种情况下都想要的,但这是一种相当常见的设置。

\NewDocumentCommand{\showchapter}{m}
{
  \group_begin:
  \keys_set:nn { wolfrevo / chapterkeys } { #1 }
  \par\textbf{showchapter-title:~}
  \l_wolfrevo_title_tl
  \par\textbf{showchapter-authors:~}
  % next line seems not to work as expected
  \clist_map_inline:Nn \l_wolfrevo_authors_clist
  {
    \wolfrevo_showauthor:n { ##1 }
  }
  \group_end:
}

但请注意,这也会将标题变为本地标题。您可以使用以下方法防止这种情况发生

  title .tl_gset:N = \g_wolfrevo_title_tl,

并替换\g_wolfrevo_title_tl\l_wolfrevo_title_tl这样,标题将保留在组中(例如,用于标题),但作者列表将不会保留。

这些变化现在已经在上面的代码中实现。

相关内容