我使用钩子制作了一个简单的多级段落计数器系统para/begin
:
\documentclass{article}
\usepackage{lipsum}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{fancyhdr}
\makeatletter
\ExplSyntaxOn
\int_gzero_new:N \g__mypkg_max_depth_int
%\int_gzero_new:N \g__mypkg_debug_count_int
\AddToHook { para/begin }
{
\int_gincr:N \g__mypkg_debug_count_int
\int_compare:nNnTF { \g__mypkg_max_depth_int } > { 0 }
{
%\textsuperscript { [ \int_to_arabic:n { \g__mypkg_debug_count_int } ] }
\textbf
{
\int_step_inline:nnn { 1 } { \g__mypkg_max_depth_int }
{ \arabic { mypkg@ \int_to_roman:n {#1} } . }
}
\int_gzero:N \g__mypkg_max_depth_int
}
{
%\textsuperscript { \int_to_arabic:n { \g__mypkg_debug_count_int } }
}
}
\int_step_inline:nnn { 1 } { 3 }
{
\int_compare:nNnTF {#1} > {1}
{
\newcounter { mypkg@ \int_to_roman:n {#1} }
[ mypkg@ \int_to_roman:n { \int_eval:n { #1 - 1 } } ]
}
{ \newcounter { mypkg@ \int_to_roman:n {#1} } }
\exp_args:Nc \NewDocumentCommand { mycmd \int_to_roman:n {#1} } {}
{
\stepcounter { mypkg@ \int_to_roman:n {#1} }
\int_gset:Nn \g__mypkg_max_depth_int
{ \int_max:nn {#1} { \g__mypkg_max_depth_int } }
\tex_ignorespaces:D
}
}
\ExplSyntaxOff
\makeatother
\pagestyle{fancy}
\begin{document}
\mycmdi \lipsum[2]
\mycmdi \mycmdii \lipsum[2]
\mycmdii \lipsum[2]
\mycmdi \lipsum[2]
\mycmdii \lipsum[2]
\mycmdii \lipsum[2]
This is a test
\mycmdi \mycmdii \mycmdiii \lipsum[1]
\end{document}
它运作良好:
但是,当页面的第二段包含计数器命令时,计数器将由para/begin
上一页页眉中的钩子打印:
通过注释掉 MWE 中的调试命令,我们可以看到,原本para/begin
应该在页面第二段执行的钩子代码却在页眉上运行,而\g__mypkg_max_depth_int
已经设置为1
。
有没有办法确保钩子只在“好”段落上运行?
答案1
只需添加一个布尔值来指示您是否在文本中,然后在fancyhdr
页眉和页脚中将其设置为 false。fancyhdr
有一个命令fancyhfinit
,您可以在其中放置这样的代码。如果您在本地设置布尔值,fancyhdr
当您离开页眉/页脚时,它将自动重置为 true。
\bool_new:N \g__mypkg_in_text
\bool_set_true:N \g__mypkg_in_text
...
\ExplSyntaxOn
\fancyhfinit{\bool_set_false:N \g__mypkg_in_text}
\ExplSyntaxOff
然后在钩子中仅当设置了布尔值时才执行计数操作。
\bool_if:NTF \g__mypkg_in_text
{
... your original code
}
{}
整个代码:
\documentclass{article}
\usepackage{lipsum}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{fancyhdr}
\makeatletter
\ExplSyntaxOn
\int_gzero_new:N \g__mypkg_max_depth_int
\int_gzero_new:N \g__mypkg_debug_count_int
\bool_new:N \g__mypkg_in_text
\bool_set_true:N \g__mypkg_in_text
\AddToHook { para/begin }
{
\int_gincr:N \g__mypkg_debug_count_int
\bool_if:NTF \g__mypkg_in_text
{
\int_compare:nNnTF { \g__mypkg_max_depth_int } > { 0 }
{
\textsuperscript { [ \int_to_arabic:n { \g__mypkg_debug_count_int } ] }
\textbf
{
\int_step_inline:nnn { 1 } { \g__mypkg_max_depth_int }
{ \arabic { mypkg@ \int_to_roman:n {#1} } . }
}
\int_gzero:N \g__mypkg_max_depth_int
}
{
\textsuperscript { \int_to_arabic:n { \g__mypkg_debug_count_int } }
}
}
{}
}
\int_step_inline:nnn { 1 } { 3 }
{
\int_compare:nNnTF {#1} > {1}
{
\newcounter { mypkg@ \int_to_roman:n {#1} }
[ mypkg@ \int_to_roman:n { \int_eval:n { #1 - 1 } } ]
}
{ \newcounter { mypkg@ \int_to_roman:n {#1} } }
\exp_args:Nc \NewDocumentCommand { mycmd \int_to_roman:n {#1} } {}
{
\stepcounter { mypkg@ \int_to_roman:n {#1} }
\int_gset:Nn \g__mypkg_max_depth_int
{ \int_max:nn {#1} { \g__mypkg_max_depth_int } }
\tex_ignorespaces:D
}
}
\ExplSyntaxOff
\makeatother
\pagestyle{fancy}
\ExplSyntaxOn
\fancyhfinit{\bool_set_false:N \g__mypkg_in_text}
\ExplSyntaxOff
\fancyhead[L]{Test Header}
\begin{document}
\mycmdi \lipsum[2]
\mycmdi \mycmdii \lipsum[2]
\mycmdii \lipsum[2]
\mycmdi \lipsum[2]
\mycmdii \lipsum[2]
\mycmdii \lipsum[2]
This is a test
\mycmdi \mycmdii \mycmdiii \lipsum[1]
\end{document}