
Я хочу проверить, находится ли макрос (a) снаружи или (b) внутри \footnote
команды, аналогично тому, что задается в (i)Как проверить, нахожусь ли я в данный момент в сноске или нет, (ii)Определить, нахожусь ли я в \footnote
?, (iii)сноска булев: как проверить, находится ли в данный момент в сноске, и (iv)та же команда с выводом X в основном тексте и Y в сноске.
Общая методика: (1) определить булеву переменную, по умолчанию false; (2) переопределить \footnote
так, чтобы она устанавливала булеву переменную в true при входе и сбрасывала ее в false при выходе. Это требует добавления к исходной \footnote
команде пре- и присоединения.
Мой вопрос отличается от ответов, данных для (i)–(iii) выше, тем, что все они выполняют переопределение с помощью \let
. Однако, хотя об этом часто забывают, \footnote
команда принимает необязательный аргумент (для номера сноски). (Например, см." \footnote
"изНеофициальное справочное руководство LaTeX2e (октябрь 2018 г.).) Этот факт должен сделать использование \let
неуместным. (Например, «Помните, что нужноникогдаиспользуйте старый трюк \let\ORIxyz\xzy
… если \xyz
было определено с необязательным аргументом».xpatch
документация)
(Ответ в (iv) переопределяет , \footnotetext
а не \footnote
, чего я не понимаю.)
Таким образом, я хочу переопределить, \footnote
используя команды \xpretocmd
и \xapptocmd
изxpatch
пакета (для добавления в начало и конец соответственно). (См.Полезное объяснение Энрико.)
Представленный ниже MWE — это моя попытка решить эту проблему.
Если я закомментирую \xapptocmd{\footnote}{\togglefalse{inFootnoteCommand}}{}{}
команду добавления, она работает хорошо (за исключением очевидной проблемы, заключающейся в том, что она не сбрасывает логическое значение в false и, следовательно, думает, что оно находится в \footnote
Even после выхода). Смотрите этот вывод:
Но когда я оставляю команду добавления незакомментированной, (а) она не сбрасывает логическое значение и (б) вывод разваливается как в основном тексте, так и в тексте сноски, и (в) я получаю ошибку, связанную с самими командами \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}.
То есть вы устанавливаете переключатель в положение «истина» и «ложь» до того, как будет виден аргумент сноски, и прерываете просмотр вперед для необязательного аргумента, который \@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}