summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/unravel/unravel.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/unravel/unravel.dtx')
-rw-r--r--Master/texmf-dist/source/latex/unravel/unravel.dtx270
1 files changed, 176 insertions, 94 deletions
diff --git a/Master/texmf-dist/source/latex/unravel/unravel.dtx b/Master/texmf-dist/source/latex/unravel/unravel.dtx
index cd7e87a4bf9..1b205fb31b2 100644
--- a/Master/texmf-dist/source/latex/unravel/unravel.dtx
+++ b/Master/texmf-dist/source/latex/unravel/unravel.dtx
@@ -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,31 +1158,31 @@
% \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
% 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,29 +4990,18 @@
% \end{macrocode}
% \end{macro}
%
-% \subsection{One step}
-%
-% \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}
-%
% \subsection{Commands}
%
% We will implement commands in order of their command codes (some of
% the more elaborate commands call auxiliaries defined in other
-% sections).
+% sections). Some cases are forbidden.
+%
+% \begin{macro}{\@@_forbidden_case:}
+% \begin{macrocode}
+\cs_new_protected:Npn \@@_forbidden_case:
+ { \@@_tex_error:nV { forbidden-case } \l_@@_head_tl }
+% \end{macrocode}
+% \end{macro}
%
% \subsubsection{Characters: from 0 to 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,13 +8231,28 @@
}
\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~