mwe.zipels-cas-templates
模板定义了lastpage
用以显示总页数:
\def\lastpage{100}
\AtEndDocument{%
% \clearpage
\immediate\write\@auxout{\string\csxdef{lastpage}{\thepage}}
}
但是如果文档最后放置浮动体,则总页数只是有文字的最后一页,是什么原因呢?如何解决
下面是自己实现的一个示例代码,也会出现同样的问题:
\documentclass{article}
\usepackage{graphicx}
\usepackage{lipsum}
\makeatletter
\ExplSyntaxOn
\iow_new:N \l_lastpage_file
\file_if_exist:nTF{\c_sys_jobname_str.page}
{
\file_input:n{\c_sys_jobname_str.page}
}
{
\cs_set_eq:NN \lastpage \relax
}
\AtEndDocument{
\iow_open:Nn \l_lastpage_file{\c_sys_jobname_str.page}
\iow_now:Nx \l_lastpage_file
{
\cs_set:Npn \exp_not:N \lastpage
{
\thepage
}
}
\iow_close:N \l_lastpage_file
}
\cs_new:Npn \__first_foot:
{
\parbox[t]{\textwidth}
{
~ \hfill Page~ \thepage {} ~of~ \lastpage }
}
\cs_set_eq:NN \@evenfoot \__first_foot:
\cs_set_eq:NN \@oddfoot \__first_foot:
\ExplSyntaxOff
\makeatother
\begin{document}
\lipsum[1-50]
\begin{figure}
\centering
\includegraphics[width=\textwidth]{1}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{1}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{1}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{1}
\caption{Example image}
\end{figure}
\end{document}
l3
语法看不懂。下面是在标准文档类中的简短的例子,以供参考。
\documentclass[UTF8]{ctexart}
\usepackage{graphicx,lipsum,zhlipsum,lastpage,mwe,geometry,fancyhdr,pgffor}
\geometry{margin=2in,showframe,a4paper}
\pagestyle{fancy}
\fancyhf{}
\setlength{\headheight}{12pt}
\renewcommand{\headrulewidth}{0pt}
\begin{document}
\cfoot{Page~\thepage~of~\pageref{LastPage}}
\lipsum[1-8]
\pagenumbering{arabic}
\zhlipsum[1-4]
\foreach \x in {1,2,3} {
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example Image \x}
\end{figure}
}
\end{document}
我还没看你expl3的实现,但是当我们发现在某个模板中lastpage
表现异常的时候,我们应该首先在标准文档类中尝试一下lastpage
的功能,这样可以确定是文档类设置的冲突问题还是lastpage
的问题,@u101077 老师给出的示例已经可以说明,这个问题来源于els-cas-templates
模板造成的可能冲突。
同时我们发现els-cas-templates
模板已经在TL中包含,因此我们可以做如下的最简测试:
\documentclass{cas-sc}%由于OP的MWE中例子为单列,因此采用`cas-sc`
\usepackage{graphicx}
\usepackage{lipsum}
\usepackage{lastpage}
\usepackage{fancyhdr}
\pagestyle{fancy}
\renewcommand{\headrulewidth}{0pt}
\cfoot{Page~\thepage~of~\pageref{LastPage}}
\begin{document}
\lipsum[1-20]
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\end{document}
els-cas-templates模板定义了lastpage用以显示总页数,但是如果文档最后放置浮动体,则总页数只是有文字的最后一页
一方面....上面的直接调用cas-sc
的MWE并无法体现你的问题,所以首先你应该补充基于els-cas-templates
的MWE,以体现这一点。
另一方面关于你写的自我l3实现,很精彩。这里唯一的小瑕疵是patch
的时间不对。我想从结果你也能猜出,\lastpage
展开为\thepage
的时间仅仅是在排版完所有文本(不包括浮动体)所致,在lthooks-doc.pdf
和ltshipout-doc.pdf
中我们可以找到应该在浮动体排版结束之后再加入这个patch
:
因此我探索出的一个方法是用\AddToHook{shipout/lastpage}
,这样可以保证在浮动体被浮动算法排版之后再展开\lastpage
为\thepage
:
(我也不是很懂输出例程(output rountine),无法给出更详细的解释...)
但总而言之,修改后的mwe如下:
\documentclass{article}
\usepackage{graphicx}
\usepackage{lipsum}
\makeatletter
\ExplSyntaxOn
\iow_new:N \l_lastpage_file
\file_if_exist:nTF{\c_sys_jobname_str.page}
{
\file_input:n{\c_sys_jobname_str.page}
}
{
\cs_set_eq:NN \lastpage \relax
}
% \AtEndDocument{%
\AddToHook{shipout/lastpage}{%
\iow_open:Nn \l_lastpage_file{\c_sys_jobname_str.page}
\iow_now:Nx \l_lastpage_file
{
\cs_set:Npn \exp_not:N \lastpage
{
\thepage
}
}
\iow_close:N \l_lastpage_file
}
\cs_new:Npn \__first_foot:
{
\parbox[t]{\textwidth}
{~\hfill Page~\thepage{}~of~ \lastpage}
}
\cs_set_eq:NN \@evenfoot \__first_foot:
\cs_set_eq:NN \@oddfoot \__first_foot:
\ExplSyntaxOff
\makeatother
\begin{document}
\lipsum[1-50]
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\begin{figure}
\centering
\includegraphics[width=\textwidth]{example-image}
\caption{Example image}
\end{figure}
\end{document}
若如此做可以得到:
此外我的l3编程经验并不多,而且对于l3file
模块也不够了解,但我仍感觉你的这一段实现似乎有点不太符合逻辑:
\file_if_exist:nTF{\c_sys_jobname_str.page}
{%
\file_input:n{\c_sys_jobname_str.page}
}
{%
\cs_set_eq:NN \lastpage \relax
}
设想如果一个10页的文档首先被编译,那么.page
文档首先展开得到\lastpage=10
,如果之后添加了部分内容,这个文档变为15页,但是上面的逻辑仍然会得到\lastpage=10
,这反复读取.page
似乎不利于多次编译,或者需要用户在第一次编译之后使用latexmk -c
删除,我不太明白这一设计的目的是什么,如果已有.page
就直接使用(为了节省编译时间咩?)如果我来写的话,我反而会担心这一辅助文件记录了上一次编译的信息,所以应该会是类似这样的删除.page
的伪代码思路:
\file_if_exist:nT{\c_sys_jobname_str.page}
{%
%\file_input:n{\c_sys_jobname_str.page}
<DELETE FILE> \c_sys_jobname_str.page
}
\cs_set_eq:NN \lastpage \relax
因为我不会改,也与本问题无关,因此我没改动。也希望原题主能解释下这里如此设计的思路,以上...
一个彩蛋...似乎旧版本的lastpage
使用的也是\AtEndDocument
...我有点感到迷惑,是不是旧版的lastpage.sty
就会导致这一问题呢...(所以是我不能复现的原因(?),我的版本是2024-07-07 v2.1c
):