etoolbox: AtBeginEnvironment is not At Begin Environment

I tried the following MWE:

\documentclass{article}
\usepackage{etoolbox}

\AtBeginEnvironment{table}{AtBeginEnvironment\par}
\AtEndEnvironment{table}{AtEndEnvironment\par}
\BeforeBeginEnvironment{table}{BeforeBeginEnvironment\par}
\AfterEndEnvironment{table}{AfterEndEnvironment\par}

\begin{document}
Text before\par
\begin{table} [t]%
Table text\par
\end{table}
Text after\par
\end{document}


and got the following result:

Table text
AtEndEnvironment
Text before
BeforeBeginEnvironment
AtBeginEnvironment
AfterEndEnvironment
Text after


I was expecting AtBeginEnvironment to travel to the top of the page together with the float. Here is what the manual has to say on the matter:

\AtBeginEnvironment{<environment>}{<code>}
Appends arbitrary <code> to a hook executed by the \begin command
at the beginning of a given <environment>, immediately before
\<environment>, inside the group opened by \begin.


I do not know what happens inside an environment definition; I guess it declares some special commands called \<environment> (e.g. \table) and \end<environment> (e.g. \endtable).

But in this case, shouldn't it be immediately after \<environment>, in order to be a complement to \AtEndEnvironment just as \BeforeBeginEnvironment is a complement to \AfterEndEnvironment?

Anyway, how can I add code to the beginning of an environment? I'm trying to set a certain font style for all tables, and \AtBeginEnvironment{table}{\small} does not work. Also I guess this behavior makes this answer incorrect, because \addvspace would stay at the point of declaration of the figure instead of moving together with it.

The etoolbox package redefines \begin so that

1. \@beforebegin@<envname>@hook is executed
2. the usual bookkeeping is performed (setting \@currenvir, for instance)
3. \@begin@<envname>@hook is executed 1 a group is started
4. the macro \<envname> is executed

Thus what you get is

\@beforebegin@table@hook
<bookkeeping>
\@begin@table@hook
\begingroup
\table


The macro \table is responsible for starting the creation of a float and expands to \@float{table}.

Thus the tokens AtBeginEnvironment\par and BeforeBeginEnvironment\par are seen and the paragraphs are typeset before the float is started.

To the contrary, \end is redefined to execute the \AtEndEnvironment tokens before \end<envname> is executed.

This should explain the output you get.

There is a hook for doing things when the float has already begun and is \@floatboxreset.

I would be wary of using the hooks for adding text: they're meant for additional setup.

• \@begin@table@hook isn't inside the group? – touhami May 28 '19 at 18:00
• Thank you. > I would be wary of using the hooks for adding text: they're meant for additional setup. I'm wary too, I just used it to see what goes where. > There is a hook for doing things when the float has already begun and is \@floatboxreset. That’s helpful, but alas, it does not allow to set different settings for different float types. – ScumCoder May 28 '19 at 18:01
• Also, I must add that I ended up using \setfloatadjustment command from memoir, on which I stumbled upon when I read your answer and started digging the \@floatboxreset. – ScumCoder May 28 '19 at 18:03
• @ScumCoder you can put float-type specific code in \@floatboxreset you just need to test \@captype – David Carlisle May 28 '19 at 18:10
• @DavidCarlisle I'm afraid this is a bit too hardcore for me yet, I'll just settle for something more philistine for the time being :) – ScumCoder May 28 '19 at 18:14

In case you intended to use this to, say, globally adjust the formatting of tables and figures, the following would be a work-around:

% Redefine figure environment so that all figures are centered and use tiny sans-serif font
\makeatletter
\let\figureorig\figure
\def\figure@i[#1]{\figureorig[#1]\centering\sffamily\tiny}  % with optional argument
\def\figure@ii{\figureorig\centering\sffamily\tiny}  % without optional argument
\def\figure{\@ifnextchar[\figure@i \figure@ii}  % Redefine depending on presence of [
\makeatother

% Redefine table environment so that all tables are set in tiny sans-serif font
\makeatletter
\let\tableorig\table
\def\table@i[#1]{\tableorig[#1]\sffamily\tiny}  % with optional argument
\def\table@ii{\tableorig\sffamily\tiny}  % without optional argument
\def\table{\@ifnextchar[\table@i \table@ii}  % Redefine depending on presence of [
\makeatother


The relatively complicated redefinition results from the fact that the figure and table environments can carry optional arguments. Thus, the redefinition looks for an opening square bracket “[” in order to determine whether an optional argument is provided or not.