
Quero testar se uma macro está (a) fora ou (b) dentro de um \footnote
comando, semelhante ao que é solicitado em (i)Como testar se estou em uma nota de rodapé ou não, (ii)Detectar se estou em um \footnote
?, (iii)nota de rodapé booleana: como verificar se está atualmente em uma nota de rodapée (iv)mesmo comando com saída X no corpo principal e Y na nota de rodapé.
A técnica geral é (1) definir um booleano, padronizado como falso; (2) redefinir \footnote
para que defina o booleano como verdadeiro na entrada e redefina-o como falso ao sair. Isso requer um acréscimo e um acréscimo ao \footnote
comando original.
Onde minha pergunta difere das respostas dadas para (i) – (iii) acima é que todas elas fazem a redefinição com a \let
. No entanto, embora muitas vezes esquecido, o\footnote
comando utiliza um argumento opcional (para o número da nota de rodapé). (Ex., veja" \footnote
"deManual de referência não oficial do LaTeX2e (outubro de 2018).) Este fato deve tornar o uso \let
inadequado. (Ex.: "Lembre-se de que é precisonuncause o velho truque \let\ORIxyz\xzy
… se \xyz
foi definido com um argumento opcional."xpatch
documentação)
(A resposta em (iv) redefine \footnotetext
em vez de \footnote
, o que não entendo.)
Assim, quero redefinir \footnote
usando os comandos \xpretocmd
e \xapptocmd
do xpatch
pacote (para preceder e acrescentar, respectivamente). (VerExplicação útil de Enrico.)
O MWE abaixo é minha tentativa de resolver esse problema.
Se eu comentar o \xapptocmd{\footnote}{\togglefalse{inFootnoteCommand}}{}{}
comando anexado, ele funcionará bem (exceto pelo problema óbvio de que ele não redefine o booleano para falso e, portanto, pensa que está no \footnote
mesmo depois de encerrado). Veja esta saída:
Mas quando deixo o comando anexado sem comentar, (a) ele falha ao redefinir o booleano e (b) a saída se desfaz tanto no corpo do texto quanto no texto da nota de rodapé e (c) recebo o erro associado aos \footnote
comandos em si:
\endcsname ausente inserido. \unskip I.38 \footnote [Aqui está a nota de rodapé:\amIInAFootnote] A sequência de controle marcada não deve aparecer entre \csname e \endcsname.
Onde eu estou errando?
Aqui está o MWE:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xpatch}
\usepackage{etoolbox}
\newtoggle{inFootnoteCommand}
\togglefalse{inFootnoteCommand}
\newcommand{\amIInAFootnote}{%
\iftoggle{inFootnoteCommand}{%
\textcolor{blue}{You are in a footnote.}
}{%
\textcolor{red}{You are NOT in a footnote.}
}%
}
\parindent=0pt
\begin{document}
This line intentionally left blank %To move the text closer to the footnote
\vspace{400pt}
\xpretocmd{\footnote}{\toggletrue{inFootnoteCommand}}{SUCCESS\\}{FAIL\\}
\xapptocmd{\footnote}{\togglefalse{inFootnoteCommand}}{SUCCESS\\}{FAIL\\}
Before a footnote: \amIInAFootnote.
At the end of this sentence is a footnote:%
\footnote{Here’s the footnote: \amIInAFootnote}
Now, I'm back from the footnote: \amIInAFootnote
\end{document}
Responder1
Se você olhar a \footnote
definição, encontrará o seguinte:
> \footnote=macro:
->\@ifnextchar [\@xfootnote {\stepcounter \@mpfn \protected@xdef \@thefnmark {\
thempfn }\@footnotemark \@footnotetext }.
Isso significa que ele nunca tenta processar o texto da nota de rodapé como argumento, mas simplesmente delega isso para \@footnotetext
. Quando você patch \footnote
, você \togglefalse
se torna o \@footnotetext
argumento e bagunça tudo. Para consertar, basta aplicar seus patches diretamente em \@footnotetext
:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xpatch}
\usepackage{etoolbox}
\newtoggle{inFootnoteCommand}
\togglefalse{inFootnoteCommand}
\newcommand{\amIInAFootnote}{%
\iftoggle{inFootnoteCommand}{%
\textcolor{blue}{You are in a footnote.}
}{%
\textcolor{red}{You are NOT in a footnote.}
}%
}
\parindent=0pt
\begin{document}
This line intentionally left blank %To move the text closer to the footnote
\vspace{400pt}
\makeatletter
\xpretocmd{\@footnotetext}{\toggletrue{inFootnoteCommand}}{SUCCESS\\}{FAIL\\}
\xapptocmd{\@footnotetext}{\togglefalse{inFootnoteCommand}}{SUCCESS\\}{FAIL\\}
\makeatother
Before a footnote: \amIInAFootnote.
At the end of this sentence is a footnote:%
\footnote{Here’s the footnote: \amIInAFootnote}
Now, I'm back from the footnote: \amIInAFootnote
\end{document}
O resultado:
Responder2
Se você adicionar
\show\footnote
depois de seus patches você encontrará
> \footnote=\protected macro:
->\toggletrue {inFootnoteCommand}\@ifnextchar [\@xfootnote {\stepcounter \@mpfn
\protected@xdef \@thefnmark {\thempfn }\@footnotemark \@footnotetext }\togglefalse {inFootnoteCommand}.
Ou seja, você está definindo a alternância para verdadeiro e falso antes que o argumento da nota de rodapé seja visto e interrompendo a visualização de um argumento opcional, como \@ifnextchar
sempre veremos\togglefalse
Você não precisa redefinir no final, basta definir a alternância dentro do grupo ou, no caso comum de que o único texto definido no tamanho das notas de rodapé sejam notas de rodapé, você não precisa de alternância, você pode simplesmente testar o tamanho da fonte.
\documentclass{article}
\usepackage{xcolor}
\usepackage{etoolbox}
\newtoggle{inFootnoteCommand}
\togglefalse{inFootnoteCommand}
\makeatletter
\let\saved@makefntext\@makefntext
\def\@makefntext#1{\saved@makefntext{\toggletrue{inFootnoteCommand}#1}}
\parindent=0pt
\begin{document}
This line intentionally left blank %To move the text closer to the footnote
\vspace{400pt}
\newcommand{\amIInAFootnote}{%
\iftoggle{inFootnoteCommand}{%
\textcolor{blue}{You are in a footnote.}%%%
}{%
\textcolor{red}{You are NOT in a footnote.}%%%
}%
}
Before a footnote: \amIInAFootnote.
At the end of this sentence is a footnote:%
\footnote{Here’s the footnote: \amIInAFootnote}
Now, I'm back from the footnote: \amIInAFootnote
\end{document}