texlive[52822] Master/texmf-dist: unravel (16nov19)

commits+karl at tug.org commits+karl at tug.org
Sat Nov 16 23:15:43 CET 2019


Revision: 52822
          http://tug.org/svn/texlive?view=revision&revision=52822
Author:   karl
Date:     2019-11-16 23:15:42 +0100 (Sat, 16 Nov 2019)
Log Message:
-----------
unravel (16nov19)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/latex/unravel/unravel.pdf
    trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx
    trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty

Modified: trunk/Master/texmf-dist/doc/latex/unravel/unravel.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx
===================================================================
--- trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx	2019-11-16 22:15:27 UTC (rev 52821)
+++ trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx	2019-11-16 22:15:42 UTC (rev 52822)
@@ -23,9 +23,9 @@
 %
 % \title{The \textsf{unravel} package: \\
 %   watching TeX digest tokens\thanks{This
-%     file has version number 0.2g, last revised 2019/03/23.}}
+%     file has version number 0.2h, last revised 2019/11/15.}}
 % \author{Bruno Le Floch}
-% \date{2019/03/23}
+% \date{2019/11/15}
 %
 % \maketitle
 % \tableofcontents
@@ -213,6 +213,24 @@
 %   neither if the option is negative.
 % \end{function}
 %
+% \begin{function}{prompt-input}
+%   Comma-delimited list option (empty by default) whose items are used
+%   one by one as if the user typed them at the prompt.  Since the
+%   key-value list is itself comma-delimited, the value here must be
+%   wrapped in braces.  For instance, |prompt-input = {s10, m, u\def}|
+%   skips $10$ steps, shows the first token's meaning, then continues
+%   silently until the first token is~|\def|, and any subsequent prompt
+%   is treated normally with user interaction.  This can be useful when
+%   repeatedly debugging complicated code when the issue is known to lie
+%   quite late in the code.
+%
+%   As for any |clist|, spaces are discarded around each comma and empty
+%   entries are removed, then for each item one pair of braces is
+%   removed (if any is present); to get an empty item use an empty brace
+%   group, such as in |prompt-input = {s10, {}, x}|.  Category codes are
+%   those in effect when the |prompt-input| option is read.
+% \end{function}
+%
 % \begin{function}{trace-assigns, trace-expansion, trace-other}
 %   Boolean options (default \texttt{true}) controlling what steps
 %   produce any output at all.  The keys |trace-assigns|,
@@ -246,17 +264,14 @@
 %   \tn{lastpenalty}, \tn{lastskip}, \tn{currentiflevel} and
 %   \tn{currentiftype} may have wrong values.  Perhaps
 %   \tn{currentgrouplevel} and \tn{currentgrouptype} too.
-% \item Tokens passed to \tn{afterassignment} are not yet kept after
-%   \pkg{unravel} is done even if there has been no assignment.
+% \item Setting \tn{globaldefs} to a non-zero value may cause problems.
 % \item Tokens passed to \tn{aftergroup} are lost when \pkg{unravel} is
 %   done.
-% \item In \XeTeX{}, characters beyond the basic multilingual plane may
-%   break \pkg{unravel} (not tested).
 % \item For \pkg{unravel}, category codes are fixed when a file is read
 %   using \tn{input},
 %   while \TeX{} only fixes category codes when the corresponding
 %   characters are converted to tokens.  Similarly, the argument of
-%   \tn{scantokens} is converted to the new category code r\'egime in
+%   \tn{scantokens} is converted to the new category code regime in
 %   one go, and the result must be balanced.
 % \item Explicit begin-group and end-group characters other than the
 %   usual left and right braces may make \pkg{unravel} choke, or may be
@@ -273,10 +288,7 @@
 % \subsection{Future perhaps}
 %
 % \begin{itemize}
-% \item Allow users to change some settings globally/for one |\unravel|.
 % \item Allow to replay steps that have already been run.
-% \item Fix the display for \tn{if} and \tn{ifcat} (remove extraneous
-%   \cs{exp_not:N}).
 % \item Use the |file-error| fatal error message: first implement
 %   \cs{@@_file_if_exist:nTF} and use it to determine whether
 %   \tn{input} will throw a fatal error in \tn{batchmode} and
@@ -545,7 +557,7 @@
   {%
     \csname @@_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2019/03/23} {0.2g} {Watching TeX digest tokens}%
+      {unravel} {2019/11/15} {0.2h} {Watching TeX digest tokens}%
     \csname @@_setup_unravel:\endcsname
   }%
 %    \end{macrocode}
@@ -870,16 +882,11 @@
 %
 % \subsubsection{Helpers for control flow}
 %
-% \begin{macro}[EXP]{\@@_exit:w, \@@_exit_error:w, \@@_exit_hard:w, \@@_exit_point:}
+% \begin{macro}[EXP]{\@@_exit:w, \@@_exit_hard:w, \@@_exit_point:}
 %   Jump to the very end of this instance of \cs{unravel}.
 %    \begin{macrocode}
 \cs_new_eq:NN \@@_exit_point: \prg_do_nothing:
 \cs_new:Npn \@@_exit:w #1 \@@_exit_point: { }
-\cs_new:Npn \@@_exit_error:w #1 \@@_exit_point: #2 \@@_final_bad:
-  {
-    \@@_error:nnnnn { runaway-unravel } { } { } { } { }
-    #2
-  }
 \cs_new:Npn \@@_exit_hard:w #1 \@@_exit_point: #2 \@@_exit_point: { }
 %    \end{macrocode}
 % \end{macro}
@@ -1151,8 +1158,8 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_prev_input_join_get:nN}
-% \begin{macro}{\@@_join_get_aux:NNN}
+% \begin{macro}{\@@_prev_input_join_get:nnN}
+% \begin{macro}{\@@_join_get_aux:NNnN}
 %   Pops the previous-input sequence twice to get some value in
 %   \cs{l_@@_head_tl} and some sign or decimal number in
 %   \cs{l_@@_tmpa_tl}.  Combines them into a value, using
@@ -1159,23 +1166,23 @@
 %   the appropriate evaluation function, determined based
 %   on~|#1|.
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_prev_input_join_get:nN #1
+\cs_new_protected:Npn \@@_prev_input_join_get:nnN #1
   {
     \int_case:nnF {#1}
       {
-        { 2 } { \@@_join_get_aux:NNN \skip_eval:n \tex_glueexpr:D }
-        { 3 } { \@@_join_get_aux:NNN \muskip_eval:n \tex_muexpr:D }
+        { 2 } { \@@_join_get_aux:NNnN \skip_eval:n \tex_glueexpr:D }
+        { 3 } { \@@_join_get_aux:NNnN \muskip_eval:n \tex_muexpr:D }
       }
       {
         \@@_error:nnnnn { internal } { join-factor } { } { } { }
-        \@@_join_get_aux:NNN \use:n \prg_do_nothing:
+        \@@_join_get_aux:NNnN \use:n \prg_do_nothing:
       }
   }
-\cs_new_protected:Npn \@@_join_get_aux:NNN #1#2#3
+\cs_new_protected:Npn \@@_join_get_aux:NNnN #1#2#3#4
   {
     \@@_prev_input_gpop:N \l_@@_head_tl
     \@@_prev_input_gpop:N \l_@@_tmpa_tl
-    \tl_set:Nx #3 { #1 { \l_@@_tmpa_tl #2 \l_@@_head_tl } }
+    \tl_set:Nx #4 { #1 { \l_@@_tmpa_tl #2 \l_@@_head_tl #3 } }
   }
 %    \end{macrocode}
 % \end{macro}
@@ -1212,6 +1219,7 @@
 %     \g_@@_default_internal_debug_bool  , \g_@@_internal_debug_bool  ,
 %     \g_@@_default_number_steps_bool    , \g_@@_number_steps_bool    ,
 %     \g_@@_default_online_int           , \g_@@_online_int           ,
+%     \g_@@_default_prompt_input_clist   , \g_@@_prompt_input_clist   ,
 %     \g_@@_default_trace_assigns_bool   , \g_@@_trace_assigns_bool   ,
 %     \g_@@_default_trace_expansion_bool , \g_@@_trace_expansion_bool ,
 %     \g_@@_default_trace_other_bool     , \g_@@_trace_other_bool     ,
@@ -1227,6 +1235,7 @@
 \bool_new:N \g_@@_default_internal_debug_bool
 \bool_new:N \g_@@_default_number_steps_bool
 \int_new:N  \g_@@_default_online_int
+\clist_new:N \g_@@_default_prompt_input_clist
 \bool_new:N \g_@@_default_trace_assigns_bool
 \bool_new:N \g_@@_default_trace_expansion_bool
 \bool_new:N \g_@@_default_trace_other_bool
@@ -1241,6 +1250,7 @@
 \bool_new:N \g_@@_internal_debug_bool
 \bool_new:N \g_@@_number_steps_bool
 \int_new:N  \g_@@_online_int
+\clist_new:N \g_@@_prompt_input_clist
 \bool_new:N \g_@@_trace_assigns_bool
 \bool_new:N \g_@@_trace_expansion_bool
 \bool_new:N \g_@@_trace_other_bool
@@ -2289,11 +2299,10 @@
 \@@_tex_primitive:nnn { pdfximagebbox     } { convert } { 31 }
 \@@_tex_primitive:nnn { jobname           } { convert } { 32 }
 \sys_if_engine_luatex:T
-  {
-    \@@_tex_primitive:nnn { directlua       } { convert } { 33 }
-    \@@_tex_primitive:nnn { expanded        } { convert } { 34 }
-    \@@_tex_primitive:nnn { luaescapestring } { convert } { 35 }
-  }
+  { \@@_tex_primitive:nnn { directlua     } { convert } { 33 } }
+\@@_tex_primitive:nnn { expanded          } { convert } { 34 }
+\sys_if_engine_luatex:T
+  { \@@_tex_primitive:nnn { luaescapestring } { convert } { 35 } }
 \sys_if_engine_xetex:T
   {
     \@@_tex_primitive:nnn { Ucharcat        } { convert } { 40 }
@@ -2329,8 +2338,11 @@
 %
 % \begin{macro}{\@@_get_next:}
 % \begin{macro}{\@@_get_next_aux:w}
-%   If the input is empty, forcefully exit.  Otherwise,
-%   remove the first token in the input, and store it in
+%   If the input is empty, insert a frozen \tn{relax} (the alternative
+%   would be either to grab a token in the input stream after
+%   \cs{unravel}, which is tough, or simply produce an error and exit;
+%   perhaps this should be configurable).
+%   Then remove the first token in the input, and store it in
 %   \cs{l_@@_head_gtl}.  Set \cs{l_@@_head_token} equal in meaning to
 %   that first token.  Then set \cs{l_@@_head_tl} to contain the token,
 %   unless it is a begin-group or end-group character, in which case
@@ -2339,20 +2351,22 @@
 \cs_new_protected:Npn \@@_get_next:
   {
     \@@_input_if_empty:TF
-      { \@@_exit_error:w }
       {
-        \@@_input_gpop:N \l_@@_head_gtl
-        \gtl_head_do:NN \l_@@_head_gtl \@@_get_next_aux:w
-        \gtl_if_tl:NTF \l_@@_head_gtl
-          {
-            \tl_set:Nx \l_@@_head_tl
-              { \gtl_head:N \l_@@_head_gtl }
-            \token_if_eq_meaning:NNT
-              \l_@@_head_token \@@_special_relax:
-              \@@_get_next_notexpanded:
-          }
-          { \tl_clear:N \l_@@_head_tl }
+        \@@_error:nnnnn { runaway-unravel } { } { } { } { }
+        \@@_back_input_gtl:N \c_@@_frozen_relax_gtl
       }
+      { }
+    \@@_input_gpop:N \l_@@_head_gtl
+    \gtl_head_do:NN \l_@@_head_gtl \@@_get_next_aux:w
+    \gtl_if_tl:NTF \l_@@_head_gtl
+      {
+        \tl_set:Nx \l_@@_head_tl
+          { \gtl_head:N \l_@@_head_gtl }
+        \token_if_eq_meaning:NNT
+          \l_@@_head_token \@@_special_relax:
+          \@@_get_next_notexpanded:
+      }
+      { \tl_clear:N \l_@@_head_tl }
   }
 \cs_new_protected:Npn \@@_get_next_aux:w
   { \cs_set_eq:NN \l_@@_head_token }
@@ -2582,7 +2596,7 @@
 %   sequence is \tn{nullfont} or similar (note that we do not search for
 %   \verb*|select font|, as the code to trim the escape character from
 %   the meaning may have removed the leading~|s|).  Otherwise, we expect
-%   the \tn{meaning} to be \tn{char} or \tn{mathchar} followed by
+%   the \tn{meaning} to be \tn{char} or \tn{mathchar} or similar followed by
 %   |"|~and an uppercase hexadecimal number, or one of \tn{count},
 %   \tn{dimen}, \tn{skip}, \tn{muskip} or \tn{toks} followed by a
 %   decimal number.
@@ -2610,7 +2624,7 @@
 %   Insert \cs{q_mark} before the first non-letter (in fact, anything
 %   less than~|A|) in the \tn{meaning} by looping one character at a
 %   time (skipping spaces, but there should be none).  We expect the
-%   first part to be |char| or~|mathchar| (or |kchar| in up\TeX{}),
+%   first part to be |char| or~|mathchar| (or |kchar| or |omathchar| in (u)p\TeX{}),
 %   or one of |count|, |dimen|,
 %   |skip|, |muskip|, or |toks|.  In the first two (three) cases, the command is
 %   |char_given| or |math_given|.  It is otherwise identical to the
@@ -2646,6 +2660,7 @@
         { char }     { \@@_set_cmd_aux_given:n { char_given } }
         { kchar }    { \@@_set_cmd_aux_given:n { char_given } }
         { mathchar } { \@@_set_cmd_aux_given:n { math_given } }
+        { omathchar } { \@@_set_cmd_aux_given:n { math_given } }
       }
       {
         \@@_set_cmd_aux_primitive:nTF {#1}
@@ -3784,7 +3799,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: comment
 % \begin{macro}{\@@_scan_expr:N}
 % \begin{macro}{\@@_scan_expr_aux:NN, \@@_scan_factor:N}
 %    \begin{macrocode}
@@ -3974,6 +3988,10 @@
 %   and |inf| is |#2|.  The third argument of this procedure is omitted
 %   here, as the corresponding shortcut is provided as a separate
 %   function, \cs{@@_scan_dim_unit:nN}.
+%
+%   Ideally, \cs{@@_scan_inf_unit_loop:} would produce an \pkg{unravel}
+%   error when reaching the third ``L'', rather than letting TeX produce
+%   the error later on.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_dimen:nN #1#2
   {
@@ -4038,11 +4056,14 @@
       {
         \@@_prev_input_gpush:
         \@@_scan_something_internal:n {#1}
-        \@@_prev_input_join_get:nN {#1} \l_@@_tmpa_tl
+        \int_compare:nNnTF \g_@@_val_level_int = { 0 }
+          { \@@_prev_input_join_get:nnN {#1} { sp } \l_@@_tmpa_tl }
+          { \@@_prev_input_join_get:nnN {#1} { } \l_@@_tmpa_tl }
         \@@_prev_input_gpush:N \l_@@_tmpa_tl
-        \@@_break:w
+        \exp_after:wN \use_none:n \@@_break:w
       }
-      { \@@_back_input: }
+      { }
+    \@@_back_input:
     \int_compare:nNnT {#1} = { 3 }
       {
         \@@_scan_keyword:nT { mMuU } { \@@_break:w }
@@ -4069,6 +4090,7 @@
     \@@_tex_error:nV { missing-pt } \l_@@_head_tl
     \@@_prev_input:n { pt }
     \@@_break_point:
+    \@@_skip_optional_space:
   }
 \cs_new_protected:Npn \@@_scan_inf_unit_loop:
   { \@@_scan_keyword:nT { lL } { \@@_scan_inf_unit_loop: } }
@@ -4119,7 +4141,7 @@
           { \@@_break:w }
       }
       { \@@_back_input: \@@_scan_dimen:nN {#1} \c_false_bool }
-    \@@_prev_input_join_get:nN {#1} \l_@@_tmpa_tl
+    \@@_prev_input_join_get:nnN {#1} { } \l_@@_tmpa_tl
     \@@_prev_input_gpush:
     \@@_prev_input_gpush:N \l_@@_tmpa_tl
     \@@_scan_keyword:nT { pPlLuUsS }
@@ -4127,7 +4149,7 @@
     \@@_scan_keyword:nT { mMiInNuUsS }
       { \@@_scan_dimen:nN {#1} \c_true_bool }
     \@@_break_point:
-    \@@_prev_input_join_get:nN {#1} \l_@@_tmpa_tl
+    \@@_prev_input_join_get:nnN {#1} { } \l_@@_tmpa_tl
     \@@_prev_input_silent:V \l_@@_tmpa_tl
   }
 %    \end{macrocode}
@@ -4185,7 +4207,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: hash doubling is wrong
 % \begin{macro}{\@@_scan_toks_to_str:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_toks_to_str:
@@ -4359,8 +4380,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: catch runaway expand/get_x_next. (get_next too, probably)
-%
 % \begin{macro}{\@@_scan_alt_rule:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_alt_rule:
@@ -4686,6 +4705,7 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_mathchar:n, \@@_mathchar:x}
+% ^^A todo: \omathchar support
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_mathchar:n #1
   {
@@ -4970,30 +4990,19 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \subsection{One step}
+% \subsection{Commands}
 %
-% \begin{macro}{\@@_do_step:}
-%   Perform the action if the corresponding command exists.  If that
-%   command does not exist, complain, and leave the token in the output.
+% We will implement commands in order of their command codes (some of
+% the more elaborate commands call auxiliaries defined in other
+% sections).  Some cases are forbidden.
+%
+% \begin{macro}{\@@_forbidden_case:}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_do_step:
-  {
-    \@@_set_action_text:
-    \bool_if:NT \g_@@_internal_debug_bool
-      { \@@_exp_args:Nx \iow_term:n { Cmd:~\int_to_arabic:n { \l_@@_head_cmd_int } } }
-    \cs_if_exist_use:cF
-      { @@_cmd_ \int_use:N \l_@@_head_cmd_int : }
-      { \@@_error:nxxxx { internal } { unknown-command } { } { } { } }
-  }
+\cs_new_protected:Npn \@@_forbidden_case:
+  { \@@_tex_error:nV { forbidden-case } \l_@@_head_tl }
 %    \end{macrocode}
 % \end{macro}
 %
-% \subsection{Commands}
-%
-% We will implement commands in order of their command codes (some of
-% the more elaborate commands call auxiliaries defined in other
-% sections).
-%
 % \subsubsection{Characters: from 0 to 15}
 %
 % This section is about command codes in the range $[0, 15]$.
@@ -5395,8 +5404,6 @@
   }
 %    \end{macrocode}
 %
-% ^^A todo: implement \@@_forbidden_case:
-%
 % \begin{macro}{\@@_do_move:}
 %   Scan a dimension and a box, and perform the shift, printing the
 %   appropriate action.
@@ -7023,8 +7030,8 @@
 %   \tn{pdffilemoddate}, \tn{pdffilesize}, \tn{pdfmdfivesum},
 %   \tn{pdffiledump}, \tn{pdfmatch}, \tn{pdflastmatch},
 %   \tn{pdfuniformdeviate}, \tn{pdfnormaldeviate}, \tn{pdfinsertht},
-%   \tn{pdfximagebbox}, \tn{jobname}, and in
-%   \LuaTeX{} \tn{directlua}, \tn{expanded}, \tn{luaescapestring}.
+%   \tn{pdfximagebbox}, \tn{jobname}, \tn{expanded}, and in
+%   \LuaTeX{} \tn{directlua}, \tn{luaescapestring}, and in \XeTeX{} \tn{Ucharcat}.
 % \item |the=111| for \tn{the}, \tn{unexpanded}, and \tn{detokenize}.
 % \item |top_bot_mark=112| \tn{topmark}, \tn{firstmark}, \tn{botmark},
 %   \tn{splitfirstmark}, \tn{splitbotmark}, \tn{topmarks},
@@ -7378,7 +7385,8 @@
     \cs_if_eq:NNTF #1 \@@_get_token_xdef:
       {
         \tl_put_right:NV \l_@@_defining_tl \l_@@_head_tl
-        \@@_prev_input:V \l_@@_head_tl
+        \@@_prev_input_silent:x { \l_@@_head_tl }
+        \@@_print_action:
       }
       {
         \cs_if_eq:NNTF #1 \@@_get_token_x:
@@ -7624,7 +7632,7 @@
     \@@_print_expansion:x
       {
         \g_@@_action_text_str = false ~
-        => ~ skipped ~ to ~ \iow_char:N\\fi
+        => ~ skip ~ to ~ \tl_to_str:N \l_@@_head_tl
       }
   }
 \cs_new_protected:Npn \@@_cond_false_loop:n #1
@@ -7671,7 +7679,6 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% ^^A todo: fix interaction with noexpand and active chars (what interaction?)
 % \begin{macro}{\@@_test_two_chars:nn, \@@_test_two_chars_get:n, \@@_test_two_chars_gtl:N}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_test_two_chars:nn #1
@@ -7710,7 +7717,10 @@
         \gtl_if_head_is_group_begin:NTF #1 { \c_group_begin_token }
           {
             \gtl_if_head_is_group_end:NTF #1 { \c_group_end_token }
-              { \exp_not:N \exp_not:N \gtl_head_do:NN #1 \exp_not:N }
+              {
+                \exp_not:N \exp_not:N
+                \exp_not:f { \gtl_head_do:NN #1 \exp_stop_f: }
+              }
           }
       }
   }
@@ -7872,10 +7882,9 @@
             \@@_set_action_text:x
               {
                 \g_@@_action_text_str \c_space_tl
-                => ~ skipped ~ to ~ \tl_to_str:N \l_@@_head_tl
+                => ~ skip ~ to ~ \tl_to_str:N \l_@@_head_tl
               }
           }
-        % ^^A todo: in the terminal output the token itself is missing.
         \@@_print_expansion:
         \@@_cond_pop:
       }
@@ -8222,14 +8231,29 @@
   }
 \cs_new_protected:Npn \@@_prompt_aux:
   {
-    \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
+    \clist_if_empty:NTF \g_@@_prompt_input_clist
       {
-        \bool_if:NTF \g_@@_explicit_prompt_bool
-          { \@@_ior_str_get:Nc \c_@@_prompt_ior }
-          { \@@_ior_str_get:Nc \c_@@_noprompt_ior }
-              { Your~input }
-        \exp_args:Nv \@@_prompt_treat:n { Your~input }
+        \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
+          {
+            \bool_if:NTF \g_@@_explicit_prompt_bool
+              { \@@_ior_str_get:Nc \c_@@_prompt_ior }
+              { \@@_ior_str_get:Nc \c_@@_noprompt_ior }
+                  { Your~input }
+            \exp_args:Nv \@@_prompt_treat:n { Your~input }
+          }
       }
+      {
+        \clist_gpop:NN \g_@@_prompt_input_clist \l_@@_tmpa_tl
+        \group_begin:
+          \@@_set_escapechar:n { 92 }
+          \@@_print:x
+            {
+              \bool_if:NT \g_@@_explicit_prompt_bool { Your~input= }
+              \tl_to_str:N \l_@@_tmpa_tl
+            }
+        \group_end:
+        \exp_args:NV \@@_prompt_treat:n \l_@@_tmpa_tl
+      }
   }
 \cs_new_protected:Npn \@@_prompt_treat:n #1
   {
@@ -8248,7 +8272,11 @@
                 \group_end:
                 \@@_exit_hard:w
               }
-            { X } { \tex_batchmode:D \tex_end:D }
+            { X }
+              {
+                \tex_batchmode:D
+                \tex_read:D -1 to \l_@@_tmpa_tl
+              }
             { s } { \@@_prompt_scan_int:nn {#1}
               \@@_prompt_silent_steps:n }
             { o } { \@@_prompt_scan_int:nn {#1}
@@ -8379,6 +8407,7 @@
               { \exp_not:N \@@:nn \tl_to_str:N \g_@@_until_tl }
           }
           {
+            \int_gzero:N \g_@@_nonstop_int
             \int_gset:Nn \g_@@_online_int { 1 }
             \tl_gclear:N \g_@@_before_print_state_tl
           }
@@ -8483,6 +8512,7 @@
     max-input        .int_gset:N  = \g_@@_default_max_input_int ,
     number-steps     .bool_gset:N = \g_@@_default_number_steps_bool ,
     online           .int_gset:N  = \g_@@_default_online_int ,
+    prompt-input     .clist_gset:N = \g_@@_default_prompt_input_clist ,
     trace-assigns    .bool_gset:N = \g_@@_default_trace_assign_bool ,
     trace-expansion  .bool_gset:N = \g_@@_default_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g_@@_default_trace_other_bool ,
@@ -8497,6 +8527,7 @@
     max-input        .int_gset:N  = \g_@@_max_input_int ,
     number-steps     .bool_gset:N = \g_@@_number_steps_bool ,
     online           .int_gset:N  = \g_@@_online_int ,
+    prompt-input     .clist_gset:N = \g_@@_prompt_input_clist ,
     trace-assigns    .bool_gset:N = \g_@@_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g_@@_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g_@@_trace_other_bool ,
@@ -8589,6 +8620,7 @@
     \@@_exit_point:
     \@@_print_outcome:
     \@@_final_test:
+    \@@_final_after_assignment:
     \@@_exit_point:
   }
 \cs_new_protected:Npn \unravel_get:nnN #1#2#3
@@ -8609,6 +8641,7 @@
     \bool_gset_eq:NN \g_@@_internal_debug_bool \g_@@_default_internal_debug_bool
     \bool_gset_eq:NN \g_@@_number_steps_bool \g_@@_default_number_steps_bool
     \int_gset_eq:NN  \g_@@_online_int \g_@@_default_online_int
+    \clist_gset_eq:NN \g_@@_prompt_input_clist \g_@@_default_prompt_input_clist
     \bool_gset_eq:NN \g_@@_trace_assigns_bool \g_@@_default_trace_assigns_bool
     \bool_gset_eq:NN \g_@@_trace_expansion_bool \g_@@_default_trace_expansion_bool
     \bool_gset_eq:NN \g_@@_trace_other_bool \g_@@_default_trace_other_bool
@@ -8669,6 +8702,22 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_do_step:}
+%   Perform the action if the corresponding command exists.  If that
+%   command does not exist, complain, and leave the token in the output.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_do_step:
+  {
+    \@@_set_action_text:
+    \bool_if:NT \g_@@_internal_debug_bool
+      { \@@_exp_args:Nx \iow_term:n { Cmd:~\int_to_arabic:n { \l_@@_head_cmd_int } } }
+    \cs_if_exist_use:cF
+      { @@_cmd_ \int_use:N \l_@@_head_cmd_int : }
+      { \@@_error:nxxxx { internal } { unknown-command } { } { } { } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % ^^A todo: improve error message
 % \begin{macro}{\@@_final_test:, \@@_final_bad:}
 %   Make sure that the \cs{unravel} finished correctly.  The error
@@ -8694,6 +8743,17 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_final_after_assignment:}
+%   Salvage any remaining \tn{afterassignment} token.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_final_after_assignment:
+  {
+    \gtl_if_empty:NF \g_@@_after_assignment_gtl
+      { \gtl_head_do:NN \g_@@_after_assignment_gtl \tex_afterassignment:D }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{Messages}
 %
 %    \begin{macrocode}
@@ -8745,12 +8805,14 @@
 \msg_new:nnn { unravel } { bad-unless }
   { \iow_char:N\\unless~not~followed~by~conditional. }
 \msg_new:nnn { unravel } { runaway-if }
-  { Runaway~\iow_char:N\\if... }
+  { Runaway~\iow_char:N\\if...~Exiting~\iow_char:N\\unravel }
 \msg_new:nnn { unravel } { runaway-macro-parameter }
   {
     Runaway~macro~parameter~\# #2~after \\\\
     \iow_indent:n {#1}
   }
+\msg_new:nnn { unravel } { runaway-text }
+  { Runaway~braced~argument~for~TeX~primitive.~Exiting~\iow_char:N\\unravel }
 \msg_new:nnn { unravel } { extra-or }
   { Extra~\iow_char:N\\or. }
 \msg_new:nnn { unravel } { missing-equals }
@@ -8779,12 +8841,32 @@
       { TeX~provides~no~further~help~for~this~error. }
       { TeX's~advice~is:\\\\ \iow_indent:n {#3} }
   }
-\msg_new:nnn { unravel } { runaway-unravel }
-  { Runaway~\iow_char:N\\unravel }
+\msg_new:nnnn { unravel } { runaway-unravel }
+  { Runaway~\iow_char:N\\unravel,~so~\iow_char:N\\relax~inserted. }
+  {
+    Some~TeX~command~expects~input~beyond~the~end~of~
+    the~argument~of~\iow_char:N\\unravel.
+  }
 %    \end{macrocode}
 %
 % Some error messages from \TeX{} itself.
 %    \begin{macrocode}
+\@@_tex_msg_new:nnn { forbidden-case }
+  {
+    You~can't~use~`\exp_after:wN \token_to_str:N \l_@@_head_tl'~in~
+    \mode_if_vertical:TF { vertical }
+      {
+        \mode_if_horizontal:TF { horizontal }
+          { \mode_if_math:TF { math } { no } }
+      } ~ mode.
+  }
+  {
+    Sorry,~but~I'm~not~programmed~to~handle~this~case;~
+    I'll~just~pretend~that~you~didn't~ask~for~it.~
+    If~you're~in~the~wrong~mode,~you~might~be~able~to~
+    return~to~the~right~one~by~typing~`I\iow_char:N\}'~or~
+    `I\iow_char:N\$'~or~`I\iow_char:N\\par'.
+  }
 \@@_tex_msg_new:nnn { incompatible-mag }
   {
     Incompatible~magnification~

Modified: trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2019-11-16 22:15:27 UTC (rev 52821)
+++ trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2019-11-16 22:15:42 UTC (rev 52822)
@@ -153,7 +153,7 @@
   {%
     \csname __unravel_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2019/03/23} {0.2g} {Watching TeX digest tokens}%
+      {unravel} {2019/11/15} {0.2h} {Watching TeX digest tokens}%
     \csname __unravel_setup_unravel:\endcsname
   }%
 \cs_new_eq:NN \__unravel_currentgrouptype:      \tex_currentgrouptype:D
@@ -324,11 +324,6 @@
   }
 \cs_new_eq:NN \__unravel_exit_point: \prg_do_nothing:
 \cs_new:Npn \__unravel_exit:w #1 \__unravel_exit_point: { }
-\cs_new:Npn \__unravel_exit_error:w #1 \__unravel_exit_point: #2 \__unravel_final_bad:
-  {
-    \__unravel_error:nnnnn { runaway-unravel } { } { } { } { }
-    #2
-  }
 \cs_new:Npn \__unravel_exit_hard:w #1 \__unravel_exit_point: #2 \__unravel_exit_point: { }
 \cs_new_eq:NN \__unravel_break_point: \prg_do_nothing:
 \cs_new:Npn \__unravel_break:w #1 \__unravel_break_point: { }
@@ -473,23 +468,23 @@
     \gtl_concat:NNN \l__unravel_prev_input_gtl \l__unravel_prev_input_gtl #1
     \__unravel_prev_input_gpush_gtl:N \l__unravel_prev_input_gtl
   }
-\cs_new_protected:Npn \__unravel_prev_input_join_get:nN #1
+\cs_new_protected:Npn \__unravel_prev_input_join_get:nnN #1
   {
     \int_case:nnF {#1}
       {
-        { 2 } { \__unravel_join_get_aux:NNN \skip_eval:n \tex_glueexpr:D }
-        { 3 } { \__unravel_join_get_aux:NNN \muskip_eval:n \tex_muexpr:D }
+        { 2 } { \__unravel_join_get_aux:NNnN \skip_eval:n \tex_glueexpr:D }
+        { 3 } { \__unravel_join_get_aux:NNnN \muskip_eval:n \tex_muexpr:D }
       }
       {
         \__unravel_error:nnnnn { internal } { join-factor } { } { } { }
-        \__unravel_join_get_aux:NNN \use:n \prg_do_nothing:
+        \__unravel_join_get_aux:NNnN \use:n \prg_do_nothing:
       }
   }
-\cs_new_protected:Npn \__unravel_join_get_aux:NNN #1#2#3
+\cs_new_protected:Npn \__unravel_join_get_aux:NNnN #1#2#3#4
   {
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
-    \tl_set:Nx #3 { #1 { \l__unravel_tmpa_tl #2 \l__unravel_head_tl } }
+    \tl_set:Nx #4 { #1 { \l__unravel_tmpa_tl #2 \l__unravel_head_tl #3 } }
   }
 \tl_new:N \g__unravel_before_print_state_tl
 \tl_new:N  \g__unravel_before_prompt_tl
@@ -499,6 +494,7 @@
 \bool_new:N \g__unravel_default_internal_debug_bool
 \bool_new:N \g__unravel_default_number_steps_bool
 \int_new:N  \g__unravel_default_online_int
+\clist_new:N \g__unravel_default_prompt_input_clist
 \bool_new:N \g__unravel_default_trace_assigns_bool
 \bool_new:N \g__unravel_default_trace_expansion_bool
 \bool_new:N \g__unravel_default_trace_other_bool
@@ -513,6 +509,7 @@
 \bool_new:N \g__unravel_internal_debug_bool
 \bool_new:N \g__unravel_number_steps_bool
 \int_new:N  \g__unravel_online_int
+\clist_new:N \g__unravel_prompt_input_clist
 \bool_new:N \g__unravel_trace_assigns_bool
 \bool_new:N \g__unravel_trace_expansion_bool
 \bool_new:N \g__unravel_trace_other_bool
@@ -1263,11 +1260,10 @@
 \__unravel_tex_primitive:nnn { pdfximagebbox     } { convert } { 31 }
 \__unravel_tex_primitive:nnn { jobname           } { convert } { 32 }
 \sys_if_engine_luatex:T
-  {
-    \__unravel_tex_primitive:nnn { directlua       } { convert } { 33 }
-    \__unravel_tex_primitive:nnn { expanded        } { convert } { 34 }
-    \__unravel_tex_primitive:nnn { luaescapestring } { convert } { 35 }
-  }
+  { \__unravel_tex_primitive:nnn { directlua     } { convert } { 33 } }
+\__unravel_tex_primitive:nnn { expanded          } { convert } { 34 }
+\sys_if_engine_luatex:T
+  { \__unravel_tex_primitive:nnn { luaescapestring } { convert } { 35 } }
 \sys_if_engine_xetex:T
   {
     \__unravel_tex_primitive:nnn { Ucharcat        } { convert } { 40 }
@@ -1288,20 +1284,22 @@
 \cs_new_protected:Npn \__unravel_get_next:
   {
     \__unravel_input_if_empty:TF
-      { \__unravel_exit_error:w }
       {
-        \__unravel_input_gpop:N \l__unravel_head_gtl
-        \gtl_head_do:NN \l__unravel_head_gtl \__unravel_get_next_aux:w
-        \gtl_if_tl:NTF \l__unravel_head_gtl
-          {
-            \tl_set:Nx \l__unravel_head_tl
-              { \gtl_head:N \l__unravel_head_gtl }
-            \token_if_eq_meaning:NNT
-              \l__unravel_head_token \__unravel_special_relax:
-              \__unravel_get_next_notexpanded:
-          }
-          { \tl_clear:N \l__unravel_head_tl }
+        \__unravel_error:nnnnn { runaway-unravel } { } { } { } { }
+        \__unravel_back_input_gtl:N \c__unravel_frozen_relax_gtl
       }
+      { }
+    \__unravel_input_gpop:N \l__unravel_head_gtl
+    \gtl_head_do:NN \l__unravel_head_gtl \__unravel_get_next_aux:w
+    \gtl_if_tl:NTF \l__unravel_head_gtl
+      {
+        \tl_set:Nx \l__unravel_head_tl
+          { \gtl_head:N \l__unravel_head_gtl }
+        \token_if_eq_meaning:NNT
+          \l__unravel_head_token \__unravel_special_relax:
+          \__unravel_get_next_notexpanded:
+      }
+      { \tl_clear:N \l__unravel_head_tl }
   }
 \cs_new_protected:Npn \__unravel_get_next_aux:w
   { \cs_set_eq:NN \l__unravel_head_token }
@@ -1470,6 +1468,7 @@
         { char }     { \__unravel_set_cmd_aux_given:n { char_given } }
         { kchar }    { \__unravel_set_cmd_aux_given:n { char_given } }
         { mathchar } { \__unravel_set_cmd_aux_given:n { math_given } }
+        { omathchar } { \__unravel_set_cmd_aux_given:n { math_given } }
       }
       {
         \__unravel_set_cmd_aux_primitive:nTF {#1}
@@ -2386,11 +2385,14 @@
       {
         \__unravel_prev_input_gpush:
         \__unravel_scan_something_internal:n {#1}
-        \__unravel_prev_input_join_get:nN {#1} \l__unravel_tmpa_tl
+        \int_compare:nNnTF \g__unravel_val_level_int = { 0 }
+          { \__unravel_prev_input_join_get:nnN {#1} { sp } \l__unravel_tmpa_tl }
+          { \__unravel_prev_input_join_get:nnN {#1} { } \l__unravel_tmpa_tl }
         \__unravel_prev_input_gpush:N \l__unravel_tmpa_tl
-        \__unravel_break:w
+        \exp_after:wN \use_none:n \__unravel_break:w
       }
-      { \__unravel_back_input: }
+      { }
+    \__unravel_back_input:
     \int_compare:nNnT {#1} = { 3 }
       {
         \__unravel_scan_keyword:nT { mMuU } { \__unravel_break:w }
@@ -2417,6 +2419,7 @@
     \__unravel_tex_error:nV { missing-pt } \l__unravel_head_tl
     \__unravel_prev_input:n { pt }
     \__unravel_break_point:
+    \__unravel_skip_optional_space:
   }
 \cs_new_protected:Npn \__unravel_scan_inf_unit_loop:
   { \__unravel_scan_keyword:nT { lL } { \__unravel_scan_inf_unit_loop: } }
@@ -2457,7 +2460,7 @@
           { \__unravel_break:w }
       }
       { \__unravel_back_input: \__unravel_scan_dimen:nN {#1} \c_false_bool }
-    \__unravel_prev_input_join_get:nN {#1} \l__unravel_tmpa_tl
+    \__unravel_prev_input_join_get:nnN {#1} { } \l__unravel_tmpa_tl
     \__unravel_prev_input_gpush:
     \__unravel_prev_input_gpush:N \l__unravel_tmpa_tl
     \__unravel_scan_keyword:nT { pPlLuUsS }
@@ -2465,7 +2468,7 @@
     \__unravel_scan_keyword:nT { mMiInNuUsS }
       { \__unravel_scan_dimen:nN {#1} \c_true_bool }
     \__unravel_break_point:
-    \__unravel_prev_input_join_get:nN {#1} \l__unravel_tmpa_tl
+    \__unravel_prev_input_join_get:nnN {#1} { } \l__unravel_tmpa_tl
     \__unravel_prev_input_silent:V \l__unravel_tmpa_tl
   }
 \cs_new_protected:Npn \__unravel_scan_file_name:
@@ -3002,15 +3005,8 @@
       }
     \__unravel_print_action:
   }
-\cs_new_protected:Npn \__unravel_do_step:
-  {
-    \__unravel_set_action_text:
-    \bool_if:NT \g__unravel_internal_debug_bool
-      { \__unravel_exp_args:Nx \iow_term:n { Cmd:~\int_to_arabic:n { \l__unravel_head_cmd_int } } }
-    \cs_if_exist_use:cF
-      { __unravel_cmd_ \int_use:N \l__unravel_head_cmd_int : }
-      { \__unravel_error:nxxxx { internal } { unknown-command } { } { } { } }
-  }
+\cs_new_protected:Npn \__unravel_forbidden_case:
+  { \__unravel_tex_error:nV { forbidden-case } \l__unravel_head_tl }
 \__unravel_new_tex_cmd:nn { relax }                                % 0
   {
     \token_if_eq_meaning:NNT \l__unravel_head_token \__unravel_special_relax:
@@ -4730,7 +4726,8 @@
     \cs_if_eq:NNTF #1 \__unravel_get_token_xdef:
       {
         \tl_put_right:NV \l__unravel_defining_tl \l__unravel_head_tl
-        \__unravel_prev_input:V \l__unravel_head_tl
+        \__unravel_prev_input_silent:x { \l__unravel_head_tl }
+        \__unravel_print_action:
       }
       {
         \cs_if_eq:NNTF #1 \__unravel_get_token_x:
@@ -4905,7 +4902,7 @@
     \__unravel_print_expansion:x
       {
         \g__unravel_action_text_str = false ~
-        => ~ skipped ~ to ~ \iow_char:N\\fi
+        => ~ skip ~ to ~ \tl_to_str:N \l__unravel_head_tl
       }
   }
 \cs_new_protected:Npn \__unravel_cond_false_loop:n #1
@@ -4980,7 +4977,10 @@
         \gtl_if_head_is_group_begin:NTF #1 { \c_group_begin_token }
           {
             \gtl_if_head_is_group_end:NTF #1 { \c_group_end_token }
-              { \exp_not:N \exp_not:N \gtl_head_do:NN #1 \exp_not:N }
+              {
+                \exp_not:N \exp_not:N
+                \exp_not:f { \gtl_head_do:NN #1 \exp_stop_f: }
+              }
           }
       }
   }
@@ -5106,10 +5106,9 @@
             \__unravel_set_action_text:x
               {
                 \g__unravel_action_text_str \c_space_tl
-                => ~ skipped ~ to ~ \tl_to_str:N \l__unravel_head_tl
+                => ~ skip ~ to ~ \tl_to_str:N \l__unravel_head_tl
               }
           }
-        % ^^A todo: in the terminal output the token itself is missing.
         \__unravel_print_expansion:
         \__unravel_cond_pop:
       }
@@ -5347,14 +5346,29 @@
   }
 \cs_new_protected:Npn \__unravel_prompt_aux:
   {
-    \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
+    \clist_if_empty:NTF \g__unravel_prompt_input_clist
       {
-        \bool_if:NTF \g__unravel_explicit_prompt_bool
-          { \__unravel_ior_str_get:Nc \c__unravel_prompt_ior }
-          { \__unravel_ior_str_get:Nc \c__unravel_noprompt_ior }
-              { Your~input }
-        \exp_args:Nv \__unravel_prompt_treat:n { Your~input }
+        \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
+          {
+            \bool_if:NTF \g__unravel_explicit_prompt_bool
+              { \__unravel_ior_str_get:Nc \c__unravel_prompt_ior }
+              { \__unravel_ior_str_get:Nc \c__unravel_noprompt_ior }
+                  { Your~input }
+            \exp_args:Nv \__unravel_prompt_treat:n { Your~input }
+          }
       }
+      {
+        \clist_gpop:NN \g__unravel_prompt_input_clist \l__unravel_tmpa_tl
+        \group_begin:
+          \__unravel_set_escapechar:n { 92 }
+          \__unravel_print:x
+            {
+              \bool_if:NT \g__unravel_explicit_prompt_bool { Your~input= }
+              \tl_to_str:N \l__unravel_tmpa_tl
+            }
+        \group_end:
+        \exp_args:NV \__unravel_prompt_treat:n \l__unravel_tmpa_tl
+      }
   }
 \cs_new_protected:Npn \__unravel_prompt_treat:n #1
   {
@@ -5373,7 +5387,11 @@
                 \group_end:
                 \__unravel_exit_hard:w
               }
-            { X } { \tex_batchmode:D \tex_end:D }
+            { X }
+              {
+                \tex_batchmode:D
+                \tex_read:D -1 to \l__unravel_tmpa_tl
+              }
             { s } { \__unravel_prompt_scan_int:nn {#1}
               \__unravel_prompt_silent_steps:n }
             { o } { \__unravel_prompt_scan_int:nn {#1}
@@ -5496,6 +5514,7 @@
               { \exp_not:N \__unravel:nn \tl_to_str:N \g__unravel_until_tl }
           }
           {
+            \int_gzero:N \g__unravel_nonstop_int
             \int_gset:Nn \g__unravel_online_int { 1 }
             \tl_gclear:N \g__unravel_before_print_state_tl
           }
@@ -5552,6 +5571,7 @@
     max-input        .int_gset:N  = \g__unravel_default_max_input_int ,
     number-steps     .bool_gset:N = \g__unravel_default_number_steps_bool ,
     online           .int_gset:N  = \g__unravel_default_online_int ,
+    prompt-input     .clist_gset:N = \g__unravel_default_prompt_input_clist ,
     trace-assigns    .bool_gset:N = \g__unravel_default_trace_assign_bool ,
     trace-expansion  .bool_gset:N = \g__unravel_default_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g__unravel_default_trace_other_bool ,
@@ -5566,6 +5586,7 @@
     max-input        .int_gset:N  = \g__unravel_max_input_int ,
     number-steps     .bool_gset:N = \g__unravel_number_steps_bool ,
     online           .int_gset:N  = \g__unravel_online_int ,
+    prompt-input     .clist_gset:N = \g__unravel_prompt_input_clist ,
     trace-assigns    .bool_gset:N = \g__unravel_trace_assigns_bool ,
     trace-expansion  .bool_gset:N = \g__unravel_trace_expansion_bool ,
     trace-other      .bool_gset:N = \g__unravel_trace_other_bool ,
@@ -5617,6 +5638,7 @@
     \__unravel_exit_point:
     \__unravel_print_outcome:
     \__unravel_final_test:
+    \__unravel_final_after_assignment:
     \__unravel_exit_point:
   }
 \cs_new_protected:Npn \unravel_get:nnN #1#2#3
@@ -5630,6 +5652,7 @@
     \bool_gset_eq:NN \g__unravel_internal_debug_bool \g__unravel_default_internal_debug_bool
     \bool_gset_eq:NN \g__unravel_number_steps_bool \g__unravel_default_number_steps_bool
     \int_gset_eq:NN  \g__unravel_online_int \g__unravel_default_online_int
+    \clist_gset_eq:NN \g__unravel_prompt_input_clist \g__unravel_default_prompt_input_clist
     \bool_gset_eq:NN \g__unravel_trace_assigns_bool \g__unravel_default_trace_assigns_bool
     \bool_gset_eq:NN \g__unravel_trace_expansion_bool \g__unravel_default_trace_expansion_bool
     \bool_gset_eq:NN \g__unravel_trace_other_bool \g__unravel_default_trace_other_bool
@@ -5666,6 +5689,15 @@
     \__unravel_do_step:
     \__unravel_main_loop:
   }
+\cs_new_protected:Npn \__unravel_do_step:
+  {
+    \__unravel_set_action_text:
+    \bool_if:NT \g__unravel_internal_debug_bool
+      { \__unravel_exp_args:Nx \iow_term:n { Cmd:~\int_to_arabic:n { \l__unravel_head_cmd_int } } }
+    \cs_if_exist_use:cF
+      { __unravel_cmd_ \int_use:N \l__unravel_head_cmd_int : }
+      { \__unravel_error:nxxxx { internal } { unknown-command } { } { } { } }
+  }
 \cs_new_protected:Npn \__unravel_final_test:
   {
     \bool_if:nTF
@@ -5683,6 +5715,11 @@
     \__unravel_error:nnnnn { internal }
       { the-last-unravel-finished-badly } { } { } { }
   }
+\cs_new_protected:Npn \__unravel_final_after_assignment:
+  {
+    \gtl_if_empty:NF \g__unravel_after_assignment_gtl
+      { \gtl_head_do:NN \g__unravel_after_assignment_gtl \tex_afterassignment:D }
+  }
 \msg_new:nnn { unravel } { unknown-primitive }
   { Internal~error:~the~primitive~'#1'~is~not~known. }
 \msg_new:nnn { unravel } { extra-fi-or-else }
@@ -5731,12 +5768,14 @@
 \msg_new:nnn { unravel } { bad-unless }
   { \iow_char:N\\unless~not~followed~by~conditional. }
 \msg_new:nnn { unravel } { runaway-if }
-  { Runaway~\iow_char:N\\if... }
+  { Runaway~\iow_char:N\\if...~Exiting~\iow_char:N\\unravel }
 \msg_new:nnn { unravel } { runaway-macro-parameter }
   {
     Runaway~macro~parameter~\# #2~after \\\\
     \iow_indent:n {#1}
   }
+\msg_new:nnn { unravel } { runaway-text }
+  { Runaway~braced~argument~for~TeX~primitive.~Exiting~\iow_char:N\\unravel }
 \msg_new:nnn { unravel } { extra-or }
   { Extra~\iow_char:N\\or. }
 \msg_new:nnn { unravel } { missing-equals }
@@ -5765,8 +5804,28 @@
       { TeX~provides~no~further~help~for~this~error. }
       { TeX's~advice~is:\\\\ \iow_indent:n {#3} }
   }
-\msg_new:nnn { unravel } { runaway-unravel }
-  { Runaway~\iow_char:N\\unravel }
+\msg_new:nnnn { unravel } { runaway-unravel }
+  { Runaway~\iow_char:N\\unravel,~so~\iow_char:N\\relax~inserted. }
+  {
+    Some~TeX~command~expects~input~beyond~the~end~of~
+    the~argument~of~\iow_char:N\\unravel.
+  }
+\__unravel_tex_msg_new:nnn { forbidden-case }
+  {
+    You~can't~use~`\exp_after:wN \token_to_str:N \l__unravel_head_tl'~in~
+    \mode_if_vertical:TF { vertical }
+      {
+        \mode_if_horizontal:TF { horizontal }
+          { \mode_if_math:TF { math } { no } }
+      } ~ mode.
+  }
+  {
+    Sorry,~but~I'm~not~programmed~to~handle~this~case;~
+    I'll~just~pretend~that~you~didn't~ask~for~it.~
+    If~you're~in~the~wrong~mode,~you~might~be~able~to~
+    return~to~the~right~one~by~typing~`I\iow_char:N\}'~or~
+    `I\iow_char:N\$'~or~`I\iow_char:N\\par'.
+  }
 \__unravel_tex_msg_new:nnn { incompatible-mag }
   {
     Incompatible~magnification~



More information about the tex-live-commits mailing list