触发 para/begin hook 中的代码,用于精确的段落

触发 para/begin hook 中的代码,用于精确的段落

我使用钩子制作了一个简单的多级段落计数器系统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}

在此处输入图片描述

相关内容