Coder Social home page Coder Social logo

latex-unravel's People

Contributors

blefloch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

muzimuzhi

latex-unravel's Issues

Runaway arg recovery for non-\long macro receiving \par

The error recovery for non-\long macros which have simple arguments (#1#2#3...) when they receive \par is different in unravel than in TeX.

\RequirePackage{unravel}
\def\test#1{}
\unravel{\test\par}

internally finds the argument \par, braces it, then expands \test{\par}. TeX complains that there is a runaway argument, and drops everything until the \par. That leaves a brace that has no reason to be there.

obtain unraveled TeX code

This is a question and perhaps a feature request.

Is there a nice way to obtain the unraveled TeX code (the FINAL step shown before the compiler exits)?

Basically, I have to move some math LaTeX code to MathJax, and since MathJax supports less features that LaTeX, the most unravelled code is what I'm after. A good solution would be a script that takes in the LaTeX code and outputs the unravelled code.

TeX's error recovery in scan_something_internal

\dimen0\relax

gives "Missing number" and "Illegal unit" errors, while

\dimen0\tenrm

gives only the first error (assuming \font\tenrm=cmr10\relax). Similarly, \muskip0\relax gives "Missing number" and "Illegal unit", while \musip0\tenrm gives "Missing number" and "Incompatible glue units" errors.

This is due to the fact that \tenrm is "something internal" hence is scanned by the TeX procedure scan_something_internal, which throws a "Missing number" error then inserts the equivalent of \c_zero_dim.

Document the possible responses to the prompt

The list of possible commands should appear in the pdf documentation, with explanations. The detailed behaviour should be explained, and the code altered to reflect the expected behaviour.

Among other things, it should be noted that it is possible to do C\unravelsetup{<options>} to set some options within an \unravel.

Improvements concerning macros

It would be good to have better error messages in case of the rather common "runaway argument" error. However, this is very tricky to do in general since \unravel must then grab arguments itself, hence must be able to determine the exact delimiters expected by the macro. All this must be done safely. Here is a possible approach.

  • Open a group.
  • Open another group. Set \escapechar=32 (space). Loop through characters until finding one that does not appear in the macro's \meaning. If none is available, give up optimizing. Save the character found (assumed below to be the 0 character ^^@). Close the group.
  • Set \escapechar=0 and \catcode0=0 (the first and second 0 have to do with the character found above, the last means that we set that character to be of category escape).
  • Open another group. Get a second version of the macro's \meaning. Set to 11 the catcode of any character which follows ^^@ in this \meaning, then get a third version of the \meaning: in it, every control sequence is followed by a space (careful: there may be control sequences containing spaces in their names). Save this \meaning. Close the group.
  • For each pattern of the form ^^@ <characters> <space> with more than one character, set the catcode of every character to 11 (letter), as this was their catcode when the macro was defined (barring trickery). (That step is probably slow and is not needed in the \char_generate:nn approach below.) If any of the corresponding control sequences is a macro parameter, give up (important!). At the same time, keep track of catcode 1 and catcode 2 characters in between such patterns and give up if the difference ever has the wrong sign. Set \catcode32=10, as it would not be possible to avoid extraneous spaces otherwise anyway.
  • Loop through the argument part, keeping track of the next expected argument number, and checking current catcodes of the characters. If a catcode 1 or catcode 2 character is found, give up optimizing. If two consecutive catcode 7 are found, give up optimizing. When seeing a catcode 6 character, check that the next character is the expected digit, otherwise give up (don't try to support trailing #). Using \scantokens later should be safe (barring \outer tokens)
  • Loop within it through the replacement part, checking current catcodes of the characters. If encountering two consecutive catcode 7 characters, give up. Test what follows catcode 6 characters: that must be a digit (at most the number of parameters) or a catcode 6 character, otherwise give up. Catcode 1 and 2 characters were already checked earlier, otherwise check them here.
  • Get a fourth version of the \meaning. Split it into prefix, arguments, and replacement code (this is provided by expl3), then build a proposal for the macro's definition. The prefixes is straightforward. The rest can use \scantokens. Define a macro using that data. If that matches the original macro, then great! Otherwise give up.
  • Close the original group.
  • Use the now known definition to grab parameters safely etc.

Possible improvement: figure out which character is the macro parameter character.
Alternative approach: go through the \meaning in an \edef, leaving characters or tokens behind in the input stream using \char_generate:nn. Some \afterassignment trickery allows to not keep track of catcode 1/2 characters. One still needs to keep track of the number of parameters.

Cache the results for each macro!

Support input (and other primitives) with braces

Right now, \unravel{\tex_input:D {.tex}} fails in all engines nowadays because unravel mistakenly searches for the file {.tex}. In fact all engines seem to search for a general text before falling back to the old syntax. Needs to be tested with \openin, \openout too.

e-TeX's \if-related integer parameters are zero

e-TeX's \if-related integer parameters (\currentiflevel, \currentifbranch and \currentiftype) are all zero inside a conditional in\unravel:

\RequirePackage{unravel}
\unravel{\ifx!!\showthe\currentiflevel\fi}
\stop

\number seems not correctly supported

If the argument to \unravel is just a valid \number expression an error is thrown:

\documentclass{article}
\usepackage{unravel}
\begin{document}
\unravel{\number`a}
\end{document}

This throws:

Runaway argument?
\__unravel_print_outcome: \__unravel_final_test: \__unravel_exit_point: \ETC.
! File ended while scanning use of \__unravel_exit_error:w.
<inserted text>
                \par

sanitize catcode of & at loading time?

Hi, I accidentally noticed that an unusual catcode for & at loading time

\documentclass{article}
\catcode`& 12
\usepackage{unravel}
\catcode`& 4
\begin{document}
\unravel{\romannumeral-`0 1}
\end{document}

compromised the functioning of the package. I hesitate raising this at an issue as I suspect it is an implicit assumption in LaTeX2e that packages are supposedly loaded under a standard catcode regime (I tried with a few other characters, but finally settled on the & as the culprit in my initial, a bit convoluted, situation).

Best,
Jean-François

Improve error messages

Most error messages given by unravel lack information. Add more. In particular, the-last-unravel-finished-badly occurs too often and should have more explanations.

\ignorespaces is completely silent in unravel

Add \@@_print_action: somewhere in the code implementing \ignorespaces, as otherwise the user cannot see what is going on.

\unravel { \ignorespaces \ignorespaces \ignorespaces }

stops immediately.

Glue sign

Glue signs are not treated properly

\unravel{\parskip=-\parskip\showthe\parskip}

eventually shows > 0.0pt plus 1.0pt. instead of > 0.0pt plus -1.0pt. This is because the sign only ends up applying to the first part of the skip, but not to the plus or minus parts.

Missing expansion of \detokenize and \unexpanded in \edef

This does not affect the outcome of an \edef, just what is shown in the terminal. For instance, the first two steps of:

\RequirePackage{unravel}
\unravel{\edef\x#1{\def\noexpand\test\detokenize{hi}{}}\show\x}
\stop

are:

[===== Step 1 =====] \detokenize = \detokenize
|| \edef \x {\def \test
|| \detokenize
|> {hi}{}}\show \x

[===== Step 2 =====] \detokenize {hi}
|| \edef \x {\def \test \detokenize {hi}
|> {}}\show \x

whereas the second step should be:

[===== Step 2 =====] \detokenize {hi}
|| \edef \x {\def \test hi
|> {}}\show \x

I traced the issue back to line 7381 of unravel.dtx, \@@_prev_input:V \l_@@_head_tl, where \l_@@_head_tl contains \detokenize {hi}. To print correctly, the contents of \l_@@_head_tl should be expanded to result in the correct hi. I changed the code in my version of unravel.sty and it seems to be working...

Stop on error

Hopefully there will be a point where unravel detects all TeX errors.

Even before that, it would be useful to have the option to stop at the first error detected by unravel. That probably is not too hard: change all \msg_error to include code that sets \g_@@_nonstop_int to the right value.

LuaTeX primitive \lastnamedcs not implemented

Since April 2018, LaTeX2e has used \lastnamedcs in \@ifundefined for LuaTeX. See commit latex3/latex2e@82b49f5. Since \@ifundefined is used by many command-defining commands, the fact that \lastnamedcs is not implemented might bring inconvenience to LuaTeX + unravel users.

Currently I seldom come to the situation that I must run LuaTeX with unravel, but not sure if this holds for other unravel users.

Space terminated dimen assignment doesn't work

There seems to be an error regarding tokens following a dimension assignment:

\makeatletter
\newdimen\ifdimen@gobbledimen
\long\def\ifdimen@test\ifdimen@false#1#2{#1}
\def\ifdimen@false{\z@\ifdimen@false\@firstofone}
\protected\long\def\ifdimen#1%
  {%
    \afterassignment\ifdimen@test
    \ifdimen@gobbledimen #1 \ifdimen@false
  }
\makeatother

\ifdimen{1}{true}{false}
\ifdimen{1pt}{true}{false}

\unravel{\ifdimen{1}{true}{false}}
\unravel{\ifdimen{1pt}{true}{false}}

This definition will work outside of \unravel but inside \unravel the space after #1 will not be gobbled if #1 is a valid dimension and therefore \ifdimen@test will throw an error as it doesn't match its definition.

On the other hand

\makeatletter
\newdimen\ifdimen@gobbledimen
\long\def\ifdimen@test\ifdimen@false#1#2{#1}
\def\ifdimen@false{\z@\ifdimen@false\@firstofone}
\protected\long\def\ifdimen#1%
  {%
    \afterassignment\ifdimen@test
    \ifdimen@gobbledimen #1\ifdimen@false
  }
\makeatother

\ifdimen{1}{true}{false}
\ifdimen{1pt}{true}{false}

\unravel{\ifdimen{1}{true}{false}}
\unravel{\ifdimen{1pt}{true}{false}}

will throw an error outside of \ifdimen if #1 is a valid dimension as \ifdimen@false will be expanded, but work inside of \unravel

\__unravel_begin_insert_or_adjust: is undefined

When unravel-ing \footnote, the \insert used inside \@footnotetext raises

! Undefined control sequence.
\__unravel_cmd_37: ...vel_begin_insert_or_adjust:

l.6 content\unravel{\footnote{abc}}

Currently \insert is not marked as "not implemented", hence \__unravel_begin_insert_or_adjust: is expected as implemented.

Example:

% unravel-footnote.tex
\documentclass{article}
\usepackage{unravel}

\begin{document}
content\unravel{\footnote{abc}}
\end{document}

Run it with pdflatex unravel-footnote, then input u\@footnotetext followed by three "Enter"s.

Expanding unknown expandable primitive

Expanding an expandable primitive unknown to unravel, such as \directlua in LuaTeX, incorrectly puts it into the output (not even into the current prev_input) rather than for instance producing an undefined control sequence error or similar. Example:

\RequirePackage{unravel}
\unravel{\edef\foo{\directlua{}}}

Macro in that grabs \fi causes 'the-last-unravel-finished-badly'

When a macro delimited by \fi is used in a conditional, \unravel seems to partially lose track of \if...\fi nesting and throws an error at the end:

\RequirePackage{unravel}
\def\aux\fi{}
\unravel{\ifx!!\aux\fi}
\stop

But the code execution seems to be carried out correctly.


Terminal output:

======== Welcome to the unravel package ========
    "<|" denotes the output to TeX's stomach.
    "||" denotes tokens waiting to be used.
    "|>" denotes tokens that we will act on.
    Press <enter> to continue; 'h' <enter> for help.

|| 
|> \ifx !!\aux \fi 

[===== Step 1 =====] \ifx = \ifx
|| \ifx 
|> !!\aux \fi 

[===== Step 2 =====] Compare: \ifx !!=true
|| 
|> \aux \fi 

[===== Step 3 =====] \aux = macro:\fi ->
|| 
|> 

[===== End =====]

! Package unravel Error: Internal error: 'the-last-unravel-finished-badly'. 
(unravel)                Please report.

Type <return> to continue.
 ...                                              
                                                  
l.5 \unravel{\ifx!!\aux\fi}
                           
?

\tl_if_in:nnTF fails

\tl_if_in:nnTF defines an auxiliary and this is clobbered by unravel's own use of some tl functions.

\RequirePackage{unravel}
\ExplSyntaxOn
\unravel{\tl_if_in:nnTF { abc } { a } { } { } }

breaks after Step 13.

Showing the \font

\RequirePackage{unravel}
\unravel{\showthe\font\relax}

should show \nullfont, but breaks with the error missing-font-id.

Make use of color capabilities of the terminal

On my terminal, running

pdftex -8bit '\message{normal\pdfunescapehex{1B5B}1;9;34mFANCY\pdfunescapehex{1B5B}mnormal}'

Gives me "normalFANCYnormal" with "FANCY" written in bold blue font and crossed through. It would sometimes be very useful to have colors distinguishing category codes of tokens, or underlining different macro parameters, etc.

Unravel until a quark

The various prompt_input_clist variables should be sequences instead. Otherwise,

\RequirePackage{unravel}
\ExplSyntaxOn
\unravel[prompt-input=u\q_nil]{\c_space_tl\boom\q_nil}

(for instance) does not continue unravelling until \q_nil. Basically, \q_nil messes up clist internals. This specific case would be fixed by fixing latex3/latex3#593 but unravel needs to work also for private quarks, so using a sequence is better.

Found by P.O. at https://tex.stackexchange.com/a/496786/2707

Rewind steps

There are many situations where it would be a life saver to rewind steps. Typically, I use \unravel to find what caused a TeX error. It would be nice to let unravel run a few steps at a time, then to stop once I see the error, and rewind a couple of steps to determine what when wrong.

It seems impossible to undo global assignments. But this is not needed! Assignments do not really have to be performed. The values of macros and other parameters, must be saved, but they are only ever used by unravel, which could be built to look for saved values rather than current values.

The following must be saved. Save input/prev/output stacks every few steps (repeatedly discard every other one once old, like one would do for backups). Save previous values for all assignments. Save the "outcome" of every step.

Some structural changes are needed, so don't expect this issue to be closed any time soon.

Add XeTeX \strcmp

That should be a one-line fix, since \pdfstrcmp is already implemented.

Implicit character in csname construction

Implicit character tokens should not be allowed in a \csname...\endcsname construction. But unravel accepts the following:

\unravel{\let\*=+\csname\*\endcsname}

instead of breaking with a "Missing \endcsname" error.

Write to own file

It would be really nice if one was able to specify another filename in which unravel then writes its logs. This would keep the log itself small (and manageable by TeXStudio, etc.). Furthermore this would simplify the automatic processing of the logs as one didn't have to worry about other log messages.

\unless\ifcsname throws low level error

If the \unless primitive is used with \ifcsname a low level Missing \endcsname is thrown in \unravel. Consider the following MWE:

\documentclass[]{article}

\usepackage{unravel}

\begin{document}
\unravel
  {%
    \unless\ifcsname section\endcsname
      not
    \fi
    defined
  }
\end{document}

The bug will be triggered for both defined and undefined macros being tested.

LuaTeX expandable luacall

LuaTeX has "new" ways of accessing Lua, through expandable luacalls. This is for instance used in \file_size:n. Currently breaks in unravel.

`\unless` became `\reverse_if:N` in action part

Example

\documentclass{article}
\usepackage{unravel}

\begin{document}
\unravel{\unless\iftrue F\else T\fi}
\end{document}
||
|> \unless \iftrue F\else T\fi

[===== Step 1 =====] \unless = \unless
|| \reverse_if:N \iftrue
|> F\else T\fi

[===== Step 2 =====] \reverse_if:N \iftrue =false => skip to \else
||
|> T\fi

Version

  • latex 2021-06-01, patch level 1
  • latex3 2021-06-01
  • unravel 2021-05-11

Avoid breaking on \unravel{\expandafter?}

At present,

\unravel{\expandafter?}

causes an internal error because it tries to fetch a token beyond the last one in \unravel. There are probably some other similar cases.

One step too many when skipping steps using u

When I use u\foo to skip some steps, unravel skips steps until \foo is in the front of the input stream and then performs one more step. An example interactive session (the last keyboard input was hitting Enter after typing u\new@command):

> pdflatex
This is pdfTeX, Version 3.14159265-2.6-1.40.20 (MiKTeX 2.9.7050 64-bit)
**\documentclass{article}\usepackage{unravel}\unravel{\newcommand\foo{asdf}}
entering extended mode
LaTeX2e <2018-12-01>
("C:\Program Files\MiKTeX 2.9\tex/latex/base\article.cls"
Document Class: article 2018/09/03 v1.4i Standard LaTeX document class
("C:\Program Files\MiKTeX 2.9\tex/latex/base\size10.clo"))
("C:\Program Files\MiKTeX 2.9\tex/latex/unravel\unravel.sty"
("C:\Program Files\MiKTeX 2.9\tex/latex/l3kernel\expl3.sty"
("C:\Program Files\MiKTeX 2.9\tex/latex/l3kernel\expl3-code.tex")
("C:\Program Files\MiKTeX 2.9\tex/latex/l3kernel\l3pdfmode.def"))
("C:\Program Files\MiKTeX 2.9\tex/latex/l3packages/xparse\xparse.sty")
("C:\Program Files\MiKTeX 2.9\tex/generic/gtl\gtl.sty"))

======== Welcome to the unravel package ========
    "<|" denotes the output to TeX's stomach.
    "||" denotes tokens waiting to be used.
    "|>" denotes tokens that we will act on.
    Press <enter> to continue; 'h' <enter> for help.

||
|> \newcommand \foo {asdf}
u\new@command
[===== Step 1 =====] \newcommand = macro:->\@star@or@long \new@command
[===== Step 2 =====] \@star@or@long = macro:#1->\@ifstar {\let \l@ng...
[===== Step 3 =====] \@ifstar = macro:#1->\@ifnextchar *{\@firstoftw...
[===== Step 4 =====] \@ifnextchar = \long macro:#1#2#3->\let \reserv...
[===== Step 5 =====] \let \reserved@d
[===== Step 6 =====] Set \reserved@d=the character *
[===== Step 7 =====] \def \reserved@a {\@firstoftwo {\let \l@ngrel@x...
[===== Step 8 =====] Set \reserved@a=macro:->\@firstoftwo {\let \l@n...
[===== Step 9 =====] \def \reserved@b {\let \l@ngrel@x \long \new@co...
[===== Step 10 =====] Set \reserved@b=macro:->\let \l@ngrel@x \long \...
[===== Step 11 =====] \futurelet \@let@token
[===== Step 12 =====] Set \@let@token=undefined
[===== Step 13 =====] \@ifnch = macro:->\ifx \@let@token \@sptoken \l...
[===== Step 14 =====] \ifx = \ifx
[===== Step 15 =====] Compare: \ifx \@let@token \@sptoken =false => s...
[===== Step 16 =====] \ifx = \ifx
[===== Step 17 =====] Compare: \ifx \@let@token \reserved@d =false =>...
[===== Step 18 =====] \let \reserved@c
[===== Step 19 =====] Set \reserved@c=macro:->\let \l@ngrel@x \long \...
[===== Step 20 =====] \fi = \fi
[===== Step 21 =====] \fi = \fi
[===== Step 22 =====] \reserved@c = macro:->\let \l@ngrel@x \long \ne...
[===== Step 23 =====] \let \l@ngrel@x
[===== Step 24 =====] Set \l@ngrel@x=\long
||
|> \new@command \foo {asdf}
[===== Step 25 =====] \new@command = macro:#1->\@testopt {\@newcomman...
||
|> \@testopt {\@newcommand \foo }0{asdf}

(I am using Windows 10's PowerShell with MiKTeX's pdflatex.)

Restrict expansion level

I'm not sure whether this is possible but if it was possible to specify a maximal expansion level one could get output that is more or less only about the relevant stages of the expansion instead of all sub-expansions going on inside.

Example:

\def\test{\pgfkeys{/a/b/.store in = \bla} bla}
\def\otherTest{\test}
\def\lastTest{\otherTest}

\unravel[max-expansion=2]{\lastTest}

Above example would then not expand \pgfkeys which would end in thousands of expansion steps when maybe one is only interested in how \lastTest expands to the level of \test.

Handle `\relax` without printing `\exp_not:N`

When I try to do

\documentclass{article}
\usepackage{unravel}
\begin{document}
\unravel{\if\relax\detokenize{}\relax\fi}
\end{document}

unravel inserts \exp_not:N in the list of tokens waiting to be used:

[===== Step 5 =====] \exp_not:N \relax 
|| \if \exp_not:N \relax \exp_not:N \relax 
|> \fi

Dimen assignment with factor in front of an implicit `<number>` fails

Sorry for bad vocabulary (not time to check e.g. TeX by Topic for exact one).

This fails with current master at 9461aa1

\documentclass{article}
\usepackage{unravel}

\begin{document}

% raises error
\unravel{\dimen255=3\catcode`\p\relax}


% this is ok
\dimen255=3\catcode`\p\relax

\number\dimen255 % 33 = 3 times 11

\end{document}

I have inserted the \relax only for extra safety.

Unravel until a given macro

It would be nice to be able to type until \somecs and have unravel do all the steps until the first token of the token list is \somecs. Even better if more than one token can be specified in this way. For instance, one could respond until \begin{document} after calling \unravel{\input{main.tex}}.

Handle catcode changes

One would want

\unravel{\scantokens{\catcode`X=12 \showX}}

to show the character X instead of producing an error "\showX not defined". A similar comment applies to \input instead of \scantokens.

With an \else part, false \if-test still shows "skipped to \fi" in action part

A false \if-test will skip to \fi if there is no \else before \fi, and to \else if there is such \else. But currently the action part shows skipped to \fi in both occasions.

An example:

\documentclass{article}
\usepackage{unravel}
\begin{document}
\leavevmode
\unravel{%
  \ifx\relax\relax T\else F\fi
  \ifx\abc\relax T\else F\fi
}
\end{document}

Terminal output

|| 
|> \ifx \relax \relax T\else F\fi \ifx \abc \relax T\else F\fi 

[===== Step 1 =====] \ifx = \ifx
|| \ifx 
|> \relax \relax T\else F\fi \ifx \abc \relax T\else F\fi 

[===== Step 2 =====] Compare: \ifx \relax \relax =true
|| 
|> T\else F\fi \ifx \abc \relax T\else F\fi 

[===== Step 3 =====] T
<| T
|| 
|> \else F\fi \ifx \abc \relax T\else F\fi 

[===== Step 4 =====] \else = \else => skipped to \fi 
<| T
|| 
|> \ifx \abc \relax T\else F\fi 

[===== Step 5 =====] \ifx = \ifx
<| T
|| \ifx 
|> \abc \relax T\else F\fi 

[===== Step 6 =====] Compare: \ifx \abc \relax =false => skipped to \fi
<| T
|| 
|> F\fi 

[===== Step 7 =====] F
<| TF
|| 
|> \fi 

[===== Step 8 =====] \fi = \fi
<| TF
|| 
|> 

[===== End =====]

In step 6, the action part says

[===== Step 6 =====] Compare: \ifx \abc \relax =false => skipped to \fi

It's better to say skipped to \else rather than \fi.

\meaning{ and \meaning} show internal unravel token

If you do \meaning<explicit begin/end-group token>, unravel will show
an internal (implicit) token. The example:

\RequirePackage{unravel}\everypar{}
\unravel{\meaning{\iffalse}\fi}
\csname @@end\endcsname

shows as:

[===== Step 1 =====] \meaning = \meaning
|| \meaning 
|> {\iffalse }\fi 

[===== Step 2 =====] \l__unravel_head_token 
|| \meaning \l__unravel_head_token 
|> \iffalse }\fi

whereas the second step should (I think) read:

[===== Step 2 =====] {
|| \meaning {
|> \iffalse }\fi

\token_to_str:N acting on brace

\RequirePackage{unravel}
\ExplSyntaxOn
\unravel{\string{}}

gives a low-level runaway argument error (of an unravel macro). This issue came up in \tl_if_head_is_group:nTF {{,}.}

Show correct value of \escapechar

Currently, when reading \escapechar=-1, unravel shows \escapechar=92 instead of -1, but does the right thing. Namely,

\unravel{\escapechar=-1\message{\the\escapechar}}

gives

|> \escapechar =-1\message {\the \escapechar }
[===== Step 1 =====] \escapechar 
|| \escapechar 
|> =-1\message {\the \escapechar }
[===== Step 2 =====] =
|| \escapechar =
|> -1\message {\the \escapechar }
[===== Step 3 =====] -
|| \escapechar =-
|> 1\message {\the \escapechar }
[===== Step 4 =====] 1
|| \escapechar =-1
|> \message {\the \escapechar }
[===== Step 5 =====] Set \escapechar(\escapechar)=92
|| 
|> \message {\the \escapechar }
[===== Step 6 =====] \message = \message
|| \message 
|> {\the \escapechar }
[===== Step 7 =====] \message = \message
|| \message 
|| {
|| \the 
|> \escapechar }
[===== Step 8 =====] \the =>-1
|| \message 
|| {-1
|> }
-1
[===== Step 9 =====] \message {-1}
|| 
|> 
[===== The end! =====]

\unless has no effect in \unravel with TL 19

The following code:

\documentclass{article}
\usepackage{unravel}

\ExplSyntaxOn
\prg_new_conditional:Npnn \pho_if_minus:n #1 { TF }
  {
    \reverse_if:N \if_charcode:w #1 - \exp_not:N \ERROR
      \prg_return_false:
    \else:
      \prg_return_true:
    \fi:
  }
\cs_new:Npn \test #1 { #1|-> \pho_if_minus:nTF {#1} { T } { F } \par }
\ExplSyntaxOff

\begin{document}

\ttfamily

\test{+}
\test{-}

\unravel{\test{+}}
\unravel{\test{-}}

\end{document}

Produces different output for \test{-} and \test{+} if they were used inside \unravel:

+|->F
-|->T
+|->T
-|->F

With TeXLive 2018 the output is the same:

+|->F
-|->T
+|->F
-|->T

\unravel fails on \char_generate:nn

\RequirePackage{unravel}
\ExplSyntaxOn
\unravel{\char_generate:nn{65}{11}}

This stops after 99 steps, despite being in the middle of many expansions.

Decide and document what is a "step"

Currently the notion of "step" in unravel is a bit haphazard. It would be good to clarify what a step can be. This would probably force the code to be simplified.

Admittedly, this issue is presently very vague.

"Too many }'s" repeatedly

\RequirePackage{unravel}
\unravel{\iffalse{\fi}}

will issue the TeX error "Too many }'s" as expected, but will do so repeatedly instead of just once.

Calls to the prepare_mag procedure

The unravel code has \@@_prepare_mag: in every place that original TeX has it. But pdfTeX (at least) adds several more places. Most of them are ultimately only called within \shipout, and the only other one is \immediate\pdfxform.

\expanded support now in all engines

You have \expanded support in luatex but it's now in pdftex etc as well


! Package unravel Error: Internal error: the primitive 'expanded' is not
(unravel)                known.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.