You would think that I would know better than to mess with an egreg solution, but in my defense I used a DavidCarlisle solution from \setbox vs. \sbox and \savebox – What are the differences I need to know about? to adapt egreg's solution to Proper way to detect empty/blank text.
This has worked fine for me up until now, but when I attempt to use it within an enumerate
environment it results in it gobbling up the item number:
Note that the item number is not gobbled for the case where there is no title to be used (Third Item).
If I replace the \sbox0{\begingroup\vbox{#1}\endgroup}
as per the original solution:
\sbox0{#1}
this particular MWE work, but causes problems elsewhere (not shown here).
Question:
So, what is the minimal change I could make to the existing \sbox0
solution so that the item numbers is not gobbledr?
I am disabling some macros within the \begingroup
so as to eliminate any side effects so do need the grouping.
Code:
\documentclass{article}
\usepackage{enumitem}
\makeatletter
\newcommand{\DoIfNonEmptyText}[1]{% Actually takes two parameters
%\sbox0{#1}%
\sbox0{\begingroup\vbox{#1}\endgroup}%
\ifdim\wd0=\z@\relax%
\expandafter\@gobble%
\else%
\expandafter\@firstofone%
\fi%
}%
\makeatother
\newcommand{\QuotableText}[3][]{%
% [#1] = optional title
% #2 = name for this (not relevant for this example)
% #3 = the content
\DoIfNonEmptyText{#1}{\textit{#1}:~}%
#3%
}%
\begin{document}
\begin{enumerate}
\item First Item
\item \QuotableText[Sub title]{Text One}{Second Item}
\item \QuotableText{Text Two}{Third Item}
\item Fourth Item
\end{enumerate}
\end{document}
Update:
Based on Frank Mittelbach's answer, I attempted to use my own \savebox
, but it still exhibits the same output as above:
\makeatletter
\newsavebox{\@DoIfNonEmptyTextBox}%
\newcommand{\DoIfNonEmptyText}[1]{% Actually takes two parameters
\begingroup
\savebox{\@DoIfNonEmptyTextBox}{\vbox{#1}}% -- This still gobbles the item number!
%\savebox{\@DoIfNonEmptyTextBox}{#1}% -- This works
\ifdim\wd\@DoIfNonEmptyTextBox=\z@\relax%
\endgroup\expandafter\@gobble%
\else%
\endgroup\expandafter\@firstofone%
\fi%
}%
\makeatother
but if I remove the \vbox{}
, then this works just fine. So, how is the use of the \vbox
(note: no use of \sbox0
here), causing the enumerate item to disappear?
Best Answer
The wrong answer (though by chance it solved the issue)
The answer is simply do not use box 0 or ensure that your use of it does no harm. This is a scratch box, but the
\item
command of LaTeX also uses that one to store its item for a tiny while (between encountering the\item
command and typesetting the label once the paragraph started) and your\QuotableText
is executed during this time.Now your change to box0 is not local thus you overwrite the content.
Solution 1: use
\newbox
to get your private box register for your testSolution 2: make your change to box0 local. You start a group and close it directly after making the measurement (which means close it in both branches):
You had
but there the group is done at the wrong place. The setting of box 0 ist still outside the group. Inside your group there is only stuff that is being typeset and so the group has no effect whatsoever.
Update (why is the
\vbox
making the item label disappear)This is a tricky one. One has to look carefully at how the list environment attaches the item label to the item paragraph.
Basically, what happens inside is that the label is constructed and stored in a box (and it is not as I claimed earlier box 0 but actually a private box (
\@labels
) so thanks for the vote of confidence, but my answer was simply wrong.Now that box is attached to the by the use of
\everypar
, the actual definition used isSo the above gets executed when a switch from vertical mode to horizontal mode happens.
Now if we just test using
\sbox
then this is building an h-box and so\everypar
is not executed. However, if we use a\vbox
inside then any text in#1
will trigger that\everypar
. And if you look carefully, the label will only be set if@inlabel
is true and this switch is globally set to false in the true case.So basically the label is put into this
\vbox
for testing and afterwards is not being typeset again.So in summary the above initial argument was wrong (I didn't look carefully, the list environment does use box 0 but that is harmless) and my redefinition only worked because I took out the
\vbox
at the same time.