Mysterious horizontal space when using \label after beginning a user-defined environment

Here is my MWE:

\documentclass{article}
\RequirePackage{expl3}
\RequirePackage{xparse}

\ExplSyntaxOn
\newcounter{exercise}
\NewDocumentEnvironment{exercise}{}
{
\refstepcounter{exercise}
\par\noindent
\theexercise.\hspace{4pt}X
\ignorespaces
}
{
\par
\ignorespacesafterend
}
\ExplSyntaxOff

\begin{document}

\begin{exercise}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\begin{exercise}\label{A}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\end{document}


Here's the result I see:

Note that there's extra space after the "X" in the second case. This appears to be caused by the \label command. Of course, I'd like it to not be there, but I'm not sure where to begin with diagnosing the problem.

You have to delay the typesetting until possibly \label has appeared. Assuming these exercises aren't inside lists, the simplest way is using \everypar.

\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{showframe}

\ExplSyntaxOn
\newcounter{exercise}
\NewDocumentEnvironment{exercise}{}
{
\refstepcounter{exercise}
\par
\everypar={{\setbox0=\lastbox}\theexercise.\hspace{4pt}\everypar={}}
}
{
\par
\ignorespacesafterend
}
\ExplSyntaxOff

\begin{document}

\begin{exercise}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\begin{exercise}\label{A}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\end{document}


With {\setbox0=\lastbox} we remove the indentation box; since \label doesn't start a paragraph, the space after it is ignored.

Possibly simpler: use a theorem-like environment.

\documentclass{article}
\usepackage{amsthm}
\usepackage{showframe}

\newtheoremstyle{exercise}
{0pt}       % ABOVESPACE
{0pt}       % BELOWSPACE
{\upshape}  % BODYFONT
{0pt}       % INDENT (empty value is the same as 0pt)
{\thmnumber{#2}}

\theoremstyle{exercise}
\newtheorem{exercise}{}

\begin{document}

\begin{exercise}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\begin{exercise}\label{A}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\end{document}


This is the case because \label was created in such a way that it doesn't introduce a second white space after it and doesn't change the spacefactor (a TeX internal variable which specifies how much the current space might be stretched to get alignment, it is set dependent on the last character prior to that space). This is done by \@bsphack and \@esphack. Unfortunately this ends the scope of \ignorespaces as there was a non-space token, and the space after \label{} is in fact inserted because there was no space prior to \label (else there would be an \ignorespaces inserted by \@esphack).

The following checks whether exercise is followed by a \label and if so eats the space after \label{}:

\documentclass{article}
\RequirePackage{expl3}
\RequirePackage{xparse}

\ExplSyntaxOn
\makeatletter
\newcounter{exercise}
\NewDocumentEnvironment{exercise}{}
{
\refstepcounter{exercise}
\par\noindent
\theexercise.\hspace{4pt}X
\@ifnextchar\label
{\eatlabel}{\ignorespaces}
}
{
\par
\ignorespacesafterend
}
\newcommand\eatlabel{}
\def\eatlabel\label#1{\label{#1}\ignorespaces}
\makeatother
\ExplSyntaxOff

\begin{document}

\begin{exercise}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\begin{exercise} \label{A}
If $H$ is a subgroup of $G$, then something.
\end{exercise}

\end{document}


• Wow. That's a surprise. One more weird LaTeXism, I guess. – Derek Aug 5 '18 at 20:53
• @Derek not so much. Considering the most use cases this is what \label and the like (so all those \@bsphack \@esphack macros) should most reasonably do. You don't want it to eat all the space around it, just not introduce a second space. – Skillmon Aug 5 '18 at 20:56