为何此宏与 Lastpage 不兼容?

为何此宏与 Lastpage 不兼容?

我制作了一个宏\@Romankern,它使罗马数字之间的字距为负数,从而使它们彼此更接近。我给它命名是\@Romankern为了允许它与一起使用\pagenumbering

在我加载包之前,宏运行良好lastpage。加载此包时,宏中断并告诉我:

! Undefined control sequence.
\@Romankern #1->\edef \temp 
                            {\@Roman {#1}}\expandafter \@romkern \temp ...

我试图追踪错误源头,但失败了……很惨。我的宏到底出了什么问题,这么脆弱?

\documentclass{article}

\usepackage{lipsum}
\usepackage{lastpage}

\makeatletter

\def\@Romankern#1{%
  \edef\temp{\@Roman{#1}}%
  \expandafter\@romkern\temp\@empty}
\def\@romkern#1#2{%
  \ifx#2\@empty
    #1%
    \let\next\relax
  \else
    #1\kern-0.07em%
    \let\next\@romkern
  \fi
  \next#2}

\begin{document}

\pagenumbering{Romankern}

\lipsum[1-50]

\end{document}

答案1

的定义\@Romankern不够稳健,因为它包含赋值(\def\temp{...}\let\next\@romkern、...)。如果将标签写入文件.aux,则不会执行赋值,并且\def\temp{...}会变成类似于 的东西\def<the expansion of \temp>{...},这是<the expansion of \temp>扩展 的当前含义的结果\temp。在 的情况下,问题\temp是未定义的,因此会引发错误。

以下示例定义了一个宏\@@Romankern,该宏以纯数字作为参数,并将转到文件.aux。 参数\@Romankern(计数器值)到纯数字的转换以可扩展且因此可靠的方式完成(通过\expandafter和)。 e-TeX 使\number该宏变得可靠,可防止在写入文件时扩展。\@@Romankern\protected\@@Romankern.aux

\documentclass{article}

\usepackage{lipsum}
\usepackage{lastpage}

\makeatletter
\def\@Romankern#1{%
  \expandafter\@@Romankern\expandafter{\number#1}%
}
\protected\def\@@Romankern#1{%
  \edef\temp{\@Roman{#1}}%
  \expandafter\@romkern\temp\@empty\@empty
}
\def\@romkern#1#2{%
  \ifx#2\@empty
    #1%
    \let\next\relax
  \else
    #1\kern-0.07em%
    \let\next\@romkern
  \fi
  \next#2}

\begin{document}

\pagenumbering{Romankern}

Last page: \pageref{LastPage}

\lipsum[1-50]

\end{document}

.aux文件包含:

\relax
\newlabel{LastPage}{{}{\@@Romankern {10}}}
\xdef\lastpage@lastpage{\@@Romankern {10}}
\gdef\lastpage@lastpageHy{}

评论:

  • \@romkern的呼唤

    \def\temp{\@Roman{#1}}%
    \expandafter\@romkern\temp\@empty\@empty
    

    修改为包含停止标记\@empty,因为\@romkern总是期望参数。但\temp对于零或负数则为空。

相关内容