[latex3-commits] [git/LaTeX3-latex3-latex2e] hotfix/gh441: Move 'top-level' chunks always at the end of the hook (6ae3cee4)

PhelypeOleinik phelype.oleinik at latex-project.org
Thu Dec 10 03:29:58 CET 2020


Repository : https://github.com/latex3/latex2e
On branch  : hotfix/gh441
Link       : https://github.com/latex3/latex2e/commit/6ae3cee46507ed5f54abc8e1d6384d0f162543ee

>---------------------------------------------------------------

commit 6ae3cee46507ed5f54abc8e1d6384d0f162543ee
Author: PhelypeOleinik <phelype.oleinik at latex-project.org>
Date:   Wed Dec 9 23:29:58 2020 -0300

    Move 'top-level' chunks always at the end of the hook
    
    Fixes #441


>---------------------------------------------------------------

6ae3cee46507ed5f54abc8e1d6384d0f162543ee
 base/lthooks.dtx | 106 ++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 78 insertions(+), 28 deletions(-)

diff --git a/base/lthooks.dtx b/base/lthooks.dtx
index 1a344741..3021e107 100644
--- a/base/lthooks.dtx
+++ b/base/lthooks.dtx
@@ -1808,6 +1808,12 @@
 %    $\meta{reversed}1$ is $+1$ for normal hooks and $-1$ for reversed
 %    ones.
 %
+%    \item[\cs{@@_toplevel~\meta{name}}] This token list stores the code
+%    inserted in the hook from the user's document, in the |top-level|
+%    label.  This label is special, and doesn't participate in sorting.
+%    Instead, all code is appended to it and executed after the normal
+%    hook code, but before the |next| code chunk.
+%
 %    \item[\cs{@@_next~\meta{name}}] Finally there is extra code
 %    (normally empty) that is used on the next invocation of the hook
 %    (and then deleted). This can be used to define some special
@@ -1899,6 +1905,7 @@
     \@@_if_exist:nF {#1}
       {
         \prop_new:c { g_@@_#1_code_prop }
+        \tl_new:c { @@_toplevel~#1 }
         \tl_new:c { @@_next~#1 }
       }
   }
@@ -2215,12 +2222,20 @@
 %    If there's code already there, then append \verb=#3= to that,
 %    otherwise just put \verb=#3=.
 %    \begin{macrocode}
-    \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+    \str_if_eq:nnTF {#2} { top-level }
+      {
+        \debug_suspend:
+        \tl_gput_right:cn { @@_toplevel~#1 } {#3}
+        \debug_resume:
+      }
       {
-        \prop_gput:cno { g_@@_#1_code_prop } {#2}
-          { \l_@@_return_tl #3 }
+        \prop_get:cnNTF { g_@@_#1_code_prop } {#2} \l_@@_return_tl
+          {
+            \prop_gput:cno { g_@@_#1_code_prop } {#2}
+              { \l_@@_return_tl #3 }
+          }
+          { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} }
       }
-      { \prop_gput:cnn { g_@@_#1_code_prop } {#2} {#3} }
   }
 %    \end{macrocode}
 % \end{macro}
@@ -2440,8 +2455,13 @@
 %    \verb=\begin{document}=.
 %    \begin{macrocode}
       {
+        \debug_suspend:
         \str_if_eq:nnTF {#2} {*}
-          { \prop_gclear:c { g_@@_#1_code_prop } }
+          {
+            \prop_gclear:c { g_@@_#1_code_prop }
+            \tl_gclear:c { @@_toplevel~#1 }
+            \tl_gclear:c { @@_next~#1 }
+          }
           {
 %    \end{macrocode}
 %    Check if the label being removed exists in the code pool.  If it does,
@@ -2453,6 +2473,7 @@
               { \@@_mark_removal:nn }
                   {#1} {#2}
           }
+        \debug_resume:
 %    \end{macrocode}
 %    Finally update the code, if the hook exists.
 %    \begin{macrocode}
@@ -2472,7 +2493,11 @@
 % \begin{macro}{\@@_gremove_code_do:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_gremove_code_do:nn #1 #2
-  { \prop_gremove:cn { g_@@_#1_code_prop } {#2} }
+  {
+    \str_if_eq:nnTF {#2} { top-level }
+      { \tl_gclear:c { @@_toplevel~#1 } }
+      { \prop_gremove:cn { g_@@_#1_code_prop } {#2} }
+  }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
@@ -2722,7 +2747,7 @@
 %  \end{macro}
 %
 % \begin{macro}[EXP]{\@@_if_label_case:nnnnn}
-%   To avoid doing the string comparison twice in \cs{@@_initialize_single:NNNn}
+%   To avoid doing the string comparison twice in \cs{@@_initialize_single:NNNNn}
 %   (once with \cs{str_if_eq:nn} and again with \cs{@@_label_ordered:nn}),
 %   we use a three-way branching macro that will compare |#1| and |#2|
 %   and expand to \cs{use_i:nnn} if they are equal, \cs{use_ii:nn} if
@@ -2815,17 +2840,22 @@
 %    If there aren't any code
 %    chunks for the current hook, there is no point in even starting
 %    the sorting routine so we make a quick test for that and in that
-%    case just update \cs{@@~\meta{hook}} to hold the next
+%    case just update \cs{@@~\meta{hook}} to hold the |next|
 %    code. If there are code chunks we call
-%    \cs{@@_initialize_single:NNNn} and pass to it ready made csnames
+%    \cs{@@_initialize_single:NNNNn} and pass to it ready made csnames
 %    as they are needed several times inside. This way we save a bit
 %    on processing time if we do that up front.
 %    \begin{macrocode}
     \hook_if_exist:nT {#1}
       {
         \prop_if_empty:cTF {g_@@_#1_code_prop}
-          { \tl_gset:co { @@~#1 }
-                        { \cs:w @@_next~#1 \cs_end: } }
+          {
+            \tl_gset:co { @@~#1 }
+              {
+                \cs:w @@_toplevel~#1 \exp_after:wN \cs_end:
+                \cs:w @@_next~#1 \cs_end:
+              }
+          }
           {
 %    \end{macrocode}
 %    By default the algorithm sorts the code chunks and then saves the
@@ -2848,8 +2878,8 @@
 %    save the old code property list so that it can be restored later.
 %    \begin{macrocode}
             \prop_set_eq:Nc \l_@@_work_prop { g_@@_#1_code_prop }
-            \@@_initialize_single:cccn
-              { @@~#1 } { @@_next~#1 }
+            \@@_initialize_single:ccccn
+              { @@~#1 } { @@_toplevel~#1 } { @@_next~#1 }
               { g_@@_#1_labels_clist } {#1}
 %    \end{macrocode}
 %    For debug display we want to keep track of those hooks that
@@ -2918,12 +2948,13 @@
 %  \end{macro}
 %
 %
-%  \begin{macro}{\@@_initialize_single:NNNn,\@@_initialize_single:cccn}
+%  \begin{macro}{\@@_initialize_single:NNNNn,\@@_initialize_single:ccccn}
 %
-%    \cs{@@_initialize_single:NNNn} implements the sorting of the code
+%    \cs{@@_initialize_single:NNNNn} implements the sorting of the code
 %    chunks for a hook and saves the result in the token list for fast
-%    execution (\verb=#3=). The arguments are \meta{hook-code-plist},
-%    \meta{hook-code-tl}, \meta{hook-next-code-tl},
+%    execution (\verb=#4=). The arguments are \meta{hook-code-plist},
+%    \meta{hook-code-tl}, \meta{hook-top-level-code-tl},
+%    \meta{hook-next-code-tl},
 %    \meta{hook-ordered-labels-clist} and \meta{hook-name} (the latter
 %    is only used for debugging---the \meta{hook-rule-plist} is accessed
 %    using the \meta{hook-name}).
@@ -2935,8 +2966,14 @@
 %    far as possible. The result is a restriction I do not test for at
 %    the moment: a label can't be equal to the number 0!  \fmi{Needs
 %    checking for, just in case}
+%
+%    ^^A #1 <- \@@~#1
+%    ^^A #2 <- \@@_toplevel~#1
+%    ^^A #3 <- \@@_next~#1
+%    ^^A #4 <- \g_@@_#1_labels_clist
+%    ^^A #5 <- #1
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_initialize_single:NNNn #1#2#3#4
+\cs_new_protected:Npn \@@_initialize_single:NNNNn #1#2#3#4#5
   {
 %    \end{macrocode}
 %    Step T1: Initialize the data structure \ldots
@@ -2947,7 +2984,7 @@
 %
 %    Store the name of the hook:
 %    \begin{macrocode}
-    \tl_set:Nn \l_@@_cur_hook_tl {#4}
+    \tl_set:Nn \l_@@_cur_hook_tl {#5}
 %    \end{macrocode}
 %    
 %    We loop over the property list holding the code and record all
@@ -2961,7 +2998,7 @@
        {
          \int_incr:N \l_@@_labels_int
          \seq_put_right:Nn \l_@@_labels_seq {##1}
-         \tl_set:cn { \@@_tl_csname:n {##1} }{0}
+         \tl_set:cn { \@@_tl_csname:n {##1} } { 0 }
          \seq_clear_new:c { \@@_seq_csname:n {##1} }
        }
 %    \end{macrocode}
@@ -2987,7 +3024,7 @@
               { \prop_map_break: }
               { \@@_apply_label_pair:nnn {##1} {####1} }
               { \@@_apply_label_pair:nnn {####1} {##1} }
-                  {#4}
+                  {#5}
           }
       }
 %    \end{macrocode}
@@ -3015,7 +3052,7 @@
 %    
 %    \begin{macrocode}
     \tl_gclear:N #1
-    \clist_gclear:N #3
+    \clist_gclear:N #4
 %    \end{macrocode}
 %
 %    The whole loop combines steps T5--T7:
@@ -3031,7 +3068,7 @@
 %    \end{macrocode}
 %    
 %    \begin{macrocode}
-        \@@_clist_gput:NV #3 \l_@@_front_tl
+        \@@_clist_gput:NV #4 \l_@@_front_tl
         \@@_debug:n{ \iow_term:x{Handled~ code~ for~ \l_@@_front_tl} }
 %    \end{macrocode}
 %
@@ -3079,14 +3116,14 @@
 %    \end{macrocode}
 %    After we have added all hook code to \verb=#1= we finish it off
 %    with adding extra code for a one time execution. That is stored
-%    in \verb=#2= but is normally empty.
+%    in \verb=#3= but is normally empty.
 %    \begin{macrocode}
-    \tl_gput_right:Nn #1 {#2}
+    \tl_gput_right:Nn #1 { #2 #3 }
   }
 %    \end{macrocode}
 %    
 %    \begin{macrocode}
-\cs_generate_variant:Nn \@@_initialize_single:NNNn {ccc}
+\cs_generate_variant:Nn \@@_initialize_single:NNNNn { cccc }
 %    \end{macrocode}
 %  \end{macro}
 %
@@ -3359,6 +3396,16 @@
 %    \end{macrocode}
 %    
 %    \begin{macrocode}
+        \@@_log_line:x { Document-level~(top-level)~code:}
+        \@@_log_line_indent:x
+          {
+            \tl_if_empty:cTF { @@_toplevel~#1 }
+              { --- }
+              { ->~ \exp_args:Nv \tl_to_str:n { @@_toplevel~#1 } }
+          }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
         \@@_log_line:x { Extra~code~for~next~invocation:}
         \@@_log_line_indent:x
           {
@@ -3565,7 +3612,6 @@
 %  \end{macro}
 %  \end{macro}
 %
-%
 % \subsection{Using the hook}
 %
 % \begin{macro}{\hook_use:n}
@@ -3730,7 +3776,11 @@
       {
         \bool_lazy_and:nnTF
             { \prop_if_empty_p:c { g_@@_#1_code_prop } }
-            { \tl_if_empty_p:c { @@_next~#1 } }
+            {
+              \bool_lazy_and_p:nn
+                { \tl_if_empty_p:c { @@_toplevel~#1 } }
+                { \tl_if_empty_p:c { @@_next~#1 } }
+            }
           { \prg_return_true: }
           { \prg_return_false: }
       }





More information about the latex3-commits mailing list.