我想测试宏是否 (a) 在命令之外或 (b) 在\footnote
命令之内,类似于 (i) 中要求的如何测试我当前是否在脚注中(二)检测我是否处于\footnote
?(三)脚注布尔值:如何检查当前是否在脚注中,以及(四)相同的命令,在主体中输出 X,在脚注中输出 Y。
通用方法是 (1) 定义一个布尔值,默认为 false;(2) 重新定义\footnote
,以便在进入时将布尔值设置为 true,并在退出时将其重置为 false。这需要在原始命令前面添加和后面添加\footnote
。
我的问题与上述 (i)–(iii) 的答案不同之处在于,它们都使用 进行重新定义\let
。然而,尽管经常被遗忘,但该\footnote
命令带有一个可选参数(用于脚注的编号)。(例如,参见“ \footnote
“的LaTeX2e 非官方参考手册(2018 年 10 月))这一事实使得使用\let
不合适。(例如,“记住,必须绝不使用老技巧\let\ORIxyz\xzy
...如果\xyz
已经用可选参数定义。”xpatch
文档)
((iv)中的答案重新定义了\footnotetext
而不是\footnote
,我不明白。)
因此,我想使用包中的\footnote
命令\xpretocmd
和命令重新定义(分别添加到前面和附加到后面)。(参见\xapptocmd
xpatch
Enrico 的有益解释。
下面的 MWE 是我解决这个问题的尝试。
如果我注释掉附加\xapptocmd{\footnote}{\togglefalse{inFootnoteCommand}}{}{}
命令,它会运行良好(除了一个明显的问题,即它不会将布尔值重置为 false,因此\footnote
在退出后认为它处于偶数状态)。请参阅此输出:
但是,当我取消注释附加命令时,(a)它无法重置布尔值,(b)输出在正文和脚注文本中都崩溃,并且(c)我收到与命令\footnote
本身相关的错误:
缺少插入的 \endcsname。\unskip I.38 \footnote [这是脚注:\amIInAFootnote] 标记的控制序列不应出现在 \csname 和 \endcsname 之间。
我哪里做错了?
这是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}
答案1
如果你看一下\footnote
定义,你会发现以下内容:
> \footnote=macro:
->\@ifnextchar [\@xfootnote {\stepcounter \@mpfn \protected@xdef \@thefnmark {\
thempfn }\@footnotemark \@footnotetext }.
这意味着它永远不会尝试将 fottnote 文本作为其参数进行处理,而只是将其委托给\@footnotetext
。当您修补 时\footnote
,您的\togglefalse
将成为\@footnotetext
参数并弄乱一切。要修复它,只需将您的补丁直接应用于\@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}
结果:
答案2
如果你添加
\show\footnote
补丁完成后你会发现
> \footnote=\protected macro:
->\toggletrue {inFootnoteCommand}\@ifnextchar [\@xfootnote {\stepcounter \@mpfn
\protected@xdef \@thefnmark {\thempfn }\@footnotemark \@footnotetext }\togglefalse {inFootnoteCommand}.
也就是说,在看到脚注参数之前,您要将切换设置为 true 和 false,并打破对可选参数的前瞻,就像\@ifnextchar
总是会看到的那样\togglefalse
您不需要在最后重置,只需在组内设置切换,或者在常见情况下,在脚注大小设置的唯一文本是脚注,您根本不需要切换,您可以简单地测试字体大小。
\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}