6

I'm trying to redefine an environment in order to add a command after the \begin without having to add this command in manually everywhere.

For example, I'd like to replace every instance of \begin{figure} with \begin{figure}\foo where \foo is a function I've defined earlier:

\newcommand{foo}{This is foobar}

If I simply do:

\renewenvironment{figure}{\begin{figure}\foo}{\end{figure}}

then this creates a recursive definition of the figure environment. This answer suggests using an intermediate command to get past the recursion problem when using \renewcommand.

But how can I get past the recursion problem when using \renewenvironment?

3
  • It works basically the same...
    – user31729
    Apr 1, 2016 at 17:21
  • 1
    Related (maybe duplicate): tex.stackexchange.com/questions/116670/duplicating-environments. You need to save original definitions, and redefine the environment in terms of the saved components. Apr 1, 2016 at 17:22
  • @StevenB.Segletes yes, this answer will be used to solve my problem. The fact I'm currently struggling to work out exactly how to apply it to my problem suggests it's not quite a duplicate.
    – LondonRob
    Apr 1, 2016 at 17:25

2 Answers 2

5

Patching existing environments or commands is almost a black art. One has to know in detail how the environment or command works.

Even saving a copy of \figure the newly defined environment will not work like the original one, particularly with respect to optional arguments.

The best place where placing code to be executed at every figure is in \@floatboxreset.

However, since you want to do it only for figure, there's something more to do.

\makeatletter
\g@addto@macro\@floatboxreset{\londonrob@floatcode{\@captype}}
\newcommand\londonrob@floatcode[1]{\@nameuse{londonrob@#1code}}
\newcommand\londonrob@figurecode{WHATEVER}
% similarly for \londonrob@tablecode if needed
\makeatother

Full example

\documentclass{article}

\usepackage{lipsum}

\makeatletter
\g@addto@macro\@floatboxreset{\londonrob@floatcode{\@captype}}
\newcommand\londonrob@floatcode[1]{\@nameuse{londonrob@#1code}}
\newcommand\londonrob@figurecode{WHATEVER}
% similarly for \londonrob@tablecode if needed
\makeatother

\begin{document}

\lipsum[2]

\begin{figure}[htp]

Something else

\caption{A caption}

\end{figure}

\lipsum[3]

\end{document}

Of course, in place of WHATEVER you'll add the code you want to be executed.

enter image description here

2
  • Ouch. I never expected to have to get in this deep. There's a lot to learn in this example. Could you mention what the exact pitfalls of the \let\temp\figure-approach are? It looks to me as if redefining figure in this way works ok.
    – LondonRob
    Apr 1, 2016 at 18:11
  • 2
    @LondonRob \figure expands to \@float{figure} and this in turn looks for the optional argument in quite an indirect fashion. If you say \let\oldfigure\figure and then \renewcommand{\figure}{\oldfigure\foo} the optional argument will never be found.
    – egreg
    Apr 1, 2016 at 18:14
-2

If you need to add something to the figure environment, you can try this:

\def\foo{This is foobar}
\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\addto\figure{\foo}
6
  • Sorry, no, it can't work; \figure expands to \@float{figure} and \@float does a check for the optional argument.
    – egreg
    Apr 1, 2016 at 17:42
  • It works. That is all.
    – wipet
    Apr 1, 2016 at 18:14
  • 1
    OP needs to substitute \begin{figure}\foo not \begin{figure}[htp]\foo.
    – wipet
    Apr 1, 2016 at 19:32
  • 1
    That's exactly the point: such a substitution would be completely useless. Question: “Can I jump off the tour Eiffel?” Your answer: “Yes, just jump”. My answer: “Get a parachute before jumping.”.
    – egreg
    Apr 1, 2016 at 19:37
  • 4
    The parachute is very dangerous when you are jumping off the Eiffel. There is no time to open it.
    – wipet
    Apr 2, 2016 at 4:54

You must log in to answer this question.

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