修补 \setcounter 和 \addotocounter 无法与 calc 配合使用

修补 \setcounter 和 \addotocounter 无法与 calc 配合使用

对于 reledac 的一些非常特殊的需求,我需要在每次更改页面计数器的值时获取它,可以通过settocounter,也可以使用addotcounter

所以我做了类似的事情(这是一个非常简化的例子,实际上,我不会直接排版计数器)。

\documentclass{article}
\usepackage{etoolbox}
\usepackage{xstring}
%\usepackage{calc}
\makeatletter
\newcount\this@c@page
\newcommand{\set@this@c@page}{\global\this@c@page=\value{page}}
\apptocmd{\setcounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%
\apptocmd{\addtocounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%
\begin{document}
s
\newpage
\the\this@c@page
\end{document}

一切都运行良好,除非我使用calc包。在这种情况下,this@c@page仍然等于 0。似乎使用此包重新定义宏会改变我们可以获取计数器值的时间,但我不明白为什么。

有什么窍门吗?

答案1

页面计数器使用以下方式递增,\stepcounter并由以下方式更新:calc\stepcounter。这是加载前的定义calc(包含在内核中latex.ltx):

\def\stepcounter#1{%
  \addtocounter{#1}\@ne
  \begingroup
    \let\@elt\@stpelt
    \csname cl@#1\endcsname
  \endgroup}

请注意 的\stepcounter使用方式\addtocounter,您已对其进行了更新,因此可以按预期工作。以下是 的新定义\stepcounter(由 重新定义calc):

\def\stepcounter#1{\@ifundefined {c@#1}%
  {\@nocounterr {#1}}%
  {\global\advance\csname c@#1\endcsname \@ne
  \begingroup
    \let\@elt\@stpelt \csname cl@#1\endcsname
  \endgroup}}%

使用calc\stepcounter不使用\addtocounter,因此不会更新计数器page或捕获它的方式。

要解决此问题,您必须按照与和\stepcounter相同的方式进行更新:\setcounter\addtocounter

\apptocmd{\stepcounter}{%
  \relax\IfStrEq{#1}{page}{\set@this@c@page}{}%
  }%
  {\PackageWarning{mypackage}{success}}%
  {\PackageWarning{mypackage}{fail}}%

calc提到更新是\setcounter为了避免经历“整个calc过程”(通过\addtocounter)。

相关内容