texlive[49515] Master/texmf-dist: unravel (28dec18)

commits+karl at tug.org commits+karl at tug.org
Fri Dec 28 22:32:14 CET 2018


Revision: 49515
          http://tug.org/svn/texlive?view=revision&revision=49515
Author:   karl
Date:     2018-12-28 22:32:14 +0100 (Fri, 28 Dec 2018)
Log Message:
-----------
unravel (28dec18)

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

Modified: trunk/Master/texmf-dist/doc/latex/unravel/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/unravel/README.md	2018-12-28 21:32:01 UTC (rev 49514)
+++ trunk/Master/texmf-dist/doc/latex/unravel/README.md	2018-12-28 21:32:14 UTC (rev 49515)
@@ -1,6 +1,6 @@
 unravel: Watching TeX digest tokens
 ====================================================
-* E-mail: blflatex at gmail.com
+* E-mail: blflatex+unravel at gmail.com
 * Released under the LaTeX Project Public License v1.3c or later
   See http://www.latex-project.org/lppl.txt
 

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	2018-12-28 21:32:01 UTC (rev 49514)
+++ trunk/Master/texmf-dist/source/latex/unravel/unravel.dtx	2018-12-28 21:32:14 UTC (rev 49515)
@@ -23,9 +23,9 @@
 %
 % \title{The \textsf{unravel} package: \\
 %   watching TeX digest tokens\thanks{This
-%     file has version number 0.2e, last revised 2018/04/04.}}
+%     file has version number 0.2f, last revised 2018/12/28.}}
 % \author{Bruno Le Floch}
-% \date{2018/04/04}
+% \date{2018/12/28}
 %
 % \maketitle
 % \tableofcontents
@@ -40,6 +40,8 @@
 % performing assignments, as well as some simple typesetting commands.
 % To use this package, one should normally run \TeX{} in a terminal.
 %
+% \subsection{Commands}
+%
 % \begin{function}{\unravel}
 %   \begin{syntax}
 %     \cs{unravel} \oarg{key-value list} \marg{code}
@@ -70,6 +72,15 @@
 %   See \cs{unravel}.
 % \end{function}
 %
+% \begin{function}{\unravel_get:nnN}
+%   \begin{syntax}
+%     \cs{unravel_get:nnN} \Arg{options} \Arg{code} \meta{tl var}
+%   \end{syntax}
+%   Performs \cs{unravel:nn} with the \meta{options} and \meta{code}
+%   then saves the output into the \meta{tl var}.  The option
+%   |mute| is useful in this case.
+% \end{function}
+%
 % \begin{function}{\unravel_setup:n}
 %   \begin{syntax}
 %     \cs{unravel_setup:n} \Arg{options}
@@ -77,6 +88,8 @@
 %   See \cs{unravelsetup}.
 % \end{function}
 %
+% \subsection{Examples}
+%
 % The \pkg{unravel} package is currently based on the behaviour of
 % \pdfTeX{}, but it should work in all engines supported by \pkg{expl3}
 % (\pdfTeX{}, \XeTeX{}, \LuaTeX{}, ep\TeX{}, eup\TeX{}) as long as none
@@ -132,7 +145,7 @@
 %
 % Given all the work that \pkg{unravel} has to do to emulate \TeX{}, it
 % is not fast on very large pieces of code.  For instance, running it on
-% |\documentclass{article}| takes about one minute on my machine, and
+% |\documentclass{article}| takes about thirty seconds on my machine, and
 % finishes after somewhat less than $21000$ steps.
 % \begin{verbatim}
 % \RequirePackage{unravel}
@@ -148,11 +161,12 @@
 % would if your file ended just after |\documentclass{article}|.  After
 % running the above through \pdfTeX{}, one can check that the result is
 % identical to that without \pkg{unravel}.  Note that
-% \cs{unravel}|{\usepackage{lipsum}\relax}|, despite taking as many steps
-% to complete, is much slower, because \tn{newcommand} uses
+% \cs{unravel}|{\usepackage{lipsum}\relax}|, despite taking roughly as many steps
+% to complete, is ten times slower, because \tn{newcommand} uses
 % delimited arguments, which prevent some optimizations that
 % \pkg{unravel} can otherwise obtain.  For comparison,
-% |\unravel{\lipsum[1-30]}| also takes $20000$ step.
+% |\unravel{\lipsum[1-30]}| also takes $20000$ step and is ten times
+% faster than loading the package.
 %
 % \subsection{Options}
 % \label{sec:options}
@@ -181,11 +195,31 @@
 %   part, and the input part.
 % \end{function}
 %
+% \begin{function}{mute}
+%   Make none of the steps produce any output, by setting
+%   |trace-assigns|, |trace-expansion|, |trace-other|, |welcome-message|
+%   to \texttt{false}.  This is only useful with \cs{unravel_get:nnN} or
+%   when other options change some of these settings.
+% \end{function}
+%
 % \begin{function}{number-steps}
 %   Boolean option (default \texttt{true}) determining whether to
 %   number steps.
 % \end{function}
 %
+% \begin{function}{online}
+%   Integer option determining where to write the output: terminal and
+%   log if the option is positive, log only if the option is zero,
+%   neither if the option is negative.
+% \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|,
+%   |trace-expansion|, |trace-other| control tracing of different types
+%   of steps.
+% \end{function}
+%
 % \begin{function}{welcome-message}
 %   Boolean option (default \texttt{true}) determining whether to
 %   display the welcome message.
@@ -198,6 +232,8 @@
 %
 % Differences.
 % \begin{itemize}
+% \item Kerning between letters of a word is omitted, which can lead to
+%   incorrect widths.
 % \item Some primitives are not implemented yet: alignments
 %   (\tn{halign}, \tn{valign}, \tn{noalign}, \tn{omit}, \tn{span},
 %   \tn{cr}, \tn{crcr},~|&|), many math mode primitives, and
@@ -229,6 +265,9 @@
 %   to implement it in a way similar to \TeX{}'s, and as it is most
 %   often used at the very end of files, in a redundant way.
 % \item \tn{outer} is not supported.
+% \item \cs{unravel} cannot be nested.
+% \item Control sequences of the form \cs{notexpanded:\ldots{}} are
+%   reserved for use by \pkg{unravel}.
 % \end{itemize}
 %
 % \subsection{Future perhaps}
@@ -329,7 +368,7 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{macro}[int]{\@@_setup_restore:}
+% \begin{macro}{\@@_setup_restore:}
 %   Use the token list to restore catcodes to their former values, then
 %   empty the list since there is no catcode to restore anymore.  This
 %   mechanism cannot be nested.
@@ -342,7 +381,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_setup_save:}
+% \begin{macro}{\@@_setup_save:}
 % \begin{macro}[EXP]{\@@_setup_save_aux:n}
 %   This saves into \cs{l_@@_setup_restore_tl} the current catcodes
 %   (from $0$ to $255$ only), \tn{endlinechar}, \tn{escapechar},
@@ -371,7 +410,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_setup_catcodes:nnn}
+% \begin{macro}{\@@_setup_catcodes:nnn}
 %   This sets all characters from |#1| to |#2| (inclusive) to have
 %   catcode |#3|.
 %    \begin{macrocode}
@@ -386,7 +425,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_setup_latexe:}
+% \begin{macro}{\@@_setup_latexe:}
 %   This saves the catcodes and related parameters, then sets them to
 %   the value they normally have in a \LaTeXe{} package (in particular,
 %   |@| is a letter).
@@ -430,7 +469,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_setup_unravel:}
+% \begin{macro}{\@@_setup_unravel:}
 %   Catcodes for \pkg{unravel} (in particular, |@| is other, |:| and
 %   |_| are letters, spaces are ignored, |~| is a space).
 %    \begin{macrocode}
@@ -488,7 +527,7 @@
 % an error.
 %    \begin{macrocode}
 \RequirePackage{expl3,xparse}[2018/02/21]
-\RequirePackage{gtl}[2018/04/04]
+\RequirePackage{gtl}[2018/12/28]
 \csname cs_if_exist:cF\endcsname{str_range:nnn}{\RequirePackage{l3str}}
 %    \end{macrocode}
 %
@@ -506,7 +545,7 @@
   {%
     \csname @@_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2018/04/04} {0.2e} {Watching TeX digest tokens}%
+      {unravel} {2018/12/28} {0.2f} {Watching TeX digest tokens}%
     \csname @@_setup_unravel:\endcsname
   }%
 %    \end{macrocode}
@@ -526,10 +565,10 @@
 %   code when that is clearer (typically when testing the meaning of
 %   a token against that of a primitive).
 %    \begin{macrocode}
-\cs_new_eq:NN \@@_currentgrouptype:      \etex_currentgrouptype:D
-\cs_new_protected_nopar:Npn \@@_set_escapechar:n
+\cs_new_eq:NN \@@_currentgrouptype:      \tex_currentgrouptype:D
+\cs_new_protected:Npn \@@_set_escapechar:n
   { \int_set:Nn \tex_escapechar:D }
-\cs_new_eq:NN \@@_everyeof:w             \etex_everyeof:D
+\cs_new_eq:NN \@@_everyeof:w             \tex_everyeof:D
 \cs_new_eq:NN \@@_everypar:w             \tex_everypar:D
 \cs_new_eq:NN \@@_hbox:w                 \tex_hbox:D
 \cs_new_eq:NN \@@_mag:                   \tex_mag:D
@@ -539,12 +578,25 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_special_relax:}
+%   A special marker slightly different from \tn{relax} (its
+%   \tn{meaning} is \tn{relax} but it differs from \tn{relax} according
+%   to \tn{ifx}).  In the right-hand side of our assignment,
+%   \cs{@@_special_relax:} could be replaced by any other expandable
+%   command.
+%    \begin{macrocode}
+\exp_after:wN \cs_new_eq:NN
+  \exp_after:wN \@@_special_relax:
+  \exp_not:N \@@_special_relax:
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{\c_@@_prompt_ior, \c_@@_noprompt_ior}
 %   These are not quite primitives, but are very low-level
 %   |ior| streams to prompt the user explicitly or not.
 %    \begin{macrocode}
-\cs_new_eq:NN \c_@@_prompt_ior \c_sixteen
-\cs_new_eq:NN \c_@@_noprompt_ior \c_minus_one
+\int_const:Nn \c_@@_prompt_ior { 16 }
+\int_const:Nn \c_@@_noprompt_ior { -1 }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -555,10 +607,8 @@
 \cs_generate_variant:Nn \seq_push:Nn { Nf }
 \cs_generate_variant:Nn \str_head:n { f }
 \cs_generate_variant:Nn \tl_to_str:n { o }
+\cs_generate_variant:Nn \tl_if_eq:nnTF { o }
 \cs_generate_variant:Nn \tl_if_head_eq_meaning:nNT { V }
-\cs_generate_variant:Nn \tl_if_in:nnF { nV }
-\cs_generate_variant:Nn \tl_if_in:nnTF { nV }
-\cs_generate_variant:Nn \tl_if_in:NnTF { No , NV }
 \cs_generate_variant:Nn \tl_if_single_token:nT { V }
 \cs_generate_variant:Nn \gtl_gput_right:Nn { NV }
 \cs_generate_variant:Nn \ior_str_get:NN { Nc }
@@ -572,6 +622,20 @@
 \cs_generate_variant:Nn \gtl_gclear_new:N { c }
 %    \end{macrocode}
 %
+% \begin{macro}{\@@_tl_if_in:ooTF}
+%   Analogue of \cs{tl_if_in:ooTF} but with an extra group because that
+%   function redefines an auxiliary that may appear in the code being
+%   debugged (see Github issue |#27|).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_tl_if_in:ooTF #1#2#3#4
+  {
+    \group_begin:
+    \exp_args:Noo \tl_if_in:nnTF {#1} {#2}
+      { \group_end: #3 } { \group_end: #4 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{variable}{\l_@@_exp_tl}
 % \begin{macro}{\@@_exp_args:Nx, \@@_exp_args:NNx}
 %   Low-level because \cs{exp_args:Nx} redefines an internal
@@ -597,7 +661,7 @@
 % \begin{macro}{\@@_tmp:w}
 %   Temporary function used to define other functions.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_tmp:w { }
+\cs_new_protected:Npn \@@_tmp:w { }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -626,7 +690,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int, EXP]{\@@_tl_first_int:N}
+% \begin{macro}[EXP]{\@@_tl_first_int:N}
 % \begin{macro}[EXP]{\@@_tl_first_int_aux:Nn}
 %   Function that finds an explicit number in a token list.  This is
 %   used for instance when implementing \tn{read}, to find the stream
@@ -669,10 +733,10 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_prepare_mag:}
+% \begin{macro}{\@@_prepare_mag:}
 %   Used whenever \TeX{} needs the value of \tn{mag}.  ^^A todo: move
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_prepare_mag:
+\cs_new_protected:Npn \@@_prepare_mag:
   {
     \int_compare:nNnT { \g_@@_mag_set_int } > { 0 }
       {
@@ -694,7 +758,7 @@
 %
 % \subsubsection{String helpers}
 %
-% \begin{macro}[int]{\@@_strip_escape:w}
+% \begin{macro}{\@@_strip_escape:w}
 % \begin{macro}{\@@_strip_escape_aux:N, \@@_strip_escape_aux:w}
 %   This is based on the 2013-07-19 (and earlier) version of
 %   \cs{cs_to_str:N}.  There are three cases.  If the escape character
@@ -703,29 +767,29 @@
 %   character is a space, the charcode test is true, and if there is no
 %   escape charcter, the test is unfinished after |\token_to_str:N \ |.
 %   In both of those cases, \cs{@@_strip_escape_aux:w} inserts
-%   |-\@@_number:w \fi: \c_zero|.  If the escape character was a
+%   |-\@@_number:w \fi: \c_zero_int|.  If the escape character was a
 %   space, the test was true, and \cs{int_value:w} converts
-%   \cs{c_zero} to~|0|, hence the leading roman numeral expansion
+%   \cs{c_zero_int} to~|0|, hence the leading roman numeral expansion
 %   removes a space from what follows (it is important that what follows
 %   cannot start with a digit).  Otherwise, the test takes~|-| as its
 %   second operand, is false, and the roman numeral expansion only sees
-%   \cs{c_zero}, thus does not remove anything from what follows.
+%   \cs{c_zero_int}, thus does not remove anything from what follows.
 %    \begin{macrocode}
-\cs_new_nopar:Npn \@@_strip_escape:w
+\cs_new:Npn \@@_strip_escape:w
   {
     \tex_romannumeral:D
       \if_charcode:w \token_to_str:N \ \@@_strip_escape_aux:w \fi:
       \@@_strip_escape_aux:N
   }
-\cs_new:Npn \@@_strip_escape_aux:N #1 { \c_zero }
+\cs_new:Npn \@@_strip_escape_aux:N #1 { \c_zero_int }
 \cs_new:Npn \@@_strip_escape_aux:w #1#2
-  { - \@@_number:w #1 \c_zero }
+  { - \@@_number:w #1 \c_zero_int }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 %
 % ^^A todo: change approach: this abuses future l3obj.
-% \begin{macro}[int,EXP]{\@@_to_str:n}
+% \begin{macro}[EXP]{\@@_to_str:n}
 % \begin{macro}[EXP]
 %   {\@@_to_str_auxi:w, \@@_to_str_auxii:w, \@@_gtl_to_str:n}
 %   Use the type-appropriate conversion to string.
@@ -753,7 +817,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_str_truncate_left:nn}
+% \begin{macro}{\@@_str_truncate_left:nn}
 % \begin{macro}{\@@_str_truncate_left_aux:nnn}
 %   Truncate the string |#1| to a maximum of |#2| characters.  If it is
 %   longer, replace some characters on the left of the string by
@@ -778,7 +842,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_str_truncate_right:nn}
+% \begin{macro}{\@@_str_truncate_right:nn}
 % \begin{macro}{\@@_str_truncate_right_aux:nnn}
 %   Truncate the string |#1| to a maximum of |#2| characters.  If it is
 %   longer, replace some characters on the right of the string by
@@ -805,7 +869,7 @@
 %
 % \subsubsection{Helpers for control flow}
 %
-% \begin{macro}[int,EXP]{\@@_exit:w, \@@_exit_point:}
+% \begin{macro}[EXP]{\@@_exit: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:
@@ -813,7 +877,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int,EXP]{\@@_break:w, \@@_break_point:}
+% \begin{macro}[EXP]{\@@_break:w, \@@_break_point:}
 %   Useful to jump out of complicated conditionals.
 %    \begin{macrocode}
 \cs_new_eq:NN \@@_break_point: \prg_do_nothing:
@@ -821,7 +885,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_cmd_if_internal:TF}
+% \begin{macro}{\@@_cmd_if_internal:TF}
 %   Test whether the \cs{l_@@_head_cmd_int} denotes an ``internal''
 %   command, between |min_internal| and |max_internal| (see
 %   Section~\ref{sec:numeric-codes}).
@@ -844,8 +908,8 @@
 %
 % \subsubsection{Helpers concerning tokens}
 %
-% \begin{macro}[int]{\@@_token_to_char:N}
-% \begin{macro}[int]{\@@_meaning_to_char:n, \@@_meaning_to_char:o}
+% \begin{macro}{\@@_token_to_char:N}
+% \begin{macro}{\@@_meaning_to_char:n, \@@_meaning_to_char:o}
 % \begin{macro}
 %   {\@@_meaning_to_char_auxi:w, \@@_meaning_to_char_auxii:w}
 %   From the meaning of a character token (with arbitrary character
@@ -866,7 +930,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int,EXP,pTF]{\@@_token_if_expandable:N}
+% \begin{macro}[EXP,pTF]{\@@_token_if_expandable:N}
 %   We need to cook up our own version of \cs{token_if_expandable:NTF}
 %   because the \pkg{expl3} one does not think that |undefined| is
 %   expandable.
@@ -883,7 +947,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int,EXP,pTF]{\@@_token_if_protected:N}
+% \begin{macro}[EXP,pTF]{\@@_token_if_protected:N}
 %   Returns \texttt{true} if the token is either not expandable or is a
 %   protected macro.
 %    \begin{macrocode}
@@ -905,24 +969,41 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int,TF]{\@@_token_if_definable:N}
+% \begin{macro}[TF]{\@@_token_if_active_char:N}
+%   Lowercase the token after setting its \tn{lccode} (more precisely
+%   the \tn{lccode} of the first character in its string representation)
+%   to a known value, then compare the result with that active
+%   character.
+%    \begin{macrocode}
+\group_begin:
+  \char_set_catcode_active:n { `Z }
+  \prg_new_protected_conditional:Npnn \@@_token_if_active_char:N #1
+    { TF }
+    {
+      \group_begin:
+        \@@_exp_args:Nx \char_set_lccode:nn
+          { ` \exp_args:No \str_head:n { \token_to_str:N #1 } }
+          { ` Z }
+        \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { Z }
+          { \group_end: \prg_return_true: }
+          { \group_end: \prg_return_false: }
+    }
+\group_end:
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[TF]{\@@_token_if_definable:N}
 %   Within a group, set the escape character to a non-space value
 %   (backslash).  Convert the token to a string with
-%   \cs{token_to_str:N}.  The result is multiple characters if the
-%   token is a control sequence, and a single character otherwise (even
-%   for explicit catcode~$6$ character tokens which would be doubled if
-%   we used \cs{tl_to_str:n} instead of \cs{token_to_str:N}).  Thus
+%   \cs{token_to_str:N}.  The result is multiple characters if the token
+%   is a control sequence, and a single character otherwise (even for
+%   explicit catcode~$6$ character tokens which would be doubled if we
+%   used \cs{tl_to_str:n} instead of \cs{token_to_str:N}).  Thus
 %   \cs{str_tail:n} gives a non-empty result exactly for control
 %   sequences.  Those are definable (technically, not always:
 %   |\expandafter\font\csname\endcsname=cmr10|
-%   |\expandafter\def\the\csname\endcsname{}|).  For characters, there
-%   remains to determine if |#1| is an active character.  One option
-%   would be to build the active character with that character code and
-%   compare them using a delimited-argument test, but that needlessly
-%   pollutes the hash table in \XeTeX{} (and \LuaTeX{}?) if the
-%   character was in fact not active.  Instead, use the \tn{lowercase}
-%   primitive to convert the character to a fixed character code~|Z|.
-%   Compare with an active~|Z|.  In all cases, remember to end the
+%   |\expandafter\def\the\csname\endcsname{}|).  For characters just
+%   check for active characters.  In both cases remember to end the
 %   group.
 %    \begin{macrocode}
 \group_begin:
@@ -936,9 +1017,7 @@
           { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
         \tl_if_empty:NTF \l_@@_tmpa_tl
           {
-            \exp_args:Nx \char_set_lccode:nn
-              { ` \str_head:n {#1} } { `Z }
-            \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { Z }
+            \@@_token_if_active_char:NTF #1
               { \group_end: \prg_return_true: }
               { \group_end: \prg_return_false: }
           }
@@ -948,7 +1027,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int,TF]{\@@_gtl_if_head_is_definable:N}
+% \begin{macro}[TF]{\@@_gtl_if_head_is_definable:N}
 %   Tests if a generalized token list is a single control sequence or a
 %   single active character.  First test that it is single, then filter
 %   out the case of (explicit) begin-group, end-group, and blank space
@@ -977,7 +1056,7 @@
 %
 % \begin{macro}[EXP]{\@@_prev_input_count:, \@@_prev_input_count_aux:n}
 %    \begin{macrocode}
-\cs_new_nopar:Npn \@@_prev_input_count:
+\cs_new:Npn \@@_prev_input_count:
   {
     \int_eval:n
       {
@@ -1003,30 +1082,30 @@
 %   }
 % ^^A todo: doc and add optional sanity checking
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_prev_input_get:N
+\cs_new_protected:Npn \@@_prev_input_get:N
   { \seq_get_right:NN \g_@@_prev_input_seq }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpush:
+\cs_new_protected:Npn \@@_prev_input_gpush:
   { \seq_gput_right:Nn \g_@@_prev_input_seq { } }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpush:N
+\cs_new_protected:Npn \@@_prev_input_gpush:N
   { \seq_gput_right:NV \g_@@_prev_input_seq }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpop:N
+\cs_new_protected:Npn \@@_prev_input_gpop:N
   { \seq_gpop_right:NN \g_@@_prev_input_seq }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpush_gtl:
+\cs_new_protected:Npn \@@_prev_input_gpush_gtl:
   { \seq_gput_right:NV \g_@@_prev_input_seq \c_empty_gtl }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpush_gtl:N
+\cs_new_protected:Npn \@@_prev_input_gpush_gtl:N
   { \seq_gput_right:NV \g_@@_prev_input_seq }
-\cs_new_protected_nopar:Npn \@@_prev_input_gpop_gtl:N
+\cs_new_protected:Npn \@@_prev_input_gpop_gtl:N
   { \seq_gpop_right:NN \g_@@_prev_input_seq }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]
+% \begin{macro}
 %   {
 %     \@@_prev_input_silent:n,
 %     \@@_prev_input_silent:V,
 %     \@@_prev_input_silent:x
 %   }
-% \begin{macro}[int]
+% \begin{macro}
 %   {
 %     \@@_prev_input:n,
 %     \@@_prev_input:V,
@@ -1054,7 +1133,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_prev_input_gtl:N}
+% \begin{macro}{\@@_prev_input_gtl:N}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_prev_input_gtl:N #1
   {
@@ -1065,7 +1144,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_prev_input_join_get:nN}
+% \begin{macro}{\@@_prev_input_join_get:nN}
 % \begin{macro}{\@@_join_get_aux:NNN}
 %   Pops the previous-input sequence twice to get some value in
 %   \cs{l_@@_head_tl} and some sign or decimal number in
@@ -1077,8 +1156,8 @@
   {
     \int_case:nnF {#1}
       {
-        { 2 } { \@@_join_get_aux:NNN \skip_eval:n \etex_glueexpr:D }
-        { 3 } { \@@_join_get_aux:NNN \muskip_eval:n \etex_muexpr:D }
+        { 2 } { \@@_join_get_aux:NNN \skip_eval:n \tex_glueexpr:D }
+        { 3 } { \@@_join_get_aux:NNN \muskip_eval:n \tex_muexpr:D }
       }
       {
         \@@_error:nnnnn { internal } { join-factor } { } { } { }
@@ -1113,12 +1192,10 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}{\g_@@_nonstop_int, \g_@@_noise_int}
+% \begin{variable}{\g_@@_nonstop_int}
 %   The number of prompts to skip.
 %    \begin{macrocode}
 \int_new:N \g_@@_nonstop_int
-\int_new:N \g_@@_noise_int
-\int_gset_eq:NN \g_@@_noise_int \c_one
 %    \end{macrocode}
 % \end{variable}
 %
@@ -1127,11 +1204,15 @@
 %     \g_@@_default_explicit_prompt_bool , \g_@@_explicit_prompt_bool ,
 %     \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_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     ,
 %     \g_@@_default_welcome_message_bool , \g_@@_welcome_message_bool ,
 %   }
 %   Variables for the options |explicit-prompt|,
-%   |internal-debug|, |number-steps|.  The
-%   \texttt{default_} booleans store the default value of these
+%   |internal-debug|, |number-steps|, and so on.  The
+%   \texttt{default_} booleans/integers store the default value of these
 %   options, and are affected by \cs{unravelsetup} or
 %   \cs{unravel_setup:n}.
 %    \begin{macrocode}
@@ -1138,12 +1219,24 @@
 \bool_new:N \g_@@_default_explicit_prompt_bool
 \bool_new:N \g_@@_default_internal_debug_bool
 \bool_new:N \g_@@_default_number_steps_bool
+\int_new:N  \g_@@_default_online_int
+\bool_new:N \g_@@_default_trace_assigns_bool
+\bool_new:N \g_@@_default_trace_expansion_bool
+\bool_new:N \g_@@_default_trace_other_bool
+\bool_new:N \g_@@_default_welcome_message_bool
 \bool_gset_true:N \g_@@_default_number_steps_bool
-\bool_new:N \g_@@_default_welcome_message_bool
+\int_gset:Nn   \g_@@_default_online_int { 1 }
+\bool_gset_true:N \g_@@_default_trace_assigns_bool
+\bool_gset_true:N \g_@@_default_trace_expansion_bool
+\bool_gset_true:N \g_@@_default_trace_other_bool
 \bool_gset_true:N \g_@@_default_welcome_message_bool
 \bool_new:N \g_@@_explicit_prompt_bool
 \bool_new:N \g_@@_internal_debug_bool
 \bool_new:N \g_@@_number_steps_bool
+\int_new:N  \g_@@_online_int
+\bool_new:N \g_@@_trace_assigns_bool
+\bool_new:N \g_@@_trace_expansion_bool
+\bool_new:N \g_@@_trace_other_bool
 \bool_new:N \g_@@_welcome_message_bool
 %    \end{macrocode}
 % \end{variable}
@@ -1278,8 +1371,15 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{variable}
-%   {\l_@@_tmpa_tl, \l_@@_tmpb_gtl, \g_@@_tmpc_tl, \l_@@_tmpa_seq, \l_@@_unused_gtl}
+% \begin{variable}{\l_@@_argi_tl, \l_@@_argii_tl}
+%   Token list variables used to store first/second arguments.
+%    \begin{macrocode}
+\tl_new:N \l_@@_argi_tl
+\tl_new:N \l_@@_argii_tl
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{variable}{\l_@@_tmpa_tl, \l_@@_tmpb_gtl, \g_@@_tmpc_tl, \l_@@_tmpa_seq, \l_@@_unused_gtl, \l_@@_tmpb_token}
 %   Temporary storage.  The \cs{l_@@_unused_gtl} is only used once,
 %   to ignore some unwanted tokens.
 %    \begin{macrocode}
@@ -1288,6 +1388,7 @@
 \gtl_new:N \l_@@_tmpb_gtl
 \tl_new:N \g_@@_tmpc_tl
 \seq_new:N \l_@@_tmpa_seq
+\cs_new_eq:NN \l_@@_tmpb_token ?
 %    \end{macrocode}
 % \end{variable}
 %
@@ -1306,7 +1407,7 @@
 %    \end{macrocode}
 % \end{variable}
 %
-% \begin{macro}[int]{\@@_inaccessible:w}
+% \begin{macro}{\@@_inaccessible:w}
 %    \begin{macrocode}
 \cs_new_eq:NN \@@_inaccessible:w ?
 %    \end{macrocode}
@@ -1458,8 +1559,8 @@
 % and a character code, to decide what action to perform upon seeing
 % them.
 %
-% \begin{macro}[int]{\@@_tex_const:nn}
-% \begin{macro}[int,EXP]{\@@_tex_use:n}
+% \begin{macro}{\@@_tex_const:nn}
+% \begin{macro}[EXP]{\@@_tex_use:n}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_tex_const:nn #1#2
   { \int_const:cn { c_@@_tex_#1_int } {#2} }
@@ -1468,7 +1569,7 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_tex_primitive:nnn}
+% \begin{macro}{\@@_tex_primitive:nnn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_tex_primitive:nnn #1#2#3
   {
@@ -1478,11 +1579,11 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_new_tex_cmd:nn, \@@_new_eq_tex_cmd:nn}
+% \begin{macro}{\@@_new_tex_cmd:nn, \@@_new_eq_tex_cmd:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_new_tex_cmd:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { @@_cmd_ \@@_tex_use:n {#1} : } {#2}
   }
 \cs_new_protected:Npn \@@_new_eq_tex_cmd:nn #1#2
@@ -1494,11 +1595,11 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_new_tex_expandable:nn}
+% \begin{macro}{\@@_new_tex_expandable:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_new_tex_expandable:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { @@_expandable_ \@@_tex_use:n {#1} : } {#2}
   }
 %    \end{macrocode}
@@ -1644,7 +1745,17 @@
 % \item |def_code| and |def_family| is shifted by |cat_code_base=3983|.
 % \item In \TeX{}, |inputlineno.char=3| and |badness.char=4|.
 % \end{itemize}
+% A special case for \LuaTeX{} deals with the fact that the
+% \cs{@@_special_relax:} has a strange meaning \enquote{[unknown command
+% code! (0, 1)]}.  For instance \tn{expandafter} \tn{show} \tn{noexpand}
+% \tn{undefined} shows this.
 %    \begin{macrocode}
+\sys_if_engine_luatex:T
+  {
+    \@@_tex_primitive:nnn
+      { \exp_after:wN \use_none:n \token_to_meaning:N \@@_special_relax: }
+      { relax } { 1 }
+  }
 \@@_tex_primitive:nnn { relax             } { relax    } { 256 }
 \@@_tex_primitive:nnn { span              } { tab_mark } { 256 }
 \@@_tex_primitive:nnn { cr                } { car_ret  } { 257 }
@@ -2153,7 +2264,8 @@
 \@@_tex_primitive:nnn { pdfescapename     } { convert } { 14 }
 \@@_tex_primitive:nnn { leftmarginkern    } { convert } { 15 }
 \@@_tex_primitive:nnn { rightmarginkern   } { convert } { 16 }
-\@@_tex_primitive:nnn { pdfstrcmp         } { convert } { 17 }
+\@@_tex_primitive:nnn
+  { \sys_if_engine_xetex:F { pdf } strcmp } { convert } { 17 }
 \@@_tex_primitive:nnn { pdfcolorstackinit } { convert } { 18 }
 \@@_tex_primitive:nnn { pdfescapehex      } { convert } { 19 }
 \@@_tex_primitive:nnn { pdfunescapehex    } { convert } { 20 }
@@ -2169,6 +2281,16 @@
 \@@_tex_primitive:nnn { pdfinsertht       } { convert } { 30 }
 \@@_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 }
+  }
+\sys_if_engine_xetex:T
+  {
+    \@@_tex_primitive:nnn { Ucharcat        } { convert } { 40 }
+  }
 \@@_tex_primitive:nnn { the               } { the } { 0 }
 \@@_tex_primitive:nnn { unexpanded        } { the } { 1 }
 \@@_tex_primitive:nnn { detokenize        } { the } { 5 }
@@ -2198,7 +2320,7 @@
 % \cs{l_@@_head_cmd_int} and \cs{l_@@_head_char_int} from
 % \cs{l_@@_head_token}.
 %
-% \begin{macro}[int]{\@@_get_next:}
+% \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
@@ -2207,7 +2329,7 @@
 %   unless it is a begin-group or end-group character, in which case
 %   this token list is emptied.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_next:
+\cs_new_protected:Npn \@@_get_next:
   {
     \@@_input_if_empty:TF
       { \@@_exit:w }
@@ -2218,22 +2340,113 @@
           {
             \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_nopar:Npn \@@_get_next_aux:w
+\cs_new_protected:Npn \@@_get_next_aux:w
   { \cs_set_eq:NN \l_@@_head_token }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_get_token:}
+% \begin{macro}{\@@_get_next_notexpanded:}
+% \begin{macro}{\@@_notexpanded_test:w, \@@_notexpanded_expand:nN, \@@_notexpanded_expand:NN}
+%   At this point we have likely encountered a special \tn{relax} marker
+%   that we use to mark cases where \tn{noexpand} acts on a control
+%   sequence or an active character.  To make sure of that check the
+%   control sequence has the form \cs{notexpanded:\ldots{}}.  Since we
+%   don't know the escape character we must use \cs{cs_to_str:N}, but
+%   that function is not meant for active characters and has a runaway
+%   argument if its argument is a space (active since we know its
+%   meaning is the special \tn{relax}).  To avoid the runaway we include
+%   an arbitrary delimiter~|Z|.  If the token in \cs{l_@@_head_tl} is
+%   not \cs{notexpanded:\ldots{}} we do nothing.  Otherwise
+%   \cs{@@_notexpanded_expand:n} reconstructs the token that was hit
+%   with \tn{noexpand} (an active character if the argument is a single
+%   character) and do the job of \cs{@@_get_next:}, setting
+%   \cs{l_@@_head_token} to the special \tn{relax} marker for expandable
+%   commands, as \tn{noexpand} would.
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1
+  {
+    \cs_new_protected:Npn \@@_get_next_notexpanded:
+      {
+        \tl_if_eq:onTF { \l_@@_head_tl } { \@@_unravel_marker: }
+          { \@@_get_next_marker: }
+          {
+            \@@_exp_args:NNx \use:nn \@@_notexpanded_test:w
+              { \scan_stop: \exp_after:wN \cs_to_str:N \l_@@_head_tl Z }
+              \q_mark \@@_notexpanded_expand:n
+              #1 Z \q_mark \use_none:n
+              \q_stop
+          }
+      }
+    \cs_new_protected:Npn \@@_notexpanded_test:w
+        ##1 #1 ##2 Z \q_mark ##3##4 \q_stop
+      { ##3 {##2} }
+  }
+\exp_args:Nx \@@_tmp:w { \scan_stop: \tl_to_str:n { notexpanded: } }
+\group_begin:
+  \char_set_catcode_active:n { 0 }
+  \cs_new_protected:Npn \@@_notexpanded_expand:n #1
+    {
+      \@@_exp_args:Nx \tl_if_empty:nTF { \str_tail:n {#1} }
+        {
+          \group_begin:
+          \char_set_lccode:nn { 0 } { `#1 }
+          \tex_lowercase:D
+            {
+              \group_end:
+              \@@_notexpanded_expand:N ^^@
+            }
+        }
+        {
+          \group_begin: \exp_args:NNc \group_end:
+          \@@_notexpanded_expand:N { \use_none:n #1 }
+        }
+    }
+\group_end:
+\cs_new_protected:Npn \@@_notexpanded_expand:N #1
+  {
+    \gtl_set:Nn \l_@@_head_gtl {#1}
+    \tl_set:Nn \l_@@_head_tl {#1}
+    \cs_set_eq:NN \l_@@_head_token \@@_special_relax:
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_next_marker:}
+%   This is used to deal with nested unravel.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_get_next_marker:
+  {
+    \@@_get_next:
+    \tl_if_eq:onTF \l_@@_head_tl { \@@:nn }
+      { \@@_error:nxxxx { nested-unravel } { } { } { } { } }
+      { \@@_error:nxxxx { internal } { marker~unknown } { } { } { } }
+    \@@_input_gpop_item:NF \l_@@_argi_tl
+      { \@@_error:nxxxx { internal } { marker~1 } { } { } { } }
+    \@@_input_gpop_item:NF \l_@@_argii_tl
+      { \@@_error:nxxxx { internal } { marker~2 } { } { } { } }
+    \exp_args:Nno \keys_set:nn { unravel } \l_@@_argi_tl
+    \@@_exp_args:Nx \@@_back_input:n
+      { \exp_not:N \exp_not:n { \exp_not:o \l_@@_argii_tl } }
+    \@@_get_next:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_get_token:}
 %   Call \cs{@@_get_next:} to set \cs{l_@@_head_gtl}, \cs{l_@@_head_tl}
 %   and \cs{l_@@_head_token}, then call \cs{@@_set_cmd:} to set
 %   \cs{l_@@_head_cmd_int} and \cs{l_@@_head_char_int}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_token:
+\cs_new_protected:Npn \@@_get_token:
   {
     \@@_get_next:
     \@@_set_cmd:
@@ -2241,7 +2454,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_set_cmd:}
+% \begin{macro}{\@@_set_cmd:}
 %   After the call to \cs{@@_get_next:}, we find the command code
 %   \cs{l_@@_head_cmd_int} and the character code
 %   \cs{l_@@_head_char_int}, based only on \cs{l_@@_head_token}.  First
@@ -2252,7 +2465,7 @@
 %   (\emph{e.g.}, an expandable \XeTeX{} or \LuaTeX{} primitive
 %   perhaps).  Otherwise, it can be a control sequence or a character.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd:
+\cs_new_protected:Npn \@@_set_cmd:
   {
     \@@_set_cmd_aux_meaning:
     \@@_set_cmd_aux_primitive:oTF { \l_@@_head_meaning_tl }
@@ -2282,7 +2495,7 @@
 %   for macros, for marks, and for that character too.  For any
 %   primitive except \tn{nullfont}, this leaves the primitive's name.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_meaning:
+\cs_new_protected:Npn \@@_set_cmd_aux_meaning:
   {
     \tl_set:Nx \l_@@_head_meaning_tl
       {
@@ -2335,7 +2548,7 @@
 %   The token is a macro.  There is no need to determine whether the
 %   macro is long/outer.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_macro:
+\cs_new_protected:Npn \@@_set_cmd_aux_macro:
   {
     \int_set:Nn \l_@@_head_cmd_int { \@@_tex_use:n { call } }
     \int_zero:N \l_@@_head_char_int
@@ -2347,7 +2560,7 @@
 %   Complain about an unknown primitive, and consider it as if it were
 %   \tn{relax}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_unknown:
+\cs_new_protected:Npn \@@_set_cmd_aux_unknown:
   {
     \exp_last_unbraced:NV \@@_set_cmd_aux_primitive:nn
       \c_@@_tex_relax_tl
@@ -2367,9 +2580,9 @@
 %   \tn{dimen}, \tn{skip}, \tn{muskip} or \tn{toks} followed by a
 %   decimal number.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_cs:
+\cs_new_protected:Npn \@@_set_cmd_aux_cs:
   {
-    \tl_if_in:NoTF \l_@@_head_meaning_tl
+    \@@_tl_if_in:ooTF \l_@@_head_meaning_tl
       { \tl_to_str:n { elect~font } }
       {
         \exp_last_unbraced:NV \@@_set_cmd_aux_primitive:nn
@@ -2390,8 +2603,9 @@
 %   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 one of |count|, |dimen|,
-%   |skip|, |muskip|, or |toks|.  In the first two cases, the command is
+%   first part to be |char| or~|mathchar| (or |kchar| in up\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
 %   corresponding primitive (\tn{count} \emph{etc.}).  We then keep
 %   track of the associated number (part after \cs{q_mark}) in
@@ -2400,7 +2614,7 @@
 %   \cs{q_mark} is inserted at their end, and is followed by~|+0|, so
 %   nothing breaks.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_numeric:
+\cs_new_protected:Npn \@@_set_cmd_aux_numeric:
   {
     \tl_set:Nx \l_@@_tmpa_tl
       {
@@ -2423,6 +2637,7 @@
     \str_case:nnF {#1}
       {
         { char }     { \@@_set_cmd_aux_given:n { char_given } }
+        { kchar }    { \@@_set_cmd_aux_given:n { char_given } }
         { mathchar } { \@@_set_cmd_aux_given:n { math_given } }
       }
       {
@@ -2452,7 +2667,7 @@
 %   the character code, there is a need to expand
 %   \cs{@@_token_to_char:N} before placing~|`|.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_cmd_aux_char:
+\cs_new_protected:Npn \@@_set_cmd_aux_char:
   {
     \tl_set:Nx \l_@@_head_meaning_tl
       { \token_to_meaning:N \l_@@_head_token }
@@ -2476,10 +2691,10 @@
 %
 % \subsubsection{Elementary operations}
 %
-% \begin{macro}[int,rEXP]{\@@_input_to_str:}
+% \begin{macro}[rEXP]{\@@_input_to_str:}
 %   Map \cs{gtl_to_str:c} through the input stack.
 %    \begin{macrocode}
-\cs_new_nopar:Npn \@@_input_to_str:
+\cs_new:Npn \@@_input_to_str:
   {
     \int_step_function:nnnN \g_@@_input_int { -1 } { 1 }
       \@@_input_to_str_aux:n
@@ -2489,7 +2704,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_input_if_empty:TF}
+% \begin{macro}{\@@_input_if_empty:TF}
 %   If the input stack is empty, the input contains no token.
 %   Otherwise, check the top of the stack for tokens: if there are, then
 %   the input is non-empty, and if there are none, then we get rid of
@@ -2497,7 +2712,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_input_if_empty:TF
   {
-    \int_compare:nNnTF \g_@@_input_int = \c_zero
+    \int_compare:nNnTF \g_@@_input_int = 0
       { \use_i:nn }
       {
         \gtl_if_empty:cTF
@@ -2517,14 +2732,14 @@
 %
 % ^^A todo: profiling to know if \@@_input_split: is beneficial.
 %
-% \begin{macro}[int]{\@@_input_split:}
+% \begin{macro}{\@@_input_split:}
 %   If the input is completely flat, and is a token list starting with
 %   an |N|-type token, try to unflatten it by splitting at each
 %   occurence of that first character
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_input_split:
+\cs_new_protected:Npn \@@_input_split:
   {
-    \int_compare:nNnT \g_@@_input_int = \c_one
+    \int_compare:nNnT \g_@@_input_int = 1
       {
         \exp_args:Nc \@@_input_split_aux:N
           { g_@@_input_1_gtl }
@@ -2559,7 +2774,7 @@
         \l_@@_input_tmpa_tl \@@_input_split_end:
       }
   }
-\cs_new_nopar:Npn \@@_input_split_end: { }
+\cs_new:Npn \@@_input_split_end: { }
 \cs_new_protected:Npn \@@_input_split_auxiii:w
     #1 \@@_input_split_end:
   {
@@ -2572,10 +2787,10 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_input_gset:n}
+% \begin{macro}{\@@_input_gset:n}
 %   At first, all of the input is in the same~\texttt{gtl}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_input_gset:n
+\cs_new_protected:Npn \@@_input_gset:n
   {
     \int_gzero:N \g_@@_input_int
     \@@_back_input:n
@@ -2583,7 +2798,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_input_get:N}
+% \begin{macro}{\@@_input_get:N}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_input_get:N #1
   {
@@ -2597,7 +2812,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_input_gpop:N}
+% \begin{macro}{\@@_input_gpop:N}
 %   Call \cs{@@_input_if_empty:TF} to remove empty levels from the input
 %   stack, then extract the first token from the left-most non-empty
 %   level.
@@ -2618,7 +2833,7 @@
 %   Merge the top two levels of input.  This requires, but does not
 %   check, that \cs{g_@@_input_int} is at least~$2$.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_input_merge:
+\cs_new_protected:Npn \@@_input_merge:
   {
     \int_gdecr:N \g_@@_input_int
     \gtl_gconcat:ccc
@@ -2631,7 +2846,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int,TF]{\@@_input_gpop_item:N}
+% \begin{macro}[TF]{\@@_input_gpop_item:N}
 % \begin{macro}{\@@_input_gpop_item_aux:NN}
 %   If there is no input, we cannot pop an item.  Othewise, try to pop
 %   from the top of the input stack.  If this succeeds, or if this
@@ -2642,7 +2857,7 @@
 %    \begin{macrocode}
 \prg_new_protected_conditional:Npnn \@@_input_gpop_item:N #1 { F }
   {
-    \int_compare:nNnTF \g_@@_input_int = \c_zero
+    \int_compare:nNnTF \g_@@_input_int = 0
       { \prg_return_false: }
       {
         \exp_args:Nc \@@_input_gpop_item_aux:NN
@@ -2654,10 +2869,10 @@
     \gtl_gpop_left_item:NNTF #1#2
       { \prg_return_true: }
       {
-        \int_compare:nNnTF { \gtl_extra_end:N #1 } > \c_zero
+        \int_compare:nNnTF { \gtl_extra_end:N #1 } > 0
           { \prg_return_false: }
           {
-            \int_compare:nNnTF \g_@@_input_int = \c_one
+            \int_compare:nNnTF \g_@@_input_int = 1
               { \prg_return_false: }
               {
                 \@@_input_merge:
@@ -2675,13 +2890,13 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_input_gpop_tl:N}
+% \begin{macro}{\@@_input_gpop_tl:N}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_input_gpop_tl:N #1
   { \tl_clear:N #1 \@@_input_gpop_tl_aux:N #1 }
 \cs_new_protected:Npn \@@_input_gpop_tl_aux:N #1
   {
-    \int_compare:nNnF \g_@@_input_int = \c_zero
+    \int_compare:nNnF \g_@@_input_int = 0
       {
         \exp_args:Nc \@@_input_gpop_tl_aux:NN
           { g_@@_input_ \int_use:N \g_@@_input_int _gtl } #1
@@ -2697,8 +2912,8 @@
         \@@_input_gpop_tl_aux:N #2
       }
       {
-        \int_compare:nNnTF \g_@@_input_int > \c_one
-          { \int_compare:nNnTF { \gtl_extra_end:N #1 } > \c_zero }
+        \int_compare:nNnTF \g_@@_input_int > 1
+          { \int_compare:nNnTF { \gtl_extra_end:N #1 } > 0 }
           { \use_i:nn }
           {
             \tl_put_right:Nx #2 { \gtl_left_tl:N #1 }
@@ -2713,12 +2928,12 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_back_input:n, \@@_back_input:x}
+% \begin{macro}{\@@_back_input:n, \@@_back_input:x}
 %   Insert a token list back into the input.  Use \cs{gtl_gclear_new:c}
 %   to define the gtl variable if necessary: this happens whenever a
 %   new largest value of \cs{g_@@_input_int} is reached.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_back_input:n
+\cs_new_protected:Npn \@@_back_input:n
   {
     \int_gincr:N \g_@@_input_int
     \gtl_gclear_new:c { g_@@_input_ \int_use:N \g_@@_input_int _gtl }
@@ -2730,7 +2945,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_back_input_gtl:N}
+% \begin{macro}{\@@_back_input_gtl:N}
 %   Insert a generalized token list back into the input.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_back_input_gtl:N #1
@@ -2747,25 +2962,25 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_back_input:}
+% \begin{macro}{\@@_back_input:}
 %   Insert the last token read back into the input stream.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_back_input:
+\cs_new_protected:Npn \@@_back_input:
   { \@@_back_input_gtl:N \l_@@_head_gtl }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_back_input_tl_o:}
+% \begin{macro}{\@@_back_input_tl_o:}
 %   Insert the \cs{l_@@_head_tl} (may or may not be the last token read)
 %   back into the input stream, after expanding it once.  Then print
 %   some diagnostic information.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_back_input_tl_o:
+\cs_new_protected:Npn \@@_back_input_tl_o:
   {
     \tl_set:Nx \l_@@_tmpa_tl
       { \exp_args:NV \exp_not:o \l_@@_head_tl }
     \@@_back_input:V \l_@@_tmpa_tl
-    \@@_print_done:x
+    \@@_print_expansion:x
       { \tl_to_str:N \l_@@_head_tl = \tl_to_str:N \l_@@_tmpa_tl }
   }
 %    \end{macrocode}
@@ -2773,13 +2988,13 @@
 %
 % \subsubsection{Insert token for error recovery}
 %
-% \begin{macro}[int]{\@@_insert_relax:}
+% \begin{macro}{\@@_insert_relax:}
 %   This function inserts \TeX{}'s |frozen_relax|.  It is called when a
 %   conditional is not done finding its condition, but hits the
 %   corresponding \tn{fi} or \tn{or} or \tn{else}, or when \tn{input}
 %   appears while \cs{g_@@_name_in_progress_bool} is \texttt{true}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_insert_relax:
+\cs_new_protected:Npn \@@_insert_relax:
   {
     \@@_back_input:
     \gtl_set_eq:NN \l_@@_head_gtl \c_@@_frozen_relax_gtl
@@ -2789,9 +3004,9 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_insert_group_begin_error:}
+% \begin{macro}{\@@_insert_group_begin_error:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_insert_group_begin_error:
+\cs_new_protected:Npn \@@_insert_group_begin_error:
   {
     \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_head_tl
     \@@_back_input:
@@ -2803,9 +3018,9 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_insert_dollar_error:}
+% \begin{macro}{\@@_insert_dollar_error:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_insert_dollar_error:
+\cs_new_protected:Npn \@@_insert_dollar_error:
   {
     \@@_back_input:
     \@@_back_input:n { $ } % $
@@ -2848,7 +3063,7 @@
 % \end{macro}
 %
 % ^^A todo: redoc
-% \begin{macro}[int]{\@@_macro_call:}
+% \begin{macro}{\@@_macro_call:}
 % \begin{macro}
 %   {
 %     \@@_macro_call_safe:,
@@ -2862,25 +3077,25 @@
 %   extracting the longest balanced prefix in the input and working with
 %   that.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_macro_call:
+\cs_new_protected:Npn \@@_macro_call:
   {
     \bool_if:NTF \g_@@_speedup_macros_bool
       {
         \tl_set:Nx \l_@@_tmpa_tl
           {^ \exp_after:wN \@@_macro_parameter:N \l_@@_head_tl }
-        \tl_if_in:NVTF \c_@@_parameters_tl \l_@@_tmpa_tl
+        \@@_tl_if_in:ooTF \c_@@_parameters_tl \l_@@_tmpa_tl
           { \@@_macro_call_quick: } { \@@_macro_call_safe: }
       }
       { \@@_macro_call_safe: }
     \exp_args:NV \@@_back_input:o \l_@@_head_tl
-    \@@_print_done:x { \g_@@_action_text_str }
+    \@@_print_expansion:
   }
-\cs_new_protected_nopar:Npn \@@_macro_call_safe:
+\cs_new_protected:Npn \@@_macro_call_safe:
   {
     \@@_input_gpop_tl:N \l_@@_tmpa_tl
     \tl_put_right:NV \l_@@_head_tl \l_@@_tmpa_tl
   }
-\cs_new_protected_nopar:Npn \@@_macro_call_quick:
+\cs_new_protected:Npn \@@_macro_call_quick:
   {
     \exp_after:wN \@@_macro_call_quick_loop:NNN \l_@@_tmpa_tl
       { ? \use_none_delimit_by_q_stop:w } \q_stop
@@ -2906,13 +3121,28 @@
 %
 % \subsection{Expand next token}
 %
-% \begin{macro}[int]{\@@_expand:}
-%   This is similar to \cs{@@_do_step:}, but operates on expandable
-%   tokens rather than (non-expandable) commands.  We mimick \TeX{}'s
-%   structure, distinguishing macros from other commands (not quite sure
-%   why).
+% \begin{macro}{\@@_expand_do:N}
+%   The argument is a command that will almost always be run to continue
+%   a loop whose aim is to find the next non-expandable token, for
+%   various purposes.  The only case where we will end up grabbing the
+%   argument is to suppress the loop by \cs{@@_noexpand:N}.
+%   \begin{itemize}
+%   \item \cs{@@_get_x_next:} when \TeX{} is looking for the first
+%     non-expandable token in the main loop or when looking for numbers,
+%     optional spaces etc.
+%   \item \cs{@@_get_x_or_protected:} at the start of an alignment cell.
+%   \item \cs{@@_get_token_xdef:} in the replacement text of \tn{edef}
+%     and \tn{xdef}.
+%   \item \cs{@@_get_token_x:} in the argument of \tn{message} and the
+%     like.
+%   \item \cs{prg_do_nothing:} in \cs{@@_expandafter:} namely after
+%     \tn{expandafter}.
+%   \end{itemize}
+%   We mimick \TeX{}'s structure, distinguishing macros from other
+%   commands because we find macro arguments very differently from
+%   primitives.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_expand:
+\cs_new_protected:Npn \@@_expand_do:N
   {
     \@@_set_action_text:
     \bool_if:NT \g_@@_internal_debug_bool
@@ -2927,15 +3157,16 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_expand_nonmacro:}
+% \begin{macro}{\@@_expand_nonmacro:}
 %   The token is a primitive.  We find its (cleaned-up) \tn{meaning},
 %   and call the function implementing that expansion.  If we do not
-%   recognize the meaning then it is probably an unknown primitive.  If
-%   we recognize the meaning but there is no corresponding function,
-%   then we probably have not implemented it yet, so dump it in the
-%   output as is.
+%   recognize the meaning then it is probably an unknown primitive.
+%   Then do something similar to what we do for macros: get all tokens
+%   that are not too unlikely to appear in the arguments of the
+%   primitive and expand the resulting token list once before putting it
+%   back into the input stream.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_expand_nonmacro:
+\cs_new_protected:Npn \@@_expand_nonmacro:
   {
     \@@_set_cmd_aux_meaning:
     \@@_set_cmd_aux_primitive:oTF { \l_@@_head_meaning_tl }
@@ -2947,46 +3178,69 @@
       {
         \@@_error:nxxxx { unknown-primitive }
           { \l_@@_head_meaning_tl } { } { } { }
-        \gtl_gput_right:NV \g_@@_output_gtl \l_@@_head_tl
-        \@@_print_action:
+        \@@_input_gpop_tl:N \l_@@_tmpa_tl
+        \tl_put_right:NV \l_@@_head_tl \l_@@_tmpa_tl
+        \exp_args:NV \@@_back_input:o \l_@@_head_tl
+        \@@_print_expansion:
       }
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_get_x_next:}
+% \begin{macro}{\@@_get_x_next:}
 %   Get a token.  If it is expandable, then expand it, and repeat.  This
-%   function does not set the |cmd| and |char| integers.
+%   function does not set the |cmd| and |char| integers.  It is the
+%   basis of all routines that look for keywords, numbers, equal signs,
+%   filenames, optional spaces etc (in the language of \LaTeX3 these are
+%   situations where \TeX{} \enquote{\texttt{f}-expands}).  It is also
+%   the basis of the \cs{@@_main_loop:}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_x_next:
+\cs_new_protected:Npn \@@_get_x_next:
   {
     \@@_get_next:
     \@@_token_if_expandable:NT \l_@@_head_token
-      {
-        \@@_expand:
-        \@@_get_x_next:
-      }
+      { \@@_expand_do:N \@@_get_x_next: }
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_get_x_or_protected:}
+% \begin{macro}{\@@_get_x_or_protected:}
 %   Get a token.  If it is expandable, but not protected, then expand
 %   it, and repeat.  This function does not set the |cmd| and |char|
-%   integers.
+%   integers.  This function is not used at present: it will be used at
+%   the start of alignment cells.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_x_or_protected:
+\cs_new_protected:Npn \@@_get_x_or_protected:
   {
     \@@_get_next:
     \@@_token_if_protected:NF \l_@@_head_token
-      {
-        \@@_expand:
-        \@@_get_x_or_protected:
-      }
+      { \@@_expand_do:N \@@_get_x_or_protected: }
   }
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_get_token_xdef:, \@@_get_token_x:}
+%   These are similar to \cs{@@_get_x_next:}, for use when reading the
+%   replacement text of \tn{edef}/\tn{xdef} or the argument of a
+%   primitive like \tn{message} that should be expanded as we read
+%   tokens.  Loop until finding a non-expandable token (or protected
+%   macro).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_get_token_xdef:
+  {
+    \@@_get_next:
+    \@@_token_if_protected:NF \l_@@_head_token
+      { \@@_expand_do:N \@@_get_token_xdef: }
+  }
+\cs_new_protected:Npn \@@_get_token_x:
+  {
+    \@@_get_next:
+    \@@_token_if_protected:NF \l_@@_head_token
+      { \@@_expand_do:N \@@_get_token_x: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{Basic scanning subroutines}
 %
 % ^^A todo: implement |test_no_ligatures|?
@@ -2995,7 +3249,7 @@
 % \begin{macro}{\@@_get_x_non_blank:}
 %   This function does not set the |cmd| and |char| integers.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_x_non_blank:
+\cs_new_protected:Npn \@@_get_x_non_blank:
   {
     \@@_get_x_next:
     \token_if_eq_catcode:NNT \l_@@_head_token \c_space_token
@@ -3007,14 +3261,18 @@
 % \begin{macro}{\@@_get_x_non_relax:}
 %   This function does not set the |cmd| and |char| integers.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_get_x_non_relax:
+\cs_new_protected:Npn \@@_get_x_non_relax:
   {
     \@@_get_x_next:
-    \token_if_eq_meaning:NNT \l_@@_head_token \scan_stop:
+    \token_if_eq_meaning:NNTF \l_@@_head_token \scan_stop:
       { \@@_get_x_non_relax: }
       {
-        \token_if_eq_catcode:NNT \l_@@_head_token \c_space_token
+        \token_if_eq_meaning:NNTF \l_@@_head_token \@@_special_relax:
           { \@@_get_x_non_relax: }
+          {
+            \token_if_eq_catcode:NNT \l_@@_head_token \c_space_token
+              { \@@_get_x_non_relax: }
+          }
       }
   }
 %    \end{macrocode}
@@ -3022,7 +3280,7 @@
 %
 % \begin{macro}{\@@_skip_optional_space:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_skip_optional_space:
+\cs_new_protected:Npn \@@_skip_optional_space:
   {
     \@@_get_x_next:
     \token_if_eq_catcode:NNF \l_@@_head_token \c_space_token
@@ -3037,7 +3295,7 @@
 %   as \cs{@@_scan_something_internal:n} leaves raw numbers in
 %   the previous-input sequence.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_optional_equals:
+\cs_new_protected:Npn \@@_scan_optional_equals:
   {
     \@@_get_x_non_blank:
     \tl_if_eq:NNTF \l_@@_head_tl \c_@@_eq_tl
@@ -3050,12 +3308,12 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_left_brace:}
+% \begin{macro}{\@@_scan_left_brace:}
 %   The presence of \tn{relax} is allowed before a begin-group token.
 %   If there is no begin-group token, insert one, produce an error, and
 %   scan that begin-group using \cs{@@_get_next:}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_left_brace:
+\cs_new_protected:Npn \@@_scan_left_brace:
   {
     \@@_get_x_non_relax:
     \token_if_eq_catcode:NNF \l_@@_head_token \c_group_begin_token
@@ -3067,8 +3325,8 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_keyword:n}
-% \begin{macro}[int,TF]{\@@_scan_keyword:n}
+% \begin{macro}{\@@_scan_keyword:n}
+% \begin{macro}[TF]{\@@_scan_keyword:n}
 % \begin{macro}
 %   {
 %     \@@_scan_keyword_loop:NNN,
@@ -3145,11 +3403,11 @@
     \@@_gtl_if_head_is_definable:NTF \l_@@_head_gtl
       { \prg_return_false: }
       {
-        \str_if_eq_x:nnTF
+        \str_if_eq:eeTF
           { \str_head:f { \gtl_to_str:N \l_@@_head_gtl } } {#1}
           { \prg_return_true: }
           {
-            \str_if_eq_x:nnTF
+            \str_if_eq:eeTF
               { \str_head:f { \gtl_to_str:N \l_@@_head_gtl } } {#2}
               { \prg_return_true: }
               { \prg_return_false: }
@@ -3156,13 +3414,13 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \@@_scan_keyword_true:
+\cs_new_protected:Npn \@@_scan_keyword_true:
   {
     \@@_prev_input_gpop_gtl:N \l_@@_tmpb_gtl
     \@@_prev_input:x { \gtl_to_str:N \l_@@_tmpb_gtl }
     \prg_return_true:
   }
-\cs_new_protected_nopar:Npn \@@_scan_keyword_false:w
+\cs_new_protected:Npn \@@_scan_keyword_false:w
     #1 \q_recursion_stop
   {
     \@@_back_input:
@@ -3179,7 +3437,7 @@
 %   Used when |to| is mandatory: after \tn{read} or \tn{readline} and
 %   after \tn{vsplit}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_to:
+\cs_new_protected:Npn \@@_scan_to:
   {
     \@@_scan_keyword:nF { tToO }
       {
@@ -3193,7 +3451,7 @@
 % \begin{macro}{\@@_scan_font_ident:}
 %   Find a font identifier.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_font_ident:
+\cs_new_protected:Npn \@@_scan_font_ident:
   {
     \@@_get_x_non_blank:
     \@@_set_cmd:
@@ -3226,7 +3484,7 @@
 %   Find operands for one of \tn{hyphenchar}'s friends (command code
 %   |assign_font_int=78|).
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_font_int:
+\cs_new_protected:Npn \@@_scan_font_int:
   {
     \int_case:nnF \l_@@_head_char_int
       {
@@ -3242,7 +3500,7 @@
 % \begin{macro}{\@@_scan_font_dimen:}
 %   Find operands for \tn{fontdimen}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_font_dimen:
+\cs_new_protected:Npn \@@_scan_font_dimen:
   {
     \@@_scan_int:
     \@@_scan_font_ident:
@@ -3316,7 +3574,7 @@
     \int_compare:nNnT {#1} = { 8 }
       {
         \@@_tex_error:nV { the-cannot } \l_@@_head_tl
-        \@@_scan_something_internal_auxii:Vn \c_zero { 0 }
+        \@@_scan_something_internal_auxii:nn 0 { 0 }
         \@@_break:w
       }
     \tl_if_empty:nF {#2}
@@ -3359,7 +3617,7 @@
 %   is~$8$, large enough so that the main function knows it is
 %   forbidden.
 %    \begin{macrocode}
-\cs_new_nopar:Npn \@@_thing_case:
+\cs_new:Npn \@@_thing_case:
   {
     \int_case:nnF \l_@@_head_cmd_int
       {
@@ -3390,9 +3648,9 @@
       }
       { 8 }
   }
-\cs_new_nopar:Npn \@@_thing_set_aux:
+\cs_new:Npn \@@_thing_set_aux:
   { \int_compare:nNnTF \l_@@_head_char_int = { 1 } { 1 } { 0 } }
-\cs_new_nopar:Npn \@@_thing_last_item:
+\cs_new:Npn \@@_thing_last_item:
   {
     \int_compare:nNnTF \l_@@_head_char_int < { 26 }
       {
@@ -3435,10 +3693,10 @@
           { }
       }
   }
-\cs_new_nopar:Npn \@@_thing_register:
+\cs_new:Npn \@@_thing_register:
   {
     \int_eval:n { \l_@@_head_char_int / 1 000 000 - 1 }
-    \int_compare:nNnT { \tl_tail:V \l_@@_head_char_int } = \c_zero
+    \int_compare:nNnT { \tl_tail:V \l_@@_head_char_int } = 0
       { \@@_scan_int: }
   }
 %    \end{macrocode}
@@ -3449,7 +3707,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_toks_register:
   {
-    \int_compare:nNnT \l_@@_head_char_int = \c_zero
+    \int_compare:nNnT \l_@@_head_char_int = 0
       { \@@_scan_int: }
   }
 %    \end{macrocode}
@@ -3474,7 +3732,7 @@
                 { 1 } \dim_eval:n
                 { 2 } \skip_eval:n
               }
-            { \int_compare:nNnT {#1} = { 3 } \etex_mutoglue:D #3 }
+            { \int_compare:nNnT {#1} = { 3 } \tex_mutoglue:D #3 }
           }
       }
       {
@@ -3485,7 +3743,7 @@
           }
           {
             \@@_tex_error:nV { incompatible-units } #3
-            \tl_set:Nx #4 { \muskip_eval:n { \etex_gluetomu:D #3 } }
+            \tl_set:Nx #4 { \muskip_eval:n { \tex_gluetomu:D #3 } }
           }
       }
   }
@@ -3573,7 +3831,7 @@
 %   Skips blanks, scans signs, and places them to the right of the last
 %   item of \cs{@@_prev_input:n}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_signs:
+\cs_new_protected:Npn \@@_scan_signs:
   {
     \@@_get_x_non_blank:
     \tl_if_eq:NNTF \l_@@_head_tl \c_@@_plus_tl
@@ -3596,7 +3854,7 @@
 % \begin{macro}
 %   {\@@_scan_int_char:, \@@_scan_int_lq:, \@@_scan_int_explicit:n}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_int:
+\cs_new_protected:Npn \@@_scan_int:
   {
     \@@_scan_signs:
     \@@_set_cmd:
@@ -3604,7 +3862,7 @@
       { \@@_scan_something_internal:n { 0 } }
       { \@@_scan_int_char: }
   }
-\cs_new_protected_nopar:Npn \@@_scan_int_char:
+\cs_new_protected:Npn \@@_scan_int_char:
   {
     \tl_case:NnF \l_@@_head_tl
       {
@@ -3624,7 +3882,7 @@
       }
       { \@@_scan_int_explicit:Nn \c_false_bool { } }
   }
-\cs_new_protected_nopar:Npn \@@_scan_int_lq:
+\cs_new_protected:Npn \@@_scan_int_lq:
   {
     \@@_get_next:
     \@@_gtl_if_head_is_definable:NF \l_@@_head_gtl
@@ -3641,7 +3899,7 @@
   }
 \cs_new_protected:Npn \@@_scan_int_explicit:Nn #1#2
   {
-    \if_int_compare:w \c_one
+    \if_int_compare:w 1
         < #2 1 \exp_after:wN \exp_not:N \l_@@_head_tl \exp_stop_f:
       \exp_after:wN \use_i:nn
     \else:
@@ -3666,14 +3924,14 @@
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_normal_dimen:}
+% \begin{macro}{\@@_scan_normal_dimen:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_normal_dimen:
+\cs_new_protected:Npn \@@_scan_normal_dimen:
   { \@@_scan_dimen:nN { 2 } \c_false_bool }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_dimen:nN}
+% \begin{macro}{\@@_scan_dimen:nN}
 %   The first argument is $2$ if the unit may not be |mu| and $3$ if
 %   the unit must be |mu| (or |fil|).  The second argument is
 %   \cs{c_true_bool} if |fil|, |fill|, |filll| are permitted, and is
@@ -3710,7 +3968,7 @@
         \@@_scan_decimal_loop:
       }
       {
-        \tl_if_in:nVTF { 0123456789 } \l_@@_head_tl
+        \@@_tl_if_in:ooTF { 0123456789 } \l_@@_head_tl
           {
             \@@_back_input:
             \@@_scan_int:
@@ -3778,14 +4036,14 @@
     \@@_prev_input:n { pt }
     \@@_break_point:
   }
-\cs_new_protected_nopar:Npn \@@_scan_inf_unit_loop:
+\cs_new_protected:Npn \@@_scan_inf_unit_loop:
   { \@@_scan_keyword:nT { lL } { \@@_scan_inf_unit_loop: } }
-\cs_new_protected_nopar:Npn \@@_scan_decimal_loop:
+\cs_new_protected:Npn \@@_scan_decimal_loop:
   {
     \@@_get_x_next:
     \tl_if_empty:NTF \l_@@_head_tl
       { \use_ii:nn }
-      { \tl_if_in:nVTF { 0123456789 } \l_@@_head_tl }
+      { \@@_tl_if_in:ooTF { 0123456789 } \l_@@_head_tl }
       {
         \@@_prev_input:V \l_@@_head_tl
         \@@_scan_decimal_loop:
@@ -3799,16 +4057,16 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_normal_glue:, \@@_scan_mu_glue:}
+% \begin{macro}{\@@_scan_normal_glue:, \@@_scan_mu_glue:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_normal_glue:
+\cs_new_protected:Npn \@@_scan_normal_glue:
   { \@@_scan_glue:n { 2 } }
-\cs_new_protected_nopar:Npn \@@_scan_mu_glue:
+\cs_new_protected:Npn \@@_scan_mu_glue:
   { \@@_scan_glue:n { 3 } }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_glue:n}
+% \begin{macro}{\@@_scan_glue:n}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_glue:n #1
   {
@@ -3842,10 +4100,10 @@
 % \end{macro}
 %
 % ^^A todo: allow \input".. .."
-% \begin{macro}[int]{\@@_scan_file_name:}
+% \begin{macro}{\@@_scan_file_name:}
 % ^^A todo: area_delimiter and ext_delimiter ??
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_file_name:
+\cs_new_protected:Npn \@@_scan_file_name:
   {
     \bool_gset_true:N \g_@@_name_in_progress_bool
     \@@_get_x_non_blank:
@@ -3853,7 +4111,7 @@
     \bool_gset_false:N \g_@@_name_in_progress_bool
     \@@_prev_input_silent:n { ~ }
   }
-\cs_new_protected_nopar:Npn \@@_scan_file_name_loop:
+\cs_new_protected:Npn \@@_scan_file_name_loop:
   {
     \@@_gtl_if_head_is_definable:NTF \l_@@_head_gtl
       { \@@_back_input: }
@@ -3871,12 +4129,12 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_r_token:}
+% \begin{macro}{\@@_scan_r_token:}
 %   This is analogous to \TeX{}'s |get_r_token|.  We store in
 %   \cs{l_@@_defined_tl} the token which we found, as this is what will
 %   be defined by the next assignment.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_r_token:
+\cs_new_protected:Npn \@@_scan_r_token:
   {
     \bool_do_while:nn
       { \tl_if_eq_p:NN \l_@@_head_tl \c_space_tl }
@@ -3907,8 +4165,25 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{\@@_scan_pdf_ext_toks:}
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_scan_pdf_ext_toks:
+  {
+    \@@_prev_input_gpush:
+    \@@_scan_toks:NN \c_false_bool \c_true_bool
+    \@@_prev_input_gpop:N \l_@@_tmpa_tl
+    \@@_prev_input_silent:x
+      { { \exp_not:N \exp_not:n \exp_not:V \l_@@_tmpa_tl } }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % ^^A todo: provide separate functions for defs (avoid hash doubling).
 % \begin{macro}{\@@_scan_toks:NN}
+%   The boolean |#1| is true if we are making a definition (then we
+%   start by scanning the parameter text), false if we are simply
+%   scanning a general text.  The boolean |#2| is true if we need to
+%   expand, false otherwise (for instance for \tn{lowercase}).
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_toks:NN #1#2
   {
@@ -3928,7 +4203,7 @@
 %   input, stop looping, and put what we collected into
 %   \cs{l_@@_defining_tl} and into the |prev_input|.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_param:
+\cs_new_protected:Npn \@@_scan_param:
   {
     \tl_clear:N \l_@@_tmpa_tl
     \@@_scan_param_aux:
@@ -3935,7 +4210,7 @@
     \tl_put_right:NV \l_@@_defining_tl \l_@@_tmpa_tl
     \@@_prev_input_silent:V \l_@@_tmpa_tl
   }
-\cs_new_protected_nopar:Npn \@@_scan_param_aux:
+\cs_new_protected:Npn \@@_scan_param_aux:
   {
     \@@_get_next:
     \tl_concat:NNN \l_@@_tmpa_tl
@@ -3948,9 +4223,14 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_scan_group_n:N}
+%   The boolean |#1| is true if we are making a definition, false
+%   otherwise.  In both cases put the open brace back and grab the first
+%   item.  The only difference is that when making a definition we store
+%   the data into \cs{l_@@_defining_tl} as well.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_group_n:N #1
   {
+    \gtl_set_eq:NN \l_@@_head_gtl \c_group_begin_gtl
     \@@_back_input:
     \@@_input_gpop_item:NF \l_@@_head_tl
       {
@@ -3966,6 +4246,8 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_scan_group_x:N}
+%   The boolean |#1| is true if we are making a definition, false
+%   otherwise.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_group_x:N #1
   {
@@ -3990,10 +4272,12 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_scan_group_xdef:n}
+%   This is to scan the replacement text of an \tn{edef} or \tn{xdef}.
+%   The integer |#1| counts the brace balance.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_group_xdef:n #1
   {
-    \@@_get_token_x:N \c_true_bool
+    \@@_get_token_xdef:
     \tl_if_empty:NTF \l_@@_head_tl
       {
         \gtl_if_head_is_group_begin:NTF \l_@@_head_gtl
@@ -4005,7 +4289,7 @@
           {
             \@@_prev_input_silent:V \c_right_brace_str
             \tl_put_right:Nn \l_@@_defining_tl { \if_false: { \fi: } }
-            \int_compare:nNnF {#1} = \c_one
+            \int_compare:nNnF {#1} = 1
               { \@@_scan_group_xdef:f { \int_eval:n { #1 - 1 } } }
           }
       }
@@ -4024,7 +4308,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_scan_group_x:n #1
   {
-    \@@_get_token_x:N \c_false_bool
+    \@@_get_token_x:
     \@@_prev_input_gtl:N \l_@@_head_gtl
     \tl_if_empty:NTF \l_@@_head_tl
       {
@@ -4031,7 +4315,7 @@
         \gtl_if_head_is_group_begin:NTF \l_@@_head_gtl
           { \@@_scan_group_x:f { \int_eval:n { #1 + 1 } } }
           {
-            \int_compare:nNnF {#1} = \c_one
+            \int_compare:nNnF {#1} = 1
               { \@@_scan_group_x:f { \int_eval:n { #1 - 1 } } }
           }
       }
@@ -4041,41 +4325,11 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_get_token_x:N}
-%    \begin{macrocode}
-\cs_new_protected:Npn \@@_get_token_x:N #1
-  {
-    \@@_get_next:
-    \@@_token_if_protected:NF \l_@@_head_token
-      {
-        \@@_set_cmd:
-        \int_compare:nNnTF
-          \l_@@_head_cmd_int = { \@@_tex_use:n { the } }
-          {
-            \@@_get_the:
-            \bool_if:NTF #1
-              {
-                \tl_put_right:NV \l_@@_defining_tl \l_@@_head_tl
-                \@@_prev_input:V \l_@@_head_tl
-              }
-              {
-                \@@_exp_args:NNx \gtl_set:Nn \l_@@_tmpb_gtl { \l_@@_head_tl }
-                \@@_prev_input_gtl:N \l_@@_tmpb_gtl
-                \@@_print_action:
-              }
-          }
-          { \@@_expand: }
-        \@@_get_token_x:N #1
-      }
-  }
-%    \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_nopar:Npn \@@_scan_alt_rule:
+\cs_new_protected:Npn \@@_scan_alt_rule:
   {
     \@@_scan_keyword:nTF { wWiIdDtThH }
       {
@@ -4104,7 +4358,7 @@
 %   Some \TeX{} primitives accept the keywords |to| and |spread|,
 %   followed by a dimension.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_spec:
+\cs_new_protected:Npn \@@_scan_spec:
   {
     \@@_scan_keyword:nTF { tToO } { \@@_scan_normal_dimen: }
       {
@@ -4165,7 +4419,7 @@
 %   \TeX{} does), there is no need to remove the after assignment token
 %   here.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_box_error:
+\cs_new_protected:Npn \@@_do_box_error:
   {
     \@@_back_input:
     \@@_error:nnnnn { missing-box } { } { } { } { }
@@ -4228,7 +4482,7 @@
 %
 % \begin{macro}{\@@_do_leaders_fetch_skip:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_leaders_fetch_skip:
+\cs_new_protected:Npn \@@_do_leaders_fetch_skip:
   {
     \@@_get_x_non_relax:
     \@@_set_cmd:
@@ -4298,7 +4552,7 @@
 \cs_new_protected:Npn \@@_box_hook:N #1
   {
     \tl_set:NV \l_@@_tmpa_tl #1
-    \str_if_eq_x:nnF
+    \str_if_eq:eeF
       { \tl_head:N \l_@@_tmpa_tl } { \exp_not:N \@@_box_hook:w }
       {
         \@@_exp_args:Nx #1
@@ -4330,7 +4584,7 @@
 %   |heigh| and |width| keywords, we are in the same situation as after
 %   finding a box.  Fetch the required skip accordingly.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_leaders_rule:
+\cs_new_protected:Npn \@@_do_leaders_rule:
   {
     \@@_prev_input:V \l_@@_head_tl
     \@@_scan_alt_rule:
@@ -4341,7 +4595,7 @@
 %
 % \subsection{Paragraphs}
 %
-% \begin{macro}[int,TF]{\@@_charcode_if_safe:n}
+% \begin{macro}[TF]{\@@_charcode_if_safe:n}
 %    \begin{macrocode}
 \prg_new_protected_conditional:Npnn \@@_charcode_if_safe:n #1 { TF }
   {
@@ -4412,7 +4666,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_new_graf:N}
+% \begin{macro}{\@@_new_graf:N}
 %   The argument is a boolean, indicating whether the paragraph should
 %   be indented.  We have much less work to do here than \TeX{} itself.
 %   Our only task is to correctly position the \tn{everypar} tokens in
@@ -4435,17 +4689,17 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_end_graf:}
+% \begin{macro}{\@@_end_graf:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_end_graf:
+\cs_new_protected:Npn \@@_end_graf:
   { \mode_if_horizontal:T { \@@_normal_paragraph: } }
 %    \end{macrocode}
 % \end{macro}
 %
 % ^^A todo: Do we need to do more?
-% \begin{macro}[int]{\@@_normal_paragraph:}
+% \begin{macro}{\@@_normal_paragraph:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_normal_paragraph:
+\cs_new_protected:Npn \@@_normal_paragraph:
   {
     \tex_par:D
     \gtl_gput_right:Nn \g_@@_output_gtl { \par }
@@ -4455,9 +4709,9 @@
 % \end{macro}
 %
 % ^^A todo: do something to the \output routine?
-% \begin{macro}[int]{\@@_build_page:}
+% \begin{macro}{\@@_build_page:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_build_page:
+\cs_new_protected:Npn \@@_build_page:
   {
   }
 %    \end{macrocode}
@@ -4475,7 +4729,7 @@
 %   When an end-group character is sensed, the result depends on the
 %   current group type.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_handle_right_brace:
+\cs_new_protected:Npn \@@_handle_right_brace:
   {
     \int_compare:nTF { 1 <= \@@_currentgrouptype: <= 13 }
       {
@@ -4511,7 +4765,7 @@
 %   This command is used to simply end a group, when there are no
 %   specific operations to perform.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_end_simple_group:
+\cs_new_protected:Npn \@@_end_simple_group:
   {
     \l_@@_head_token
     \@@_print_action:
@@ -4524,7 +4778,7 @@
 %   \tn{hbox}) can either be simple, or can mean that we need to find a
 %   skip for a \tn{leaders}/\tn{cleaders}/\tn{xleaders} construction.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_end_box_group:
+\cs_new_protected:Npn \@@_end_box_group:
   {
     \seq_pop:NN \l_@@_leaders_box_seq \l_@@_tmpa_tl
     \exp_args:No \@@_end_box_group_aux:n { \l_@@_tmpa_tl }
@@ -4531,7 +4785,7 @@
   }
 \cs_new_protected:Npn \@@_end_box_group_aux:n #1
   {
-    \str_if_eq_x:nnTF {#1} { Z }
+    \str_if_eq:eeTF {#1} { Z }
       { \@@_end_simple_group: }
       {
         \@@_get_x_non_relax:
@@ -4554,7 +4808,7 @@
 %
 % \begin{macro}{\@@_off_save:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_off_save:
+\cs_new_protected:Npn \@@_off_save:
   {
     \int_compare:nNnTF \@@_currentgrouptype: = { 0 }
       { % bottom-level
@@ -4585,7 +4839,7 @@
 % ^^A todo: implement \aftergroup and things happening at end-group
 % ^^A todo: implement \@@_scan_math:
 %
-% \begin{macro}[int]
+% \begin{macro}
 %   {\@@_mode_math:n, \@@_mode_non_math:n, \@@_mode_vertical:n}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_mode_math:n #1
@@ -4610,7 +4864,7 @@
 % \begin{macro}{\@@_head_for_vmode:}
 %   See \TeX{}'s |head_for_vmode|.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_head_for_vmode:
+\cs_new_protected:Npn \@@_head_for_vmode:
   {
     \mode_if_inner:TF
       {
@@ -4633,7 +4887,7 @@
 % ^^A todo: should push_math be provided?
 % \begin{macro}{\@@_goto_inner_math:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_goto_inner_math:
+\cs_new_protected:Npn \@@_goto_inner_math:
   {
     \@@_box_hook:N \tex_everymath:D
     $ % $
@@ -4644,7 +4898,7 @@
 %
 % \begin{macro}{\@@_goto_display_math:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_goto_display_math:
+\cs_new_protected:Npn \@@_goto_display_math:
   {
     \@@_box_hook:N \tex_everydisplay:D
     $ $
@@ -4655,7 +4909,7 @@
 %
 % \begin{macro}{\@@_after_math:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_after_math:
+\cs_new_protected:Npn \@@_after_math:
   {
     \mode_if_inner:TF
       {
@@ -4684,11 +4938,11 @@
 %
 % \subsection{One step}
 %
-% \begin{macro}[int]{\@@_do_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_nopar:Npn \@@_do_step:
+\cs_new_protected:Npn \@@_do_step:
   {
     \@@_set_action_text:
     \bool_if:NT \g_@@_internal_debug_bool
@@ -4734,7 +4988,18 @@
 % \tn{relax} does nothing.
 %    \begin{macrocode}
 \@@_new_tex_cmd:nn { relax }                                % 0
-  { \@@_print_action: }
+  {
+    \token_if_eq_meaning:NNT \l_@@_head_token \@@_special_relax:
+      {
+        \exp_after:wN \@@_token_if_expandable:NTF \l_@@_head_tl
+          {
+            \@@_set_action_text:x
+              { \iow_char:N \\notexpanded: \g_@@_action_text_str }
+          }
+          { }
+      }
+    \@@_print_action:
+  }
 %    \end{macrocode}
 %
 % Begin-group characters are sent to the output, as their grouping
@@ -4808,7 +5073,7 @@
   { \@@_mode_math:n { \@@_sub_sup: } }
 \@@_new_tex_cmd:nn { subscript_char }                       % 8
   { \@@_mode_math:n { \@@_sub_sup: } }
-\cs_new_protected_nopar:Npn \@@_sub_sup:
+\cs_new_protected:Npn \@@_sub_sup:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -4919,7 +5184,7 @@
           {
             % ^^A todo: unless its_all_over
             \int_gdecr:N \g_@@_ends_int
-            \int_compare:nNnTF \g_@@_ends_int > \c_zero
+            \int_compare:nNnTF \g_@@_ends_int > 0
               {
                 \@@_back_input:
                 \@@_back_input:n
@@ -5024,7 +5289,7 @@
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
-    \int_compare:nNnF \l_@@_head_char_int = \c_zero
+    \int_compare:nNnF \l_@@_head_char_int = 0
       { \@@_scan_int: }
     \@@_prev_input_gpush:
     \@@_scan_toks:NN \c_false_bool \c_true_bool
@@ -5057,7 +5322,13 @@
           { % show
             \@@_get_next:
             \@@_prev_input_gpop:N \l_@@_tmpa_tl
-            \gtl_head_do:NN \l_@@_head_gtl \l_@@_tmpa_tl
+            \token_if_eq_meaning:NNTF
+              \l_@@_head_token \@@_special_relax:
+              {
+                \exp_after:wN \exp_after:wN \exp_after:wN \l_@@_tmpa_tl
+                \exp_after:wN \exp_not:N \l_@@_head_tl
+              }
+              { \gtl_head_do:NN \l_@@_head_gtl \l_@@_tmpa_tl }
           }
         { 2 }
           { % showthe
@@ -5065,13 +5336,13 @@
             \@@_scan_something_internal:n { 5 }
             \@@_prev_input_gpop:N \l_@@_head_tl
             \@@_exp_args:Nx \use:n
-              { \etex_showtokens:D { \tl_tail:N \l_@@_head_tl } }
+              { \tex_showtokens:D { \tl_tail:N \l_@@_head_tl } }
           }
       }
       { % no operand for showlists, showgroups, showifs
-        \int_compare:nNnT \l_@@_head_char_int = \c_one % showbox
+        \int_compare:nNnT \l_@@_head_char_int = 1 % showbox
           { \@@_scan_int: }
-        \int_compare:nNnT \l_@@_head_char_int = \c_five % showtokens
+        \int_compare:nNnT \l_@@_head_char_int = 5 % showtokens
           { \@@_scan_toks:NN \c_false_bool \c_false_bool }
         \@@_prev_input_gpop:N \l_@@_head_tl
         \tl_use:N \l_@@_head_tl \scan_stop:
@@ -5096,7 +5367,7 @@
 %   Scan a dimension and a box, and perform the shift, printing the
 %   appropriate action.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_move:
+\cs_new_protected:Npn \@@_do_move:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5126,7 +5397,7 @@
 %
 % \begin{macro}{\@@_do_unpackage:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_unpackage:
+\cs_new_protected:Npn \@@_do_unpackage:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5174,7 +5445,7 @@
 %   glue (\cs{l_@@_head_char_int} is $4$ or~$5$), then call the
 %   primitive with that operand, and print the whole thing as an action.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_append_glue:
+\cs_new_protected:Npn \@@_do_append_glue:
   {
     \int_compare:nNnTF \l_@@_head_char_int < { 4 }
       { \tl_use:N \l_@@_head_tl \@@_print_action: }
@@ -5215,7 +5486,7 @@
 %   See \cs{@@_do_append_glue:}.  This function is used for the
 %   primitives \tn{kern} and \tn{mkern} only.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_append_kern:
+\cs_new_protected:Npn \@@_do_append_kern:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5289,7 +5560,7 @@
   { \@@_mode_non_vertical:n { \@@_do_rule: } }
 \@@_new_tex_cmd:nn { hrule }                                % 36
   { \@@_mode_vertical:n { \@@_do_rule: } }
-\cs_new_protected_nopar:Npn \@@_do_rule:
+\cs_new_protected:Npn \@@_do_rule:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5347,7 +5618,7 @@
   {
     \tl_set_eq:NN \l_@@_tmpa_tl \l_@@_head_tl
     \@@_get_next:
-    \int_compare:nNnTF \@@_currentgrouptype: = \c_zero
+    \int_compare:nNnTF \@@_currentgrouptype: = 0
       {
         \@@_print_action:x
           {
@@ -5411,7 +5682,7 @@
 %
 % \begin{macro}{\@@_do_accent:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_accent:
+\cs_new_protected:Npn \@@_do_accent:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5450,7 +5721,7 @@
 %   \TeX{} will complain if \cs{l_@@_head_tl} happens to start with
 %   \tn{accent} (the user used \tn{accent} in math mode).
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_math_accent:
+\cs_new_protected:Npn \@@_do_math_accent:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_print_action:
@@ -5715,9 +5986,9 @@
 % \subsubsection{Extensions}
 % ^^A todo: move this section.
 %
-% \begin{macro}[int]{\@@_scan_extension_operands:}
+% \begin{macro}{\@@_scan_extension_operands:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_extension_operands:
+\cs_new_protected:Npn \@@_scan_extension_operands:
   {
     \int_case:nnF \l_@@_head_char_int
       {
@@ -5897,7 +6168,7 @@
 %
 % \begin{macro}{\@@_scan_pdfcolorstack_operands:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_pdfcolorstack_operands:
+\cs_new_protected:Npn \@@_scan_pdfcolorstack_operands:
   {
     \@@_scan_int:
     \@@_scan_keyword:nF { sSeEtT }
@@ -5920,7 +6191,7 @@
 %
 % \begin{macro}{\@@_scan_rule_attr:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_rule_attr:
+\cs_new_protected:Npn \@@_scan_rule_attr:
   {
     \@@_scan_alt_rule:
     \@@_scan_keyword:nT { aAtTtTrR }
@@ -5929,9 +6200,9 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_action:}
+% \begin{macro}{\@@_scan_action:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_action:
+\cs_new_protected:Npn \@@_scan_action:
   {
     \@@_scan_keyword:nTF { uUsSeErR }
       { \@@_scan_pdf_ext_toks: }
@@ -5971,7 +6242,7 @@
 % \begin{macro}{\@@_scan_image:}
 %   Used by \tn{pdfximage}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_image:
+\cs_new_protected:Npn \@@_scan_image:
   {
     \@@_scan_rule_attr:
     \@@_scan_keyword:nTF { nNaAmMeEdD }
@@ -5987,9 +6258,9 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_scan_immediate_operands:}
+% \begin{macro}{\@@_scan_immediate_operands:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_immediate_operands:
+\cs_new_protected:Npn \@@_scan_immediate_operands:
   {
     \@@_get_x_next:
     \@@_set_cmd:
@@ -6011,12 +6282,12 @@
       }
       { \@@_scan_immediate_operands_bad: }
   }
-\cs_new_protected_nopar:Npn \@@_scan_immediate_operands_aux:
+\cs_new_protected:Npn \@@_scan_immediate_operands_aux:
   {
     \@@_prev_input:V \l_@@_head_tl
     \@@_scan_extension_operands:
   }
-\cs_new_protected_nopar:Npn \@@_scan_immediate_operands_bad:
+\cs_new_protected:Npn \@@_scan_immediate_operands_bad:
   {
     \@@_back_input:
     \@@_prev_input_gpop:N \l_@@_head_tl
@@ -6029,7 +6300,7 @@
 %
 % \begin{macro}{\@@_scan_pdfdest_operands:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_scan_pdfdest_operands:
+\cs_new_protected:Npn \@@_scan_pdfdest_operands:
   {
     \@@_scan_keyword:nTF { nNuUmM }
       { \@@_scan_int: }
@@ -6089,7 +6360,7 @@
 % We define all those commands in one go, from
 % |max_non_prefixed_command+1=71| to |max_command=102|.
 %    \begin{macrocode}
-\cs_set_protected_nopar:Npn \@@_tmp:w
+\cs_set_protected:Npn \@@_tmp:w
   {
     \@@_prev_input_gpush:
     \@@_prefixed_command:
@@ -6101,11 +6372,11 @@
   { \cs_new_eq:cN { @@_cmd_#1: } \@@_tmp:w }
 %    \end{macrocode}
 %
-% \begin{macro}[int]{\@@_prefixed_command:}
+% \begin{macro}{\@@_prefixed_command:}
 %   Accumulated prefix codes so far are stored as the last item of
 %   the previous-input sequence.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_prefixed_command:
+\cs_new_protected:Npn \@@_prefixed_command:
   {
     \int_while_do:nNnn
       \l_@@_head_cmd_int = { \@@_tex_use:n { prefix } }
@@ -6144,28 +6415,28 @@
 % \begin{macro}{\@@_after_assignment:}
 % \begin{macro}{\@@_omit_after_assignment:w}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_after_assignment:
+\cs_new_protected:Npn \@@_after_assignment:
   {
     \@@_back_input_gtl:N \g_@@_after_assignment_gtl
     \gtl_gclear:N \g_@@_after_assignment_gtl
   }
-\cs_new_protected_nopar:Npn \@@_omit_after_assignment:w
+\cs_new_protected:Npn \@@_omit_after_assignment:w
     #1 \@@_after_assignment: { }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_prefixed_new:nn}
+% \begin{macro}{\@@_prefixed_new:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_prefixed_new:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { @@_prefixed_ \@@_tex_use:n {#1} : } {#2}
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_assign_token:n}
+% \begin{macro}{\@@_assign_token:n}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_assign_token:n #1
   {
@@ -6177,9 +6448,9 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_assign_register:}
+% \begin{macro}{\@@_assign_register:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_assign_register:
+\cs_new_protected:Npn \@@_assign_register:
   {
     \@@_prev_input_gpop:N \l_@@_head_tl
     \tl_use:N \l_@@_head_tl \scan_stop:
@@ -6188,7 +6459,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_assign_value:nn}
+% \begin{macro}{\@@_assign_value:nn}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_assign_value:nn #1#2
   {
@@ -6212,7 +6483,7 @@
 %    \begin{macrocode}
 \@@_prefixed_new:nn { toks_register }                       % 71
   {
-    \int_compare:nNnT \l_@@_head_char_int = \c_zero
+    \int_compare:nNnT \l_@@_head_char_int = 0
       { % \toks
         \@@_prev_input_gpush:N \l_@@_head_tl
         \@@_print_action:
@@ -6223,7 +6494,7 @@
   }
 \@@_prefixed_new:nn { assign_toks }                         % 72
   { \@@_assign_toks: }
-\cs_new_protected_nopar:Npn \@@_assign_toks:
+\cs_new_protected:Npn \@@_assign_toks:
   {
     \@@_prev_input_silent:V \l_@@_head_tl
     \@@_print_action:
@@ -6235,7 +6506,7 @@
       \l_@@_head_cmd_int = { \@@_tex_use:n { toks_register } }
       {
         \@@_prev_input:V \l_@@_head_tl
-        \int_compare:nNnT \l_@@_head_char_int = \c_zero
+        \int_compare:nNnT \l_@@_head_char_int = 0
           { \@@_scan_int: }
       }
       {
@@ -6274,7 +6545,7 @@
   }
 \@@_prefixed_new:nn { set_aux }                             % 79
   { % prevdepth = 1, spacefactor = 102
-    \int_compare:nNnTF \l_@@_head_char_int = \c_one
+    \int_compare:nNnTF \l_@@_head_char_int = 1
       { \@@_assign_value:nn { } { \@@_scan_normal_dimen: } }
       { \@@_assign_value:nn { } { \@@_scan_int: } }
   }
@@ -6299,7 +6570,7 @@
         \prg_replicate:nn
           {
             \tl_if_head_eq_meaning:VNT
-              \l_@@_defined_tl \tex_parshape:D { \c_two * }
+              \l_@@_defined_tl \tex_parshape:D { 2 * }
             \tl_tail:N \l_@@_defined_tl
           }
           { \@@_scan_int: }
@@ -6438,7 +6709,7 @@
   }
 \prg_new_conditional:Npnn \@@_read_to_cs_safe:n #1 { TF }
   {
-    \int_compare:nNnTF { \etex_interactionmode:D } > { 1 }
+    \int_compare:nNnTF { \tex_interactionmode:D } > { 1 }
       { \prg_return_true: }
       {
         \int_compare:nNnTF {#1} < { 0 }
@@ -6467,7 +6738,7 @@
     \tl_set:NV \l_@@_defining_tl \l_@@_tmpa_tl
     \tl_put_right:NV \l_@@_defining_tl \l_@@_head_tl
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \int_compare:nNnTF \l_@@_head_char_int < \c_two
+    \int_compare:nNnTF \l_@@_head_char_int < 2
       { % def/gdef
         \@@_scan_r_token:
         \tl_put_right:NV \l_@@_defining_tl \l_@@_defined_tl
@@ -6522,7 +6793,7 @@
     \@@_prev_input_gpop:N \l_@@_tmpa_tl
     \tl_put_left:NV \l_@@_head_tl \l_@@_tmpa_tl
     \tl_use:N \l_@@_head_tl \scan_stop:
-    \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+    \@@_print_assignment:x { \tl_to_str:N \l_@@_head_tl }
   }
 %    \end{macrocode}
 %
@@ -6563,13 +6834,13 @@
 % \tn{muskip}, and commands with a built-in number).
 %    \begin{macrocode}
 \@@_prefixed_new:nn { register }                            % 89
-  { \@@_do_register:N \c_zero }
+  { \@@_do_register:N 0 }
 \@@_prefixed_new:nn { advance }                             % 90
-  { \@@_do_operation:N \c_one }
+  { \@@_do_operation:N 1 }
 \@@_prefixed_new:nn { multiply }                            % 91
-  { \@@_do_operation:N \c_two }
+  { \@@_do_operation:N 2 }
 \@@_prefixed_new:nn { divide }                              % 92
-  { \@@_do_operation:N \c_three }
+  { \@@_do_operation:N 3 }
 %    \end{macrocode}
 %
 % \begin{macro}{\@@_do_operation:N, \@@_do_operation_fail:w}
@@ -6605,7 +6876,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \@@_do_operation_fail:w
+\cs_new_protected:Npn \@@_do_operation_fail:w
   {
     \@@_error:nnnnn { after-advance } { } { } { } { }
     \@@_prev_input_gpop:N \l_@@_tmpa_tl
@@ -6623,10 +6894,10 @@
   }
 \cs_new_protected:Npn \@@_do_register_aux:Nn #1#2
   {
-    \int_compare:nNnTF { \tl_tail:n {#2} } = \c_zero
+    \int_compare:nNnTF { \tl_tail:n {#2} } = 0
       {
         \@@_prev_input_gpush:N \l_@@_head_tl
-        \@@_print_action:
+        \@@_print_assignment:
         \@@_scan_int:
         \@@_prev_input_gpop:N \l_@@_head_tl
         \@@_prev_input_silent:V \l_@@_head_tl
@@ -6633,7 +6904,7 @@
       }
       {
         \@@_prev_input_silent:V \l_@@_head_tl
-        \@@_print_action:
+        \@@_print_assignment:
       }
     \tl_set_eq:NN \l_@@_defined_tl \l_@@_head_tl
     \exp_args:NNf \@@_do_register_set:Nn #1
@@ -6646,7 +6917,7 @@
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_do_register_set:Nn #1#2
   {
-    \int_compare:nNnTF {#1} = \c_zero
+    \int_compare:nNnTF {#1} = 0
       { % truly register command
         \@@_scan_optional_equals:
       }
@@ -6654,7 +6925,7 @@
         \@@_scan_keyword:nF { bByY }
           { \@@_prev_input_silent:n { by } }
       }
-    \int_compare:nNnTF {#1} < \c_two
+    \int_compare:nNnTF {#1} < 2
       {
         \int_case:nnF {#2}
           {
@@ -6673,7 +6944,7 @@
 %
 % The following is used for instance when making accents.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_do_assignments:
+\cs_new_protected:Npn \@@_do_assignments:
   {
     \@@_get_x_non_relax:
     \@@_set_cmd:
@@ -6718,7 +6989,8 @@
 %   \tn{pdffilemoddate}, \tn{pdffilesize}, \tn{pdfmdfivesum},
 %   \tn{pdffiledump}, \tn{pdfmatch}, \tn{pdflastmatch},
 %   \tn{pdfuniformdeviate}, \tn{pdfnormaldeviate}, \tn{pdfinsertht},
-%   \tn{pdfximagebbox}, and \tn{jobname}.
+%   \tn{pdfximagebbox}, \tn{jobname}, and in
+%   \LuaTeX{} \tn{directlua}, \tn{expanded}, \tn{luaescapestring}.
 % \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},
@@ -6731,7 +7003,7 @@
 % Let \TeX{} trigger an error.
 %    \begin{macrocode}
 \@@_new_tex_expandable:nn { undefined_cs }                  % 103
-  { \tl_use:N \l_@@_head_tl \@@_print_action: }
+  { \tl_use:N \l_@@_head_tl \@@_print_expansion: }
 %    \end{macrocode}
 %
 % \begin{macro}{\@@_expandafter:, \@@_unless:, \@@_unless_bad:}
@@ -6741,7 +7013,7 @@
     \token_if_eq_meaning:NNTF \l_@@_head_token \tex_expandafter:D
       { \@@_expandafter: } { \@@_unless: }
   }
-\cs_new_protected_nopar:Npn \@@_expandafter:
+\cs_new_protected:Npn \@@_expandafter:
   {
     \gtl_set_eq:NN \l_@@_tmpb_gtl \l_@@_head_gtl
     \@@_get_next:
@@ -6748,10 +7020,10 @@
     \gtl_concat:NNN \l_@@_head_gtl
       \l_@@_tmpb_gtl \l_@@_head_gtl
     \@@_prev_input_gpush_gtl:N \l_@@_head_gtl
-    \@@_print_action:x { \gtl_to_str:N \l_@@_head_gtl }
+    \@@_print_expansion:x { \gtl_to_str:N \l_@@_head_gtl }
     \@@_get_next:
     \@@_token_if_expandable:NTF \l_@@_head_token
-      { \@@_expand: }
+      { \@@_expand_do:N \prg_do_nothing: }
       { \@@_back_input: }
     \@@_prev_input_gpop:N \l_@@_head_gtl
     \@@_set_action_text:x
@@ -6758,9 +7030,9 @@
       { back_input: ~ \gtl_to_str:N \l_@@_head_gtl }
     \gtl_pop_left:N \l_@@_head_gtl
     \@@_back_input:
-    \@@_print_action:
+    \@@_print_expansion:
   }
-\cs_new_protected_nopar:Npn \@@_unless:
+\cs_new_protected:Npn \@@_unless:
   {
     \@@_get_token:
     \int_compare:nNnTF
@@ -6776,7 +7048,7 @@
       }
       { \@@_unless_bad: }
   }
-\cs_new_protected_nopar:Npn \@@_unless_bad:
+\cs_new_protected:Npn \@@_unless_bad:
   {
     \@@_error:nnnnn { bad-unless } { } { } { } { }
     \@@_back_input:
@@ -6784,30 +7056,72 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_noexpand:, \@@_pdfprimitive:}
+% \begin{macro}{\@@_noexpand:N, \@@_noexpand_after:, \@@_pdfprimitive:}
+%   Currently not fully implemented.
+%
+%   The argument of \cs{@@_noexpand:N} is \cs{prg_do_nothing:} when
+%   \tn{noexpand} is hit by \tn{expandafter}; otherwise it is one of
+%   various loop commands (\cs{@@_get_x_next:},
+%   \cs{@@_get_x_or_protected:}, \cs{@@_get_token_xdef:},
+%   \cs{@@_get_token_x:}) that would call \cs{@@_get_next:} and possibly
+%   expand the token more.  For these cases we simply stop after
+%   \cs{@@_get_next:} and if the token is expandable we pretend its
+%   meaning is \tn{relax}.
+%
+%   The case of \tn{expandafter} (so \cs{prg_do_nothing:}) is tougher.
+%   Do nothing if the next token is an explicit non-active character
+%   (begin-group and end-group characters are detected by
+%   \cs{l_@@_head_tl}, the rest by testing if the token is definable).
+%   Otherwise the token must be marked with \cs{notexpanded:} (even if
+%   the token is currently a non-expandable primitive, as its meaning
+%   can be changed by the code skipped over by \tn{expandafter}).  That
+%   \cs{notexpanded:} marker should be removed if the token is taken as
+%   the argument of a macro, but we fail to do that.  We set the
+%   \cs{notexpanded:\ldots{}} command to be a special \tn{relax} marker
+%   to make it quickly recognizable in \cs{@@_get_next:}.  This is
+%   incidentally the same meaning used by \TeX{} for expandable commands.
 %    \begin{macrocode}
 \@@_new_tex_expandable:nn { no_expand }                     % 105
   {
     \token_if_eq_meaning:NNTF \l_@@_head_token \tex_noexpand:D
-      { \@@_noexpand: }
+      { \@@_noexpand:N }
       { \@@_pdfprimitive: }
   }
-\cs_new_protected_nopar:Npn \@@_noexpand:
+\cs_new_protected:Npn \@@_noexpand:N #1
   {
     \@@_get_token:
-    \@@_back_input:
-    \@@_token_if_expandable:NT \l_@@_head_token
+    \cs_if_eq:NNTF #1 \prg_do_nothing:
       {
-        \cs_gset_protected_nopar:Npx \@@_get_next:
+        \tl_if_empty:NTF \l_@@_head_tl
+          { \@@_back_input: }
           {
-            \cs_gset_protected_nopar:Npn \@@_get_next:
-              { \exp_not:o { \@@_get_next: } }
-            \exp_not:o { \@@_get_next: }
-            \exp_not:n { \cs_set_eq:NN \l_@@_head_token \tex_relax:D }
+            \exp_after:wN \@@_token_if_definable:NTF \l_@@_head_tl
+              { \@@_noexpand_after: }
+              { \@@_back_input: }
           }
       }
+      {
+        \@@_back_input:
+        \@@_get_next:
+        \@@_token_if_expandable:NT \l_@@_head_token
+          { \cs_set_eq:NN \l_@@_head_token \@@_special_relax: }
+      }
   }
-\cs_new_protected_nopar:Npn \@@_pdfprimitive:
+\cs_new_protected:Npn \@@_noexpand_after:
+  {
+    \group_begin:
+      \@@_set_escapechar:n { 92 }
+      \exp_args:NNc
+    \group_end:
+    \@@_noexpand_after:N
+      { notexpanded: \exp_after:wN \token_to_str:N \l_@@_head_tl }
+  }
+\cs_new_protected:Npn \@@_noexpand_after:N #1
+  {
+    \cs_gset_eq:NN #1 \@@_special_relax:
+    \@@_back_input:n {#1}
+  }
+\cs_new_protected:Npn \@@_pdfprimitive:
   { \@@_not_implemented:n { pdfprimitive } }
 %    \end{macrocode}
 % \end{macro}
@@ -6826,14 +7140,14 @@
           { \@@_insert_relax: } { \@@_input: }
       }
   }
-\cs_new_protected_nopar:Npn \@@_endinput:
+\cs_new_protected:Npn \@@_endinput:
   {
     \group_begin:
       \msg_warning:nn { unravel } { endinput-ignored }
     \group_end:
-    \@@_print_action:
+    \@@_print_expansion:
   }
-\cs_new_protected_nopar:Npn \@@_scantokens:
+\cs_new_protected:Npn \@@_scantokens:
   {
     \@@_prev_input_gpush:
     \@@_scan_toks:NN \c_false_bool \c_false_bool
@@ -6840,9 +7154,9 @@
     \@@_prev_input_gpop:N \l_@@_tmpa_tl
     \tl_set_rescan:Nno \l_@@_head_tl { } \l_@@_tmpa_tl
     \@@_back_input:V \l_@@_head_tl
-    \@@_print_action:x { \tl_to_str:N \l_@@_tmpa_tl }
+    \@@_print_expansion:x { \tl_to_str:N \l_@@_tmpa_tl }
   }
-\cs_new_protected_nopar:Npn \@@_input:
+\cs_new_protected:Npn \@@_input:
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
     \@@_scan_file_name:
@@ -6850,7 +7164,7 @@
     \tl_set:Nx \l_@@_tmpa_tl { \tl_tail:N \l_@@_head_tl }
     \@@_file_get:nN \l_@@_tmpa_tl \l_@@_tmpa_tl
     \@@_back_input:V \l_@@_tmpa_tl
-    \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+    \@@_print_expansion:x { \tl_to_str:N \l_@@_head_tl }
   }
 %    \end{macrocode}
 % \end{macro}
@@ -6860,13 +7174,13 @@
 \@@_new_tex_expandable:nn { cs_name }                       % 109
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_action:
+    \@@_print_expansion:
     \@@_csname_loop:
     \@@_prev_input_silent:V \l_@@_head_tl
     \@@_prev_input_gpop:N \l_@@_head_tl
     \@@_back_input_tl_o:
   }
-\cs_new_protected_nopar:Npn \@@_csname_loop:
+\cs_new_protected:Npn \@@_csname_loop:
   {
     \@@_get_x_next:
     \@@_gtl_if_head_is_definable:NTF \l_@@_head_gtl
@@ -6891,13 +7205,13 @@
 \@@_new_tex_expandable:nn { convert }                       % 110
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_action:
+    \@@_print_expansion:
     \int_case:nn \l_@@_head_char_int
       {
         0      \@@_scan_int:
         1      \@@_scan_int:
-        2 { \@@_get_next: \@@_prev_input:V \l_@@_head_tl }
-        3 { \@@_get_next: \@@_prev_input:V \l_@@_head_tl }
+        2      \@@_convert_string:
+        3      \@@_convert_meaning:
         4      \@@_scan_font_ident:
         8      \@@_scan_font_ident:
         9      \@@_scan_font_ident:
@@ -6925,18 +7239,41 @@
         { 28 } \@@_scan_int:
         { 30 } \@@_scan_int:
         { 31 } \@@_scan_pdfximagebbox:
+        { 33 } \@@_scan_directlua:
+        { 34 } \@@_scan_pdf_ext_toks:
+        { 35 } \@@_scan_pdf_ext_toks:
+        { 40 }
+          {
+            \@@_scan_int:
+            \@@_prev_input_silent:n { ~ }
+            \@@_scan_int:
+          }
       }
     \@@_prev_input_gpop:N \l_@@_head_tl
     \@@_back_input_tl_o:
   }
-\cs_new_protected_nopar:Npn \@@_scan_pdfstrcmp:
+\cs_new_protected:Npn \@@_convert_string:
   {
+    \@@_get_next:
+    \tl_if_empty:NTF \l_@@_head_tl
+      { \@@_prev_input:x { \gtl_to_str:N \l_@@_head_gtl } }
+      { \@@_prev_input:V \l_@@_head_tl }
+  }
+\cs_new_protected:Npn \@@_convert_meaning:
+  {
+    \@@_get_next:
+    \tl_if_empty:NTF \l_@@_head_tl
+      { \@@_prev_input:n { \l_@@_head_token } }
+      { \@@_prev_input:V \l_@@_head_tl }
+  }
+\cs_new_protected:Npn \@@_scan_pdfstrcmp:
+  {
     \@@_scan_toks_to_str:
     \@@_scan_toks_to_str:
   }
-\cs_new_protected_nopar:Npn \@@_scan_pdfximagebbox:
+\cs_new_protected:Npn \@@_scan_pdfximagebbox:
   { \@@_scan_int: \@@_scan_int: }
-\cs_new_protected_nopar:Npn \@@_scan_pdfcolorstackinit:
+\cs_new_protected:Npn \@@_scan_pdfcolorstackinit:
   {
     \@@_scan_keyword:nTF { pPaAgGeE }
       { \bool_set_true:N \l_@@_tmpa_bool }
@@ -6945,13 +7282,13 @@
       { \@@_scan_keyword:n { pPaAgGeE } }
     \@@_scan_toks_to_str:
   }
-\cs_new_protected_nopar:Npn \@@_scan_pdffiledump:
+\cs_new_protected:Npn \@@_scan_pdffiledump:
   {
     \@@_scan_keyword:nT { oOfFfFsSeEtT } \@@_scan_int:
     \@@_scan_keyword:nT { lLeEnNgGtThH } \@@_scan_int:
     \@@_scan_pdf_ext_toks:
   }
-\cs_new_protected_nopar:Npn \@@_scan_pdfmatch:
+\cs_new_protected:Npn \@@_scan_pdfmatch:
   {
     \@@_scan_keyword:n { iIcCaAsSeE }
     \@@_scan_keyword:nT { sSuUbBcCoOuUnNtT }
@@ -6959,21 +7296,33 @@
     \@@_scan_pdf_ext_toks:
     \@@_scan_pdf_ext_toks:
   }
+\sys_if_engine_luatex:T
+  {
+    \cs_new_protected:Npn \@@_scan_directlua:
+      {
+        \@@_get_x_non_relax:
+        \token_if_eq_catcode:NNTF \l_@@_head_token \c_group_begin_token
+          { \@@_back_input: }
+          {
+            \@@_scan_int:
+            \@@_get_x_non_relax:
+          }
+        \@@_scan_pdf_ext_toks:
+     }
+  }
 %    \end{macrocode}
 %
-% \begin{macro}{\@@_get_the:}
+% \begin{macro}{\@@_get_the:N}
+%   |#1| is \cs{@@_get_token_xdef:} in \tn{edef} or \tn{xdef},
+%   \cs{@@_get_token_x:} in \tn{message} and the like, and can be other
+%   commands.
 %    \begin{macrocode}
 \@@_new_tex_expandable:nn { the }                           % 111
+  { \@@_get_the:N }
+\cs_new_protected:Npn \@@_get_the:N #1
   {
-    \@@_get_the:
-    \tl_set:Nx \l_@@_tmpa_tl { \exp_args:NV \exp_not:o \l_@@_head_tl }
-    \@@_back_input:V \l_@@_tmpa_tl
-    \@@_print_action:
-  }
-\cs_new_protected_nopar:Npn \@@_get_the:
-  {
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_action:
+    \@@_print_expansion:
     \int_if_odd:nTF \l_@@_head_char_int
       { % \unexpanded, \detokenize
         \@@_scan_toks:NN \c_false_bool \c_false_bool
@@ -6992,6 +7341,24 @@
         \tl_set:Nx \l_@@_head_tl
           { \exp_not:N \exp_not:n { \tl_tail:N \l_@@_head_tl } }
       }
+    \cs_if_eq:NNTF #1 \@@_get_token_xdef:
+      {
+        \tl_put_right:NV \l_@@_defining_tl \l_@@_head_tl
+        \@@_prev_input:V \l_@@_head_tl
+      }
+      {
+        \cs_if_eq:NNTF #1 \@@_get_token_x:
+          {
+            \@@_exp_args:NNx \gtl_set:Nn \l_@@_tmpb_gtl { \l_@@_head_tl }
+            \@@_prev_input_gtl:N \l_@@_tmpb_gtl
+          }
+          {
+            \tl_set:Nx \l_@@_tmpa_tl { \exp_args:NV \exp_not:o \l_@@_head_tl }
+            \@@_back_input:V \l_@@_tmpa_tl
+          }
+        \@@_print_expansion:
+      }
+    #1
   }
 %    \end{macrocode}
 % \end{macro}
@@ -7013,10 +7380,10 @@
 % \subsubsection{Conditionals}
 %
 % ^^A todo: simply use \cs{@@_input_gpop:N} right away.
-% \begin{macro}[int]{\@@_pass_text:}
+% \begin{macro}{\@@_pass_text:}
 % \begin{macro}{\@@_pass_text_done:w}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_pass_text:
+\cs_new_protected:Npn \@@_pass_text:
   {
     \@@_input_if_empty:TF
       { \@@_pass_text_empty: }
@@ -7023,7 +7390,7 @@
       {
         \@@_input_get:N \l_@@_tmpb_gtl
         \if_true:
-          \if_case:w \gtl_head_do:NN \l_@@_tmpb_gtl \c_one
+          \if_case:w \gtl_head_do:NN \l_@@_tmpb_gtl \c_one_int
             \exp_after:wN \@@_pass_text_done:w
           \fi:
           \@@_input_gpop:N \l_@@_tmpb_gtl
@@ -7030,13 +7397,13 @@
           \exp_after:wN \@@_pass_text:
         \else:
           \use:c { fi: }
-          \int_set_eq:NN \l_@@_if_nesting_int \c_one
+          \int_set:Nn \l_@@_if_nesting_int { 1 }
           \@@_input_gpop:N \l_@@_tmpb_gtl
           \exp_after:wN \@@_pass_text_nested:
         \fi:
       }
   }
-\cs_new_protected_nopar:Npn \@@_pass_text_done:w
+\cs_new_protected:Npn \@@_pass_text_done:w
   {
     \@@_get_next:
     \token_if_eq_meaning:NNT \l_@@_head_token \fi: { \if_true: }
@@ -7063,7 +7430,7 @@
 %   \cs{fi:}, the nesting integer is decremented before removing most
 %   \cs{fi:}.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_pass_text_nested:
+\cs_new_protected:Npn \@@_pass_text_nested:
   {
     \@@_input_if_empty:TF
       { \@@_pass_text_empty: }
@@ -7080,7 +7447,7 @@
         \int_incr:N \l_@@_if_nesting_int
         \fi:
         \@@_input_gpop:N \l_@@_unused_gtl
-        \int_compare:nNnTF \l_@@_if_nesting_int = \c_zero
+        \int_compare:nNnTF \l_@@_if_nesting_int = 0
           { \@@_pass_text: }
           { \@@_pass_text_nested: }
       }
@@ -7090,7 +7457,7 @@
 %
 % \begin{macro}{\@@_pass_text_empty:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_pass_text_empty:
+\cs_new_protected:Npn \@@_pass_text_empty:
   {
     \@@_error:nnnnn { runaway-if } { } { } { } { }
     \@@_exit:w
@@ -7098,7 +7465,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_cond_push:, \@@_cond_pop:}
+% \begin{macro}{\@@_cond_push:, \@@_cond_pop:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_cond_push:
   {
@@ -7107,7 +7474,7 @@
     \int_gincr:N \g_@@_if_depth_int
     \int_gzero:N \g_@@_if_limit_int
   }
-\cs_new_protected_nopar:Npn \@@_cond_pop:
+\cs_new_protected:Npn \@@_cond_pop:
   {
     \int_gset:Nn \g_@@_if_limit_int
       { \tl_head:N \g_@@_if_limit_tl }
@@ -7126,7 +7493,7 @@
       { \int_gset:Nn \g_@@_if_limit_int {#1} }
       {
         \tl_clear:N \l_@@_tmpa_tl
-        \prg_replicate:nn { \g_@@_if_depth_int - #2 - \c_one }
+        \prg_replicate:nn { \g_@@_if_depth_int - #2 - 1 }
           {
             \tl_put_right:Nx \l_@@_tmpa_tl
               { { \tl_head:N \g_@@_if_limit_tl } }
@@ -7160,7 +7527,7 @@
       }
       {
         \@@_prev_input_gpush:N \l_@@_head_tl
-        \@@_print_action:
+        \@@_print_expansion:
         \int_case:nn \l_@@_head_char_int
           {
             {  0 } { \@@_test_two_chars: } % if
@@ -7208,7 +7575,7 @@
 \cs_new_protected:Npn \@@_cond_true:n #1
   {
     \@@_change_if_limit:nn { 3 } {#1} % wait for else/fi
-    \@@_print_action:x { \g_@@_action_text_str = true }
+    \@@_print_expansion:x { \g_@@_action_text_str = true }
   }
 %    \end{macrocode}
 % \end{macro}
@@ -7220,7 +7587,11 @@
   {
     \@@_cond_false_loop:n {#1}
     \@@_cond_false_common:
-    \@@_print_action:x { \g_@@_action_text_str = false }
+    \@@_print_expansion:x
+      {
+        \g_@@_action_text_str = false ~
+        => ~ skipped ~ to ~ \iow_char:N\\fi
+      }
   }
 \cs_new_protected:Npn \@@_cond_false_loop:n #1
   {
@@ -7239,7 +7610,7 @@
         \@@_cond_false_loop:n {#1}
       }
   }
-\cs_new_protected_nopar:Npn \@@_cond_false_common:
+\cs_new_protected:Npn \@@_cond_false_common:
   {
     \token_if_eq_meaning:NNTF \l_@@_head_token \fi:
       { \@@_cond_pop: }
@@ -7254,7 +7625,7 @@
   {
     #1
     \@@_get_x_non_blank:
-    \tl_if_in:nVF { < = > } \l_@@_head_tl
+    \@@_tl_if_in:ooTF { < = > } \l_@@_head_tl { }
       {
         \@@_error:nnnnn { missing-equals } { } { } { } { }
         \@@_back_input:
@@ -7270,7 +7641,7 @@
 % ^^A todo: fix non-brace begin-group and end-group tokens
 % \begin{macro}{\@@_test_two_chars:, \@@_test_two_chars_aux:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_test_two_chars:
+\cs_new_protected:Npn \@@_test_two_chars:
   {
     \@@_test_two_chars_aux:
     \@@_prev_input:V \l_@@_head_tl
@@ -7277,7 +7648,7 @@
     \@@_test_two_chars_aux:
     \@@_prev_input:V \l_@@_head_tl
   }
-\cs_new_protected_nopar:Npn \@@_test_two_chars_aux:
+\cs_new_protected:Npn \@@_test_two_chars_aux:
   {
     \@@_get_x_next:
     \gtl_if_tl:NF \l_@@_head_gtl
@@ -7293,23 +7664,37 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\@@_test_ifx:n, \@@_test_ifx_aux:w}
+% \begin{macro}{\@@_test_ifx:n, \@@_test_ifx_str:NN, \@@_test_ifx_aux:NNN, \@@_test_ifx_aux:w}
+%   The token equal to \tn{ifx} is pushed as a previous input to show an
+%   action nicely, then retrieved as \cs{l_@@_tmpa_tl} after getting the
+%   next two tokens as |tmpb| and |head|.  Then we call
+%   \cs{l_@@_tmpa_tl} followed by these two tokens.  A previous
+%   implementation made sure to get these tokens from unpacking the
+%   |gtl|, presumably (I should have documented, now I might be missing
+%   something) to deal nicely with the master counter in case these
+%   tokens are braces.  On the other hand we must take care of tokens
+%   affected by \tn{noexpand} and whose current definition is
+%   expandable, in which case the trustworthy \tn{meaning} is that of
+%   the \cs{l_@@_head_token} or \cs{l_@@_tmpb_token} rather than that of
+%   the token in \cs{l_@@_head_gtl} or \cs{l_@@_tmpb_gtl}.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_test_ifx:n #1
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_action:
+    \@@_print_expansion:
     \@@_get_next:
     \gtl_set_eq:NN \l_@@_tmpb_gtl \l_@@_head_gtl
+    \cs_set_eq:NN \l_@@_tmpb_token \l_@@_head_token
     \@@_get_next:
     \@@_prev_input_gpop:N \l_@@_tmpa_tl
     \@@_set_action_text:x
       {
         Compare:~ \tl_to_str:N \l_@@_tmpa_tl
-        \gtl_to_str:N \l_@@_tmpb_gtl
-        \gtl_to_str:N \l_@@_head_gtl
+        \@@_test_ifx_str:NN \l_@@_tmpb_token \l_@@_tmpb_gtl
+        \@@_test_ifx_str:NN \l_@@_head_token \l_@@_head_gtl
       }
-    \gtl_head_do:NN \l_@@_tmpb_gtl \@@_test_ifx_aux:w
+    \@@_test_ifx_aux:NNN \l_@@_tmpb_token \l_@@_tmpb_gtl
+      \@@_test_ifx_aux:w
       \exp_after:wN \@@_cond_true:n
     \else:
       \exp_after:wN \@@_cond_false:n
@@ -7316,8 +7701,26 @@
     \fi:
     {#1}
   }
-\cs_new_nopar:Npn \@@_test_ifx_aux:w
-  { \gtl_head_do:NN \l_@@_head_gtl \l_@@_tmpa_tl }
+\cs_new:Npn \@@_test_ifx_str:NN #1#2
+  {
+    \token_if_eq_meaning:NNT #1 \@@_special_relax:
+      { \iow_char:N \\notexpanded: }
+    \gtl_to_str:N #2
+  }
+\cs_new_protected:Npn \@@_test_ifx_aux:NNN #1#2#3
+  {
+    \token_if_eq_meaning:NNTF #1 \@@_special_relax:
+      {
+        \gtl_head_do:NN #2 \@@_token_if_expandable:NTF
+          { #3 #1 } { \gtl_head_do:NN #2 #3 }
+      }
+      { \gtl_head_do:NN #2 #3 }
+  }
+\cs_new:Npn \@@_test_ifx_aux:w
+  {
+    \@@_test_ifx_aux:NNN \l_@@_head_token \l_@@_head_gtl
+      \l_@@_tmpa_tl
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -7326,7 +7729,7 @@
 \cs_new_protected:Npn \@@_test_case:n #1
   {
     \@@_prev_input_gpush:N \l_@@_head_tl
-    \@@_print_action:
+    \@@_print_expansion:
     \bool_if:NT \g_@@_internal_debug_bool { \iow_term:n { {\ifcase level~#1} } }
     \@@_scan_int:
     \@@_prev_input_get:N \l_@@_head_tl
@@ -7334,11 +7737,11 @@
     % ^^A does text_case_aux use prev_input_seq?
     \exp_args:No \@@_test_case_aux:nn { \l_@@_head_tl } {#1}
     \@@_prev_input_gpop:N \l_@@_head_tl
-    \@@_print_action:x { \tl_to_str:N \l_@@_head_tl }
+    \@@_print_expansion:x { \tl_to_str:N \l_@@_head_tl }
   }
 \cs_new_protected:Npn \@@_test_case_aux:nn #1#2
   {
-    \int_compare:nNnTF {#1} = \c_zero
+    \int_compare:nNnTF {#1} = 0
       { \@@_change_if_limit:nn { 4 } {#2} }
       {
         \@@_pass_text:
@@ -7363,7 +7766,7 @@
 %
 % \begin{macro}{\@@_test_ifdefined:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_test_ifdefined:
+\cs_new_protected:Npn \@@_test_ifdefined:
   {
     \@@_input_if_empty:TF
       { \@@_pass_text_empty: }
@@ -7387,7 +7790,7 @@
 %
 % \begin{macro}{\@@_test_ifcsname:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_test_ifcsname:
+\cs_new_protected:Npn \@@_test_ifcsname:
   {
     \@@_csname_loop:
     \@@_prev_input:V \l_@@_head_tl
@@ -7400,9 +7803,9 @@
   {
     \int_compare:nNnTF \l_@@_head_char_int > \g_@@_if_limit_int
       {
-        \int_compare:nNnTF \g_@@_if_limit_int = \c_zero
+        \int_compare:nNnTF \g_@@_if_limit_int = 0
           {
-            \int_compare:nNnTF \g_@@_if_depth_int = \c_zero
+            \int_compare:nNnTF \g_@@_if_depth_int = 0
               { \@@_error:nnnnn { extra-fi-or-else } { } { } { } { } }
               { \@@_insert_relax: }
           }
@@ -7410,7 +7813,7 @@
       }
       {
         \@@_set_action_text:
-        \int_compare:nNnF \l_@@_head_char_int = \c_two
+        \int_compare:nNnF \l_@@_head_char_int = 2
           {
             \@@_fi_or_else_loop:
             \@@_set_action_text:x
@@ -7419,14 +7822,14 @@
                 => ~ skipped ~ to ~ \tl_to_str:N \l_@@_head_tl
               }
           }
-        % ^^A todo: in this print_action the token itself is missing.
-        \@@_print_action:
+        % ^^A todo: in the terminal output the token itself is missing.
+        \@@_print_expansion:
         \@@_cond_pop:
       }
   }
-\cs_new_protected_nopar:Npn \@@_fi_or_else_loop:
+\cs_new_protected:Npn \@@_fi_or_else_loop:
   {
-    \int_compare:nNnF \l_@@_head_char_int = \c_two
+    \int_compare:nNnF \l_@@_head_char_int = 2
       {
         \@@_pass_text:
         \@@_set_cmd:
@@ -7464,7 +7867,7 @@
 % \end{variable}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print:n, \@@_print:x}
+% \begin{macro}{\@@_print:n, \@@_print:x, \@@_log:n}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print:n #1
   {
@@ -7474,20 +7877,34 @@
   }
 \cs_new_protected:Npn \@@_print:x
   { \@@_exp_args:Nx \@@_print:n }
+\cs_new_protected:Npn \@@_log:n #1
+  {
+    \tl_set:Nn \l_@@_print_tl {#1}
+    \@@_print_normalize_null:
+    \@@_exp_args:Nx \iow_log:n { \l_@@_print_tl }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_message:nn}
+% \begin{macro}{\@@_print_message:nn}
 %   The message to be printed should come already detokenized, as~|#2|.
 %   It will be wrapped to 80 characters per line, with~|#1| before each
-%   line.
+%   line.  The message is properly suppressed (or sent only to the log)
+%   according to \cs{g_@@_online_int}.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_message:nn #1 #2
-  { \iow_wrap:nnnN { #1 #2 } { #1 } { } \@@_print:n }
+  {
+    \int_compare:nNnF \g_@@_online_int < 0
+      {
+        \int_compare:nNnTF \g_@@_online_int = 0
+          { \iow_wrap:nnnN { #1 #2 } { #1 } { } \@@_log:n }
+          { \iow_wrap:nnnN { #1 #2 } { #1 } { } \@@_print:n }
+      }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_set_action_text:x}
+% \begin{macro}{\@@_set_action_text:x}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_set_action_text:x #1
   {
@@ -7499,21 +7916,21 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_set_action_text:}
+% \begin{macro}{\@@_set_action_text:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_set_action_text:
+\cs_new_protected:Npn \@@_set_action_text:
   {
     \@@_set_action_text:x
       {
         \tl_to_str:N \l_@@_head_tl
         \tl_if_single_token:VT \l_@@_head_tl
-          { = ~ \exp_after:wN \token_to_meaning:N \l_@@_head_tl }
+          { = ~ \token_to_meaning:N \l_@@_head_token }
       }
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_state:}
+% \begin{macro}{\@@_print_state:}
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_state:
   {
@@ -7520,7 +7937,7 @@
     \group_begin:
       \@@_set_escapechar:n { 92 }
       \tl_use:N \g_@@_before_print_state_tl
-      \int_compare:nNnT \g_@@_noise_int > \c_zero
+      \int_compare:nNnT \g_@@_online_int > 0
         {
           \@@_print_state_output:
           \@@_print_state_prev:
@@ -7527,7 +7944,6 @@
           \@@_print_state_input:
         }
     \group_end:
-    \@@_prompt:
   }
 %    \end{macrocode}
 % \end{macro}
@@ -7537,7 +7953,7 @@
 %   The \cs{@@_str_truncate_left:nn} function trims |#1| if needed, to
 %   fit in a maximum of \cs{g_@@_max_output_int} characters.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_state_output:
+\cs_new_protected:Npn \@@_print_state_output:
   {
     \@@_exp_args:Nx \@@_print_state_output:n
       { \gtl_to_str:N \g_@@_output_gtl }
@@ -7556,7 +7972,7 @@
 % \begin{macro}{\@@_print_state_prev:}
 %   Never trim~|##1|.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_state_prev:
+\cs_new_protected:Npn \@@_print_state_prev:
   {
     \seq_set_map:NNn \l_@@_tmpa_seq \g_@@_prev_input_seq
       { \@@_to_str:n {##1} }
@@ -7578,7 +7994,7 @@
 %   \cs{@@_str_truncate_right:nn} function trims |#1| if needed, to fit
 %   in a maximum of \cs{g_@@_max_input_int} characters.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_state_input:
+\cs_new_protected:Npn \@@_print_state_input:
   {
     \@@_exp_args:Nx \@@_print_state_input:n
       { \@@_input_to_str: }
@@ -7609,57 +8025,65 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_action:, \@@_print_action:x}
+% \begin{macro}{\@@_print_action:, \@@_print_action:x, \@@_print_assignment:, \@@_print_assignment:x, \@@_print_expansion:, \@@_print_expansion:x, \@@_print_action_aux:N}
+%   Some of these commands are currently synonyms but we may decide to
+%   make some options act differently on them.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_print_action:
+  { \@@_print_action_aux:N \g_@@_trace_other_bool }
+\cs_new_protected:Npn \@@_print_action:x #1
   {
+    \@@_set_action_text:x {#1}
+    \@@_print_action:
+  }
+\cs_new_protected:Npn \@@_print_assignment:
+  { \@@_print_action_aux:N \g_@@_trace_assigns_bool }
+\cs_new_protected:Npn \@@_print_assignment:x #1
+  {
+    \@@_set_action_text:x {#1}
+    \@@_print_assignment:
+  }
+\cs_new_protected:Npn \@@_print_expansion:
+  { \@@_print_action_aux:N \g_@@_trace_expansion_bool }
+\cs_new_protected:Npn \@@_print_expansion:x #1
+  {
+    \@@_set_action_text:x {#1}
+    \@@_print_expansion:
+  }
+\cs_new_protected:Npn \@@_print_action_aux:N #1
+  {
+    \int_gdecr:N \g_@@_nonstop_int
     \int_gincr:N \g_@@_step_int
-    \@@_print:x
+    \bool_if:NT #1
       {
-        [=====
-        \bool_if:NT \g_@@_number_steps_bool
-          { ~ Step ~ \int_to_arabic:n { \g_@@_step_int } ~ }
-        =====]~
-        \int_compare:nNnTF
-          { \str_count:N \g_@@_action_text_str }
-          > { \g_@@_max_action_int }
+        \@@_print:x
           {
-            \str_range:Nnn \g_@@_action_text_str
-              { 1 } { \g_@@_max_action_int - 3 } ...
+            [=====
+            \bool_if:NT \g_@@_number_steps_bool
+              { ~ Step ~ \int_to_arabic:n { \g_@@_step_int } ~ }
+            =====]~
+            \int_compare:nNnTF
+              { \str_count:N \g_@@_action_text_str }
+              > { \g_@@_max_action_int }
+              {
+                \str_range:Nnn \g_@@_action_text_str
+                  { 1 } { \g_@@_max_action_int - 3 } ...
+              }
+              { \g_@@_action_text_str }
           }
-          { \g_@@_action_text_str }
+        \@@_print_state:
+        \@@_prompt:
       }
-    \@@_print_state:
   }
-\cs_new_protected:Npn \@@_print_action:x #1
-  {
-    \@@_set_action_text:x {#1}
-    \@@_print_action:
-  }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_gtl_action:N}
+% \begin{macro}{\@@_print_assigned_token:, \@@_print_assigned_register:}
 %    \begin{macrocode}
-\cs_new_protected:Npn \@@_print_gtl_action:N #1
+\cs_new_protected:Npn \@@_print_assigned_token:
   {
-    \@@_print_action:x { \gtl_to_str:N #1 }
-  }
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[int]{\@@_print_done:x}
-%    \begin{macrocode}
-\cs_new_eq:NN \@@_print_done:x \@@_print_action:x
-%    \end{macrocode}
-% \end{macro}
-%
-% \begin{macro}[int]{\@@_print_assigned_token:, \@@_print_assigned_register:}
-%    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_assigned_token:
-  {
     \@@_after_assignment: % ^^A todo: simplify
-    \@@_print_action:x
+    \@@_print_assignment:x
       {
         Set~ \exp_after:wN \token_to_str:N \l_@@_defined_tl
         = \exp_after:wN \token_to_meaning:N \l_@@_defined_tl
@@ -7666,10 +8090,10 @@
       }
     \@@_omit_after_assignment:w
   }
-\cs_new_protected_nopar:Npn \@@_print_assigned_register:
+\cs_new_protected:Npn \@@_print_assigned_register:
   {
     \@@_after_assignment: % ^^A todo: simplify
-    \@@_exp_args:Nx \@@_print_action:x
+    \@@_exp_args:Nx \@@_print_assignment:x
       {
         \exp_not:n
           {
@@ -7684,10 +8108,10 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_welcome:}
+% \begin{macro}{\@@_print_welcome:}
 %   Welcome message.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_welcome:
+\cs_new_protected:Npn \@@_print_welcome:
   {
     \@@_print_message:nn { }
       {
@@ -7706,38 +8130,38 @@
           { [=====~Start~=====] }
       }
     \@@_print_state:
+    \@@_prompt:
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_print_outcome:}
+% \begin{macro}{\@@_print_outcome:}
 %   Final message.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_print_outcome:
-  { \@@_print:n { [=====~End~=====] } }
+\cs_new_protected:Npn \@@_print_outcome:
+  { \@@_print_message:nn { } { [=====~End~=====] } }
 %    \end{macrocode}
 % \end{macro}
 %
 % \subsubsection{Prompt}
 %
-% \begin{macro}[int]{\@@_prompt:}
+% \begin{macro}{\@@_prompt:}
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_prompt:
+\cs_new_protected:Npn \@@_prompt:
   {
-    \int_gdecr:N \g_@@_nonstop_int
-    \int_compare:nNnF \g_@@_nonstop_int > \c_zero
+    \int_compare:nNnF \g_@@_nonstop_int > 0
       {
         \group_begin:
           \@@_set_escapechar:n { -1 }
-          \int_set_eq:NN \tex_endlinechar:D \c_minus_one
+          \int_set:Nn \tex_endlinechar:D { -1 }
           \tl_use:N \g_@@_before_prompt_tl
           \@@_prompt_aux:
         \group_end:
       }
   }
-\cs_new_protected_nopar:Npn \@@_prompt_aux:
+\cs_new_protected:Npn \@@_prompt_aux:
   {
-    \int_compare:nNnT { \etex_interactionmode:D } = { 3 }
+    \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
       {
         \bool_if:NTF \g_@@_explicit_prompt_bool
           { \ior_str_get:Nc \c_@@_prompt_ior }
@@ -7755,7 +8179,7 @@
             { m } { \@@_print_meaning: \@@_prompt_aux: }
             { q }
               {
-                \int_gset_eq:NN \g_@@_noise_int \c_minus_one
+                \int_gset:Nn \g_@@_online_int { -1 }
                 \int_gzero:N \g_@@_nonstop_int
               }
             { x }
@@ -7767,7 +8191,7 @@
             { s } { \@@_prompt_scan_int:nn {#1}
               \@@_prompt_silent_steps:n }
             { o } { \@@_prompt_scan_int:nn {#1}
-              { \int_gset:Nn \g_@@_noise_int } }
+              { \int_gset:Nn \g_@@_online_int } }
             { C }
               {
                 \@@_exp_args:Nx \use:n
@@ -7801,7 +8225,7 @@
 \cs_new_protected:Npn \@@_prompt_help:
   {
     \@@_print:n { "m":~meaning~of~first~token }
-    \@@_print:n { "q":~semi-quiet~(same~as~"o1") }
+    \@@_print:n { "q":~semi-quiet~(same~as~"o-1") }
     \@@_print:n { "x"/"X":~exit~this~instance~of~unravel/TeX }
     \@@_print:n { "s<num>":~do~<num>~steps~silently }
     \@@_print:n
@@ -7813,12 +8237,12 @@
   }
 \cs_new_protected:Npn \@@_prompt_silent_steps:n #1
   {
-    \int_compare:nNnF {#1} < \c_zero
+    \int_compare:nNnF {#1} < 0
       {
-        \int_gset_eq:NN \g_@@_noise_int \c_minus_one
+        \int_gset:Nn \g_@@_online_int { -1 }
         \tl_gset:Nn \g_@@_before_prompt_tl
           {
-            \int_gset_eq:NN \g_@@_noise_int \c_one
+            \int_gset:Nn \g_@@_online_int { 1 }
             \tl_gclear:N \g_@@_before_prompt_tl
           }
         \int_gset:Nn \g_@@_nonstop_int {#1}
@@ -7832,7 +8256,7 @@
   }
 \cs_new_protected:Npn \@@_prompt_vert:Nn #1#2
   {
-    \int_gset_eq:NN \g_@@_noise_int \c_minus_one
+    \int_gset:Nn \g_@@_online_int { -1 }
     \tl_gset:Nf \g_@@_before_print_state_tl
       {
         \exp_args:NNf \exp_stop_f: \int_compare:nNnTF
@@ -7843,12 +8267,12 @@
               { \int_max:nn { \g_@@_nonstop_int } { 2 } }
           }
           {
-            \int_gset_eq:NN \g_@@_noise_int \c_one
+            \int_gset:Nn \g_@@_online_int { 1 }
             \tl_gclear:N \g_@@_before_print_state_tl
           }
       }
   }
-\cs_new_protected_nopar:Npn \@@_prompt_all:
+\cs_new_protected:Npn \@@_prompt_all:
   {
     \tl_gset:Nx \g_@@_tmpc_tl
       {
@@ -7858,6 +8282,8 @@
             \int_gset_eq:NN \g_@@_max_output_int \c_max_int
             \int_gset_eq:NN \g_@@_max_input_int \c_max_int
             \@@_print_state:
+            \int_gdecr:N \g_@@_nonstop_int
+            \@@_prompt:
           }
         \@@_prompt_all_aux:N \g_@@_max_output_int
         \@@_prompt_all_aux:N \g_@@_max_input_int
@@ -7880,7 +8306,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_error:nnnnn, \@@_error:nxxxx}
+% \begin{macro}{\@@_error:nnnnn, \@@_error:nxxxx}
 %   Errors within a group to make sure that none of the \pkg{l3msg}
 %   variables (or others) that may be currently in use in the code being
 %   debugged are modified.
@@ -7900,18 +8326,18 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_tex_msg_new:nnn}
+% \begin{macro}{\@@_tex_msg_new:nnn}
 %   This stores a \TeX{} error message.
 %    \begin{macrocode}
 \cs_new_protected:Npn \@@_tex_msg_new:nnn #1#2#3
   {
-    \cs_new_nopar:cpn { @@_tex_msg_error_#1: } {#2}
-    \cs_new_nopar:cpn { @@_tex_msg_help_#1: } {#3}
+    \cs_new:cpn { @@_tex_msg_error_#1: } {#2}
+    \cs_new:cpn { @@_tex_msg_help_#1: } {#3}
   }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_tex_error:nn, \@@_tex_error:nV}
+% \begin{macro}{\@@_tex_error:nn, \@@_tex_error:nV}
 %   Throw the |tex-error| message, with arguments: |#2| which triggered
 %   the error, \TeX{}'s error message, and \TeX{}'s help text.
 %    \begin{macrocode}
@@ -7928,7 +8354,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_tex_fatal_error:nn, \@@_tex_fatal_error:nV}
+% \begin{macro}{\@@_tex_fatal_error:nn, \@@_tex_fatal_error:nV}
 %   Throw the |tex-fatal| error message, with arguments: |#2| which
 %   triggered the fatal error, \TeX{}'s error message, and \TeX{}'s
 %   help text.
@@ -7961,6 +8387,10 @@
     max-output       .int_gset:N  = \g_@@_default_max_output_int ,
     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 ,
+    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 ,
     welcome-message  .bool_gset:N = \g_@@_default_welcome_message_bool ,
   }
 \keys_define:nn { unravel }
@@ -7971,14 +8401,18 @@
     max-output       .int_gset:N  = \g_@@_max_output_int ,
     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 ,
+    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 ,
     welcome-message  .bool_gset:N = \g_@@_welcome_message_bool ,
   }
 %    \end{macrocode}
 %
-% The |machine| option is somewhat special so it is clearer to define
-% it separately.  The code is identical for |unravel/defaults| and
-% |unravel| keys.  To be sure of which options are set, use |.meta:nn|
-% and give the path explicitly.
+% The |machine| and |trace| options are somewhat special so it is
+% clearer to define them separately.  The code is identical for
+% |unravel/defaults| and |unravel| keys.  To be sure of which options
+% are set, use |.meta:nn| and give the path explicitly.
 %    \begin{macrocode}
 \tl_map_inline:nn { { /defaults } { } }
   {
@@ -7995,6 +8429,15 @@
             number-steps    = false ,
             welcome-message = false ,
           } ,
+        mute          .meta:nn =
+          { unravel #1 }
+          {
+            trace-assigns = false ,
+            trace-expansion = false ,
+            trace-other = false ,
+            welcome-message = false ,
+            online = -1 ,
+          }
       }
   }
 %    \end{macrocode}
@@ -8004,7 +8447,7 @@
 % \begin{macro}{\unravel}
 %   Simply call an underlying code-level command.
 %    \begin{macrocode}
-\NewDocumentCommand \unravel { O { } m } { \unravel:nn {#1} {#2} }
+\NewDocumentCommand \unravel { O { } +m } { \unravel:nn {#1} {#2} }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -8026,7 +8469,10 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\unravel:nn}
+% \begin{macro}{\unravel:nn, \@@:nn, \@@_unravel_marker:}
+%   The command starts with \cs{@@_unravel_marker:} to detect nesting of
+%   \tn{unravel} in \tn{unravel} and avoid re-initializing important
+%   variables.
 %   Initialize and setup keys.  Initialize and setup other variables
 %   including the input.  Welcome the user.  Then comes the main loop:
 %   until the input is exhausted, print the current status and do one
@@ -8035,7 +8481,9 @@
 %   (and last) one instead.  If the main loop finished correctly, print
 %   its outcome and finally test that everything is all right.
 %    \begin{macrocode}
-\cs_new_protected:Npn \unravel:nn #1#2
+\cs_new_protected:Npn \unravel:nn { \@@_unravel_marker: \@@:nn }
+\cs_new_eq:NN \@@_unravel_marker: \@@_special_relax:
+\cs_new_protected:Npn \@@:nn #1#2
   {
     \@@_init_key_vars:
     \keys_set:nn { unravel } {#1}
@@ -8048,6 +8496,11 @@
     \@@_final_test:
     \@@_exit_point:
   }
+\cs_new_protected:Npn \unravel_get:nnN #1#2#3
+  {
+    \unravel:nn {#1} {#2}
+    \tl_set:Nx #3 { \gtl_left_tl:N \g_@@_output_gtl }
+  }
 %    \end{macrocode}
 % \end{macro}
 %
@@ -8055,15 +8508,20 @@
 %   Give variables that are affected by keys their default values (also
 %   controlled by keys).
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_init_key_vars:
+\cs_new_protected:Npn \@@_init_key_vars:
   {
     \bool_gset_eq:NN \g_@@_explicit_prompt_bool \g_@@_default_explicit_prompt_bool
     \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
+    \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
     \bool_gset_eq:NN \g_@@_welcome_message_bool \g_@@_default_welcome_message_bool
     \int_gset_eq:NN \g_@@_max_action_int \g_@@_default_max_action_int
     \int_gset_eq:NN \g_@@_max_output_int \g_@@_default_max_output_int
     \int_gset_eq:NN \g_@@_max_input_int  \g_@@_default_max_input_int
+    \int_gzero:N \g_@@_nonstop_int
   }
 %    \end{macrocode}
 % \end{macro}
@@ -8073,7 +8531,7 @@
 %   have no reason to be modified by the user: neither directly nor
 %   through keys.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_init_vars:
+\cs_new_protected:Npn \@@_init_vars:
   {
     \seq_gclear:N \g_@@_prev_input_seq
     \gtl_gclear:N \g_@@_output_gtl
@@ -8089,11 +8547,11 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[int]{\@@_main_loop:}
+% \begin{macro}{\@@_main_loop:}
 %   Loop forever, getting the next token (with expansion) and
 %   performing the corresponding command.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_main_loop:
+\cs_new_protected:Npn \@@_main_loop:
   {
     \@@_get_x_next:
     \@@_set_cmd:
@@ -8108,19 +8566,19 @@
 %   Make sure that the \cs{unravel} finished correctly.  The error
 %   message is a bit primitive.
 %    \begin{macrocode}
-\cs_new_protected_nopar:Npn \@@_final_test:
+\cs_new_protected:Npn \@@_final_test:
   {
     \bool_if:nTF
       {
         \tl_if_empty_p:N \g_@@_if_limit_tl
-        && \int_compare_p:nNn \g_@@_if_limit_int = \c_zero
-        && \int_compare_p:nNn \g_@@_if_depth_int = \c_zero
+        && \int_compare_p:nNn \g_@@_if_limit_int = 0
+        && \int_compare_p:nNn \g_@@_if_depth_int = 0
         && \seq_if_empty_p:N \g_@@_prev_input_seq
       }
       { \@@_input_if_empty:TF { } { \@@_final_bad: } }
       { \@@_final_bad: }
   }
-\cs_new_protected_nopar:Npn \@@_final_bad:
+\cs_new_protected:Npn \@@_final_bad:
   {
     \@@_error:nnnnn { internal }
       { the-last-unravel-finished-badly } { } { } { }
@@ -8197,6 +8655,8 @@
   { The~primitive~\iow_char:N\\endinput~was~ignored. }
 \msg_new:nnn { unravel } { missing-something }
   { Something~is~missing,~sorry! }
+\msg_new:nnn { unravel } { nested-unravel }
+  { The~\iow_char:N\\unravel~command~may~not~be~nested. }
 \msg_new:nnnn { unravel } { tex-error }
   { TeX~sees~"#1"~and~throws~an~error:\\\\ \iow_indent:n {#2} }
   {

Modified: trunk/Master/texmf-dist/source/latex/unravel/unravel.ins
===================================================================
--- trunk/Master/texmf-dist/source/latex/unravel/unravel.ins	2018-12-28 21:32:01 UTC (rev 49514)
+++ trunk/Master/texmf-dist/source/latex/unravel/unravel.ins	2018-12-28 21:32:14 UTC (rev 49515)
@@ -6,7 +6,7 @@
 Do not distribute a modified version of this file.
 
 Communicate any suggestions for changing this package
-to Bruno Le Floch (blflatex at gmail.com).
+to Bruno Le Floch (blflatex+unravel at gmail.com).
 
 \endpreamble
 % stop docstrip adding \endinput

Modified: trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2018-12-28 21:32:01 UTC (rev 49514)
+++ trunk/Master/texmf-dist/tex/latex/unravel/unravel.sty	2018-12-28 21:32:14 UTC (rev 49515)
@@ -9,7 +9,7 @@
 %% Do not distribute a modified version of this file.
 %% 
 %% Communicate any suggestions for changing this package
-%% to Bruno Le Floch (blflatex at gmail.com).
+%% to Bruno Le Floch (blflatex+unravel at gmail.com).
 %% 
 %% File: unravel.dtx Copyright (C) 2013, 2015, 2018 Bruno Le Floch
 %%
@@ -147,19 +147,19 @@
   }
 \expandafter \endgroup \__unravel_setup_latexe:
 \RequirePackage{expl3,xparse}[2018/02/21]
-\RequirePackage{gtl}[2018/04/04]
+\RequirePackage{gtl}[2018/12/28]
 \csname cs_if_exist:cF\endcsname{str_range:nnn}{\RequirePackage{l3str}}
 \csname use:n\endcsname
   {%
     \csname __unravel_setup_restore:\endcsname
     \ProvidesExplPackage
-      {unravel} {2018/04/04} {0.2e} {Watching TeX digest tokens}%
+      {unravel} {2018/12/28} {0.2f} {Watching TeX digest tokens}%
     \csname __unravel_setup_unravel:\endcsname
   }%
-\cs_new_eq:NN \__unravel_currentgrouptype:      \etex_currentgrouptype:D
-\cs_new_protected_nopar:Npn \__unravel_set_escapechar:n
+\cs_new_eq:NN \__unravel_currentgrouptype:      \tex_currentgrouptype:D
+\cs_new_protected:Npn \__unravel_set_escapechar:n
   { \int_set:Nn \tex_escapechar:D }
-\cs_new_eq:NN \__unravel_everyeof:w             \etex_everyeof:D
+\cs_new_eq:NN \__unravel_everyeof:w             \tex_everyeof:D
 \cs_new_eq:NN \__unravel_everypar:w             \tex_everypar:D
 \cs_new_eq:NN \__unravel_hbox:w                 \tex_hbox:D
 \cs_new_eq:NN \__unravel_mag:                   \tex_mag:D
@@ -166,15 +166,16 @@
 \cs_new_eq:NN \__unravel_nullfont:              \tex_nullfont:D
 \cs_new_eq:NN \__unravel_the:w                  \tex_the:D
 \cs_new_eq:NN \__unravel_number:w               \tex_number:D
-\cs_new_eq:NN \c__unravel_prompt_ior \c_sixteen
-\cs_new_eq:NN \c__unravel_noprompt_ior \c_minus_one
+\exp_after:wN \cs_new_eq:NN
+  \exp_after:wN \__unravel_special_relax:
+  \exp_not:N \__unravel_special_relax:
+\int_const:Nn \c__unravel_prompt_ior { 16 }
+\int_const:Nn \c__unravel_noprompt_ior { -1 }
 \cs_generate_variant:Nn \seq_push:Nn { Nf }
 \cs_generate_variant:Nn \str_head:n { f }
 \cs_generate_variant:Nn \tl_to_str:n { o }
+\cs_generate_variant:Nn \tl_if_eq:nnTF { o }
 \cs_generate_variant:Nn \tl_if_head_eq_meaning:nNT { V }
-\cs_generate_variant:Nn \tl_if_in:nnF { nV }
-\cs_generate_variant:Nn \tl_if_in:nnTF { nV }
-\cs_generate_variant:Nn \tl_if_in:NnTF { No , NV }
 \cs_generate_variant:Nn \tl_if_single_token:nT { V }
 \cs_generate_variant:Nn \gtl_gput_right:Nn { NV }
 \cs_generate_variant:Nn \ior_str_get:NN { Nc }
@@ -186,6 +187,12 @@
 \cs_generate_variant:Nn \gtl_gconcat:NNN { ccc , cNc }
 \cs_generate_variant:Nn \gtl_gclear:N { c }
 \cs_generate_variant:Nn \gtl_gclear_new:N { c }
+\cs_new_protected:Npn \__unravel_tl_if_in:ooTF #1#2#3#4
+  {
+    \group_begin:
+    \exp_args:Noo \tl_if_in:nnTF {#1} {#2}
+      { \group_end: #3 } { \group_end: #4 }
+  }
 \tl_new:N \l__unravel_exp_tl
 \cs_new_protected:Npn \__unravel_exp_args:Nx #1#2
   {
@@ -197,7 +204,7 @@
     \cs_set_nopar:Npx \l__unravel_exp_tl { \exp_not:N #1 \exp_not:N #2 {#3} }
     \l__unravel_exp_tl
   }
-\cs_new_protected_nopar:Npn \__unravel_tmp:w { }
+\cs_new_protected:Npn \__unravel_tmp:w { }
 \cs_set_protected:Npn \__unravel_tmp:w #1
   {
     \cs_new_protected:Npn \__unravel_file_get:nN ##1##2
@@ -241,7 +248,7 @@
       }
     #1
   }
-\cs_new_protected_nopar:Npn \__unravel_prepare_mag:
+\cs_new_protected:Npn \__unravel_prepare_mag:
   {
     \int_compare:nNnT { \g__unravel_mag_set_int } > { 0 }
       {
@@ -258,15 +265,15 @@
       }
     \int_gset_eq:NN \g__unravel_mag_set_int \__unravel_mag:
   }
-\cs_new_nopar:Npn \__unravel_strip_escape:w
+\cs_new:Npn \__unravel_strip_escape:w
   {
     \tex_romannumeral:D
       \if_charcode:w \token_to_str:N \ \__unravel_strip_escape_aux:w \fi:
       \__unravel_strip_escape_aux:N
   }
-\cs_new:Npn \__unravel_strip_escape_aux:N #1 { \c_zero }
+\cs_new:Npn \__unravel_strip_escape_aux:N #1 { \c_zero_int }
 \cs_new:Npn \__unravel_strip_escape_aux:w #1#2
-  { - \__unravel_number:w #1 \c_zero }
+  { - \__unravel_number:w #1 \c_zero_int }
 \cs_new:Npn \__unravel_to_str:n #1
   {
     \tl_if_head_eq_meaning:nNTF {#1} \scan_stop:
@@ -366,6 +373,20 @@
   }
 \group_begin:
   \char_set_catcode_active:n { `Z }
+  \prg_new_protected_conditional:Npnn \__unravel_token_if_active_char:N #1
+    { TF }
+    {
+      \group_begin:
+        \__unravel_exp_args:Nx \char_set_lccode:nn
+          { ` \exp_args:No \str_head:n { \token_to_str:N #1 } }
+          { ` Z }
+        \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { Z }
+          { \group_end: \prg_return_true: }
+          { \group_end: \prg_return_false: }
+    }
+\group_end:
+\group_begin:
+  \char_set_catcode_active:n { `Z }
   \prg_new_protected_conditional:Npnn \__unravel_token_if_definable:N #1
     { TF }
     {
@@ -375,9 +396,7 @@
           { \exp_args:No \str_tail:n { \token_to_str:N #1 } }
         \tl_if_empty:NTF \l__unravel_tmpa_tl
           {
-            \exp_args:Nx \char_set_lccode:nn
-              { ` \str_head:n {#1} } { `Z }
-            \tex_lowercase:D { \tl_if_eq:nnTF {#1} } { Z }
+            \__unravel_token_if_active_char:NTF #1
               { \group_end: \prg_return_true: }
               { \group_end: \prg_return_false: }
           }
@@ -399,7 +418,7 @@
       }
       { \prg_return_false: }
   }
-\cs_new_nopar:Npn \__unravel_prev_input_count:
+\cs_new:Npn \__unravel_prev_input_count:
   {
     \int_eval:n
       {
@@ -410,19 +429,19 @@
   }
 \cs_new:Npn \__unravel_prev_input_count_aux:n #1
   { \tl_if_empty:nF {#1} { + 1 } }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_get:N
+\cs_new_protected:Npn \__unravel_prev_input_get:N
   { \seq_get_right:NN \g__unravel_prev_input_seq }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpush:
+\cs_new_protected:Npn \__unravel_prev_input_gpush:
   { \seq_gput_right:Nn \g__unravel_prev_input_seq { } }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpush:N
+\cs_new_protected:Npn \__unravel_prev_input_gpush:N
   { \seq_gput_right:NV \g__unravel_prev_input_seq }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpop:N
+\cs_new_protected:Npn \__unravel_prev_input_gpop:N
   { \seq_gpop_right:NN \g__unravel_prev_input_seq }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpush_gtl:
+\cs_new_protected:Npn \__unravel_prev_input_gpush_gtl:
   { \seq_gput_right:NV \g__unravel_prev_input_seq \c_empty_gtl }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpush_gtl:N
+\cs_new_protected:Npn \__unravel_prev_input_gpush_gtl:N
   { \seq_gput_right:NV \g__unravel_prev_input_seq }
-\cs_new_protected_nopar:Npn \__unravel_prev_input_gpop_gtl:N
+\cs_new_protected:Npn \__unravel_prev_input_gpop_gtl:N
   { \seq_gpop_right:NN \g__unravel_prev_input_seq }
 \cs_new_protected:Npn \__unravel_prev_input_silent:n #1
   {
@@ -451,8 +470,8 @@
   {
     \int_case:nnF {#1}
       {
-        { 2 } { \__unravel_join_get_aux:NNN \skip_eval:n \etex_glueexpr:D }
-        { 3 } { \__unravel_join_get_aux:NNN \muskip_eval:n \etex_muexpr:D }
+        { 2 } { \__unravel_join_get_aux:NNN \skip_eval:n \tex_glueexpr:D }
+        { 3 } { \__unravel_join_get_aux:NNN \muskip_eval:n \tex_muexpr:D }
       }
       {
         \__unravel_error:nnnnn { internal } { join-factor } { } { } { }
@@ -469,17 +488,27 @@
 \tl_new:N  \g__unravel_before_prompt_tl
 \int_new:N \l__unravel_prompt_tmpa_int
 \int_new:N \g__unravel_nonstop_int
-\int_new:N \g__unravel_noise_int
-\int_gset_eq:NN \g__unravel_noise_int \c_one
 \bool_new:N \g__unravel_default_explicit_prompt_bool
 \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
+\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
+\bool_new:N \g__unravel_default_welcome_message_bool
 \bool_gset_true:N \g__unravel_default_number_steps_bool
-\bool_new:N \g__unravel_default_welcome_message_bool
+\int_gset:Nn   \g__unravel_default_online_int { 1 }
+\bool_gset_true:N \g__unravel_default_trace_assigns_bool
+\bool_gset_true:N \g__unravel_default_trace_expansion_bool
+\bool_gset_true:N \g__unravel_default_trace_other_bool
 \bool_gset_true:N \g__unravel_default_welcome_message_bool
 \bool_new:N \g__unravel_explicit_prompt_bool
 \bool_new:N \g__unravel_internal_debug_bool
 \bool_new:N \g__unravel_number_steps_bool
+\int_new:N  \g__unravel_online_int
+\bool_new:N \g__unravel_trace_assigns_bool
+\bool_new:N \g__unravel_trace_expansion_bool
+\bool_new:N \g__unravel_trace_other_bool
 \bool_new:N \g__unravel_welcome_message_bool
 \int_new:N \g__unravel_step_int
 \str_new:N \g__unravel_action_text_str
@@ -508,11 +537,14 @@
 \int_new:N \l__unravel_head_cmd_int
 \int_new:N \l__unravel_head_char_int
 \tl_new:N \l__unravel_head_meaning_tl
+\tl_new:N \l__unravel_argi_tl
+\tl_new:N \l__unravel_argii_tl
 \tl_new:N \l__unravel_tmpa_tl
 \gtl_new:N \l__unravel_unused_gtl
 \gtl_new:N \l__unravel_tmpb_gtl
 \tl_new:N \g__unravel_tmpc_tl
 \seq_new:N \l__unravel_tmpa_seq
+\cs_new_eq:NN \l__unravel_tmpb_token ?
 \tl_new:N \l__unravel_defined_tl
 \tl_new:N \l__unravel_defining_tl
 \cs_new_eq:NN \__unravel_inaccessible:w ?
@@ -557,7 +589,7 @@
   }
 \cs_new_protected:Npn \__unravel_new_tex_cmd:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { __unravel_cmd_ \__unravel_tex_use:n {#1} : } {#2}
   }
 \cs_new_protected:Npn \__unravel_new_eq_tex_cmd:nn #1#2
@@ -568,7 +600,7 @@
   }
 \cs_new_protected:Npn \__unravel_new_tex_expandable:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { __unravel_expandable_ \__unravel_tex_use:n {#1} : } {#2}
   }
 \__unravel_tex_const:nn { relax                    } { 0 }
@@ -692,6 +724,12 @@
 \__unravel_tex_const:nn { top_bot_mark             } { 112 }
 \__unravel_tex_const:nn { call                     } { 113 }
 \__unravel_tex_const:nn { end_template             } { 117 }
+\sys_if_engine_luatex:T
+  {
+    \__unravel_tex_primitive:nnn
+      { \exp_after:wN \use_none:n \token_to_meaning:N \__unravel_special_relax: }
+      { relax } { 1 }
+  }
 \__unravel_tex_primitive:nnn { relax             } { relax    } { 256 }
 \__unravel_tex_primitive:nnn { span              } { tab_mark } { 256 }
 \__unravel_tex_primitive:nnn { cr                } { car_ret  } { 257 }
@@ -1200,7 +1238,8 @@
 \__unravel_tex_primitive:nnn { pdfescapename     } { convert } { 14 }
 \__unravel_tex_primitive:nnn { leftmarginkern    } { convert } { 15 }
 \__unravel_tex_primitive:nnn { rightmarginkern   } { convert } { 16 }
-\__unravel_tex_primitive:nnn { pdfstrcmp         } { convert } { 17 }
+\__unravel_tex_primitive:nnn
+  { \sys_if_engine_xetex:F { pdf } strcmp } { convert } { 17 }
 \__unravel_tex_primitive:nnn { pdfcolorstackinit } { convert } { 18 }
 \__unravel_tex_primitive:nnn { pdfescapehex      } { convert } { 19 }
 \__unravel_tex_primitive:nnn { pdfunescapehex    } { convert } { 20 }
@@ -1216,6 +1255,16 @@
 \__unravel_tex_primitive:nnn { pdfinsertht       } { convert } { 30 }
 \__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 }
+  }
+\sys_if_engine_xetex:T
+  {
+    \__unravel_tex_primitive:nnn { Ucharcat        } { convert } { 40 }
+  }
 \__unravel_tex_primitive:nnn { the               } { the } { 0 }
 \__unravel_tex_primitive:nnn { unexpanded        } { the } { 1 }
 \__unravel_tex_primitive:nnn { detokenize        } { the } { 5 }
@@ -1229,7 +1278,7 @@
 \__unravel_tex_primitive:nnn { botmarks          } { top_bot_mark } { 7 }
 \__unravel_tex_primitive:nnn { splitfirstmarks   } { top_bot_mark } { 8 }
 \__unravel_tex_primitive:nnn { splitbotmarks     } { top_bot_mark } { 9 }
-\cs_new_protected_nopar:Npn \__unravel_get_next:
+\cs_new_protected:Npn \__unravel_get_next:
   {
     \__unravel_input_if_empty:TF
       { \__unravel_exit:w }
@@ -1240,18 +1289,81 @@
           {
             \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_nopar:Npn \__unravel_get_next_aux:w
+\cs_new_protected:Npn \__unravel_get_next_aux:w
   { \cs_set_eq:NN \l__unravel_head_token }
-\cs_new_protected_nopar:Npn \__unravel_get_token:
+\cs_set_protected:Npn \__unravel_tmp:w #1
   {
+    \cs_new_protected:Npn \__unravel_get_next_notexpanded:
+      {
+        \tl_if_eq:onTF { \l__unravel_head_tl } { \__unravel_unravel_marker: }
+          { \__unravel_get_next_marker: }
+          {
+            \__unravel_exp_args:NNx \use:nn \__unravel_notexpanded_test:w
+              { \scan_stop: \exp_after:wN \cs_to_str:N \l__unravel_head_tl Z }
+              \q_mark \__unravel_notexpanded_expand:n
+              #1 Z \q_mark \use_none:n
+              \q_stop
+          }
+      }
+    \cs_new_protected:Npn \__unravel_notexpanded_test:w
+        ##1 #1 ##2 Z \q_mark ##3##4 \q_stop
+      { ##3 {##2} }
+  }
+\exp_args:Nx \__unravel_tmp:w { \scan_stop: \tl_to_str:n { notexpanded: } }
+\group_begin:
+  \char_set_catcode_active:n { 0 }
+  \cs_new_protected:Npn \__unravel_notexpanded_expand:n #1
+    {
+      \__unravel_exp_args:Nx \tl_if_empty:nTF { \str_tail:n {#1} }
+        {
+          \group_begin:
+          \char_set_lccode:nn { 0 } { `#1 }
+          \tex_lowercase:D
+            {
+              \group_end:
+              \__unravel_notexpanded_expand:N ^^@
+            }
+        }
+        {
+          \group_begin: \exp_args:NNc \group_end:
+          \__unravel_notexpanded_expand:N { \use_none:n #1 }
+        }
+    }
+\group_end:
+\cs_new_protected:Npn \__unravel_notexpanded_expand:N #1
+  {
+    \gtl_set:Nn \l__unravel_head_gtl {#1}
+    \tl_set:Nn \l__unravel_head_tl {#1}
+    \cs_set_eq:NN \l__unravel_head_token \__unravel_special_relax:
+  }
+\cs_new_protected:Npn \__unravel_get_next_marker:
+  {
     \__unravel_get_next:
+    \tl_if_eq:onTF \l__unravel_head_tl { \__unravel:nn }
+      { \__unravel_error:nxxxx { nested-unravel } { } { } { } { } }
+      { \__unravel_error:nxxxx { internal } { marker~unknown } { } { } { } }
+    \__unravel_input_gpop_item:NF \l__unravel_argi_tl
+      { \__unravel_error:nxxxx { internal } { marker~1 } { } { } { } }
+    \__unravel_input_gpop_item:NF \l__unravel_argii_tl
+      { \__unravel_error:nxxxx { internal } { marker~2 } { } { } { } }
+    \exp_args:Nno \keys_set:nn { unravel } \l__unravel_argi_tl
+    \__unravel_exp_args:Nx \__unravel_back_input:n
+      { \exp_not:N \exp_not:n { \exp_not:o \l__unravel_argii_tl } }
+    \__unravel_get_next:
+  }
+\cs_new_protected:Npn \__unravel_get_token:
+  {
+    \__unravel_get_next:
     \__unravel_set_cmd:
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd:
+\cs_new_protected:Npn \__unravel_set_cmd:
   {
     \__unravel_set_cmd_aux_meaning:
     \__unravel_set_cmd_aux_primitive:oTF { \l__unravel_head_meaning_tl }
@@ -1270,7 +1382,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_meaning:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_meaning:
   {
     \tl_set:Nx \l__unravel_head_meaning_tl
       {
@@ -1304,12 +1416,12 @@
     \int_set:Nn \l__unravel_head_cmd_int {#1}
     \int_set:Nn \l__unravel_head_char_int {#2}
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_macro:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_macro:
   {
     \int_set:Nn \l__unravel_head_cmd_int { \__unravel_tex_use:n { call } }
     \int_zero:N \l__unravel_head_char_int
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_unknown:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_unknown:
   {
     \exp_last_unbraced:NV \__unravel_set_cmd_aux_primitive:nn
       \c__unravel_tex_relax_tl
@@ -1316,9 +1428,9 @@
     \__unravel_error:nxxxx { unknown-primitive }
       { \l__unravel_head_meaning_tl } { } { } { }
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_cs:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_cs:
   {
-    \tl_if_in:NoTF \l__unravel_head_meaning_tl
+    \__unravel_tl_if_in:ooTF \l__unravel_head_meaning_tl
       { \tl_to_str:n { elect~font } }
       {
         \exp_last_unbraced:NV \__unravel_set_cmd_aux_primitive:nn
@@ -1326,7 +1438,7 @@
       }
       { \__unravel_set_cmd_aux_numeric: }
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_numeric:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_numeric:
   {
     \tl_set:Nx \l__unravel_tmpa_tl
       {
@@ -1349,6 +1461,7 @@
     \str_case:nnF {#1}
       {
         { 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 } }
       }
       {
@@ -1364,7 +1477,7 @@
     \int_set:Nn \l__unravel_head_cmd_int { \__unravel_tex_use:n {#1} }
     \int_zero:N \l__unravel_head_char_int
   }
-\cs_new_protected_nopar:Npn \__unravel_set_cmd_aux_char:
+\cs_new_protected:Npn \__unravel_set_cmd_aux_char:
   {
     \tl_set:Nx \l__unravel_head_meaning_tl
       { \token_to_meaning:N \l__unravel_head_token }
@@ -1380,7 +1493,7 @@
     \int_set:Nn \l__unravel_head_cmd_int
       { \__unravel_tex_use:n { #1_char } }
   }
-\cs_new_nopar:Npn \__unravel_input_to_str:
+\cs_new:Npn \__unravel_input_to_str:
   {
     \int_step_function:nnnN \g__unravel_input_int { -1 } { 1 }
       \__unravel_input_to_str_aux:n
@@ -1389,7 +1502,7 @@
   { \gtl_to_str:c { g__unravel_input_#1_gtl } }
 \cs_new_protected:Npn \__unravel_input_if_empty:TF
   {
-    \int_compare:nNnTF \g__unravel_input_int = \c_zero
+    \int_compare:nNnTF \g__unravel_input_int = 0
       { \use_i:nn }
       {
         \gtl_if_empty:cTF
@@ -1404,9 +1517,9 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_input_split:
+\cs_new_protected:Npn \__unravel_input_split:
   {
-    \int_compare:nNnT \g__unravel_input_int = \c_one
+    \int_compare:nNnT \g__unravel_input_int = 1
       {
         \exp_args:Nc \__unravel_input_split_aux:N
           { g__unravel_input_1_gtl }
@@ -1441,7 +1554,7 @@
         \l__unravel_input_tmpa_tl \__unravel_input_split_end:
       }
   }
-\cs_new_nopar:Npn \__unravel_input_split_end: { }
+\cs_new:Npn \__unravel_input_split_end: { }
 \cs_new_protected:Npn \__unravel_input_split_auxiii:w
     #1 \__unravel_input_split_end:
   {
@@ -1451,7 +1564,7 @@
       { g__unravel_input_ \int_use:N \g__unravel_input_tmpa_int _gtl } {#1}
     \int_gdecr:N \g__unravel_input_tmpa_int
   }
-\cs_new_protected_nopar:Npn \__unravel_input_gset:n
+\cs_new_protected:Npn \__unravel_input_gset:n
   {
     \int_gzero:N \g__unravel_input_int
     \__unravel_back_input:n
@@ -1474,7 +1587,7 @@
           { g__unravel_input_ \int_use:N \g__unravel_input_int _gtl } #1
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_input_merge:
+\cs_new_protected:Npn \__unravel_input_merge:
   {
     \int_gdecr:N \g__unravel_input_int
     \gtl_gconcat:ccc
@@ -1486,7 +1599,7 @@
   }
 \prg_new_protected_conditional:Npnn \__unravel_input_gpop_item:N #1 { F }
   {
-    \int_compare:nNnTF \g__unravel_input_int = \c_zero
+    \int_compare:nNnTF \g__unravel_input_int = 0
       { \prg_return_false: }
       {
         \exp_args:Nc \__unravel_input_gpop_item_aux:NN
@@ -1498,10 +1611,10 @@
     \gtl_gpop_left_item:NNTF #1#2
       { \prg_return_true: }
       {
-        \int_compare:nNnTF { \gtl_extra_end:N #1 } > \c_zero
+        \int_compare:nNnTF { \gtl_extra_end:N #1 } > 0
           { \prg_return_false: }
           {
-            \int_compare:nNnTF \g__unravel_input_int = \c_one
+            \int_compare:nNnTF \g__unravel_input_int = 1
               { \prg_return_false: }
               {
                 \__unravel_input_merge:
@@ -1519,7 +1632,7 @@
   { \tl_clear:N #1 \__unravel_input_gpop_tl_aux:N #1 }
 \cs_new_protected:Npn \__unravel_input_gpop_tl_aux:N #1
   {
-    \int_compare:nNnF \g__unravel_input_int = \c_zero
+    \int_compare:nNnF \g__unravel_input_int = 0
       {
         \exp_args:Nc \__unravel_input_gpop_tl_aux:NN
           { g__unravel_input_ \int_use:N \g__unravel_input_int _gtl } #1
@@ -1535,8 +1648,8 @@
         \__unravel_input_gpop_tl_aux:N #2
       }
       {
-        \int_compare:nNnTF \g__unravel_input_int > \c_one
-          { \int_compare:nNnTF { \gtl_extra_end:N #1 } > \c_zero }
+        \int_compare:nNnTF \g__unravel_input_int > 1
+          { \int_compare:nNnTF { \gtl_extra_end:N #1 } > 0 }
           { \use_i:nn }
           {
             \tl_put_right:Nx #2 { \gtl_left_tl:N #1 }
@@ -1548,7 +1661,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_back_input:n
+\cs_new_protected:Npn \__unravel_back_input:n
   {
     \int_gincr:N \g__unravel_input_int
     \gtl_gclear_new:c { g__unravel_input_ \int_use:N \g__unravel_input_int _gtl }
@@ -1568,17 +1681,17 @@
           { g__unravel_input_ \int_use:N \g__unravel_input_int _gtl }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_back_input:
+\cs_new_protected:Npn \__unravel_back_input:
   { \__unravel_back_input_gtl:N \l__unravel_head_gtl }
-\cs_new_protected_nopar:Npn \__unravel_back_input_tl_o:
+\cs_new_protected:Npn \__unravel_back_input_tl_o:
   {
     \tl_set:Nx \l__unravel_tmpa_tl
       { \exp_args:NV \exp_not:o \l__unravel_head_tl }
     \__unravel_back_input:V \l__unravel_tmpa_tl
-    \__unravel_print_done:x
+    \__unravel_print_expansion:x
       { \tl_to_str:N \l__unravel_head_tl = \tl_to_str:N \l__unravel_tmpa_tl }
   }
-\cs_new_protected_nopar:Npn \__unravel_insert_relax:
+\cs_new_protected:Npn \__unravel_insert_relax:
   {
     \__unravel_back_input:
     \gtl_set_eq:NN \l__unravel_head_gtl \c__unravel_frozen_relax_gtl
@@ -1585,7 +1698,7 @@
     \__unravel_back_input:
     \__unravel_print_action:
   }
-\cs_new_protected_nopar:Npn \__unravel_insert_group_begin_error:
+\cs_new_protected:Npn \__unravel_insert_group_begin_error:
   {
     \tl_set_eq:NN \l__unravel_tmpa_tl \l__unravel_head_tl
     \__unravel_back_input:
@@ -1594,7 +1707,7 @@
     \__unravel_tex_error:nV { missing-lbrace } \l__unravel_tmpa_tl
     \__unravel_print_action:
   }
-\cs_new_protected_nopar:Npn \__unravel_insert_dollar_error:
+\cs_new_protected:Npn \__unravel_insert_dollar_error:
   {
     \__unravel_back_input:
     \__unravel_back_input:n { $ } % $
@@ -1621,25 +1734,25 @@
   { \__unravel_macro_split_do:NN #1 \use_ii:nnn }
 \cs_new:Npn \__unravel_macro_replacement:N #1
   { \__unravel_macro_split_do:NN #1 \use_iii:nnn }
-\cs_new_protected_nopar:Npn \__unravel_macro_call:
+\cs_new_protected:Npn \__unravel_macro_call:
   {
     \bool_if:NTF \g__unravel_speedup_macros_bool
       {
         \tl_set:Nx \l__unravel_tmpa_tl
           {^ \exp_after:wN \__unravel_macro_parameter:N \l__unravel_head_tl }
-        \tl_if_in:NVTF \c__unravel_parameters_tl \l__unravel_tmpa_tl
+        \__unravel_tl_if_in:ooTF \c__unravel_parameters_tl \l__unravel_tmpa_tl
           { \__unravel_macro_call_quick: } { \__unravel_macro_call_safe: }
       }
       { \__unravel_macro_call_safe: }
     \exp_args:NV \__unravel_back_input:o \l__unravel_head_tl
-    \__unravel_print_done:x { \g__unravel_action_text_str }
+    \__unravel_print_expansion:
   }
-\cs_new_protected_nopar:Npn \__unravel_macro_call_safe:
+\cs_new_protected:Npn \__unravel_macro_call_safe:
   {
     \__unravel_input_gpop_tl:N \l__unravel_tmpa_tl
     \tl_put_right:NV \l__unravel_head_tl \l__unravel_tmpa_tl
   }
-\cs_new_protected_nopar:Npn \__unravel_macro_call_quick:
+\cs_new_protected:Npn \__unravel_macro_call_quick:
   {
     \exp_after:wN \__unravel_macro_call_quick_loop:NNN \l__unravel_tmpa_tl
       { ? \use_none_delimit_by_q_stop:w } \q_stop
@@ -1659,7 +1772,7 @@
     \__unravel_error:nxxxx { runaway-macro-parameter }
       { \tl_to_str:N \l__unravel_head_tl } { \tl_to_str:n {#1} } { } { }
   }
-\cs_new_protected_nopar:Npn \__unravel_expand:
+\cs_new_protected:Npn \__unravel_expand_do:N
   {
     \__unravel_set_action_text:
     \bool_if:NT \g__unravel_internal_debug_bool
@@ -1671,7 +1784,7 @@
       { \__unravel_macro_call: }
       { \__unravel_expand_nonmacro: }
   }
-\cs_new_protected_nopar:Npn \__unravel_expand_nonmacro:
+\cs_new_protected:Npn \__unravel_expand_nonmacro:
   {
     \__unravel_set_cmd_aux_meaning:
     \__unravel_set_cmd_aux_primitive:oTF { \l__unravel_head_meaning_tl }
@@ -1683,51 +1796,63 @@
       {
         \__unravel_error:nxxxx { unknown-primitive }
           { \l__unravel_head_meaning_tl } { } { } { }
-        \gtl_gput_right:NV \g__unravel_output_gtl \l__unravel_head_tl
-        \__unravel_print_action:
+        \__unravel_input_gpop_tl:N \l__unravel_tmpa_tl
+        \tl_put_right:NV \l__unravel_head_tl \l__unravel_tmpa_tl
+        \exp_args:NV \__unravel_back_input:o \l__unravel_head_tl
+        \__unravel_print_expansion:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_get_x_next:
+\cs_new_protected:Npn \__unravel_get_x_next:
   {
     \__unravel_get_next:
     \__unravel_token_if_expandable:NT \l__unravel_head_token
-      {
-        \__unravel_expand:
-        \__unravel_get_x_next:
-      }
+      { \__unravel_expand_do:N \__unravel_get_x_next: }
   }
-\cs_new_protected_nopar:Npn \__unravel_get_x_or_protected:
+\cs_new_protected:Npn \__unravel_get_x_or_protected:
   {
     \__unravel_get_next:
     \__unravel_token_if_protected:NF \l__unravel_head_token
-      {
-        \__unravel_expand:
-        \__unravel_get_x_or_protected:
-      }
+      { \__unravel_expand_do:N \__unravel_get_x_or_protected: }
   }
-\cs_new_protected_nopar:Npn \__unravel_get_x_non_blank:
+\cs_new_protected:Npn \__unravel_get_token_xdef:
   {
+    \__unravel_get_next:
+    \__unravel_token_if_protected:NF \l__unravel_head_token
+      { \__unravel_expand_do:N \__unravel_get_token_xdef: }
+  }
+\cs_new_protected:Npn \__unravel_get_token_x:
+  {
+    \__unravel_get_next:
+    \__unravel_token_if_protected:NF \l__unravel_head_token
+      { \__unravel_expand_do:N \__unravel_get_token_x: }
+  }
+\cs_new_protected:Npn \__unravel_get_x_non_blank:
+  {
     \__unravel_get_x_next:
     \token_if_eq_catcode:NNT \l__unravel_head_token \c_space_token
       { \__unravel_get_x_non_blank: }
   }
-\cs_new_protected_nopar:Npn \__unravel_get_x_non_relax:
+\cs_new_protected:Npn \__unravel_get_x_non_relax:
   {
     \__unravel_get_x_next:
-    \token_if_eq_meaning:NNT \l__unravel_head_token \scan_stop:
+    \token_if_eq_meaning:NNTF \l__unravel_head_token \scan_stop:
       { \__unravel_get_x_non_relax: }
       {
-        \token_if_eq_catcode:NNT \l__unravel_head_token \c_space_token
+        \token_if_eq_meaning:NNTF \l__unravel_head_token \__unravel_special_relax:
           { \__unravel_get_x_non_relax: }
+          {
+            \token_if_eq_catcode:NNT \l__unravel_head_token \c_space_token
+              { \__unravel_get_x_non_relax: }
+          }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_skip_optional_space:
+\cs_new_protected:Npn \__unravel_skip_optional_space:
   {
     \__unravel_get_x_next:
     \token_if_eq_catcode:NNF \l__unravel_head_token \c_space_token
       { \__unravel_back_input: }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_optional_equals:
+\cs_new_protected:Npn \__unravel_scan_optional_equals:
   {
     \__unravel_get_x_non_blank:
     \tl_if_eq:NNTF \l__unravel_head_tl \c__unravel_eq_tl
@@ -1737,7 +1862,7 @@
         \__unravel_back_input:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_left_brace:
+\cs_new_protected:Npn \__unravel_scan_left_brace:
   {
     \__unravel_get_x_non_relax:
     \token_if_eq_catcode:NNF \l__unravel_head_token \c_group_begin_token
@@ -1781,11 +1906,11 @@
     \__unravel_gtl_if_head_is_definable:NTF \l__unravel_head_gtl
       { \prg_return_false: }
       {
-        \str_if_eq_x:nnTF
+        \str_if_eq:eeTF
           { \str_head:f { \gtl_to_str:N \l__unravel_head_gtl } } {#1}
           { \prg_return_true: }
           {
-            \str_if_eq_x:nnTF
+            \str_if_eq:eeTF
               { \str_head:f { \gtl_to_str:N \l__unravel_head_gtl } } {#2}
               { \prg_return_true: }
               { \prg_return_false: }
@@ -1792,13 +1917,13 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_keyword_true:
+\cs_new_protected:Npn \__unravel_scan_keyword_true:
   {
     \__unravel_prev_input_gpop_gtl:N \l__unravel_tmpb_gtl
     \__unravel_prev_input:x { \gtl_to_str:N \l__unravel_tmpb_gtl }
     \prg_return_true:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_keyword_false:w
+\cs_new_protected:Npn \__unravel_scan_keyword_false:w
     #1 \q_recursion_stop
   {
     \__unravel_back_input:
@@ -1806,7 +1931,7 @@
     \__unravel_back_input_gtl:N \l__unravel_tmpb_gtl
     \prg_return_false:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_to:
+\cs_new_protected:Npn \__unravel_scan_to:
   {
     \__unravel_scan_keyword:nF { tToO }
       {
@@ -1814,7 +1939,7 @@
         \__unravel_prev_input:n { to }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_font_ident:
+\cs_new_protected:Npn \__unravel_scan_font_ident:
   {
     \__unravel_get_x_non_blank:
     \__unravel_set_cmd:
@@ -1840,7 +1965,7 @@
         \__unravel_prev_input:n { \__unravel_nullfont: }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_font_int:
+\cs_new_protected:Npn \__unravel_scan_font_int:
   {
     \int_case:nnF \l__unravel_head_char_int
       {
@@ -1850,7 +1975,7 @@
       }
       { \__unravel_scan_font_ident: \__unravel_scan_int: }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_font_dimen:
+\cs_new_protected:Npn \__unravel_scan_font_dimen:
   {
     \__unravel_scan_int:
     \__unravel_scan_font_ident:
@@ -1876,7 +2001,7 @@
     \int_compare:nNnT {#1} = { 8 }
       {
         \__unravel_tex_error:nV { the-cannot } \l__unravel_head_tl
-        \__unravel_scan_something_internal_auxii:Vn \c_zero { 0 }
+        \__unravel_scan_something_internal_auxii:nn 0 { 0 }
         \__unravel_break:w
       }
     \tl_if_empty:nF {#2}
@@ -1902,7 +2027,7 @@
     \int_gset:Nn \g__unravel_val_level_int {#2}
   }
 \cs_generate_variant:Nn \__unravel_scan_something_internal_auxii:nn { V }
-\cs_new_nopar:Npn \__unravel_thing_case:
+\cs_new:Npn \__unravel_thing_case:
   {
     \int_case:nnF \l__unravel_head_cmd_int
       {
@@ -1933,9 +2058,9 @@
       }
       { 8 }
   }
-\cs_new_nopar:Npn \__unravel_thing_set_aux:
+\cs_new:Npn \__unravel_thing_set_aux:
   { \int_compare:nNnTF \l__unravel_head_char_int = { 1 } { 1 } { 0 } }
-\cs_new_nopar:Npn \__unravel_thing_last_item:
+\cs_new:Npn \__unravel_thing_last_item:
   {
     \int_compare:nNnTF \l__unravel_head_char_int < { 26 }
       {
@@ -1978,15 +2103,15 @@
           { }
       }
   }
-\cs_new_nopar:Npn \__unravel_thing_register:
+\cs_new:Npn \__unravel_thing_register:
   {
     \int_eval:n { \l__unravel_head_char_int / 1 000 000 - 1 }
-    \int_compare:nNnT { \tl_tail:V \l__unravel_head_char_int } = \c_zero
+    \int_compare:nNnT { \tl_tail:V \l__unravel_head_char_int } = 0
       { \__unravel_scan_int: }
   }
 \cs_new_protected:Npn \__unravel_scan_toks_register:
   {
-    \int_compare:nNnT \l__unravel_head_char_int = \c_zero
+    \int_compare:nNnT \l__unravel_head_char_int = 0
       { \__unravel_scan_int: }
   }
 \cs_new_protected:Npn \__unravel_thing_use_get:nnNN #1#2#3#4
@@ -2003,7 +2128,7 @@
                 { 1 } \dim_eval:n
                 { 2 } \skip_eval:n
               }
-            { \int_compare:nNnT {#1} = { 3 } \etex_mutoglue:D #3 }
+            { \int_compare:nNnT {#1} = { 3 } \tex_mutoglue:D #3 }
           }
       }
       {
@@ -2014,7 +2139,7 @@
           }
           {
             \__unravel_tex_error:nV { incompatible-units } #3
-            \tl_set:Nx #4 { \muskip_eval:n { \etex_gluetomu:D #3 } }
+            \tl_set:Nx #4 { \muskip_eval:n { \tex_gluetomu:D #3 } }
           }
       }
   }
@@ -2087,7 +2212,7 @@
         #1
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_signs:
+\cs_new_protected:Npn \__unravel_scan_signs:
   {
     \__unravel_get_x_non_blank:
     \tl_if_eq:NNTF \l__unravel_head_tl \c__unravel_plus_tl
@@ -2103,7 +2228,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_int:
+\cs_new_protected:Npn \__unravel_scan_int:
   {
     \__unravel_scan_signs:
     \__unravel_set_cmd:
@@ -2111,7 +2236,7 @@
       { \__unravel_scan_something_internal:n { 0 } }
       { \__unravel_scan_int_char: }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_int_char:
+\cs_new_protected:Npn \__unravel_scan_int_char:
   {
     \tl_case:NnF \l__unravel_head_tl
       {
@@ -2131,7 +2256,7 @@
       }
       { \__unravel_scan_int_explicit:Nn \c_false_bool { } }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_int_lq:
+\cs_new_protected:Npn \__unravel_scan_int_lq:
   {
     \__unravel_get_next:
     \__unravel_gtl_if_head_is_definable:NF \l__unravel_head_gtl
@@ -2148,7 +2273,7 @@
   }
 \cs_new_protected:Npn \__unravel_scan_int_explicit:Nn #1#2
   {
-    \if_int_compare:w \c_one
+    \if_int_compare:w 1
         < #2 1 \exp_after:wN \exp_not:N \l__unravel_head_tl \exp_stop_f:
       \exp_after:wN \use_i:nn
     \else:
@@ -2169,7 +2294,7 @@
         }
     }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_normal_dimen:
+\cs_new_protected:Npn \__unravel_scan_normal_dimen:
   { \__unravel_scan_dimen:nN { 2 } \c_false_bool }
 \cs_new_protected:Npn \__unravel_scan_dimen:nN #1#2
   {
@@ -2198,7 +2323,7 @@
         \__unravel_scan_decimal_loop:
       }
       {
-        \tl_if_in:nVTF { 0123456789 } \l__unravel_head_tl
+        \__unravel_tl_if_in:ooTF { 0123456789 } \l__unravel_head_tl
           {
             \__unravel_back_input:
             \__unravel_scan_int:
@@ -2266,14 +2391,14 @@
     \__unravel_prev_input:n { pt }
     \__unravel_break_point:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_inf_unit_loop:
+\cs_new_protected:Npn \__unravel_scan_inf_unit_loop:
   { \__unravel_scan_keyword:nT { lL } { \__unravel_scan_inf_unit_loop: } }
-\cs_new_protected_nopar:Npn \__unravel_scan_decimal_loop:
+\cs_new_protected:Npn \__unravel_scan_decimal_loop:
   {
     \__unravel_get_x_next:
     \tl_if_empty:NTF \l__unravel_head_tl
       { \use_ii:nn }
-      { \tl_if_in:nVTF { 0123456789 } \l__unravel_head_tl }
+      { \__unravel_tl_if_in:ooTF { 0123456789 } \l__unravel_head_tl }
       {
         \__unravel_prev_input:V \l__unravel_head_tl
         \__unravel_scan_decimal_loop:
@@ -2284,9 +2409,9 @@
         \__unravel_prev_input_silent:n { ~ }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_normal_glue:
+\cs_new_protected:Npn \__unravel_scan_normal_glue:
   { \__unravel_scan_glue:n { 2 } }
-\cs_new_protected_nopar:Npn \__unravel_scan_mu_glue:
+\cs_new_protected:Npn \__unravel_scan_mu_glue:
   { \__unravel_scan_glue:n { 3 } }
 \cs_new_protected:Npn \__unravel_scan_glue:n #1
   {
@@ -2316,7 +2441,7 @@
     \__unravel_prev_input_join_get:nN {#1} \l__unravel_tmpa_tl
     \__unravel_prev_input_silent:V \l__unravel_tmpa_tl
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_file_name:
+\cs_new_protected:Npn \__unravel_scan_file_name:
   {
     \bool_gset_true:N \g__unravel_name_in_progress_bool
     \__unravel_get_x_non_blank:
@@ -2324,7 +2449,7 @@
     \bool_gset_false:N \g__unravel_name_in_progress_bool
     \__unravel_prev_input_silent:n { ~ }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_file_name_loop:
+\cs_new_protected:Npn \__unravel_scan_file_name_loop:
   {
     \__unravel_gtl_if_head_is_definable:NTF \l__unravel_head_gtl
       { \__unravel_back_input: }
@@ -2339,7 +2464,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_r_token:
+\cs_new_protected:Npn \__unravel_scan_r_token:
   {
     \bool_do_while:nn
       { \tl_if_eq_p:NN \l__unravel_head_tl \c_space_tl }
@@ -2361,6 +2486,14 @@
     \__unravel_prev_input_silent:x
       { { \exp_after:wN \tl_to_str:n \l__unravel_tmpa_tl } }
   }
+\cs_new_protected:Npn \__unravel_scan_pdf_ext_toks:
+  {
+    \__unravel_prev_input_gpush:
+    \__unravel_scan_toks:NN \c_false_bool \c_true_bool
+    \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
+    \__unravel_prev_input_silent:x
+      { { \exp_not:N \exp_not:n \exp_not:V \l__unravel_tmpa_tl } }
+  }
 \cs_new_protected:Npn \__unravel_scan_toks:NN #1#2
   {
     \bool_if:NT #1 { \__unravel_scan_param: }
@@ -2369,7 +2502,7 @@
       { \__unravel_scan_group_x:N #1 }
       { \__unravel_scan_group_n:N #1 }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_param:
+\cs_new_protected:Npn \__unravel_scan_param:
   {
     \tl_clear:N \l__unravel_tmpa_tl
     \__unravel_scan_param_aux:
@@ -2376,7 +2509,7 @@
     \tl_put_right:NV \l__unravel_defining_tl \l__unravel_tmpa_tl
     \__unravel_prev_input_silent:V \l__unravel_tmpa_tl
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_param_aux:
+\cs_new_protected:Npn \__unravel_scan_param_aux:
   {
     \__unravel_get_next:
     \tl_concat:NNN \l__unravel_tmpa_tl
@@ -2386,6 +2519,7 @@
   }
 \cs_new_protected:Npn \__unravel_scan_group_n:N #1
   {
+    \gtl_set_eq:NN \l__unravel_head_gtl \c_group_begin_gtl
     \__unravel_back_input:
     \__unravel_input_gpop_item:NF \l__unravel_head_tl
       {
@@ -2418,7 +2552,7 @@
   }
 \cs_new_protected:Npn \__unravel_scan_group_xdef:n #1
   {
-    \__unravel_get_token_x:N \c_true_bool
+    \__unravel_get_token_xdef:
     \tl_if_empty:NTF \l__unravel_head_tl
       {
         \gtl_if_head_is_group_begin:NTF \l__unravel_head_gtl
@@ -2430,7 +2564,7 @@
           {
             \__unravel_prev_input_silent:V \c_right_brace_str
             \tl_put_right:Nn \l__unravel_defining_tl { \if_false: { \fi: } }
-            \int_compare:nNnF {#1} = \c_one
+            \int_compare:nNnF {#1} = 1
               { \__unravel_scan_group_xdef:f { \int_eval:n { #1 - 1 } } }
           }
       }
@@ -2444,7 +2578,7 @@
 \cs_generate_variant:Nn \__unravel_scan_group_xdef:n { f }
 \cs_new_protected:Npn \__unravel_scan_group_x:n #1
   {
-    \__unravel_get_token_x:N \c_false_bool
+    \__unravel_get_token_x:
     \__unravel_prev_input_gtl:N \l__unravel_head_gtl
     \tl_if_empty:NTF \l__unravel_head_tl
       {
@@ -2451,7 +2585,7 @@
         \gtl_if_head_is_group_begin:NTF \l__unravel_head_gtl
           { \__unravel_scan_group_x:f { \int_eval:n { #1 + 1 } } }
           {
-            \int_compare:nNnF {#1} = \c_one
+            \int_compare:nNnF {#1} = 1
               { \__unravel_scan_group_x:f { \int_eval:n { #1 - 1 } } }
           }
       }
@@ -2458,33 +2592,8 @@
       { \__unravel_scan_group_x:n {#1} }
   }
 \cs_generate_variant:Nn \__unravel_scan_group_x:n { f }
-\cs_new_protected:Npn \__unravel_get_token_x:N #1
+\cs_new_protected:Npn \__unravel_scan_alt_rule:
   {
-    \__unravel_get_next:
-    \__unravel_token_if_protected:NF \l__unravel_head_token
-      {
-        \__unravel_set_cmd:
-        \int_compare:nNnTF
-          \l__unravel_head_cmd_int = { \__unravel_tex_use:n { the } }
-          {
-            \__unravel_get_the:
-            \bool_if:NTF #1
-              {
-                \tl_put_right:NV \l__unravel_defining_tl \l__unravel_head_tl
-                \__unravel_prev_input:V \l__unravel_head_tl
-              }
-              {
-                \__unravel_exp_args:NNx \gtl_set:Nn \l__unravel_tmpb_gtl { \l__unravel_head_tl }
-                \__unravel_prev_input_gtl:N \l__unravel_tmpb_gtl
-                \__unravel_print_action:
-              }
-          }
-          { \__unravel_expand: }
-        \__unravel_get_token_x:N #1
-      }
-  }
-\cs_new_protected_nopar:Npn \__unravel_scan_alt_rule:
-  {
     \__unravel_scan_keyword:nTF { wWiIdDtThH }
       {
         \__unravel_scan_normal_dimen:
@@ -2505,7 +2614,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_spec:
+\cs_new_protected:Npn \__unravel_scan_spec:
   {
     \__unravel_scan_keyword:nTF { tToO } { \__unravel_scan_normal_dimen: }
       {
@@ -2535,7 +2644,7 @@
           { \__unravel_do_box_error: }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_do_box_error:
+\cs_new_protected:Npn \__unravel_do_box_error:
   {
     \__unravel_back_input:
     \__unravel_error:nnnnn { missing-box } { } { } { } { }
@@ -2572,7 +2681,7 @@
         \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_do_leaders_fetch_skip:
+\cs_new_protected:Npn \__unravel_do_leaders_fetch_skip:
   {
     \__unravel_get_x_non_relax:
     \__unravel_set_cmd:
@@ -2611,7 +2720,7 @@
 \cs_new_protected:Npn \__unravel_box_hook:N #1
   {
     \tl_set:NV \l__unravel_tmpa_tl #1
-    \str_if_eq_x:nnF
+    \str_if_eq:eeF
       { \tl_head:N \l__unravel_tmpa_tl } { \exp_not:N \__unravel_box_hook:w }
       {
         \__unravel_exp_args:Nx #1
@@ -2634,7 +2743,7 @@
   }
 \cs_new_eq:NN \__unravel_box_hook:w \prg_do_nothing:
 \cs_new_eq:NN \__unravel_box_hook_end: \prg_do_nothing:
-\cs_new_protected_nopar:Npn \__unravel_do_leaders_rule:
+\cs_new_protected:Npn \__unravel_do_leaders_rule:
   {
     \__unravel_prev_input:V \l__unravel_head_tl
     \__unravel_scan_alt_rule:
@@ -2703,18 +2812,18 @@
         \token_to_str:N \everypar = { \tl_to_str:N \l__unravel_tmpa_tl }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_end_graf:
+\cs_new_protected:Npn \__unravel_end_graf:
   { \mode_if_horizontal:T { \__unravel_normal_paragraph: } }
-\cs_new_protected_nopar:Npn \__unravel_normal_paragraph:
+\cs_new_protected:Npn \__unravel_normal_paragraph:
   {
     \tex_par:D
     \gtl_gput_right:Nn \g__unravel_output_gtl { \par }
     \__unravel_print_action:x { Paragraph~end. }
   }
-\cs_new_protected_nopar:Npn \__unravel_build_page:
+\cs_new_protected:Npn \__unravel_build_page:
   {
   }
-\cs_new_protected_nopar:Npn \__unravel_handle_right_brace:
+\cs_new_protected:Npn \__unravel_handle_right_brace:
   {
     \int_compare:nTF { 1 <= \__unravel_currentgrouptype: <= 13 }
       {
@@ -2743,12 +2852,12 @@
         \__unravel_print_action:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_end_simple_group:
+\cs_new_protected:Npn \__unravel_end_simple_group:
   {
     \l__unravel_head_token
     \__unravel_print_action:
   }
-\cs_new_protected_nopar:Npn \__unravel_end_box_group:
+\cs_new_protected:Npn \__unravel_end_box_group:
   {
     \seq_pop:NN \l__unravel_leaders_box_seq \l__unravel_tmpa_tl
     \exp_args:No \__unravel_end_box_group_aux:n { \l__unravel_tmpa_tl }
@@ -2755,7 +2864,7 @@
   }
 \cs_new_protected:Npn \__unravel_end_box_group_aux:n #1
   {
-    \str_if_eq_x:nnTF {#1} { Z }
+    \str_if_eq:eeTF {#1} { Z }
       { \__unravel_end_simple_group: }
       {
         \__unravel_get_x_non_relax:
@@ -2773,7 +2882,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_off_save:
+\cs_new_protected:Npn \__unravel_off_save:
   {
     \int_compare:nNnTF \__unravel_currentgrouptype: = { 0 }
       { % bottom-level
@@ -2813,7 +2922,7 @@
       { \__unravel_back_input: \__unravel_new_graf:N \c_true_bool }
       {#1}
   }
-\cs_new_protected_nopar:Npn \__unravel_head_for_vmode:
+\cs_new_protected:Npn \__unravel_head_for_vmode:
   {
     \mode_if_inner:TF
       {
@@ -2830,19 +2939,19 @@
         \__unravel_back_input:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_goto_inner_math:
+\cs_new_protected:Npn \__unravel_goto_inner_math:
   {
     \__unravel_box_hook:N \tex_everymath:D
     $ % $
     \__unravel_box_hook_end:
   }
-\cs_new_protected_nopar:Npn \__unravel_goto_display_math:
+\cs_new_protected:Npn \__unravel_goto_display_math:
   {
     \__unravel_box_hook:N \tex_everydisplay:D
     $ $
     \__unravel_box_hook_end:
   }
-\cs_new_protected_nopar:Npn \__unravel_after_math:
+\cs_new_protected:Npn \__unravel_after_math:
   {
     \mode_if_inner:TF
       {
@@ -2866,7 +2975,7 @@
       }
     \__unravel_print_action:
   }
-\cs_new_protected_nopar:Npn \__unravel_do_step:
+\cs_new_protected:Npn \__unravel_do_step:
   {
     \__unravel_set_action_text:
     \bool_if:NT \g__unravel_internal_debug_bool
@@ -2876,7 +2985,18 @@
       { \__unravel_error:nxxxx { internal } { unknown-command } { } { } { } }
   }
 \__unravel_new_tex_cmd:nn { relax }                                % 0
-  { \__unravel_print_action: }
+  {
+    \token_if_eq_meaning:NNT \l__unravel_head_token \__unravel_special_relax:
+      {
+        \exp_after:wN \__unravel_token_if_expandable:NTF \l__unravel_head_tl
+          {
+            \__unravel_set_action_text:x
+              { \iow_char:N \\notexpanded: \g__unravel_action_text_str }
+          }
+          { }
+      }
+    \__unravel_print_action:
+  }
 \__unravel_new_tex_cmd:nn { begin-group_char }                     % 1
   {
     \gtl_gconcat:NNN \g__unravel_output_gtl
@@ -2926,7 +3046,7 @@
   { \__unravel_mode_math:n { \__unravel_sub_sup: } }
 \__unravel_new_tex_cmd:nn { subscript_char }                       % 8
   { \__unravel_mode_math:n { \__unravel_sub_sup: } }
-\cs_new_protected_nopar:Npn \__unravel_sub_sup:
+\cs_new_protected:Npn \__unravel_sub_sup:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3017,7 +3137,7 @@
           {
             % ^^A todo: unless its_all_over
             \int_gdecr:N \g__unravel_ends_int
-            \int_compare:nNnTF \g__unravel_ends_int > \c_zero
+            \int_compare:nNnTF \g__unravel_ends_int > 0
               {
                 \__unravel_back_input:
                 \__unravel_back_input:n
@@ -3076,7 +3196,7 @@
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
-    \int_compare:nNnF \l__unravel_head_char_int = \c_zero
+    \int_compare:nNnF \l__unravel_head_char_int = 0
       { \__unravel_scan_int: }
     \__unravel_prev_input_gpush:
     \__unravel_scan_toks:NN \c_false_bool \c_true_bool
@@ -3098,7 +3218,13 @@
           { % show
             \__unravel_get_next:
             \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
-            \gtl_head_do:NN \l__unravel_head_gtl \l__unravel_tmpa_tl
+            \token_if_eq_meaning:NNTF
+              \l__unravel_head_token \__unravel_special_relax:
+              {
+                \exp_after:wN \exp_after:wN \exp_after:wN \l__unravel_tmpa_tl
+                \exp_after:wN \exp_not:N \l__unravel_head_tl
+              }
+              { \gtl_head_do:NN \l__unravel_head_gtl \l__unravel_tmpa_tl }
           }
         { 2 }
           { % showthe
@@ -3106,13 +3232,13 @@
             \__unravel_scan_something_internal:n { 5 }
             \__unravel_prev_input_gpop:N \l__unravel_head_tl
             \__unravel_exp_args:Nx \use:n
-              { \etex_showtokens:D { \tl_tail:N \l__unravel_head_tl } }
+              { \tex_showtokens:D { \tl_tail:N \l__unravel_head_tl } }
           }
       }
       { % no operand for showlists, showgroups, showifs
-        \int_compare:nNnT \l__unravel_head_char_int = \c_one % showbox
+        \int_compare:nNnT \l__unravel_head_char_int = 1 % showbox
           { \__unravel_scan_int: }
-        \int_compare:nNnT \l__unravel_head_char_int = \c_five % showtokens
+        \int_compare:nNnT \l__unravel_head_char_int = 5 % showtokens
           { \__unravel_scan_toks:NN \c_false_bool \c_false_bool }
         \__unravel_prev_input_gpop:N \l__unravel_head_tl
         \tl_use:N \l__unravel_head_tl \scan_stop:
@@ -3124,7 +3250,7 @@
     \__unravel_back_input:
     \__unravel_do_box:N \c_false_bool
   }
-\cs_new_protected_nopar:Npn \__unravel_do_move:
+\cs_new_protected:Npn \__unravel_do_move:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3141,7 +3267,7 @@
     \mode_if_vertical:TF
       { \__unravel_forbidden_case: } { \__unravel_do_move: }
   }
-\cs_new_protected_nopar:Npn \__unravel_do_unpackage:
+\cs_new_protected:Npn \__unravel_do_unpackage:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3163,7 +3289,7 @@
   }
 \__unravel_new_tex_cmd:nn { remove_item }                          % 25
   { \l__unravel_head_token \__unravel_print_action: }
-\cs_new_protected_nopar:Npn \__unravel_do_append_glue:
+\cs_new_protected:Npn \__unravel_do_append_glue:
   {
     \int_compare:nNnTF \l__unravel_head_char_int < { 4 }
       { \tl_use:N \l__unravel_head_tl \__unravel_print_action: }
@@ -3183,7 +3309,7 @@
   { \__unravel_mode_vertical:n { \__unravel_do_append_glue: } }
 \__unravel_new_tex_cmd:nn { mskip }                                % 28
   { \__unravel_mode_math:n { \__unravel_do_append_glue: } }
-\cs_new_protected_nopar:Npn \__unravel_do_append_kern:
+\cs_new_protected:Npn \__unravel_do_append_kern:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3214,7 +3340,7 @@
   { \__unravel_mode_non_vertical:n { \__unravel_do_rule: } }
 \__unravel_new_tex_cmd:nn { hrule }                                % 36
   { \__unravel_mode_vertical:n { \__unravel_do_rule: } }
-\cs_new_protected_nopar:Npn \__unravel_do_rule:
+\cs_new_protected:Npn \__unravel_do_rule:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3256,7 +3382,7 @@
   {
     \tl_set_eq:NN \l__unravel_tmpa_tl \l__unravel_head_tl
     \__unravel_get_next:
-    \int_compare:nNnTF \__unravel_currentgrouptype: = \c_zero
+    \int_compare:nNnTF \__unravel_currentgrouptype: = 0
       {
         \__unravel_print_action:x
           {
@@ -3306,7 +3432,7 @@
     \mode_if_vertical:TF { \__unravel_forbidden_case: }
       { \l__unravel_head_token \__unravel_print_action: }
   }
-\cs_new_protected_nopar:Npn \__unravel_do_accent:
+\cs_new_protected:Npn \__unravel_do_accent:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3338,7 +3464,7 @@
     \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
     \__unravel_break_point:
   }
-\cs_new_protected_nopar:Npn \__unravel_do_math_accent:
+\cs_new_protected:Npn \__unravel_do_math_accent:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_print_action:
@@ -3486,7 +3612,7 @@
   }
 \__unravel_new_tex_cmd:nn { last_item }                            % 70
   { \__unravel_forbidden_case: }
-\cs_new_protected_nopar:Npn \__unravel_scan_extension_operands:
+\cs_new_protected:Npn \__unravel_scan_extension_operands:
   {
     \int_case:nnF \l__unravel_head_char_int
       {
@@ -3661,7 +3787,7 @@
       }
       { } % no other cases.
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfcolorstack_operands:
+\cs_new_protected:Npn \__unravel_scan_pdfcolorstack_operands:
   {
     \__unravel_scan_int:
     \__unravel_scan_keyword:nF { sSeEtT }
@@ -3679,13 +3805,13 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_rule_attr:
+\cs_new_protected:Npn \__unravel_scan_rule_attr:
   {
     \__unravel_scan_alt_rule:
     \__unravel_scan_keyword:nT { aAtTtTrR }
       { \__unravel_scan_pdf_ext_toks: }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_action:
+\cs_new_protected:Npn \__unravel_scan_action:
   {
     \__unravel_scan_keyword:nTF { uUsSeErR }
       { \__unravel_scan_pdf_ext_toks: }
@@ -3719,7 +3845,7 @@
           { \__unravel_skip_optional_space: }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_image:
+\cs_new_protected:Npn \__unravel_scan_image:
   {
     \__unravel_scan_rule_attr:
     \__unravel_scan_keyword:nTF { nNaAmMeEdD }
@@ -3732,7 +3858,7 @@
       { \__unravel_scan_int: }
     \__unravel_scan_pdf_ext_toks:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_immediate_operands:
+\cs_new_protected:Npn \__unravel_scan_immediate_operands:
   {
     \__unravel_get_x_next:
     \__unravel_set_cmd:
@@ -3754,12 +3880,12 @@
       }
       { \__unravel_scan_immediate_operands_bad: }
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_immediate_operands_aux:
+\cs_new_protected:Npn \__unravel_scan_immediate_operands_aux:
   {
     \__unravel_prev_input:V \l__unravel_head_tl
     \__unravel_scan_extension_operands:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_immediate_operands_bad:
+\cs_new_protected:Npn \__unravel_scan_immediate_operands_bad:
   {
     \__unravel_back_input:
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
@@ -3767,7 +3893,7 @@
     \__unravel_prev_input_gpush:
   }
 
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfdest_operands:
+\cs_new_protected:Npn \__unravel_scan_pdfdest_operands:
   {
     \__unravel_scan_keyword:nTF { nNuUmM }
       { \__unravel_scan_int: }
@@ -3815,7 +3941,7 @@
       }
     \__unravel_skip_optional_space:
   }
-\cs_set_protected_nopar:Npn \__unravel_tmp:w
+\cs_set_protected:Npn \__unravel_tmp:w
   {
     \__unravel_prev_input_gpush:
     \__unravel_prefixed_command:
@@ -3825,7 +3951,7 @@
   { 1 }
   { \__unravel_tex_use:n { max_command } }
   { \cs_new_eq:cN { __unravel_cmd_#1: } \__unravel_tmp:w }
-\cs_new_protected_nopar:Npn \__unravel_prefixed_command:
+\cs_new_protected:Npn \__unravel_prefixed_command:
   {
     \int_while_do:nNnn
       \l__unravel_head_cmd_int = { \__unravel_tex_use:n { prefix } }
@@ -3855,16 +3981,16 @@
       }
     \__unravel_after_assignment:
   }
-\cs_new_protected_nopar:Npn \__unravel_after_assignment:
+\cs_new_protected:Npn \__unravel_after_assignment:
   {
     \__unravel_back_input_gtl:N \g__unravel_after_assignment_gtl
     \gtl_gclear:N \g__unravel_after_assignment_gtl
   }
-\cs_new_protected_nopar:Npn \__unravel_omit_after_assignment:w
+\cs_new_protected:Npn \__unravel_omit_after_assignment:w
     #1 \__unravel_after_assignment: { }
 \cs_new_protected:Npn \__unravel_prefixed_new:nn #1#2
   {
-    \cs_new_protected_nopar:cpn
+    \cs_new_protected:cpn
       { __unravel_prefixed_ \__unravel_tex_use:n {#1} : } {#2}
   }
 \cs_new_protected:Npn \__unravel_assign_token:n #1
@@ -3874,7 +4000,7 @@
     \tl_use:N \l__unravel_head_tl \scan_stop:
     \__unravel_print_assigned_token:
   }
-\cs_new_protected_nopar:Npn \__unravel_assign_register:
+\cs_new_protected:Npn \__unravel_assign_register:
   {
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \tl_use:N \l__unravel_head_tl \scan_stop:
@@ -3897,7 +4023,7 @@
   }
 \__unravel_prefixed_new:nn { toks_register }                       % 71
   {
-    \int_compare:nNnT \l__unravel_head_char_int = \c_zero
+    \int_compare:nNnT \l__unravel_head_char_int = 0
       { % \toks
         \__unravel_prev_input_gpush:N \l__unravel_head_tl
         \__unravel_print_action:
@@ -3908,7 +4034,7 @@
   }
 \__unravel_prefixed_new:nn { assign_toks }                         % 72
   { \__unravel_assign_toks: }
-\cs_new_protected_nopar:Npn \__unravel_assign_toks:
+\cs_new_protected:Npn \__unravel_assign_toks:
   {
     \__unravel_prev_input_silent:V \l__unravel_head_tl
     \__unravel_print_action:
@@ -3920,7 +4046,7 @@
       \l__unravel_head_cmd_int = { \__unravel_tex_use:n { toks_register } }
       {
         \__unravel_prev_input:V \l__unravel_head_tl
-        \int_compare:nNnT \l__unravel_head_char_int = \c_zero
+        \int_compare:nNnT \l__unravel_head_char_int = 0
           { \__unravel_scan_int: }
       }
       {
@@ -3955,7 +4081,7 @@
   }
 \__unravel_prefixed_new:nn { set_aux }                             % 79
   { % prevdepth = 1, spacefactor = 102
-    \int_compare:nNnTF \l__unravel_head_char_int = \c_one
+    \int_compare:nNnTF \l__unravel_head_char_int = 1
       { \__unravel_assign_value:nn { } { \__unravel_scan_normal_dimen: } }
       { \__unravel_assign_value:nn { } { \__unravel_scan_int: } }
   }
@@ -3977,7 +4103,7 @@
         \prg_replicate:nn
           {
             \tl_if_head_eq_meaning:VNT
-              \l__unravel_defined_tl \tex_parshape:D { \c_two * }
+              \l__unravel_defined_tl \tex_parshape:D { 2 * }
             \tl_tail:N \l__unravel_defined_tl
           }
           { \__unravel_scan_int: }
@@ -4089,7 +4215,7 @@
   }
 \prg_new_conditional:Npnn \__unravel_read_to_cs_safe:n #1 { TF }
   {
-    \int_compare:nNnTF { \etex_interactionmode:D } > { 1 }
+    \int_compare:nNnTF { \tex_interactionmode:D } > { 1 }
       { \prg_return_true: }
       {
         \int_compare:nNnTF {#1} < { 0 }
@@ -4114,7 +4240,7 @@
     \tl_set:NV \l__unravel_defining_tl \l__unravel_tmpa_tl
     \tl_put_right:NV \l__unravel_defining_tl \l__unravel_head_tl
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \int_compare:nNnTF \l__unravel_head_char_int < \c_two
+    \int_compare:nNnTF \l__unravel_head_char_int < 2
       { % def/gdef
         \__unravel_scan_r_token:
         \tl_put_right:NV \l__unravel_defining_tl \l__unravel_defined_tl
@@ -4154,7 +4280,7 @@
     \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
     \tl_put_left:NV \l__unravel_head_tl \l__unravel_tmpa_tl
     \tl_use:N \l__unravel_head_tl \scan_stop:
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+    \__unravel_print_assignment:x { \tl_to_str:N \l__unravel_head_tl }
   }
 \__unravel_prefixed_new:nn { letterspace_font }                    % 101
   {
@@ -4182,13 +4308,13 @@
     \__unravel_assign_token:n { }
   }
 \__unravel_prefixed_new:nn { register }                            % 89
-  { \__unravel_do_register:N \c_zero }
+  { \__unravel_do_register:N 0 }
 \__unravel_prefixed_new:nn { advance }                             % 90
-  { \__unravel_do_operation:N \c_one }
+  { \__unravel_do_operation:N 1 }
 \__unravel_prefixed_new:nn { multiply }                            % 91
-  { \__unravel_do_operation:N \c_two }
+  { \__unravel_do_operation:N 2 }
 \__unravel_prefixed_new:nn { divide }                              % 92
-  { \__unravel_do_operation:N \c_three }
+  { \__unravel_do_operation:N 3 }
 \cs_new_protected:Npn \__unravel_do_operation:N #1
   {
     \__unravel_prev_input_silent:V \l__unravel_head_tl
@@ -4220,7 +4346,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_do_operation_fail:w
+\cs_new_protected:Npn \__unravel_do_operation_fail:w
   {
     \__unravel_error:nnnnn { after-advance } { } { } { } { }
     \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
@@ -4233,10 +4359,10 @@
   }
 \cs_new_protected:Npn \__unravel_do_register_aux:Nn #1#2
   {
-    \int_compare:nNnTF { \tl_tail:n {#2} } = \c_zero
+    \int_compare:nNnTF { \tl_tail:n {#2} } = 0
       {
         \__unravel_prev_input_gpush:N \l__unravel_head_tl
-        \__unravel_print_action:
+        \__unravel_print_assignment:
         \__unravel_scan_int:
         \__unravel_prev_input_gpop:N \l__unravel_head_tl
         \__unravel_prev_input_silent:V \l__unravel_head_tl
@@ -4243,7 +4369,7 @@
       }
       {
         \__unravel_prev_input_silent:V \l__unravel_head_tl
-        \__unravel_print_action:
+        \__unravel_print_assignment:
       }
     \tl_set_eq:NN \l__unravel_defined_tl \l__unravel_head_tl
     \exp_args:NNf \__unravel_do_register_set:Nn #1
@@ -4251,7 +4377,7 @@
   }
 \cs_new_protected:Npn \__unravel_do_register_set:Nn #1#2
   {
-    \int_compare:nNnTF {#1} = \c_zero
+    \int_compare:nNnTF {#1} = 0
       { % truly register command
         \__unravel_scan_optional_equals:
       }
@@ -4259,7 +4385,7 @@
         \__unravel_scan_keyword:nF { bByY }
           { \__unravel_prev_input_silent:n { by } }
       }
-    \int_compare:nNnTF {#1} < \c_two
+    \int_compare:nNnTF {#1} < 2
       {
         \int_case:nnF {#2}
           {
@@ -4273,7 +4399,7 @@
       { \__unravel_scan_int: }
     \__unravel_assign_register:
   }
-\cs_new_protected_nopar:Npn \__unravel_do_assignments:
+\cs_new_protected:Npn \__unravel_do_assignments:
   {
     \__unravel_get_x_non_relax:
     \__unravel_set_cmd:
@@ -4289,13 +4415,13 @@
       }
   }
 \__unravel_new_tex_expandable:nn { undefined_cs }                  % 103
-  { \tl_use:N \l__unravel_head_tl \__unravel_print_action: }
+  { \tl_use:N \l__unravel_head_tl \__unravel_print_expansion: }
 \__unravel_new_tex_expandable:nn { expand_after }                  % 104
   {
     \token_if_eq_meaning:NNTF \l__unravel_head_token \tex_expandafter:D
       { \__unravel_expandafter: } { \__unravel_unless: }
   }
-\cs_new_protected_nopar:Npn \__unravel_expandafter:
+\cs_new_protected:Npn \__unravel_expandafter:
   {
     \gtl_set_eq:NN \l__unravel_tmpb_gtl \l__unravel_head_gtl
     \__unravel_get_next:
@@ -4302,10 +4428,10 @@
     \gtl_concat:NNN \l__unravel_head_gtl
       \l__unravel_tmpb_gtl \l__unravel_head_gtl
     \__unravel_prev_input_gpush_gtl:N \l__unravel_head_gtl
-    \__unravel_print_action:x { \gtl_to_str:N \l__unravel_head_gtl }
+    \__unravel_print_expansion:x { \gtl_to_str:N \l__unravel_head_gtl }
     \__unravel_get_next:
     \__unravel_token_if_expandable:NTF \l__unravel_head_token
-      { \__unravel_expand: }
+      { \__unravel_expand_do:N \prg_do_nothing: }
       { \__unravel_back_input: }
     \__unravel_prev_input_gpop:N \l__unravel_head_gtl
     \__unravel_set_action_text:x
@@ -4312,9 +4438,9 @@
       { back_input: ~ \gtl_to_str:N \l__unravel_head_gtl }
     \gtl_pop_left:N \l__unravel_head_gtl
     \__unravel_back_input:
-    \__unravel_print_action:
+    \__unravel_print_expansion:
   }
-\cs_new_protected_nopar:Npn \__unravel_unless:
+\cs_new_protected:Npn \__unravel_unless:
   {
     \__unravel_get_token:
     \int_compare:nNnTF
@@ -4330,7 +4456,7 @@
       }
       { \__unravel_unless_bad: }
   }
-\cs_new_protected_nopar:Npn \__unravel_unless_bad:
+\cs_new_protected:Npn \__unravel_unless_bad:
   {
     \__unravel_error:nnnnn { bad-unless } { } { } { } { }
     \__unravel_back_input:
@@ -4338,25 +4464,44 @@
 \__unravel_new_tex_expandable:nn { no_expand }                     % 105
   {
     \token_if_eq_meaning:NNTF \l__unravel_head_token \tex_noexpand:D
-      { \__unravel_noexpand: }
+      { \__unravel_noexpand:N }
       { \__unravel_pdfprimitive: }
   }
-\cs_new_protected_nopar:Npn \__unravel_noexpand:
+\cs_new_protected:Npn \__unravel_noexpand:N #1
   {
     \__unravel_get_token:
-    \__unravel_back_input:
-    \__unravel_token_if_expandable:NT \l__unravel_head_token
+    \cs_if_eq:NNTF #1 \prg_do_nothing:
       {
-        \cs_gset_protected_nopar:Npx \__unravel_get_next:
+        \tl_if_empty:NTF \l__unravel_head_tl
+          { \__unravel_back_input: }
           {
-            \cs_gset_protected_nopar:Npn \__unravel_get_next:
-              { \exp_not:o { \__unravel_get_next: } }
-            \exp_not:o { \__unravel_get_next: }
-            \exp_not:n { \cs_set_eq:NN \l__unravel_head_token \tex_relax:D }
+            \exp_after:wN \__unravel_token_if_definable:NTF \l__unravel_head_tl
+              { \__unravel_noexpand_after: }
+              { \__unravel_back_input: }
           }
       }
+      {
+        \__unravel_back_input:
+        \__unravel_get_next:
+        \__unravel_token_if_expandable:NT \l__unravel_head_token
+          { \cs_set_eq:NN \l__unravel_head_token \__unravel_special_relax: }
+      }
   }
-\cs_new_protected_nopar:Npn \__unravel_pdfprimitive:
+\cs_new_protected:Npn \__unravel_noexpand_after:
+  {
+    \group_begin:
+      \__unravel_set_escapechar:n { 92 }
+      \exp_args:NNc
+    \group_end:
+    \__unravel_noexpand_after:N
+      { notexpanded: \exp_after:wN \token_to_str:N \l__unravel_head_tl }
+  }
+\cs_new_protected:Npn \__unravel_noexpand_after:N #1
+  {
+    \cs_gset_eq:NN #1 \__unravel_special_relax:
+    \__unravel_back_input:n {#1}
+  }
+\cs_new_protected:Npn \__unravel_pdfprimitive:
   { \__unravel_not_implemented:n { pdfprimitive } }
 \__unravel_new_tex_expandable:nn { input }                       % 106
   {
@@ -4370,14 +4515,14 @@
           { \__unravel_insert_relax: } { \__unravel_input: }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_endinput:
+\cs_new_protected:Npn \__unravel_endinput:
   {
     \group_begin:
       \msg_warning:nn { unravel } { endinput-ignored }
     \group_end:
-    \__unravel_print_action:
+    \__unravel_print_expansion:
   }
-\cs_new_protected_nopar:Npn \__unravel_scantokens:
+\cs_new_protected:Npn \__unravel_scantokens:
   {
     \__unravel_prev_input_gpush:
     \__unravel_scan_toks:NN \c_false_bool \c_false_bool
@@ -4384,9 +4529,9 @@
     \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
     \tl_set_rescan:Nno \l__unravel_head_tl { } \l__unravel_tmpa_tl
     \__unravel_back_input:V \l__unravel_head_tl
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_tmpa_tl }
+    \__unravel_print_expansion:x { \tl_to_str:N \l__unravel_tmpa_tl }
   }
-\cs_new_protected_nopar:Npn \__unravel_input:
+\cs_new_protected:Npn \__unravel_input:
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
     \__unravel_scan_file_name:
@@ -4394,18 +4539,18 @@
     \tl_set:Nx \l__unravel_tmpa_tl { \tl_tail:N \l__unravel_head_tl }
     \__unravel_file_get:nN \l__unravel_tmpa_tl \l__unravel_tmpa_tl
     \__unravel_back_input:V \l__unravel_tmpa_tl
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+    \__unravel_print_expansion:x { \tl_to_str:N \l__unravel_head_tl }
   }
 \__unravel_new_tex_expandable:nn { cs_name }                       % 109
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_action:
+    \__unravel_print_expansion:
     \__unravel_csname_loop:
     \__unravel_prev_input_silent:V \l__unravel_head_tl
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \__unravel_back_input_tl_o:
   }
-\cs_new_protected_nopar:Npn \__unravel_csname_loop:
+\cs_new_protected:Npn \__unravel_csname_loop:
   {
     \__unravel_get_x_next:
     \__unravel_gtl_if_head_is_definable:NTF \l__unravel_head_gtl
@@ -4426,13 +4571,13 @@
 \__unravel_new_tex_expandable:nn { convert }                       % 110
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_action:
+    \__unravel_print_expansion:
     \int_case:nn \l__unravel_head_char_int
       {
         0      \__unravel_scan_int:
         1      \__unravel_scan_int:
-        2 { \__unravel_get_next: \__unravel_prev_input:V \l__unravel_head_tl }
-        3 { \__unravel_get_next: \__unravel_prev_input:V \l__unravel_head_tl }
+        2      \__unravel_convert_string:
+        3      \__unravel_convert_meaning:
         4      \__unravel_scan_font_ident:
         8      \__unravel_scan_font_ident:
         9      \__unravel_scan_font_ident:
@@ -4460,18 +4605,41 @@
         { 28 } \__unravel_scan_int:
         { 30 } \__unravel_scan_int:
         { 31 } \__unravel_scan_pdfximagebbox:
+        { 33 } \__unravel_scan_directlua:
+        { 34 } \__unravel_scan_pdf_ext_toks:
+        { 35 } \__unravel_scan_pdf_ext_toks:
+        { 40 }
+          {
+            \__unravel_scan_int:
+            \__unravel_prev_input_silent:n { ~ }
+            \__unravel_scan_int:
+          }
       }
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
     \__unravel_back_input_tl_o:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfstrcmp:
+\cs_new_protected:Npn \__unravel_convert_string:
   {
+    \__unravel_get_next:
+    \tl_if_empty:NTF \l__unravel_head_tl
+      { \__unravel_prev_input:x { \gtl_to_str:N \l__unravel_head_gtl } }
+      { \__unravel_prev_input:V \l__unravel_head_tl }
+  }
+\cs_new_protected:Npn \__unravel_convert_meaning:
+  {
+    \__unravel_get_next:
+    \tl_if_empty:NTF \l__unravel_head_tl
+      { \__unravel_prev_input:n { \l__unravel_head_token } }
+      { \__unravel_prev_input:V \l__unravel_head_tl }
+  }
+\cs_new_protected:Npn \__unravel_scan_pdfstrcmp:
+  {
     \__unravel_scan_toks_to_str:
     \__unravel_scan_toks_to_str:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfximagebbox:
+\cs_new_protected:Npn \__unravel_scan_pdfximagebbox:
   { \__unravel_scan_int: \__unravel_scan_int: }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfcolorstackinit:
+\cs_new_protected:Npn \__unravel_scan_pdfcolorstackinit:
   {
     \__unravel_scan_keyword:nTF { pPaAgGeE }
       { \bool_set_true:N \l__unravel_tmpa_bool }
@@ -4480,13 +4648,13 @@
       { \__unravel_scan_keyword:n { pPaAgGeE } }
     \__unravel_scan_toks_to_str:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdffiledump:
+\cs_new_protected:Npn \__unravel_scan_pdffiledump:
   {
     \__unravel_scan_keyword:nT { oOfFfFsSeEtT } \__unravel_scan_int:
     \__unravel_scan_keyword:nT { lLeEnNgGtThH } \__unravel_scan_int:
     \__unravel_scan_pdf_ext_toks:
   }
-\cs_new_protected_nopar:Npn \__unravel_scan_pdfmatch:
+\cs_new_protected:Npn \__unravel_scan_pdfmatch:
   {
     \__unravel_scan_keyword:n { iIcCaAsSeE }
     \__unravel_scan_keyword:nT { sSuUbBcCoOuUnNtT }
@@ -4494,17 +4662,26 @@
     \__unravel_scan_pdf_ext_toks:
     \__unravel_scan_pdf_ext_toks:
   }
-\__unravel_new_tex_expandable:nn { the }                           % 111
+\sys_if_engine_luatex:T
   {
-    \__unravel_get_the:
-    \tl_set:Nx \l__unravel_tmpa_tl { \exp_args:NV \exp_not:o \l__unravel_head_tl }
-    \__unravel_back_input:V \l__unravel_tmpa_tl
-    \__unravel_print_action:
+    \cs_new_protected:Npn \__unravel_scan_directlua:
+      {
+        \__unravel_get_x_non_relax:
+        \token_if_eq_catcode:NNTF \l__unravel_head_token \c_group_begin_token
+          { \__unravel_back_input: }
+          {
+            \__unravel_scan_int:
+            \__unravel_get_x_non_relax:
+          }
+        \__unravel_scan_pdf_ext_toks:
+     }
   }
-\cs_new_protected_nopar:Npn \__unravel_get_the:
+\__unravel_new_tex_expandable:nn { the }                           % 111
+  { \__unravel_get_the:N }
+\cs_new_protected:Npn \__unravel_get_the:N #1
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_action:
+    \__unravel_print_expansion:
     \int_if_odd:nTF \l__unravel_head_char_int
       { % \unexpanded, \detokenize
         \__unravel_scan_toks:NN \c_false_bool \c_false_bool
@@ -4523,6 +4700,24 @@
         \tl_set:Nx \l__unravel_head_tl
           { \exp_not:N \exp_not:n { \tl_tail:N \l__unravel_head_tl } }
       }
+    \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
+      }
+      {
+        \cs_if_eq:NNTF #1 \__unravel_get_token_x:
+          {
+            \__unravel_exp_args:NNx \gtl_set:Nn \l__unravel_tmpb_gtl { \l__unravel_head_tl }
+            \__unravel_prev_input_gtl:N \l__unravel_tmpb_gtl
+          }
+          {
+            \tl_set:Nx \l__unravel_tmpa_tl { \exp_args:NV \exp_not:o \l__unravel_head_tl }
+            \__unravel_back_input:V \l__unravel_tmpa_tl
+          }
+        \__unravel_print_expansion:
+      }
+    #1
   }
 \__unravel_new_tex_expandable:nn { top_bot_mark }                  % 112
   { \__unravel_back_input_tl_o: }
@@ -4531,7 +4726,7 @@
     \__unravel_not_implemented:n { end-template } { } { } { }
     \__unravel_back_input_tl_o:
   }
-\cs_new_protected_nopar:Npn \__unravel_pass_text:
+\cs_new_protected:Npn \__unravel_pass_text:
   {
     \__unravel_input_if_empty:TF
       { \__unravel_pass_text_empty: }
@@ -4538,7 +4733,7 @@
       {
         \__unravel_input_get:N \l__unravel_tmpb_gtl
         \if_true:
-          \if_case:w \gtl_head_do:NN \l__unravel_tmpb_gtl \c_one
+          \if_case:w \gtl_head_do:NN \l__unravel_tmpb_gtl \c_one_int
             \exp_after:wN \__unravel_pass_text_done:w
           \fi:
           \__unravel_input_gpop:N \l__unravel_tmpb_gtl
@@ -4545,19 +4740,19 @@
           \exp_after:wN \__unravel_pass_text:
         \else:
           \use:c { fi: }
-          \int_set_eq:NN \l__unravel_if_nesting_int \c_one
+          \int_set:Nn \l__unravel_if_nesting_int { 1 }
           \__unravel_input_gpop:N \l__unravel_tmpb_gtl
           \exp_after:wN \__unravel_pass_text_nested:
         \fi:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_pass_text_done:w
+\cs_new_protected:Npn \__unravel_pass_text_done:w
   {
     \__unravel_get_next:
     \token_if_eq_meaning:NNT \l__unravel_head_token \fi: { \if_true: }
     \else:
   }
-\cs_new_protected_nopar:Npn \__unravel_pass_text_nested:
+\cs_new_protected:Npn \__unravel_pass_text_nested:
   {
     \__unravel_input_if_empty:TF
       { \__unravel_pass_text_empty: }
@@ -4574,12 +4769,12 @@
         \int_incr:N \l__unravel_if_nesting_int
         \fi:
         \__unravel_input_gpop:N \l__unravel_unused_gtl
-        \int_compare:nNnTF \l__unravel_if_nesting_int = \c_zero
+        \int_compare:nNnTF \l__unravel_if_nesting_int = 0
           { \__unravel_pass_text: }
           { \__unravel_pass_text_nested: }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_pass_text_empty:
+\cs_new_protected:Npn \__unravel_pass_text_empty:
   {
     \__unravel_error:nnnnn { runaway-if } { } { } { } { }
     \__unravel_exit:w
@@ -4591,7 +4786,7 @@
     \int_gincr:N \g__unravel_if_depth_int
     \int_gzero:N \g__unravel_if_limit_int
   }
-\cs_new_protected_nopar:Npn \__unravel_cond_pop:
+\cs_new_protected:Npn \__unravel_cond_pop:
   {
     \int_gset:Nn \g__unravel_if_limit_int
       { \tl_head:N \g__unravel_if_limit_tl }
@@ -4605,7 +4800,7 @@
       { \int_gset:Nn \g__unravel_if_limit_int {#1} }
       {
         \tl_clear:N \l__unravel_tmpa_tl
-        \prg_replicate:nn { \g__unravel_if_depth_int - #2 - \c_one }
+        \prg_replicate:nn { \g__unravel_if_depth_int - #2 - 1 }
           {
             \tl_put_right:Nx \l__unravel_tmpa_tl
               { { \tl_head:N \g__unravel_if_limit_tl } }
@@ -4631,7 +4826,7 @@
       }
       {
         \__unravel_prev_input_gpush:N \l__unravel_head_tl
-        \__unravel_print_action:
+        \__unravel_print_expansion:
         \int_case:nn \l__unravel_head_char_int
           {
             {  0 } { \__unravel_test_two_chars: } % if
@@ -4674,13 +4869,17 @@
 \cs_new_protected:Npn \__unravel_cond_true:n #1
   {
     \__unravel_change_if_limit:nn { 3 } {#1} % wait for else/fi
-    \__unravel_print_action:x { \g__unravel_action_text_str = true }
+    \__unravel_print_expansion:x { \g__unravel_action_text_str = true }
   }
 \cs_new_protected:Npn \__unravel_cond_false:n #1
   {
     \__unravel_cond_false_loop:n {#1}
     \__unravel_cond_false_common:
-    \__unravel_print_action:x { \g__unravel_action_text_str = false }
+    \__unravel_print_expansion:x
+      {
+        \g__unravel_action_text_str = false ~
+        => ~ skipped ~ to ~ \iow_char:N\\fi
+      }
   }
 \cs_new_protected:Npn \__unravel_cond_false_loop:n #1
   {
@@ -4699,7 +4898,7 @@
         \__unravel_cond_false_loop:n {#1}
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_cond_false_common:
+\cs_new_protected:Npn \__unravel_cond_false_common:
   {
     \token_if_eq_meaning:NNTF \l__unravel_head_token \fi:
       { \__unravel_cond_pop: }
@@ -4709,7 +4908,7 @@
   {
     #1
     \__unravel_get_x_non_blank:
-    \tl_if_in:nVF { < = > } \l__unravel_head_tl
+    \__unravel_tl_if_in:ooTF { < = > } \l__unravel_head_tl { }
       {
         \__unravel_error:nnnnn { missing-equals } { } { } { } { }
         \__unravel_back_input:
@@ -4718,7 +4917,7 @@
     \__unravel_prev_input:V \l__unravel_head_tl
     #1
   }
-\cs_new_protected_nopar:Npn \__unravel_test_two_chars:
+\cs_new_protected:Npn \__unravel_test_two_chars:
   {
     \__unravel_test_two_chars_aux:
     \__unravel_prev_input:V \l__unravel_head_tl
@@ -4725,7 +4924,7 @@
     \__unravel_test_two_chars_aux:
     \__unravel_prev_input:V \l__unravel_head_tl
   }
-\cs_new_protected_nopar:Npn \__unravel_test_two_chars_aux:
+\cs_new_protected:Npn \__unravel_test_two_chars_aux:
   {
     \__unravel_get_x_next:
     \gtl_if_tl:NF \l__unravel_head_gtl
@@ -4741,18 +4940,20 @@
 \cs_new_protected:Npn \__unravel_test_ifx:n #1
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_action:
+    \__unravel_print_expansion:
     \__unravel_get_next:
     \gtl_set_eq:NN \l__unravel_tmpb_gtl \l__unravel_head_gtl
+    \cs_set_eq:NN \l__unravel_tmpb_token \l__unravel_head_token
     \__unravel_get_next:
     \__unravel_prev_input_gpop:N \l__unravel_tmpa_tl
     \__unravel_set_action_text:x
       {
         Compare:~ \tl_to_str:N \l__unravel_tmpa_tl
-        \gtl_to_str:N \l__unravel_tmpb_gtl
-        \gtl_to_str:N \l__unravel_head_gtl
+        \__unravel_test_ifx_str:NN \l__unravel_tmpb_token \l__unravel_tmpb_gtl
+        \__unravel_test_ifx_str:NN \l__unravel_head_token \l__unravel_head_gtl
       }
-    \gtl_head_do:NN \l__unravel_tmpb_gtl \__unravel_test_ifx_aux:w
+    \__unravel_test_ifx_aux:NNN \l__unravel_tmpb_token \l__unravel_tmpb_gtl
+      \__unravel_test_ifx_aux:w
       \exp_after:wN \__unravel_cond_true:n
     \else:
       \exp_after:wN \__unravel_cond_false:n
@@ -4759,12 +4960,30 @@
     \fi:
     {#1}
   }
-\cs_new_nopar:Npn \__unravel_test_ifx_aux:w
-  { \gtl_head_do:NN \l__unravel_head_gtl \l__unravel_tmpa_tl }
+\cs_new:Npn \__unravel_test_ifx_str:NN #1#2
+  {
+    \token_if_eq_meaning:NNT #1 \__unravel_special_relax:
+      { \iow_char:N \\notexpanded: }
+    \gtl_to_str:N #2
+  }
+\cs_new_protected:Npn \__unravel_test_ifx_aux:NNN #1#2#3
+  {
+    \token_if_eq_meaning:NNTF #1 \__unravel_special_relax:
+      {
+        \gtl_head_do:NN #2 \__unravel_token_if_expandable:NTF
+          { #3 #1 } { \gtl_head_do:NN #2 #3 }
+      }
+      { \gtl_head_do:NN #2 #3 }
+  }
+\cs_new:Npn \__unravel_test_ifx_aux:w
+  {
+    \__unravel_test_ifx_aux:NNN \l__unravel_head_token \l__unravel_head_gtl
+      \l__unravel_tmpa_tl
+  }
 \cs_new_protected:Npn \__unravel_test_case:n #1
   {
     \__unravel_prev_input_gpush:N \l__unravel_head_tl
-    \__unravel_print_action:
+    \__unravel_print_expansion:
     \bool_if:NT \g__unravel_internal_debug_bool { \iow_term:n { {\ifcase level~#1} } }
     \__unravel_scan_int:
     \__unravel_prev_input_get:N \l__unravel_head_tl
@@ -4772,11 +4991,11 @@
     % ^^A does text_case_aux use prev_input_seq?
     \exp_args:No \__unravel_test_case_aux:nn { \l__unravel_head_tl } {#1}
     \__unravel_prev_input_gpop:N \l__unravel_head_tl
-    \__unravel_print_action:x { \tl_to_str:N \l__unravel_head_tl }
+    \__unravel_print_expansion:x { \tl_to_str:N \l__unravel_head_tl }
   }
 \cs_new_protected:Npn \__unravel_test_case_aux:nn #1#2
   {
-    \int_compare:nNnTF {#1} = \c_zero
+    \int_compare:nNnTF {#1} = 0
       { \__unravel_change_if_limit:nn { 4 } {#2} }
       {
         \__unravel_pass_text:
@@ -4796,7 +5015,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_test_ifdefined:
+\cs_new_protected:Npn \__unravel_test_ifdefined:
   {
     \__unravel_input_if_empty:TF
       { \__unravel_pass_text_empty: }
@@ -4815,7 +5034,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_test_ifcsname:
+\cs_new_protected:Npn \__unravel_test_ifcsname:
   {
     \__unravel_csname_loop:
     \__unravel_prev_input:V \l__unravel_head_tl
@@ -4824,9 +5043,9 @@
   {
     \int_compare:nNnTF \l__unravel_head_char_int > \g__unravel_if_limit_int
       {
-        \int_compare:nNnTF \g__unravel_if_limit_int = \c_zero
+        \int_compare:nNnTF \g__unravel_if_limit_int = 0
           {
-            \int_compare:nNnTF \g__unravel_if_depth_int = \c_zero
+            \int_compare:nNnTF \g__unravel_if_depth_int = 0
               { \__unravel_error:nnnnn { extra-fi-or-else } { } { } { } { } }
               { \__unravel_insert_relax: }
           }
@@ -4834,7 +5053,7 @@
       }
       {
         \__unravel_set_action_text:
-        \int_compare:nNnF \l__unravel_head_char_int = \c_two
+        \int_compare:nNnF \l__unravel_head_char_int = 2
           {
             \__unravel_fi_or_else_loop:
             \__unravel_set_action_text:x
@@ -4843,14 +5062,14 @@
                 => ~ skipped ~ to ~ \tl_to_str:N \l__unravel_head_tl
               }
           }
-        % ^^A todo: in this print_action the token itself is missing.
-        \__unravel_print_action:
+        % ^^A todo: in the terminal output the token itself is missing.
+        \__unravel_print_expansion:
         \__unravel_cond_pop:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_fi_or_else_loop:
+\cs_new_protected:Npn \__unravel_fi_or_else_loop:
   {
-    \int_compare:nNnF \l__unravel_head_char_int = \c_two
+    \int_compare:nNnF \l__unravel_head_char_int = 2
       {
         \__unravel_pass_text:
         \__unravel_set_cmd:
@@ -4876,8 +5095,21 @@
   }
 \cs_new_protected:Npn \__unravel_print:x
   { \__unravel_exp_args:Nx \__unravel_print:n }
+\cs_new_protected:Npn \__unravel_log:n #1
+  {
+    \tl_set:Nn \l__unravel_print_tl {#1}
+    \__unravel_print_normalize_null:
+    \__unravel_exp_args:Nx \iow_log:n { \l__unravel_print_tl }
+  }
 \cs_new_protected:Npn \__unravel_print_message:nn #1 #2
-  { \iow_wrap:nnnN { #1 #2 } { #1 } { } \__unravel_print:n }
+  {
+    \int_compare:nNnF \g__unravel_online_int < 0
+      {
+        \int_compare:nNnTF \g__unravel_online_int = 0
+          { \iow_wrap:nnnN { #1 #2 } { #1 } { } \__unravel_log:n }
+          { \iow_wrap:nnnN { #1 #2 } { #1 } { } \__unravel_print:n }
+      }
+  }
 \cs_new_protected:Npn \__unravel_set_action_text:x #1
   {
     \group_begin:
@@ -4885,13 +5117,13 @@
       \str_gset:Nx \g__unravel_action_text_str {#1}
     \group_end:
   }
-\cs_new_protected_nopar:Npn \__unravel_set_action_text:
+\cs_new_protected:Npn \__unravel_set_action_text:
   {
     \__unravel_set_action_text:x
       {
         \tl_to_str:N \l__unravel_head_tl
         \tl_if_single_token:VT \l__unravel_head_tl
-          { = ~ \exp_after:wN \token_to_meaning:N \l__unravel_head_tl }
+          { = ~ \token_to_meaning:N \l__unravel_head_token }
       }
   }
 \cs_new_protected:Npn \__unravel_print_state:
@@ -4899,7 +5131,7 @@
     \group_begin:
       \__unravel_set_escapechar:n { 92 }
       \tl_use:N \g__unravel_before_print_state_tl
-      \int_compare:nNnT \g__unravel_noise_int > \c_zero
+      \int_compare:nNnT \g__unravel_online_int > 0
         {
           \__unravel_print_state_output:
           \__unravel_print_state_prev:
@@ -4906,9 +5138,8 @@
           \__unravel_print_state_input:
         }
     \group_end:
-    \__unravel_prompt:
   }
-\cs_new_protected_nopar:Npn \__unravel_print_state_output:
+\cs_new_protected:Npn \__unravel_print_state_output:
   {
     \__unravel_exp_args:Nx \__unravel_print_state_output:n
       { \gtl_to_str:N \g__unravel_output_gtl }
@@ -4921,7 +5152,7 @@
           { \__unravel_str_truncate_left:nn {#1} { \g__unravel_max_output_int } }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_print_state_prev:
+\cs_new_protected:Npn \__unravel_print_state_prev:
   {
     \seq_set_map:NNn \l__unravel_tmpa_seq \g__unravel_prev_input_seq
       { \__unravel_to_str:n {##1} }
@@ -4935,7 +5166,7 @@
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_print_state_input:
+\cs_new_protected:Npn \__unravel_print_state_input:
   {
     \__unravel_exp_args:Nx \__unravel_print_state_input:n
       { \__unravel_input_to_str: }
@@ -4959,39 +5190,55 @@
       }
   }
 \cs_new_protected:Npn \__unravel_print_action:
+  { \__unravel_print_action_aux:N \g__unravel_trace_other_bool }
+\cs_new_protected:Npn \__unravel_print_action:x #1
   {
+    \__unravel_set_action_text:x {#1}
+    \__unravel_print_action:
+  }
+\cs_new_protected:Npn \__unravel_print_assignment:
+  { \__unravel_print_action_aux:N \g__unravel_trace_assigns_bool }
+\cs_new_protected:Npn \__unravel_print_assignment:x #1
+  {
+    \__unravel_set_action_text:x {#1}
+    \__unravel_print_assignment:
+  }
+\cs_new_protected:Npn \__unravel_print_expansion:
+  { \__unravel_print_action_aux:N \g__unravel_trace_expansion_bool }
+\cs_new_protected:Npn \__unravel_print_expansion:x #1
+  {
+    \__unravel_set_action_text:x {#1}
+    \__unravel_print_expansion:
+  }
+\cs_new_protected:Npn \__unravel_print_action_aux:N #1
+  {
+    \int_gdecr:N \g__unravel_nonstop_int
     \int_gincr:N \g__unravel_step_int
-    \__unravel_print:x
+    \bool_if:NT #1
       {
-        [=====
-        \bool_if:NT \g__unravel_number_steps_bool
-          { ~ Step ~ \int_to_arabic:n { \g__unravel_step_int } ~ }
-        =====]~
-        \int_compare:nNnTF
-          { \str_count:N \g__unravel_action_text_str }
-          > { \g__unravel_max_action_int }
+        \__unravel_print:x
           {
-            \str_range:Nnn \g__unravel_action_text_str
-              { 1 } { \g__unravel_max_action_int - 3 } ...
+            [=====
+            \bool_if:NT \g__unravel_number_steps_bool
+              { ~ Step ~ \int_to_arabic:n { \g__unravel_step_int } ~ }
+            =====]~
+            \int_compare:nNnTF
+              { \str_count:N \g__unravel_action_text_str }
+              > { \g__unravel_max_action_int }
+              {
+                \str_range:Nnn \g__unravel_action_text_str
+                  { 1 } { \g__unravel_max_action_int - 3 } ...
+              }
+              { \g__unravel_action_text_str }
           }
-          { \g__unravel_action_text_str }
+        \__unravel_print_state:
+        \__unravel_prompt:
       }
-    \__unravel_print_state:
   }
-\cs_new_protected:Npn \__unravel_print_action:x #1
+\cs_new_protected:Npn \__unravel_print_assigned_token:
   {
-    \__unravel_set_action_text:x {#1}
-    \__unravel_print_action:
-  }
-\cs_new_protected:Npn \__unravel_print_gtl_action:N #1
-  {
-    \__unravel_print_action:x { \gtl_to_str:N #1 }
-  }
-\cs_new_eq:NN \__unravel_print_done:x \__unravel_print_action:x
-\cs_new_protected_nopar:Npn \__unravel_print_assigned_token:
-  {
     \__unravel_after_assignment: % ^^A todo: simplify
-    \__unravel_print_action:x
+    \__unravel_print_assignment:x
       {
         Set~ \exp_after:wN \token_to_str:N \l__unravel_defined_tl
         = \exp_after:wN \token_to_meaning:N \l__unravel_defined_tl
@@ -4998,10 +5245,10 @@
       }
     \__unravel_omit_after_assignment:w
   }
-\cs_new_protected_nopar:Npn \__unravel_print_assigned_register:
+\cs_new_protected:Npn \__unravel_print_assigned_register:
   {
     \__unravel_after_assignment: % ^^A todo: simplify
-    \__unravel_exp_args:Nx \__unravel_print_action:x
+    \__unravel_exp_args:Nx \__unravel_print_assignment:x
       {
         \exp_not:n
           {
@@ -5013,7 +5260,7 @@
       }
     \__unravel_omit_after_assignment:w
   }
-\cs_new_protected_nopar:Npn \__unravel_print_welcome:
+\cs_new_protected:Npn \__unravel_print_welcome:
   {
     \__unravel_print_message:nn { }
       {
@@ -5032,25 +5279,25 @@
           { [=====~Start~=====] }
       }
     \__unravel_print_state:
+    \__unravel_prompt:
   }
-\cs_new_protected_nopar:Npn \__unravel_print_outcome:
-  { \__unravel_print:n { [=====~End~=====] } }
-\cs_new_protected_nopar:Npn \__unravel_prompt:
+\cs_new_protected:Npn \__unravel_print_outcome:
+  { \__unravel_print_message:nn { } { [=====~End~=====] } }
+\cs_new_protected:Npn \__unravel_prompt:
   {
-    \int_gdecr:N \g__unravel_nonstop_int
-    \int_compare:nNnF \g__unravel_nonstop_int > \c_zero
+    \int_compare:nNnF \g__unravel_nonstop_int > 0
       {
         \group_begin:
           \__unravel_set_escapechar:n { -1 }
-          \int_set_eq:NN \tex_endlinechar:D \c_minus_one
+          \int_set:Nn \tex_endlinechar:D { -1 }
           \tl_use:N \g__unravel_before_prompt_tl
           \__unravel_prompt_aux:
         \group_end:
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_prompt_aux:
+\cs_new_protected:Npn \__unravel_prompt_aux:
   {
-    \int_compare:nNnT { \etex_interactionmode:D } = { 3 }
+    \int_compare:nNnT { \tex_interactionmode:D } = { 3 }
       {
         \bool_if:NTF \g__unravel_explicit_prompt_bool
           { \ior_str_get:Nc \c__unravel_prompt_ior }
@@ -5068,7 +5315,7 @@
             { m } { \__unravel_print_meaning: \__unravel_prompt_aux: }
             { q }
               {
-                \int_gset_eq:NN \g__unravel_noise_int \c_minus_one
+                \int_gset:Nn \g__unravel_online_int { -1 }
                 \int_gzero:N \g__unravel_nonstop_int
               }
             { x }
@@ -5080,7 +5327,7 @@
             { s } { \__unravel_prompt_scan_int:nn {#1}
               \__unravel_prompt_silent_steps:n }
             { o } { \__unravel_prompt_scan_int:nn {#1}
-              { \int_gset:Nn \g__unravel_noise_int } }
+              { \int_gset:Nn \g__unravel_online_int } }
             { C }
               {
                 \__unravel_exp_args:Nx \use:n
@@ -5114,7 +5361,7 @@
 \cs_new_protected:Npn \__unravel_prompt_help:
   {
     \__unravel_print:n { "m":~meaning~of~first~token }
-    \__unravel_print:n { "q":~semi-quiet~(same~as~"o1") }
+    \__unravel_print:n { "q":~semi-quiet~(same~as~"o-1") }
     \__unravel_print:n { "x"/"X":~exit~this~instance~of~unravel/TeX }
     \__unravel_print:n { "s<num>":~do~<num>~steps~silently }
     \__unravel_print:n
@@ -5126,12 +5373,12 @@
   }
 \cs_new_protected:Npn \__unravel_prompt_silent_steps:n #1
   {
-    \int_compare:nNnF {#1} < \c_zero
+    \int_compare:nNnF {#1} < 0
       {
-        \int_gset_eq:NN \g__unravel_noise_int \c_minus_one
+        \int_gset:Nn \g__unravel_online_int { -1 }
         \tl_gset:Nn \g__unravel_before_prompt_tl
           {
-            \int_gset_eq:NN \g__unravel_noise_int \c_one
+            \int_gset:Nn \g__unravel_online_int { 1 }
             \tl_gclear:N \g__unravel_before_prompt_tl
           }
         \int_gset:Nn \g__unravel_nonstop_int {#1}
@@ -5145,7 +5392,7 @@
   }
 \cs_new_protected:Npn \__unravel_prompt_vert:Nn #1#2
   {
-    \int_gset_eq:NN \g__unravel_noise_int \c_minus_one
+    \int_gset:Nn \g__unravel_online_int { -1 }
     \tl_gset:Nf \g__unravel_before_print_state_tl
       {
         \exp_args:NNf \exp_stop_f: \int_compare:nNnTF
@@ -5156,12 +5403,12 @@
               { \int_max:nn { \g__unravel_nonstop_int } { 2 } }
           }
           {
-            \int_gset_eq:NN \g__unravel_noise_int \c_one
+            \int_gset:Nn \g__unravel_online_int { 1 }
             \tl_gclear:N \g__unravel_before_print_state_tl
           }
       }
   }
-\cs_new_protected_nopar:Npn \__unravel_prompt_all:
+\cs_new_protected:Npn \__unravel_prompt_all:
   {
     \tl_gset:Nx \g__unravel_tmpc_tl
       {
@@ -5171,6 +5418,8 @@
             \int_gset_eq:NN \g__unravel_max_output_int \c_max_int
             \int_gset_eq:NN \g__unravel_max_input_int \c_max_int
             \__unravel_print_state:
+            \int_gdecr:N \g__unravel_nonstop_int
+            \__unravel_prompt:
           }
         \__unravel_prompt_all_aux:N \g__unravel_max_output_int
         \__unravel_prompt_all_aux:N \g__unravel_max_input_int
@@ -5195,8 +5444,8 @@
   }
 \cs_new_protected:Npn \__unravel_tex_msg_new:nnn #1#2#3
   {
-    \cs_new_nopar:cpn { __unravel_tex_msg_error_#1: } {#2}
-    \cs_new_nopar:cpn { __unravel_tex_msg_help_#1: } {#3}
+    \cs_new:cpn { __unravel_tex_msg_error_#1: } {#2}
+    \cs_new:cpn { __unravel_tex_msg_help_#1: } {#3}
   }
 \cs_new_protected:Npn \__unravel_tex_error:nn #1#2
   {
@@ -5225,6 +5474,10 @@
     max-output       .int_gset:N  = \g__unravel_default_max_output_int ,
     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 ,
+    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 ,
     welcome-message  .bool_gset:N = \g__unravel_default_welcome_message_bool ,
   }
 \keys_define:nn { unravel }
@@ -5235,6 +5488,10 @@
     max-output       .int_gset:N  = \g__unravel_max_output_int ,
     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 ,
+    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 ,
     welcome-message  .bool_gset:N = \g__unravel_welcome_message_bool ,
   }
 \tl_map_inline:nn { { /defaults } { } }
@@ -5252,9 +5509,18 @@
             number-steps    = false ,
             welcome-message = false ,
           } ,
+        mute          .meta:nn =
+          { unravel #1 }
+          {
+            trace-assigns = false ,
+            trace-expansion = false ,
+            trace-other = false ,
+            welcome-message = false ,
+            online = -1 ,
+          }
       }
   }
-\NewDocumentCommand \unravel { O { } m } { \unravel:nn {#1} {#2} }
+\NewDocumentCommand \unravel { O { } +m } { \unravel:nn {#1} {#2} }
 \NewDocumentCommand \unravelsetup { m } { \unravel_setup:n {#1} }
 \cs_new_protected:Npn \unravel_setup:n #1
   {
@@ -5261,7 +5527,9 @@
     \keys_set:nn { unravel/defaults } {#1}
     \keys_set:nn { unravel } {#1}
   }
-\cs_new_protected:Npn \unravel:nn #1#2
+\cs_new_protected:Npn \unravel:nn { \__unravel_unravel_marker: \__unravel:nn }
+\cs_new_eq:NN \__unravel_unravel_marker: \__unravel_special_relax:
+\cs_new_protected:Npn \__unravel:nn #1#2
   {
     \__unravel_init_key_vars:
     \keys_set:nn { unravel } {#1}
@@ -5274,17 +5542,27 @@
     \__unravel_final_test:
     \__unravel_exit_point:
   }
-\cs_new_protected_nopar:Npn \__unravel_init_key_vars:
+\cs_new_protected:Npn \unravel_get:nnN #1#2#3
   {
+    \unravel:nn {#1} {#2}
+    \tl_set:Nx #3 { \gtl_left_tl:N \g__unravel_output_gtl }
+  }
+\cs_new_protected:Npn \__unravel_init_key_vars:
+  {
     \bool_gset_eq:NN \g__unravel_explicit_prompt_bool \g__unravel_default_explicit_prompt_bool
     \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
+    \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
     \bool_gset_eq:NN \g__unravel_welcome_message_bool \g__unravel_default_welcome_message_bool
     \int_gset_eq:NN \g__unravel_max_action_int \g__unravel_default_max_action_int
     \int_gset_eq:NN \g__unravel_max_output_int \g__unravel_default_max_output_int
     \int_gset_eq:NN \g__unravel_max_input_int  \g__unravel_default_max_input_int
+    \int_gzero:N \g__unravel_nonstop_int
   }
-\cs_new_protected_nopar:Npn \__unravel_init_vars:
+\cs_new_protected:Npn \__unravel_init_vars:
   {
     \seq_gclear:N \g__unravel_prev_input_seq
     \gtl_gclear:N \g__unravel_output_gtl
@@ -5297,7 +5575,7 @@
     \bool_gset_false:N \g__unravel_name_in_progress_bool
     \gtl_clear:N \l__unravel_after_group_gtl
   }
-\cs_new_protected_nopar:Npn \__unravel_main_loop:
+\cs_new_protected:Npn \__unravel_main_loop:
   {
     \__unravel_get_x_next:
     \__unravel_set_cmd:
@@ -5304,19 +5582,19 @@
     \__unravel_do_step:
     \__unravel_main_loop:
   }
-\cs_new_protected_nopar:Npn \__unravel_final_test:
+\cs_new_protected:Npn \__unravel_final_test:
   {
     \bool_if:nTF
       {
         \tl_if_empty_p:N \g__unravel_if_limit_tl
-        && \int_compare_p:nNn \g__unravel_if_limit_int = \c_zero
-        && \int_compare_p:nNn \g__unravel_if_depth_int = \c_zero
+        && \int_compare_p:nNn \g__unravel_if_limit_int = 0
+        && \int_compare_p:nNn \g__unravel_if_depth_int = 0
         && \seq_if_empty_p:N \g__unravel_prev_input_seq
       }
       { \__unravel_input_if_empty:TF { } { \__unravel_final_bad: } }
       { \__unravel_final_bad: }
   }
-\cs_new_protected_nopar:Npn \__unravel_final_bad:
+\cs_new_protected:Npn \__unravel_final_bad:
   {
     \__unravel_error:nnnnn { internal }
       { the-last-unravel-finished-badly } { } { } { }
@@ -5387,6 +5665,8 @@
   { The~primitive~\iow_char:N\\endinput~was~ignored. }
 \msg_new:nnn { unravel } { missing-something }
   { Something~is~missing,~sorry! }
+\msg_new:nnn { unravel } { nested-unravel }
+  { The~\iow_char:N\\unravel~command~may~not~be~nested. }
 \msg_new:nnnn { unravel } { tex-error }
   { TeX~sees~"#1"~and~throws~an~error:\\\\ \iow_indent:n {#2} }
   {



More information about the tex-live-commits mailing list