Declarando soma globalmente
Considere o seguinte 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}
No exemplo acima, os pontos totais são calculados corretamente no final, mas se eu tentar chamar o comando antes da declaração dos pontos, ele imprime zero.
Qual é a melhor maneira de redefinir isso para que a soma possa ser acessada em qualquer lugar do documento?
Observe que a solução foi fornecida por @egreg em https://tex.stackexchange.com/a/160089/10898
Respostas
Você precisa salvar o total no .auxarquivo (então, naturalmente, você precisa executar o documento pelo menos duas vezes para obter a soma correta). Eu adicionei um novo contador, então você tem um para imprimir a soma, que estará errado quando você adicionar / remover pontos até que você execute novamente o documento, e outro que manterá o controle dos pontos durante a execução do documento. No final da execução, eles são comparados e um aviso é emitido para que você saiba que precisa executar o LaTeX novamente.
\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}
Após a primeira corrida você tem
e um aviso no .log:
Package azetina Warning: Point count differs. Rerun LaTeX to get it right.
e após a segunda execução, nenhum aviso e