使用带有 xstring 的 nth 包

使用带有 xstring 的 nth 包

在我正在写的一本书中,我使用命令中的包中\IfStrEqCasexstring命令来组织对整个文档中我需要的几条信息的访问,而不必为每条信息定义单独的命令。其中一个关键是这本书的版本。显然,由于这很容易发生变化,因此将这些数据本地化到一个地方会很方便。

在这本书的版权页中,我有一个版权声明,其中包括这本书的名称和上述版本号。我非常喜欢这个nth包,并在我的文档的其他地方使用它。然而,当我尝试将它与我的命令结合起来时,我得到了编译错误。这是一个演示错误的 MWE:

\documentclass{article}

\usepackage{xstring}
\usepackage{nth}

\DeclareRobustCommand{\Gkeys}[1]{%
    \IfStrEqCase{#1} {%
        {edition}{10}%
        {author}{John Doe}%
        {title}{Title of My Book}%
    }[\textbf{??key not found??}]%
}

\begin{document}

\textbf{\Gkeys{title}}, \textsc{\nth{\Gkeys{edition}} Edition}\\
\Gkeys{author} 2017

\end{document}

当我尝试编译该文档时pdflatex出现以下错误:

! Missing number, treated as zero.
<to be read again> 
                   \protect 
l.16 ...}}, \textsc{\nth{\Gkeys{edition}} Edition}
                                                  \\
?

我不确定这里发生了什么,导致它不起作用。如果我定义一个简单的命令,比如说,这可以正常工作,但显然这会失去我声明的命令\def\BookEditionNumber{10}的便利性。\Gkeys

编辑:

一条评论指出,由于我\GKeys用声明\DeclareRobusCommand,因此我使其无法扩展,因此\nth无法用它做任何事情。我这样做的动机是允许它与 之类的命令一起工作\section。然而,出于好奇,我把命令改成了用 声明\newcommand。有趣的是,这也不起作用。当我尝试编译文档,我收到以下错误:

! Missing number, treated as zero.
<to be read again> 
                   \let 
l.16 ...}}, \textsc{\nth{\Gkeys{edition}} Edition}
                                                  \\
? 

答案1

\IfStrEqCase不可扩展,因此即使\Gkeys其本身可扩展,内部命令也不可扩展。

我建议使用\str_case:nnF包中的可扩展命令expl3进行检查,其语法与几乎相同\IfStrEqCase

唯一需要考虑的是,空格会被域吞噬\ExplSyntaxOn...\ExplSyntaxOff。可以~在这里使用它作为普通空格标记(而不是不可破坏的空格)

\documentclass{article}

\usepackage{xstring}
\usepackage{nth}

\usepackage{expl3}

\ExplSyntaxOn
\newcommand{\Gkeys}[1]{%
  \str_case:nnF {#1} {
    {edition}{10}%
    {author}{John~Doe}%
    {title}{Title~of~My~Book}%
  }{\textbf{??key~not~found??}}%
}
\ExplSyntaxOff

\begin{document}
\textbf{\Gkeys{title}}

\nth{\Gkeys{edition}}

\textsc{\nth{\Gkeys{edition}} Edition}

\Gkeys{author} 2017

\section{\Gkeys{author} 2017}

\end{document}

在此处输入图片描述

答案2

您可以使用更方便的界面,例如

\defineset{my}{
  author=John Doe,
  title=Title of my book,
  edition=10,
}

在下面的宏中,您可以根据需要定义任意数量的集合;我还展示了如何定义缩写形式,如\Gkeys作为的别名\getkey{my}

\documentclass{article}
\usepackage{xparse}
\usepackage{nth}

\ExplSyntaxOn
\NewDocumentCommand{\defineset}{mm}
 {
  \prop_set_eq:NN \l__keith_set_temp_prop \g_keith_set_initial_prop
  \keys_set:nn { keith/set } { #2 }
  \prop_new:c {g_keith_set_#1_prop}
  \prop_gset_eq:cN {g_keith_set_#1_prop} \l__keith_set_temp_prop
 }
\NewExpandableDocumentCommand{\getkey}{mm}
 {
  \prop_item:cn {g_keith_set_#1_prop} { #2 }
 }
\keys_define:nn { keith/set }
 {
  author  .code:n = \prop_put:Nnn \l__keith_set_temp_prop { author } { #1 },
  title   .code:n = \prop_put:Nnn \l__keith_set_temp_prop { title } { #1 },
  edition .code:n = \prop_put:Nnn \l__keith_set_temp_prop { edition } { #1 },
 }
\prop_new:N \l__keith_set_temp_prop
\prop_new:N \g_keith_set_initial_prop
\prop_gput:Nnn \g_keith_set_initial_prop { author } { ??MISSING?? }
\prop_gput:Nnn \g_keith_set_initial_prop { title } { ??MISSING?? }
\prop_gput:Nnn \g_keith_set_initial_prop { edition } { ??MISSING?? }
\ExplSyntaxOff

\defineset{my}{
  author=John Doe,
  title=Title of my book,
  edition=10,
}
\defineset{another}{
  author=Jane Doe,
  title=Title of her book,
  edition=2,
}


\newcommand{\Gkeys}[1]{\getkey{my}{#1}}

\begin{document}

\textbf{\Gkeys{title}}

\nth{\Gkeys{edition}}

\textsc{\nth{\Gkeys{edition}} Edition}

\Gkeys{author} 2017

\section{\Gkeys{author} 2017}

\nth{\getkey{another}{edition}}

\end{document}

在此处输入图片描述

相关内容