[latex3-commits] [git/LaTeX3-latex3-latex3] l3text: Make finding math-in-text f-type expandable (86bfc62cc)

Joseph Wright joseph.wright at morningstar2.co.uk
Sun Dec 8 23:32:04 CET 2019


Repository : https://github.com/latex3/latex3
On branch  : l3text
Link       : https://github.com/latex3/latex3/commit/86bfc62ccda57de71ed51ee234b61b811217f946

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

commit 86bfc62ccda57de71ed51ee234b61b811217f946
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Sun Dec 8 21:07:18 2019 +0000

    Make finding math-in-text f-type expandable
    
    This then allows a 'follow-on' command:
    currently the no-op and the simple (hyperref-like)
    approaches are available.


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

86bfc62ccda57de71ed51ee234b61b811217f946
 l3kernel/l3text.dtx                     | 234 ++++++++++++++++++++++++++------
 l3kernel/testfiles/m3text003.luatex.tlg |   2 +-
 l3kernel/testfiles/m3text003.ptex.tlg   |   2 +-
 l3kernel/testfiles/m3text003.tlg        |   2 +-
 l3kernel/testfiles/m3text003.uptex.tlg  |   2 +-
 l3kernel/testfiles/m3text003.xetex.tlg  |   2 +-
 6 files changed, 199 insertions(+), 45 deletions(-)

diff --git a/l3kernel/l3text.dtx b/l3kernel/l3text.dtx
index 8bff981dd..494e3b340 100644
--- a/l3kernel/l3text.dtx
+++ b/l3kernel/l3text.dtx
@@ -167,12 +167,13 @@
 %   \end{syntax}
 %   Takes user input \meta{text} and expands as described for
 %   \cs{text_expand:n}, then removes all functions from the resulting
-%   text. No processing takes place of math mode material (as delimited by
-%   pairs given in \cs{l_text_math_delims_tl} or as the argument to commands
-%   listed in \cs{l_text_math_arg_tl}); these tokens and functions are left
-%   in-place. Non-expandable functions present in the \meta{text} must either
-%   have a defined equivalent (see \cs{text_declare_purify_equivalent:Nn})
-%   or will be removed from the result.
+%   text. Math mode material (as delimited by pairs given in
+%   \cs{l_text_math_delims_tl} or as the argument to commands listed in
+%   \cs{l_text_math_arg_tl}) is processed as determined by the current
+%   setting for \cs{text_set_purify_math_mode:n}, and is left contained
+%   in a pair of delimiters.  Non-expandable functions present in the
+%   \meta{text} must either have a defined equivalent (see
+%   \cs{text_declare_purify_equivalent:Nn}) or will be removed from the result.
 % \end{function}
 %
 % \begin{function}[added = 2019-12-05]
@@ -188,6 +189,36 @@
 %   should be expandable.
 % \end{function}
 %
+% \begin{function}[rEXP, added = 2019-12-08]
+%   {
+%     \text_purify_math_unchanged:n,
+%     \text_purify_math_chars:n
+%   }
+%   \begin{syntax}
+%     \cs{text_purify_math_unchanged:n} \Arg{math}
+%   \end{syntax}
+%   Takes user input \meta{math} (which should be free of outer math mode
+%   delimiters) and expresses it in the \meta{form}:
+%   \begin{itemize}
+%     \item \texttt{unchanged}: no manipulation at all, the tokens are
+%       left delimited by the first pair in \cs{l_text_math_delims_tl}
+%       (or if empty, a pair of |$|)
+%     \item \textt{chars} Retains only the text characters (category code
+%      $11$ and $12$) and spaces in the math mode material, and drops all
+%      other content
+%   \end{itemize}
+%   In all cases, the result is protected from further expansion by
+%   \cs{exp_not:n}.
+% \end{function}
+%
+% \begin{function}[added = 2019-12-08]{\text_set_purify_math_mode:n}
+%   \begin{syntax}
+%     \cs{text_set_purify_math_mode:n} \meta{mode}
+%   \end{syntax}
+%   Sets the math purification mode to one of \texttt{unchanged} or
+%   \textt{chars}.
+% \end{function}
+%
 % \begin{variable}{\l_text_accents_tl}
 %   Lists commands which represent accents, and which are left unchanged
 %   by expansion.
@@ -481,6 +512,14 @@
 %    \end{macrocode}
 % \end{variable}
 %
+% \begin{macro}{\l_@@_math_mode_tl}
+%   Used to control math mode output: internal as there is a dedicated
+%   setter.
+%    \begin{macrocode}
+\tl_new:N \l_@@_math_mode_tl
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{Expansion to formatted text}
 %
 % \begin{variable}{\c_@@_chardef_space_token, \c_@@_mathchardef_space_token}
@@ -2252,10 +2291,14 @@
 % \begin{macro}[rEXP]{\@@_purify_space:w}
 % \begin{macro}[rEXP]{\@@_purify_N_type:N, \@@_purify_N_type_aux:N}
 % \begin{macro}[rEXP]{\@@_purify_math_search:NNN}
-% \begin{macro}[rEXP]{\@@_purify_math_loop:Nw}
-% \begin{macro}[rEXP]{\@@_purify_math_N_type:NN}
-% \begin{macro}[rEXP]{\@@_purify_math_group:Nn}
-% \begin{macro}[rEXP]{\@@_purify_math_space:Nw}
+% \begin{macro}[rEXP]{\@@_purify_math_start:NNw}
+% \begin{macro}[rEXP]{\@@_purify_math_store:n}
+% \begin{macro}[rEXP]{\@@_purify_math_store:nw}
+% \begin{macro}[rEXP]{\@@_purify_math_end:w
+% \begin{macro}[rEXP]{\@@_purify_math_loop:NNw}
+% \begin{macro}[rEXP]{\@@_purify_math_N_type:NNN}
+% \begin{macro}[rEXP]{\@@_purify_math_group:NNn}
+% \begin{macro}[rEXP]{\@@_purify_math_space:NNw}
 % \begin{macro}[rEXP]{\@@_purify_math_cmd:N}
 % \begin{macro}[rEXP]{\@@_purify_math_cmd:NN}
 % \begin{macro}[rEXP]{\@@_purify_math_cmd:Nn}
@@ -2322,42 +2365,59 @@
     \token_if_eq_meaning:NNTF #1 #2
       {
         \use_i_delimit_by_q_recursion_stop:nw
-           {
-             \exp_not:n {#1}
-             \@@_purify_math_loop:Nw #3
-           }
+           { \@@_purify_math_start:NNw #2 #3 }
       }
       { \@@_purify_math_search:NNN #1 }
   }
-\cs_new:Npn \@@_purify_math_loop:Nw #1#2 \q_recursion_stop
+\cs_new:Npn \@@_purify_math_start:NNw #1#2#3 \q_recursion_stop
   {
-    \tl_if_head_is_N_type:nTF {#2}
-      { \@@_purify_math_N_type:NN }
+    \@@_purify_math_loop:NNw #1#2#3 \q_recursion_stop
+      \@@_purify_math_result:n { }
+  }
+\cs_new:Npn \@@_purify_math_store:n #1
+  { \@@_purify_math_store:nw {#1} }
+\cs_new:Npn \@@_purify_math_store:nw #1#2 \@@_purify_math_result:n #3
+  { #2 \@@_purify_math_result:n { #3 #1 } }
+\cs_new:Npn \@@_purify_math_end:w #1 \@@_purify_math_result:n #2
+  {
+    \use:c { text_purify_math_ \l_@@_math_mode_tl :n } {#2}
+    \@@_purify_loop:w #1
+  }
+\cs_new:Npn \@@_purify_math_stop:Nw #1 \@@_purify_math_result:n #2
+  { \exp_not:n {#1#2} }
+\cs_new:Npn \@@_purify_math_loop:NNw #1#2#3 \q_recursion_stop
+  {
+    \tl_if_head_is_N_type:nTF {#3}
+      { \@@_purify_math_N_type:NNN }
       {
-        \tl_if_head_is_group:nTF {#2}
-          { \@@_purify_math_group:Nn }
-          { \@@_purify_math_space:Nw }
+        \tl_if_head_is_group:nTF {#3}
+          { \@@_purify_math_group:NNn }
+          { \@@_purify_math_space:NNw }
       }
-    #1#2 \q_recursion_stop
+        #1#2#3 \q_recursion_stop
   }
-\cs_new:Npn \@@_purify_math_N_type:NN #1#2
+\cs_new:Npn \@@_purify_math_N_type:NNN #1#2#3
   {
-    \quark_if_recursion_tail_stop:N #2
-    \exp_not:n {#2}
-    \token_if_eq_meaning:NNTF #2 #1
-      { \@@_purify_loop:w }
-      { \@@_purify_math_loop:Nw #1 }
+    \quark_if_recursion_tail_stop_do:Nn #3
+      { \@@_purify_math_stop:Nw #1 }
+    \token_if_eq_meaning:NNTF #3 #2
+      { \@@_purify_math_end:w }
+      {
+        \@@_purify_math_store:n {#3}
+        \@@_purify_math_loop:NNw #1#2
+      }
   }
-\cs_new:Npn \@@_purify_math_group:Nn #1#2
+\cs_new:Npn \@@_purify_math_group:NNn #1#2#3
   {
-    { \exp_not:n {#2} }
-    \@@_purify_math_loop:Nw #1
+    \@@_purify_math_store:n { {#3} }
+    \@@_purify_math_loop:NNw #1#2
   }
-\exp_after:wN \cs_new:Npn \exp_after:wN \@@_purify_math_space:Nw 
-  \exp_after:wN # \exp_after:wN 1 \c_space_tl
+\exp_after:wN \cs_new:Npn \exp_after:wN \@@_purify_math_space:NNw 
+  \exp_after:wN # \exp_after:wN 1
+  \exp_after:wN # \exp_after:wN 2 \c_space_tl
   {
-    \c_space_tl
-    \@@_purify_math_loop:Nw #1
+    \@@_purify_math_store:n { ~ }
+    \@@_purify_math_loop:NNw #1#2
   }
 %    \end{macrocode}
 %   Then handle math mode as an argument: same outcomes, different input
@@ -2375,15 +2435,12 @@
     \cs_if_eq:NNTF #2 #1
       {
         \use_i_delimit_by_q_recursion_stop:nw
-          { \@@_purify_math_cmd:Nn #1 }
+          { \@@_purify_math_cmd:n }
       }
       { \@@_purify_math_cmd:NN #1 }
   }
-\cs_new:Npn \@@_purify_math_cmd:Nn #1#2
-  {
-    \exp_not:n { #1 {#2} }
-    \@@_purify_loop:w
-  }
+\cs_new:Npn \@@_purify_math_cmd:n #1
+  { \@@_purify_math_end:w \@@_purify_math_result:n {#1} }
 %    \end{macrocode}
 %   For \texttt{N}-type tokens, we first look for a string-context replacement
 %   before anything else: this can therefore cover anything. Assuming we don't
@@ -2447,6 +2504,10 @@
 % \end{macro}
 % \end{macro}
 % \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
 %
 % \begin{macro}
 %   {
@@ -2933,6 +2994,99 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \subsection{Purifying math}
+%
+% \begin{macro}[rEXP]{\text_purify_math_unchanged:n}
+% \begin{macro}[rEXP]{\@@_purify_math_unchanged:Nw}
+% \begin{macro}[rEXP]{\@@_purify_math_unchanged:NNw}
+%   Top-level functions for purifying math mode: just keep as-is.
+%    \begin{macrocode}
+\cs_new:Npn \text_purify_math_unchanged:n #1
+  {
+    \exp_after:wN \@@_purify_math_unchanged:Nw
+      \l_text_math_delims_tl $ $ \q_stop
+    \exp_not:n {#1}
+    \exp_after:wN \@@_purify_math_unchanged:NNw
+      \l_text_math_delims_tl $ $ \q_stop
+  }
+\cs_new:Npn \@@_purify_math_unchanged:Nw #1#2 \q_stop
+  { \exp_not:n {#1} }
+\cs_new:Npn \@@_purify_math_unchanged:NNw #1#2#3 \q_stop
+  { \exp_not:n {#2} }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[rEXP]{\text_purify_math_chars:n}
+% \begin{macro}[rEXP]{\@@_purify_math_chars_loop:w}
+% \begin{macro}[rEXP]{\@@_purify_math_chars_space:w}
+% \begin{macro}[rEXP]{\@@_purify_math_chars_group:n
+% \begin{macro}[rEXP]{\@@_purify_math_chars_N_type:N}
+%   Just keeping the character text could be done using a faster loop,
+%   but that looses the spaces. Not a big issue in math mode (thought it
+%   is nice to keep them), but any nested text-in-math needs them: this
+%   was there is no need to actually check for such material.
+%    \begin{macrocode}
+\cs_new:Npn \text_purify_math_chars:n #1
+  {
+    \@@_purify_math_chars_loop:w #1
+      \q_recursion_tail \q_recursion_stop
+  }
+\cs_new:Npn \@@_purify_math_chars_loop:w #1 \q_recursion_stop
+  {
+    \tl_if_head_is_N_type:nTF {#1}
+      { \@@_purify_math_chars_N_type:N }
+      {
+        \tl_if_head_is_group:nTF {#1}
+          { \@@_purify_math_chars_group:n }
+          { \@@_purify_math_chars_space:w }
+      }
+    #1 \q_recursion_stop
+  }
+\exp_last_unbraced:NNo \cs_new:Npn \@@_purify_math_chars_space:w
+  \c_space_tl
+  {
+    \c_space_tl
+    \@@_purify_math_chars_loop:w
+  }
+\cs_new:Npn \@@_purify_math_chars_group:n #1
+  { \@@_purify_math_chars_loop:w #1 }
+\cs_new:Npn \@@_purify_math_chars_N_type:N #1
+  {
+    \quark_if_recursion_tail_stop:N #1
+    \bool_lazy_or:nnT
+      { \token_if_letter_p:N #1 }
+      { \token_if_other_p:N #1 }
+      { #1 }
+    \@@_purify_math_chars_loop:w
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\text_set_purify_math_mode:n}
+%   Set up the mode for purification.
+%    \begin{macrocode}
+\cs_new_protected:Npn \text_set_purify_math_mode:n #1
+  {
+    \cs_if_exist:cTF { text_purify_math_ #1:n }
+      { \tl_set:Nn \l_@@_math_mode_tl {#1} }
+      { \__kernel_msg_error:nnn { kernel } { unknown-purify-mode } {#1} }
+  }
+\text_set_purify_math_mode:n { unchanged }
+\__kernel_msg_new:nnnn { kernel } { unknown-purify-mode }
+  { Unknown~math_purification~mode~'#1'. }
+  {
+    LaTeX~knows~how~to~purify~math~mode~as~'unchanged',~
+    'simple'~and~'unicode',~and~does~not~know~'#1'.
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 %    \begin{macrocode}
 %</initex|package>
 %    \end{macrocode}
diff --git a/l3kernel/testfiles/m3text003.luatex.tlg b/l3kernel/testfiles/m3text003.luatex.tlg
index 165d69b57..afbb1475e 100644
--- a/l3kernel/testfiles/m3text003.luatex.tlg
+++ b/l3kernel/testfiles/m3text003.luatex.tlg
@@ -23,7 +23,7 @@ TEST 4: Math-mode escape
 ============================================================
 Some text $y = \sin \theta $
 Opps not close token in $y = \sin \theta 
-\ensuremath {y=mx+c} is an equation
+$y=mx+c$ is an equation
 ============================================================
 ============================================================
 TEST 5: Letter-like commands
diff --git a/l3kernel/testfiles/m3text003.ptex.tlg b/l3kernel/testfiles/m3text003.ptex.tlg
index f3efcb6c4..632ce1f8a 100644
--- a/l3kernel/testfiles/m3text003.ptex.tlg
+++ b/l3kernel/testfiles/m3text003.ptex.tlg
@@ -23,5 +23,5 @@ TEST 4: Math-mode escape
 ============================================================
 Some text $y = \sin \theta $
 Opps not close token in $y = \sin \theta 
-\ensuremath {y=mx+c} is an equation
+$y=mx+c$ is an equation
 ============================================================
diff --git a/l3kernel/testfiles/m3text003.tlg b/l3kernel/testfiles/m3text003.tlg
index 509f3fd2d..a7bcec9b4 100644
--- a/l3kernel/testfiles/m3text003.tlg
+++ b/l3kernel/testfiles/m3text003.tlg
@@ -23,7 +23,7 @@ TEST 4: Math-mode escape
 ============================================================
 Some text $y = \sin \theta $
 Opps not close token in $y = \sin \theta 
-\ensuremath {y=mx+c} is an equation
+$y=mx+c$ is an equation
 ============================================================
 ============================================================
 TEST 5: Letter-like commands
diff --git a/l3kernel/testfiles/m3text003.uptex.tlg b/l3kernel/testfiles/m3text003.uptex.tlg
index 165d69b57..afbb1475e 100644
--- a/l3kernel/testfiles/m3text003.uptex.tlg
+++ b/l3kernel/testfiles/m3text003.uptex.tlg
@@ -23,7 +23,7 @@ TEST 4: Math-mode escape
 ============================================================
 Some text $y = \sin \theta $
 Opps not close token in $y = \sin \theta 
-\ensuremath {y=mx+c} is an equation
+$y=mx+c$ is an equation
 ============================================================
 ============================================================
 TEST 5: Letter-like commands
diff --git a/l3kernel/testfiles/m3text003.xetex.tlg b/l3kernel/testfiles/m3text003.xetex.tlg
index 165d69b57..afbb1475e 100644
--- a/l3kernel/testfiles/m3text003.xetex.tlg
+++ b/l3kernel/testfiles/m3text003.xetex.tlg
@@ -23,7 +23,7 @@ TEST 4: Math-mode escape
 ============================================================
 Some text $y = \sin \theta $
 Opps not close token in $y = \sin \theta 
-\ensuremath {y=mx+c} is an equation
+$y=mx+c$ is an equation
 ============================================================
 ============================================================
 TEST 5: Letter-like commands





More information about the latex3-commits mailing list