Globalne deklarowanie sumy
Rozważmy następujący MWE:
\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}
W powyższym przykładzie suma punktów jest obliczana poprawnie na końcu, ale jeśli spróbuję wywołać polecenie przed deklaracją punktów, wypisuje zero.
Jaki jest najlepszy sposób na przedefiniowanie tego, aby suma była dostępna w dowolnym miejscu dokumentu?
Zauważ, że rozwiązanie zostało dostarczone przez @egreg w https://tex.stackexchange.com/a/160089/10898
Odpowiedzi
Musisz zapisać sumę do .auxpliku (więc naturalnie musisz uruchomić dokument co najmniej dwa razy, aby uzyskać właściwą sumę). Dodałem nowy licznik, więc masz jeden do wydrukowania sumy, który będzie nieprawidłowy, gdy dodasz / usuniesz punkty do czasu ponownego uruchomienia dokumentu, i inny, który będzie śledzić punkty podczas pracy dokumentu. Pod koniec cyklu są one porównywane i pojawia się ostrzeżenie, więc wiesz, że musisz ponownie uruchomić 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}
Po pierwszym biegu masz
oraz ostrzeżenie w .log:
Package azetina Warning: Point count differs. Rerun LaTeX to get it right.
a po drugim biegu bez ostrzeżenia i