16

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.

2 Answers 2

17

The etoolbox package redefines \begin so that

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

Thus what you get is

\@beforebegin@table@hook
\begingroup
<bookkeeping>
\@begin@table@hook
\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.

0
2

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .