[Tex/LaTex] Making \footnote work in leftbar environment

environmentsfootnotesframedmacros

Sorry, it's me again. Gonzalo has hinted me to the very nice leftbar environment in the framed package, which I now use for definitions, theorems and similar environment. Now I've got a new problem: Footnotes (\footnote) from inside the leftbar environment are not shown! The label is there, but there is no footnote with the corresponding number.

According to this here and similar sources, this can be fixed by using \footnotemark and \footnotetext. The problem is: I'm using SWP and would like to have the \footnote command for footnotes. I thought of something like this:

\renewcommand{\footnote}[1]{\footnotemark \footnotetext{#1}}

But \footnotemark and \footnotetext need a label. So what I would like the most is someting like

\renewcommand{\footnote}[1]{\footnotemark[some arbitrary string "x" that cannot collide with an "x" from a different footnotemark] \footnotetext["x"]{#1}}

I've tried to use #1 itself as "x", but this spits out errors (not surprisingly, given that it is non-sanitized LaTeX). Is there a trick here, or is my syntax wrong?

EDIT: My renewcommand is stupid anyway. The trick is to have the \footnotetext come after the end of the leftbar environment. Is there a way to get this through renewcommand?

Best Answer

A slightly longer code, which allows you to only type \footnote. The idea is to make each footnote append \footnotetext{#1} to a token list. This token list is then typeset at the right place. Some trickery is required to get nesting right, as well as hyperref support. Normally, this can be used for other (non-verbatim-ish) environments.

Comments in the code.

\documentclass{article}
\usepackage{etoolbox} % for "\pretocmd".
\makeatletter
%
% User command, see the end of the preamble for use.
% We redefine the environment by adding "\savefoot@begin" at 
% the beginning, and "\savefoot@end" at the end.
%
\newcommand{\DeclareSavefootEnvironment}[1]{%
  \expandafter\pretocmd\csname #1\endcsname
              {\savefoot@begin}{}{\savefoot@patch@error{#1}}%
  \expandafter\pretocmd\csname end#1\endcsname
              {\savefoot@end}{}{\savefoot@patch@error{#1}}%
}
\newcommand{\savefoot@patch@error}[1]{%
  \PackageError{savefoot}{etoolbox failed to patch the environment #1, sorry}{}}
%
% Register allocation.
%
\newcount\c@savefoot@depth
\newtoks\savefoot@toks
%
% "\savefoot@begin" starts an environment which saves footnotes.
% We only want to output footnotes outside any such environment,
% so we count how deep we are in this kind of environment using
% the count "\c@savefoot@depth", which pretends to be a LaTeX
% counter. 
%
% We will store all the "\footnotetext" into the toks 
% "\savefoot@toks". This is initialized _locally_ at the start
% of each "savefoot" environment.
% 
\newcommand{\savefoot@begin}{%
  \advance\c@savefoot@depth by 1\relax  
  \savefoot@toks={}}
%
% When ending a savefoot environment, we check if it was the 
% outermost one. In that case, "\@secondoftwo", we output the
% "\footnotetext" that we saved, after the end of the group.
% The "\endgroup" must be explicitly there; this is the case
% because of how "\end{...}" works in LaTeX2e.
% 
% Since the register "\savefoot@toks" is restored at the end 
% of the group, we need to expand it inside the group, then 
% send "\savefoot@append{<expanded \savefoot@toks>}" after the
% "\endgroup", hence the "\expandafter"s. Same thing when we 
% need to typeset.
% 
\newcommand{\savefoot@end}{%
  \ifnum\c@savefoot@depth>\@ne
  \expandafter\@firstoftwo
  \else
  \expandafter\@secondoftwo
  \fi
  {% Nested, don't output, save to the level above.
    \expandafter\do@after@explicit@endgroup\expandafter{%
      \expandafter\savefoot@append\expandafter{\the\savefoot@toks}}%
  }%
  {% Outside, output.
    \expandafter\do@after@explicit@endgroup\expandafter{%
      \the\savefoot@toks}%
  }%
}
%
% Appending to a toks is standard.
%
\newcommand{\savefoot@append}[1]{%
  \savefoot@toks\expandafter{\the\savefoot@toks#1}}%
%
% To put after "\endgroup", we need delimited parameters,
% hence the "\def". We first check that the command is new,
% just in case.
% 
\newcommand{\do@after@explicit@endgroup}{}
\def\do@after@explicit@endgroup#1#2\endgroup{#2\endgroup#1}
%
% Now the footnote command. We save the old definition, 
% used in the case where we are outside any savefoot
% environment. If we are inside a savefoot environment,
% place the "\footnotemark", and append 
% 
%    \savefoot@setcounter{<explicit number>}\footnotetext{<text>}
% 
% to our register. This will be typeset at the end. We cannot
% just do "\footnotetext[<explicit number>]{<text>}", because
% the hyperref package does not like that.
% 
\let\savefoot@old@footnote\footnote
\renewcommand{\footnote}[1]{%
  \ifnum\c@savefoot@depth>\z@
  \expandafter\@firstoftwo
  \else
  \expandafter\@secondoftwo
  \fi
  {% Inside a leftbar, save the text in the relevant toks.
    \footnotemark
    \savefoot@toks=\expandafter{%
      \the\expandafter\savefoot@toks
      \expandafter\savefoot@setcounter\expandafter{\the\c@footnote}%
      \footnotetext{#1}%
    }%
  }%
  {% Don't save, just typeset.
    \savefoot@old@footnote{#1}%
  }%
}
%
% When not using hyperref, just give the counter "footnote" 
% the right value (in that case, "\savefoot@hhyperref@support{#1}"
% will be defined to do nothing).
% 
\newcommand{\savefoot@setcounter}[1]{%
  \setcounter{footnote}{#1}%
  \savefoot@hyperref@support{#1}%
}
% 
% Getting "\footnotetext" and "\footnotemark" to work with hyperref
% is non-trivial, and I probably did something wrong. But at first
% sight it seems ok.
%
\newcommand{\savefoot@hyperref@support}[1]{%
  \setcounter{Hfootnote}{#1}%
  \global \let \Hy@saved@currentHlabel \@currentHlabel 
  \global \let \Hy@saved@currentHref \@currentHref 
  \hyper@makecurrent {Hfootnote}%
  \global \let \Hy@footnote@currentHlabel \@currentHlabel 
  \global \let \Hy@footnote@currentHref \@currentHref 
  \global \let \@currentHlabel \Hy@saved@currentHlabel 
  \global \let \@currentHref \Hy@saved@currentHref
}
%
% If hyperref is not loaded, we disable the hyperref support.
% We check at the "\begin{document}".
%   
\AtBeginDocument{%
  \@ifpackageloaded{hyperref}{}{\let\savefoot@hyperref@support\@gobble}%
}
\makeatother


% ============= Example =====================

\usepackage{framed}
\usepackage{hyperref}
\DeclareSavefootEnvironment{leftbar}

\begin{document}

Some text,\footnote{With a normal footnote.} in which 
footnotes are preserved.\footnote{Even when you put several 
  in a row.}\footnote{Like this.}

\begin{leftbar}
  Also true for the leftbar environment.\footnote{The relevant 
    commands are placed after the end of the environment.} 
  \begin{leftbar}
    And we check that nesting works.\footnote{That was the tricky part\ldots}
  \end{leftbar}
  Maybe it breaks after nesting?\footnote{Let's see.}
\end{leftbar} 

More footnotes.\footnote{Like this.}\footnote{And that.}

\begin{leftbar}
  And another leftbar environment to be sure.\footnote{Does it 
    work? I'll see soon, when I compile.}
\end{leftbar}

\end{document}
Related Question