Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using [resume*] without antecedent leads to edge case #48

Closed
wwywong opened this issue Apr 11, 2024 · 1 comment
Closed

Using [resume*] without antecedent leads to edge case #48

wwywong opened this issue Apr 11, 2024 · 1 comment

Comments

@wwywong
Copy link

wwywong commented Apr 11, 2024

Consider the (somewhat unrealistic) MWE

\documentclass{article}

\usepackage{enumitem}

\begin{document}

\begin{enumerate}[resume*]
        \item Test
\end{enumerate}
\end{document}

This will print the text resume,, before the list starts.

My TeX.SE answer describes why, and this can be solved by using a different token to check of list termination in the definition of \enitkv@do#1, (currently it uses \relax to mark end of list, which is the cause of the problem as \csname ... \endcsname returns \relax when the macro is undefined.


A more realistic use case which leads to this showing up is if a user used \begin{enumerate}...\end{enumerate} within an environment (so in a group), and then tried to call \begin{enumerate}[resume*] ... \end{enumerate} afterwards from outside the group. This can be abstracted as

\documentclass{article}

\usepackage{enumitem}

\begin{document}

\bgroup
\begin{enumerate}
        \item Test 1
\end{enumerate}
Text
\begin{enumerate}[resume*]
        \item Test 2
\end{enumerate}
\egroup

\begin{enumerate}[resume*]
        \item Test
\end{enumerate}
\end{document}

In this case, we see a very strange behavior. The first time the resume* environment hits, everything is okay. The second time the resume* environment hits, we get the weird resume,, text showing up, but the counter is resumed correctly!

This is because for resume* it doesn't save the optional arguments, but it saves the counter via \global. While the first call to enumerate saves both but only locally. From the package:

\def\enit@endlist{%
  \enit@after
  \endlist
  \ifx\enit@series\relax\else % discards resume*, too
    \ifnum\enit@resuming=\@ne % ie, series=
      \enit@setresumekeys{series@\enit@series}\global\global
    \else % ie, resume=, resume*= (save count, but not keys)
      \enit@setresumekeys{series@\enit@series}\@gobblefour\global
    \fi
    \enit@afterlist
  \fi
  \ifnum\enit@resuming=\thr@@ % ie, resume* list (save count only)
    \enit@setresumekeys\@currenvir\@gobblefour\global
  \else
    \enit@setresumekeys\@currenvir\@empty\@empty
  \fi
  \aftergroup\enit@afterlist}

Part of me is also wondering whether for the resume* (but not series) case, it would make more sense to have \@gobblefour\@empty instead of \@gobblefour\global to line up with the other non-series cases.

@muzimuzhi
Copy link

muzimuzhi commented Apr 12, 2024

Here is a patch which makes use of resume* without antecedent behaves the same as such use of resume: input is accepted silently and nothing is resumed.

\documentclass{article}
\usepackage{enumitem}

\makeatletter
\@namedef{enitkv@enumitem-resume@resume*@default}{%
   \let\enit@resuming\thr@@
  \enit@ifunset{enit@resumekeys@\@currenvir}
    % Nothing to resume if this is the first occurrance of \@currenvir.
    % An empty \enit@resumekeys results in \enitkv@setkeys{enumitem}{,resume}
    % called in \enit@setresume.
    {\def\enit@resumekeys{}}
    {\let\enit@resuming\thr@@
     \expandafter\let\expandafter\enit@resumekeys
       \csname enit@resumekeys@\@currenvir\endcsname
     \@nameuse{enit@resume@\@currenvir}\relax}%
  }
\makeatother

\newlist{myenum}{enumerate}{3}
\setlist[myenum]{label=\roman*}

\begin{document}

\begin{enumerate}[resume*]
  \item Test \texttt{resume*} without antecedent
\end{enumerate}

\begin{enumerate}[resume*]
  \item b
  \item c
\end{enumerate}

\begin{myenum}[resume]
  \item Test \texttt{resume} without antecedent
\end{myenum}

\begin{myenum}[resume]
  \item b
  \item c
\end{myenum}

\end{document}

image

enumitem/enumitem.sty

Lines 393 to 406 in 1bdcad0

\@namedef{enitkv@enumitem-resume@resume*}#1{%
\enit@checkseries@m
\let\enit@resuming\tw@
\edef\enit@series{#1}%
\enit@ifunset{enit@resumekeys@series@#1}%
{\enit@noserieserror{#1}}%
{\expandafter\let\expandafter\enit@resumekeys
\csname enit@resumekeys@series@#1\endcsname}}
\@namedef{enitkv@enumitem-resume@resume*@default}{%
\let\enit@resuming\thr@@
\expandafter\let\expandafter\enit@resumekeys
\csname enit@resumekeys@\@currenvir\endcsname
\@nameuse{enit@resume@\@currenvir}\relax}

@jbezos jbezos closed this as completed in 3637958 Jan 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants