Déclarer la somme globalement

Nov 03 2020

Considérez le MWE suivant:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\shcpoint}{ m }
 {
  \azetina_shcpoint:n { #1 }
 }

\NewDocumentCommand{\printtotal}{ }
 {
  \int_to_arabic:n { \g_azetina_totalpoints_int }
 }

\int_new:N \g_azetina_totalpoints_int
\box_new:N \l_azetina_points_box
\cs_new_protected:Npn \azetina_shcpoint:n #1
 {
  \int_gadd:Nn \g_azetina_totalpoints_int { #1 }
  \hbox_set:Nn \l_azetina_points_box { (0 ~ \textit{points}) }
  \makebox[\box_wd:N \l_azetina_points_box][l]
   {
    (\textit{#1 ~ point\int_compare:nT { #1 > 1 } { s }})
   }
  \quad
}
\ExplSyntaxOff

\begin{document}
Total points: \printtotal

\shcpoint{1} X

\shcpoint{3} X

\shcpoint{1} X

Total points: \printtotal

\end{document}

Dans l'exemple ci-dessus, le total des points est calculé correctement à la fin mais si j'essaie d'appeler la commande avant la déclaration des points, elle imprime zéro.

Quelle est la meilleure façon de redéfinir cela afin que la somme soit accessible n'importe où dans le document?

Notez que la solution a été fournie par @egreg dans https://tex.stackexchange.com/a/160089/10898

Réponses

2 LaTeXer Nov 03 2020 at 06:10

Vous devez enregistrer le total dans le .auxfichier (vous devez donc naturellement exécuter le document au moins deux fois pour obtenir la bonne somme). J'ai ajouté un nouveau compteur, vous en avez donc un pour imprimer la somme, ce qui sera faux lorsque vous ajoutez / supprimez des points jusqu'à ce que vous réexécutiez le document, et un autre qui gardera une trace des points pendant l'exécution du document. À la fin de l'analyse, ils sont comparés et un avertissement est émis pour que vous sachiez que vous devez réexécuter LaTeX.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\shcpoint}{ m }
 {
  \azetina_shcpoint:n { #1 }
 }

\NewDocumentCommand{\printtotal}{ }
 {
  \int_to_arabic:n { \g_azetina_totalpoints_int }
 }

\NewDocumentCommand{\shcsettotal}{ m }
 {
  \int_gset:Nn \g_azetina_totalpoints_int {#1}
 }

\int_new:N \g_azetina_totalpoints_int
\int_new:N \g__azetina_counttotal_int
\box_new:N \l_azetina_points_box
\cs_new_protected:Npn \azetina_shcpoint:n #1
 {
  \int_gadd:Nn \g__azetina_counttotal_int { #1 }
  \hbox_set:Nn \l_azetina_points_box { (0 ~ \textit{points}) }
  \makebox[\box_wd:N \l_azetina_points_box][l]
   {
    (\textit{#1 ~ point\int_compare:nT { #1 > 1 } { s }})
   }
  \quad
}

\makeatletter
\AtEndDocument
  {
    \iow_now:Nx \@auxout
      {
        \shcsettotal { \int_use:N \g__azetina_counttotal_int }
      }
    \int_compare:nNnF \g__azetina_counttotal_int = \g_azetina_totalpoints_int
      {
        \msg_warning:nn { azetina } { rerun-points }
      }
  }
\msg_new:nnn { azetina } { rerun-points }
  {
    Point~count~differs.~Rerun~LaTeX~to~get~it~right.
  }
\makeatother
\ExplSyntaxOff

\begin{document}
Total points: \printtotal

\shcpoint{1} X

\shcpoint{3} X

\shcpoint{1} X

Total points: \printtotal

\end{document}

Après la première course, vous avez

et un avertissement dans le .log:

Package azetina Warning: Point count differs. Rerun LaTeX to get it right.

et après le deuxième passage, aucun avertissement et