Skip to content

Instantly share code, notes, and snippets.

@jfbu
Created June 20, 2017 14:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfbu/2f3d04414359f716f98ea64dac91eb0e to your computer and use it in GitHub Desktop.
Save jfbu/2f3d04414359f716f98ea64dac91eb0e to your computer and use it in GitHub Desktop.
illustration of a peculiarity of TeX paragraph building
\documentclass{article}
\usepackage{mwe}
\begin{document}
% or anything filling the line with less than inter-word space shrinkability
\noindent\rule{\linewidth}{1pt} % <-- we deliberately leave a space token here
\begin{figure}[htbp]
\centering
% only by way of example, close to real life examples
\includegraphics[height=1cm]{example-image-a}
\caption{Hello, is there extra space above figure env?}
\end{figure}
\noindent\rule{\linewidth}{1pt}
\begin{figure}[htbp]
\centering
\includegraphics[height=1cm]{example-image-a}
\caption{This one doesn't have any...}
\end{figure}
\end{document}
@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

TeX's paragraph routine starts a new (empty) line due to the space token. If figure had done \par the problem would not show.

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

so the derivative question is: is there any reason figure environment does not do \par upfront ?

\let\oldfigure\figure
\def\figure{\par\oldfigure}

and then there is no empty line above figure.

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

my comment at https://gist.github.com/jfbu/2f3d04414359f716f98ea64dac91eb0e#file-figure-tex-L6 is not quite accurate.

Indeed:

\noindent\rule{\dimexpr\linewidth-1sp}{1pt} 
\begin{figure}[htbp]

does not have the extra line. And we left only 1sp room...

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

I have encountered this same issue in various disguises (see for example mention of it in the filecontentsdef manual.

@davidcarlisle
Copy link

figure is designed to work inline it can't start with \par

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

@davidcarlisle I had never checked out the figure code (and still haven't really), hence I wasn't aware of that, thanks. I see the point of being able to put a figure mid-paragraph without forcing the text line above it to be flushleft. However if I try out figure with a line above being something like (noindent is for comparing 2 lines) \noindent AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA AAAA, I see that the material above behave as if it had been ended by \par. Adding and removing \par changes nothing to the output. edit my testing was not done with continuation of source after \end{figure}, see next comment.

Well, the phenomenon this gist is about is from a real life case. I reproduce it with this

AAAAAAAA  AAAAAAAA  AAAAAAAA  AAAAAAAA  AAAAAAAA IIII.
\begin{figure}[htbp]
  \centering
  x
\end{figure}

Adding \ifhmode\unskip\fi to start of \figure the problem is fixed. Perhaps something could be hacked into sphack ?

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

ok sorry @davidcarlisle. I see now the point of figure in paragraph, I just had not tested with enough material after the figure in tex source.

@jfbu
Copy link
Author

jfbu commented Jun 20, 2017

problem indeed disappears if there is some continuation immediately after \end{figure} because rather than an empty line we get that continuation material there.

Bottom line thus seems to be that if one leaves an empty line after figure environment in source, one should also leave a blank line in source above figure environment. Else the real life problem may (and does sometimes) occur. (this was reported at Sphinx issue tracker sphinx-doc/sphinx#3881)

@davidcarlisle
Copy link

\ifhmode\unskip\fi is exactly what bsphack does so no need to hack that in!

@jfbu
Copy link
Author

jfbu commented Jun 21, 2017

about bsphack/esphack I was probably meaning: as bsphack does \ifhmode\unskip\fi already perhaps a modified esphack would handle that problem. But I admit I do not have examined in detail why there is still the problem even with \end{figure}\par ... (many edits)....

Arrrgh.. you fooled me ;-) no that's not true, \@bpshack does NOT do \unskip. There is only an \ignorespaces in \@esphack rather...

\def\@bsphack{%
  \relax
  \ifhmode
    \@savsk\lastskip
    \@savsf\spacefactor
  \fi}

(edited)

@jfbu
Copy link
Author

jfbu commented Jun 21, 2017

as proof of concept, I hacked this version

\def\@bsphack{%
  \relax
  \ifhmode
    \@savsk\lastskip
    \@savsf\spacefactor
    \unskip % ADDED
  \fi}
\def\@esphack{%
  \relax
  \ifhmode
    \spacefactor\@savsf
    \ifdim\@savsk>\z@
      \hskip\@savsk % ADDED
      \ifdim\lastskip=\z@
        \nobreak \hskip\z@skip
      \fi
      \ignorespaces
    \fi
  \fi}%

It surely has issues, but with this, the problem of this gist with figure goes away.

But, anyhow I do not at all advocate this, not only because I have not tried to analyse consequences in general, but mainly from my earlier comment about what end user should do.

@davidcarlisle
Copy link

well true but anyway adding an extra unskip would break the intention of bsphack, that's what I meant. bspack/espack is supposed to leave a space if there is a space before or a space after, it would probably have been better if it removed the space from the start and re-inserted at the end but a bit scary to change that now it's been the way it is since the dawn of time, and in your case with a figure at the end of a paragraph it wouldn't help as you'd still end up with two spaces (perhaps, depending on details of unwritten code)

@davidcarlisle
Copy link

\hskip@savsk % ADDED
\ifdim\lastskip=\z@

for example can't be right as written as the test will never be true (that's probably fixable but this is a very delicate area, and early on in 2e we tried several variants all broke something)

@jfbu
Copy link
Author

jfbu commented Jun 21, 2017

@davidcarlisle Yes of course, the \ifdim will never be true, I just dropped the extra line in for checking it worked in my use case, I should I have put it after but didn't like the \nobreak, and didn't think twice

@jfbu
Copy link
Author

jfbu commented Jun 21, 2017

about figure at end of paragraph, the \ignorespaces it still there. It does make the issue go away in my testing. the ignorespaces is not relevant here. It works without it. (see next comment)

@jfbu
Copy link
Author

jfbu commented Jun 21, 2017

for example with

AAAAAAAA  AAAAAAAA  AAAAAAAA  AAAAAAAA  AAAAAAAA IIII.
\begin{figure}[htbp]
  \centering
  x
  \caption{Hello, is there extra space above figure env?}
\end{figure} {} {}

and the modified sphack, there is no issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment