当我尝试定义包含另一个先前定义的命令的命令时,我总是收到非法参数错误。我知道您必须小心处理嵌套定义,但我没想到我会这样做。以下是 MWE:
\documentclass{memoir}
\usepackage{xstring,xparse,xspace}
\NewDocumentCommand{}{\pfc}{Preface~\StrGobbleLeft{#1}{1}\xspace}
\NewDocumentCommand{\D}{ o }{%
\IfNoValueTF{#1} {%
\emph{D}\xspace}{%
\IfBeginWith{#1}%
{p}{\emph{D} \pfc}{%
\IfStrEqCase{#1}{%
{f}{\emph{Daybreak}\xspace}%
{g}{\emph{Morgenröte}\xspace}%
}%
[\emph{D}~#1\xspace]%
}%
}%
}
\begin{document}
\D[p1]
我期望的是以下情况:
德前言 1
但我只是得到了非法参数错误。大概是因为我不想使用 ##1,因为我没有在宏中更新命令。如果我只是将 \pfc 的内容而不是命令放入 \D 命令中,那么它就可以工作,但我不想这样做。
有任何想法吗?
答案1
您将其定义为不带参数但在定义中使用过的命令,#1
因此会出现错误,就像使用\newcommand
或 一样\def
。
要将外部命令的参数传递给您,\pfc
您需要将其定义\pfc
为一个带有一个参数的宏,然后\pfc{#1}
在第二个定义中使用它来传递该参数。
所以
\NewDocumentCommand{\pfc}{m}{... #1 ...}
....
....\pfc{#1}
基本上,当 TeX 看到一个宏带有一个参数时,它会从输入流中删除它\foo{aaa}
,并将其替换为替换为的替换文本。这是这样做的\foo
\foo{aaa}
\foo
#1
aaa
第一的,那么 TeX 开始处理替换文本时会忘记所有关于 的内容\foo
。因此,当它看到\pfc
你的定义并展开它时,#1
与顶级命令的参数的所有关联都会被忘记。
答案2
的定义中有一个明显的错误\pfc
,但它本身似乎并不是一个真正有用的命令。
通过充分使用,您可以获得更简单的实现expl3
:
\documentclass{memoir}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xparse,xspace}
\ExplSyntaxOn
\NewDocumentCommand{\D}{ o }
{
\IfNoValueTF{#1}
{% No optional argument: just print D
\emph{D}\xspace
}
{% Optional argument: pass control to an inner function
\rowthorn_D:n { #1 }
}
}
\cs_new:Npn \rowthorn_D:n #1
{% Check what's the first token in the optional argument
\str_case_x:nnF { \tl_head:n { #1 } }
{% if it's `p', remove it and print the rest
{p}{\emph{D}\nobreakspace Preface\nobreakspace\tl_tail:n { #1 }}
}
{% otherwise, if it's f or g ...
\str_case:nnF { #1 }
{
{f}{\emph{Daybreak}}% it's `f': print Daybreak
{g}{\emph{Morgenr\"ote}}% it's `g': print Morgenröte
}
{\emph{D}\nobreakspace#1}% otherwise print the whole argument
}
}
\ExplSyntaxOff
\begin{document}
\D[p1] xyz
\D[f] xyz
\D xyz
\D[g] xyz
\D[ff] xyz
\end{document}
请注意,\xspace
仅在“没有可选参数”的情况下才需要(如果有的话)。