在我正在写的一本书中,我使用命令中的包中\IfStrEqCase
的xstring
命令来组织对整个文档中我需要的几条信息的访问,而不必为每条信息定义单独的命令。其中一个关键是这本书的版本。显然,由于这很容易发生变化,因此将这些数据本地化到一个地方会很方便。
在这本书的版权页中,我有一个版权声明,其中包括这本书的名称和上述版本号。我非常喜欢这个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}