12

My custom enumerateoptional enumitem environment is putting a useless empty line in the middle of my enumeration list.

To reproduce this, you need to fill a line 100%. See this example I extracted from my full document, reproducing the problem:

\documentclass[12pt]{article}
\errorcontextlines 10000
\usepackage[shortlabels]{enumitem}

\def\renewenumerateoptionalitem{%
  \let\itemenumerateoptional\item%
  \renewcommand{\item}[1][]{%
      \refstepcounter{enumerateoptionali}% increment the counter
      \itemenumerateoptional[\bfseries##1~\theenumerateoptionali]%
  }%
}

\newlist{enumerateoptional}{enumerate}{1}
\setlist[enumerateoptional]{
    before=\renewenumerateoptionalitem,
    label=\arabic*,
    nosep,
    align=left,
    leftmargin=*,
    after=\let\item\itemenumerateoptional,
}

\usepackage{hyperref}
\begin{document}
\begin{enumerateoptional}[1.]
    \item[\bfseries test\_duplicatedContext] Detecção de contextos duplicados e
    emissão de um erro semântico.
    \item[\bfseries test\_duplicatedIncludes] Detecção de inclusões duplicadas  e
    emissão de um erro semântico.
    \item[\bfseries test\_invalidRegexInput] Detecção de expressões regulares 
    inválidas e emissão de um erro semântico.
    \item[\bfseries test\_missingIncludeDetection] Detecção da inclusão um bloco 
    inexistente.
    \item[\bfseries test\_duplicatedGlobalNames] Detecção de múltiplas definições 
    do nome da gramática e
    emissão de um erro semântico.
    \item[\bfseries test\_missingScopeGlobalName] Detecção da falta da definição do 
    nome do escopo global da gramática e emissão de um erro semântico.
\end{enumerateoptional}
\end{document}

On the following image, the extra new line is between the 4th and 5th item. It is happening because the 4th line is filled 100% the maximum width and latex is putting a extra new line right after it I do not know why.

enter image description here

How can I stop this useless empty line popping up in the middle of my lists, depending on each item line size?

  • 2
    Adding an empty line after that item removes the spurious empty line. I'm not sure why that happens, though... Should be something related to the fact that \item does a \par eventually, but apparently at the time it does it's too late. Adding the \par (blank line) earlier works... – Phelype Oleinik Oct 21 at 3:40
  • what about the accented letters? maybe some package calculates the dimensions of an \item including the accented letters, but the typeset example doesn't inlcude them. Does the output look the same if you replace the text in the source code by Deteco da incluso um bloco inexistente.? – thymaro Oct 21 at 3:46
  • @thymaro, with or without the accented letter, the problem happens the same way. On my full document, I got the accented latter correctly displayed. – user Oct 21 at 3:52
  • @PhelypeOleinik, Indeed, I added a empty line before each \item and it was fixed. Thanks! – user Oct 21 at 3:55
  • 5
    Really puzzling... I narrowed the issue down to the hyperref package only. There is something that is making this weird behaviour. Add a \par after the item and the problem goes away. Add a % after the item and the problem also goes away. Comment out the \refstepcounter line and the problem goes away. Comment out hyperref and, you guessed, the problem goes away. Looks like a bug (or at least a quite odd feature) to me... – Phelype Oleinik Oct 21 at 4:54
18

The blank line you see is a misfeature of your code and hyperref making a PDF destination (when you use \refstepcounter) at that exact point.

The workaround of adding a \par after the text works because the paragraph is built and then the PDF destination is inserted at the beginning of the next line and everything goes well. Adding the PDF destination at the end of the line may cause the destination to go to the next (as far as TeX can see) and then the line seems empty.

An arguably better workaround would be to add \par at the beginning of the definition of your modified \item command, so that you make sure that the PDF destination is inserted in the correct place.

However the correct way would be to attach the destination to the \item itself, so that the PDF destination will always be in the right place. One good bad place to insert it, is right before printing the value of the counter. As Ulrike said in the comment, the label is typeset in a box (by default), and the \@currentlabel is lost (I assumed, incorrectly, that its assignment was global as the counter).

Here's a reworked version which uses a patched version of \@item which uses \refstepcounter in the right place, and uses a few more enumitem

\documentclass[10pt]{article}
\usepackage[shortlabels]{enumitem}
\usepackage{etoolbox}
\makeatletter
\let\user@item\@item
\patchcmd\user@item{\if@noitemarg}{\iftrue}{}{\FAILED}
\enitkv@key{}{formatarg}{\def\enit@format##1{#1}}
% Compatibility with older enumitem.sty:
\@ifundefined{enitkv@enumitem@formatarg}
  {\enitkv@key{enumitem}{formatarg}{\def\enit@format##1{#1}}}{}
\newlist{enumerateoptional}{enumerate}{1}
\setlist[enumerateoptional]{%
    before=\let\@item\user@item,
    formatarg=\textbf{########1~\@itemlabel},
    nosep,
    align=left,
    leftmargin=*,
}
\makeatother
\usepackage[colorlinks]{hyperref}
\begin{document}
\begin{enumerateoptional}[1.]
  \item[test\_duplicatedContext] Detecção de contextos duplicados e
    emissão de um erro semântico.
  \item[test\_duplicatedIncludes] Detecção de inclusões duplicadas  e
    emissão de um erro semântico.
  \item[test\_invalidRegexInput] Detecção de expressões regulares 
    inválidas e emissão de um erro semântico.
  \item[test\_missingIncludeDetection]\label{this} Detecção da inclusão um bloco 
    inexistente.
  \item[test\_duplicatedGlobalNames] Detecção de múltiplas definições 
    do nome da gramática e
    emissão de um erro semântico.
  \item[test\_missingScopeGlobalName] Detecção da falta da definição do 
    nome do escopo global da gramática e emissão de um erro semântico. Ver item~\ref{this}.
\end{enumerateoptional}
\end{document}

enter image description here

Also there is no need to restore \item in the after code (it doesn't harm either) because the \let you do is local to the environment, so once it ends \item is restored to its original definition.

You also don't need \bfseries in every single \item: you already use \bfseries in the new definition of \item.

  • 2
    Adding \refstepcounter{enumerateoptionali} inside the optional argument doesn't work: this is a box and you loose the \@currentlabel and the destination for links. Imho a really sane solution would need a change to the latex \@item command so that it allows to increase the counter even if an optional argument is present (or accepts a second optional argument). – Ulrike Fischer Oct 21 at 9:25
  • @UlrikeFischer I assumed the assignment to \@currentlabel was global too. I fixed it. Thanks :-) – Phelype Oleinik Oct 21 at 15:08
  • @PhelypeOleinik, after you latest update, the example image is missing the dot . after the number (remember the enumitem shortlabel [1.] I passed when instantiating the list on \begin{enumerateoptional}[1.]). Also, latex cannot build you example anymore. It throws: main.tex:20: Package enumitem Error: formatarg undefined. I tested both with MikTek and TexLive 2017. – user Oct 22 at 0:53
  • @user Oops. Fixed it to take the label into account. The error formatarg undefined is probably because you a) didn't copy the line that says \enitkv@key{}{formatarg}{\def\enit@format##1{#1}}, or b) forgot to write \makeatletter before it. The key formatarg is not defined by enumitem: I defined it to be a small variation of the format key. – Phelype Oleinik Oct 22 at 9:59
  • @PhelypeOleinik, I copied you whole example into a 100% clean new document. I recorded a video proving it to you: i.imgur.com/D2xTY5e.gif – user Oct 22 at 22:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.