在环境中使用该firstnumber=...
选项时,我发现与宏有关的奇怪行为差异。以下内容没有问题:Verbatim
fancyvrb
\def\foo{2}
\begin{Verbatim}[firstnumber=\foo]
line 2
\end{Verbatim}
但以下给出! Missing number, treated as zero
错误
\def\foo{last}
\begin{Verbatim}[commandchars=\\\{\},firstnumber=\foo]
line 2
\end{Verbatim}
(commandchars=\\\{\}
选项没有区别。)原因是什么?我找到了一种解决方法,\fvset{firstnumber=last}
如果我想的话可以使用(或明确替换\foo
)last
,但我想学习。
这是一个最小的工作示例:
\documentclass{article}
\usepackage{fancyvrb}
\begin{document}
\fvset{numbers=left}
\begin{Verbatim}
line 1
\end{Verbatim}
\def\foo{2}
\begin{Verbatim}[firstnumber=\foo]
line 2
\end{Verbatim}
%% problem HERE
\def\foo{last}
\begin{Verbatim}[firstnumber=\foo]
line 3
\end{Verbatim}
\end{document}
(我没有写,commandchars=\\\{\}
因为没什么区别。)错误信息是:
! Missing number, treated as zero.
<to be read again>
l
l.18 line 3
答案1
相关代码定义在,fancyvrb.sty
其中firstnumber
key定义如下:
\define@key{FV}{firstnumber}[auto]{%
\def\@tempa{#1}\def\@tempb{auto}%
\ifx\@tempa\@tempb
\def\FV@SetLineNo{%
\c@FancyVerbLine\FV@CodeLineNo
\advance\c@FancyVerbLine\m@ne}%
\else
\def\@tempb{last}%
\ifx\@tempa\@tempb
\let\FV@SetLineNo\relax
\else
\def\FV@SetLineNo{\c@FancyVerbLine#1}%
\fi
\fi}
以下是仅包含必要部分的精简版本:
\define@key{FV}{firstnumber}[auto]{%
\def\@tempa{#1}%
\def\@tempb{last}%
\ifx\@tempa\@tempb
\let\FV@SetLineNo\relax
\else
\def\FV@SetLineNo{\c@FancyVerbLine#1}%
\fi}
\@tempa
定义为参数 to 的值firstnumber
( #1
),\@tempb
定义为last
。现在让我们考虑这两种情况:
firstnumber=last
:在这种情况下,我们有\def\@tempa{last}
与 基本相同的\def\@tempb{last}
。当\ifx\@tempa\@tempb
展开时,\ifx
将比较后面的两个标记。如果它们是控制序列,则如果它们是相同的原始命令,或者具有相同的参数文本、相同的替换文本以及相同的修饰符(如 ),则两者都被视为相等。\long
这里的参数对于\@tempa
和是相同的\@tempb
(它们没有任何参数),它们的替换文本也是相同的(last
),并且两者都缺少任何修饰符。在这种情况下, 的测试\ifx
被认为是肯定的,并且以下赋值\let\FV@SetLineNo\relax
是最终扩展。(在某个时候\FV@SetLineNo
调用 来设置新块的行号。然后定义\relax
不会做任何更改。)firstnumber=\foo
:现在第一个参数是\foo
,而 的定义\@tempa
变为\def\@tempa{\foo}
,而\@tempb
仍然是last
。由于\ifx
在比较两个宏时不进行完全展开,因此要比较的替换文本现在是 和\foo
,last
它们是不是与之前相同。因此,结果为负数,\else
部分成为最终扩展。再次\FV@SetLineNo
定义,但现在我们\c@FancyVerbLine#1
在其中找到赋值,它将(整数)计数器设置\c@FancyVerbLine
为第一个参数的值\foo
。在某个时候,这个宏被展开,导致赋值不是以数字开头,而是以 from 开头l
。last
这正是您在错误消息中看到的错误。
这也解释了为什么不同的值commandchars
在这里没有任何影响,而\def\foo{2}
另一方面却可以正常工作。