Correção de problemas anexando ao comando \footnote. "Faltando \endcsname inserido"

Correção de problemas anexando ao comando \footnote. "Faltando \endcsname inserido"

Quero testar se uma macro está (a) fora ou (b) dentro de um \footnotecomando, 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 \footnotepara 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 \footnotecomando 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 \letinadequado. (Ex.: "Lembre-se de que é precisonuncause o velho truque \let\ORIxyz\xzy… se \xyzfoi definido com um argumento opcional."xpatchdocumentação)

(A resposta em (iv) redefine \footnotetextem vez de \footnote, o que não entendo.)

Assim, quero redefinir \footnoteusando os comandos \xpretocmde \xapptocmddo xpatchpacote (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 \footnotemesmo depois de encerrado). Veja esta saída:

insira a descrição da imagem aqui

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 \footnotecomandos 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.

Aqui está o resultado: insira a descrição da imagem aqui

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 \footnotedefiniçã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ê \togglefalsese torna o \@footnotetextargumento 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:

insira a descrição da imagem aqui

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 \@ifnextcharsempre 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.

insira a descrição da imagem aqui

\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}

informação relacionada