4

I have read multiple questions on this site like How to influence the position of float environments like figure and table in LaTeX? and it seems to me that default behaviour of floats is not what I need.

The behaviour that I would like: If there is eneough space left on the page -> place float where it is called. Start the next paragraph after the float. Else place it in queue and check after every following paragraph -> if float can be placed there -> do it.

What float actually does is either splits some paragraph (on page breaks) leaving single last word of paragraph after the float or it waits for a long time skipping spots where the float would have fitted nicely between paragraphs.

Is there any package or tool that does what I want - simply place figures and tables between paragraphs as soon as there is place left on that page?

I understand that float might not be the correct term as this behaviour might be called by other name, but what is it?

Džuris
  • 195
  • 2
    if you use [htp] then it tries here or puts it on a queue the only difference is that the check for using the queue is at page breaks not every paragraph (doing the latter would be hard in tex, and you'd need some mechanism to prevent the floats at "internal" paragraphs where you don't want it to appear such as sections headings, list labels, etc. Because of tex's asynchronous page breaker what you ask isn't simple at all, tex may collect multiple pages worth of material before invoking the page breaker so you can not simply ask if anything fits "here" until you know the page breaking. – David Carlisle May 21 '15 at 08:10
  • @DavidCarlisle, are you saying that such behaviour would be near impossible? Or there is a chance that some package might deliver that? I dislike floating at page breaks because it leaves couple of lonely words from previous paragraph after float. Paragraph splitting is OK for page break but not OK if there is a float in the middle. – Džuris May 21 '15 at 10:45
  • people can write xml parsers or regex engines in tex so nothing's impossible (and this is likely easier than that) but it isn't simple and might require more code than a typical answer here (but I have some thoughts on a possible approach so may answer one day....:-) Note latex's behaviour is perhaps closer to traditional journal figure placement than your requested behaviour, I don't think in traditional layouts an inserted figure would ever be inserted mid-page. – David Carlisle May 21 '15 at 11:29
  • @DavidCarlisle Good point about journals. Maybe if floats would differ a bit it would be ok. I'll try adding borders or changing formatting of caption. Btw Here is a disastrous example - section's last word is left alone after figure...on a new page :) – Džuris May 21 '15 at 11:44
  • yes in cases like that what you really want to do is get the page breaker to inform the line breaker to break the paragraph differently, putting \loosness=-1 at the start of the paragraph on the previous page would get tex to try to make the para one line shorter which would avoid the bad word, usually that is possible if the paragraphs are not too short, but the architecture of tex makes that impossible to do automatically in a single run (luatex might change this, but currently it doesn't have all the hooks you'd really want to do this) – David Carlisle May 21 '15 at 13:00
  • @Juris -- the example you show indicates a poorly designed (or at least poorly thought out) system. it's easy to prevent widows with \widowpenalty10000, and usually very little reason not to do so. regarding placement of figures in general, if you want a figure between specific paragraphs (if it fits), the only way to ensure that is to input the code for placing the figure right there in your input file. – barbara beeton May 21 '15 at 13:08
  • 2
    You could always use a minipage and \captionof instead of a float. – John Kormylo May 21 '15 at 14:45

1 Answers1

10

Something like this, the command \flushhere if placed between paragraphs tries to take a float off the deferred list and make it a here float at this point, if it succeeds it tries to pop the next deferred float and so on until it runs out.

So if you use [hp] floats between paragraphs and put \flushhere after subsequent paragraphs, any floats that didn't get placed "here" should be flushed out between paragraphs...

Only tested in this file, I probably missed something...

enter image description here

\documentclass{article}


\setcounter{totalnumber}{30}% lots of here floats

\def\a{One two \stepcounter{enumi}\roman{enumi} three four five six. }
\def\b{\a\a  red \stepcounter{enumi}\roman{enumi} red green yellow 
random longer typesetting expressions that might invoke hyphenation. }
\def\c{\a\b\a\a\b\b\a}

\def\f#1{\begin{figure}[hp]\centering\rule{2cm}{1cm}\par\caption{ff: #1}\end{figure}}
\def\t#1{\begin{table}[hp]\centering\caption{tt: #1}\par\bigskip\begin{tabular}{cc}1&2\\33&44\\555&666\end{tabular}\end{table}}

\makeatletter
\def\flushhere{\par{%
 \let\s@deferlist\@deferlist
 \let\@currbox\relax
\@next\@currbox\@deferlist{%
  \ifodd\count\@currbox
\typeout{Trying \meaning\@currbox (\number\@currbox/\the\count\@currbox),
        adding to \meaning\@currlist}%
    \@cons\@currlist\@currbox
\typeout{added: to \meaning\@currlist}%
\typeout{deferlist was \s@deferlist, now \@deferlist}%
\let\s@@deferlist\@deferlist\@empty
\global\let\@deferlist\@empty
    \@floatpenalty -\@Miii
      \penalty -\@Miv
      \@tempdima\prevdepth
      \vbox{}%
      \prevdepth\@tempdima
      \penalty\@floatpenalty
       \@@par
   \ifx\@deferlist\@empty
\typeout{float placed here}%
\global\let\@deferlist\s@@deferlist
   \flushhere
\else
\typeout{float not placed here}%
\global\let\@deferlist\s@deferlist
\fi
    \else
\typeout{not h}%
    \global\let\@deferlist\s@deferlist
    \fi
   }%
  {%
\typeout{no pending float}%
}\par}}

\makeatother

%\let\flushhere\relax

\begin{document}

AA \c \verb|\t{a}\f{a}|

\t{a}\f{a}

BB \c\b \verb|\t{b}\t{c}|

\t{b}\t{c}

BB2 \b \verb|\f{b}\f{c}|

\flushhere

\f{b}\f{c}

CC2 \a

\flushhere

CC \c \verb|\t{d}|

\flushhere
\t{d}

DD \c

\typeout{before DD2}
\flushhere

DD2 \c

\flushhere
\f{d}

EE \c

\typeout{before FF}
\flushhere

FF \c\b 

%\flushhere

\end{document}
David Carlisle
  • 757,742
  • This is actually brilliant! It seems to surely deliver what I was willing for. Only thing that's missing is a routine that puts \flushhere automatically between all there paragraphs. It couldn't harm in any way, could it? – Džuris May 22 '15 at 10:12
  • Although this solution requires a little input between paragraphs, the answer makes it very easy to solve what I was asking for and is useful for me. Therefore I mark it as accepted. – Džuris May 22 '15 at 10:15
  • @Juris as I mentioned the difficulty is deciding which paragraphs are safe you wouldn't want to flush floats after a heading (or inside a heading, which internally is a paragraph) or between a list bullet and the item text or.... – David Carlisle May 22 '15 at 10:15
  • @DavidCarlisle could you explain more please? I couldn't really understand where to add \flushhere. I would appreciate if you could provide simple MWE. – aan Sep 05 '19 at 22:24
  • @aan the answer already contains a test document? – David Carlisle Sep 05 '19 at 22:34
  • what is the used of \flushhere Could you explain more? I tried to add in and compile error said: undefined control sequence, the compiler is having trouble understanding a command you have used – aan Sep 08 '19 at 14:56
  • @aan really you can not ask for personal help via comments on old questions, that is not how the site works. What you show is not the format of a tex error message, the tex error would show which command you have used which is undefined, if you are using an undefined command then you have not used the code posted here. If you get errors make a small test document that shows an error and post a new question. – David Carlisle Sep 08 '19 at 16:55
  • @DavidCarlisle, thanks. I try to create a new MWE and posted my new questions here https://tex.stackexchange.com/questions/507528/using-flushhere-for-table-figure-position – aan Sep 08 '19 at 20:09
  • What do you mean by “a here float”: the float with the behavior of [h], [!h], or [H]? Or, when saying “make it a here float”, do you simply mean a natural-language “put the float here“? –  Aug 20 '22 at 17:00
  • @GeekestGeek it means a h float, H is no float and doesn't get on the deferred list (which makes it pretty curious, considering it stems from a package called float). – Skillmon Aug 20 '22 at 19:49
  • @Skillmon So, “a here float” is a h float. Thanks a lot! (It took me some time to understand your last comment because you used the comma to separate independent clauses. In English, a comma splice is forbidden or at least unusual, depending on the circumstances and on whom you ask. Thanks anyway; I got the contents anyhow!) –  Aug 20 '22 at 20:14
  • @Skillmon actually H came originally from a package (of great repute and pedigree) called here – David Carlisle Aug 20 '22 at 20:36