patching \ setcounter e \ addotocounter non funzionano bene con calc

Oct 10 2020

per alcune esigenze molto specifiche di reledac, ho bisogno di ottenere il valore del contatore di pagine ogni volta che viene modificato, tramite settocountero con addotcounter.

Quindi ho fatto qualcosa di simile (è un esempio molto semplificato e in realtà non compongo direttamente il contatore).

\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}

Tutto funziona bene, tranne se uso il calcpacchetto. In questo caso, this@c@pageè ancora uguale a 0. Sembra che la ridefinizione della macro con questo pacchetto cambi qualcosa per il tempo in cui possiamo ottenere il valore del contatore, ma non capisco perché.

Qualche trucco?

Risposte

2 Werner Oct 10 2020 at 02:31

Il contatore delle pagine viene incrementato utilizzando \stepcounterche viene aggiornato anche da calc. Ecco la definizione di \stepcounterprima del caricamento calc(contenuta nel kernel latex.ltx):

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

Nota come \stepcounterutilizza \addtocounter, che hai aggiornato e quindi funziona come previsto. Ecco la nuova definizione di \stepcounter(ridefinita da 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}}%

Con calc, \stepcounternon usa \addtocounter, quindi nessun aggiornamento al pagecontatore o al modo in cui lo stai catturando.

Per risolvere questo problema, dovrai aggiornare \stepcounternello stesso modo in cui hai fatto \setcountere \addtocounter:

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

calcafferma che l'aggiornamento \setcounterè per evitare di dover passare attraverso "l'intero calcprocesso" (via \addtocounter).