回答我之前的一个问题提供了此代码来引用一系列行,其中行标签放置在行范围的开始和结束处。
\makeatletter
\newcommand{\reflines}[1]{%
\begingroup
\def\temp@a{\getrefnumber{start:#1}}%
\def\temp@b{\getrefnumber{end:#1}}%
\ifnum\temp@a = \temp@b
line \temp@a%
\else
lines \temp@a--\temp@b%
\fi
\endgroup
}
\makeatother
在 MWE 中,如果我们将 的一个实例更改\reflines
为 在 内发生\edef
,则会出现编译错误:
\documentclass{memoir}
\usepackage{refcount}
\usepackage{lineno}
\newcommand{\labellines}[2]{%
\linelabel{start:#1}%
#2%
\linelabel{end:#1}%
}
\makeatletter
\newcommand{\reflines}[1]{%
\begingroup
\edef\temp@a{\getrefnumber{start:#1}}%
\edef\temp@b{\getrefnumber{end:#1}}%
\ifnum\temp@a = \temp@b
line \temp@a%
\else
lines \temp@a\ and \temp@b%
\fi
\endgroup
}
\makeatother
\begin{document}
\runninglinenumbers*
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lacinia posuere
magna ut imperdiet. \labellines{nunc-pellentesque}{Nunc pellentesque} velit quis
leo interdum ullamcorper. Ut fringilla sapien ut sem viverra, et rhoncus enim
lobortis. Morbi diam eros, tristique nec feugiat eu, consequat ac dui. Duis
molestie, sem id efficitur dignissim, velit metus auctor orci, sit amet mattis
metus purus in nibh. Etiam mattis, magna ut imperdiet molestie, ex leo viverra
velit, ac posuere augue est maximus risus. Etiam ac pellentesque nulla. Morbi
quis pharetra purus. Proin porta, turpis et scelerisque hendrerit, elit eros
malesuada mi, a imperdiet massa est id nibh. Class aptent taciti sociosqu ad
litora torquent per conubia nostra, per inceptos himenaeos.
\labellines{nunc-pharetra}{Nunc pharetra vehicula metus, eu tincidunt arcu
aliquet et. Aenean ac odio nunc. Etiam ultricies purus non dolor tincidunt, et
ultricies turpis consequat. Integer vitae ullamcorper eros. Nullam pulvinar
dictum nunc. Morbi ac justo mi.}
% \reflines{nunc-pellentesque} should print "line 2"
``Nunc pellentesque\ldots'' was on \reflines{nunc-pellentesque}.
\edef\nuncref{\reflines{nunc-pharetra}}
% \reflines{nunc-pharetra} should print "lines 10--13"
``Nunc pharetra\ldots'' was on \nuncref.
\end{document}
为什么是这样?
答案1
让我们看看当你有
\makeatletter
\newcommand{\reflines}[1]{%
\begingroup
\edef\temp@a{\getrefnumber{start:#1}}%
\edef\temp@b{\getrefnumber{end:#1}}%
\ifnum\temp@a = \temp@b
line \temp@a%
\else
lines \temp@a\ and \temp@b%
\fi
\endgroup
}
\makeatother
并尝试去做
\edef\nuncref{\reflines{nunc-pharetra}}
首先\reflines
是扩展,也就是找到它的参数,吸收它并用替换文本替换整个内容:
\begingroup
\edef\temp@a{\getrefnumber{start:nunc-pharetra}}%
\edef\temp@b{\getrefnumber{end:nunc-pharetra}}%
\ifnum\temp@a = \temp@b
line \temp@a
\else
lines \temp@a\ and \temp@b
\fi
\endgroup
但是,\edef
它会一直进行扩展,因此它会继续扫描标记列表以查找可扩展的标记;前两个是\begingroup
和\edef
,它们是不可扩展的,因此它们会原封不动地通过。接下来是\temp@a
,它是未定义的;实际上,错误消息是
! Undefined control sequence.
\reflines #1->\begingroup \edef \temp@a
{\getrefnumber {start:#1}}\edef \tem...
l.47 \edef\nuncref{\reflines{nunc-pharetra}
}
这是一个常见的误解,它\edef
也会执行命令,但实际上它不会。如果你尝试
\edef\foo{\edef\foobar{A}}
假设你\def\foobar{B}
在这之前有某个地方,那么替换文本\foo
将是
\edef B{A}
在使用时会引发错误\foo
。它将不是执行时引发错误\edef\foo{...}
。这与此级别的脆弱命令无关。
尝试\protected@edef\nuncref{\protect\reflines{nunc-pharetra}}
是完全没用的,因为替换的文本\nuncref
将是
\protect\reflines{nunc-pharetra}
如下\show\nuncref
所示:
> \nuncref=macro:
->\protect \reflines {nunc-pharetra}.
目前还不清楚你为什么要使用\edef
宏\nuncref
,因为这样做并没有什么好处
\newcommand\nuncref{\reflines{nunc-pharetra}
答案2
您的问题是由于\reflines
存在组和作业(\def
)而无法扩展。这些是不需要的,所以我们可以删除它们
\newcommand{\reflines}[1]{%
\ifnum\getrefnumber{start:#1}=\getrefnumber{end:#1} %
line \getrefnumber{start:#1}%
\else
lines \getrefnumber{start:#1}\ and \getrefnumber{end:#1}%
\fi
}
此时你能 \edef
\reflines
。可以强制对两个查找各进行一次评估,但是这里似乎不需要付出努力。
答案3
它是脆弱命令的老问题。
\documentclass{memoir}
\usepackage{refcount}
\usepackage{lineno}
\newcommand{\labellines}[2]{%
\linelabel{start:#1}%
#2%
\linelabel{end:#1}%
}
\makeatletter
\newcommand{\reflines}[1]{%
\begingroup
\edef\temp@a{\getrefnumber{start:#1}}%
\edef\temp@b{\getrefnumber{end:#1}}%
\ifnum\temp@a = \temp@b
line \temp@a%
\else
lines \temp@a\ and \temp@b%
\fi
\endgroup
}
\makeatother
\begin{document}
\runninglinenumbers*
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam lacinia posuere
magna ut imperdiet. \labellines{nunc-pellentesque}{Nunc pellentesque} velit quis
leo interdum ullamcorper. Ut fringilla sapien ut sem viverra, et rhoncus enim
lobortis. Morbi diam eros, tristique nec feugiat eu, consequat ac dui. Duis
molestie, sem id efficitur dignissim, velit metus auctor orci, sit amet mattis
metus purus in nibh. Etiam mattis, magna ut imperdiet molestie, ex leo viverra
velit, ac posuere augue est maximus risus. Etiam ac pellentesque nulla. Morbi
quis pharetra purus. Proin porta, turpis et scelerisque hendrerit, elit eros
malesuada mi, a imperdiet massa est id nibh. Class aptent taciti sociosqu ad
litora torquent per conubia nostra, per inceptos himenaeos.
\labellines{nunc-pharetra}{Nunc pharetra vehicula metus, eu tincidunt arcu
aliquet et. Aenean ac odio nunc. Etiam ultricies purus non dolor tincidunt, et
ultricies turpis consequat. Integer vitae ullamcorper eros. Nullam pulvinar
dictum nunc. Morbi ac justo mi.}
% \reflines{nunc-pellentesque} should print "line 2"
``Nunc pellentesque\ldots'' was on \reflines{nunc-pellentesque}.
\makeatletter
\protected@edef\nuncref{\protect\reflines{nunc-pharetra}}
\makeatother
% \reflines{nunc-pharetra} should print "lines 10--13"
``Nunc pharetra\ldots'' was on \nuncref.
\end{document}