![\IfFileExists 在与 \input 一起测试另一个布尔值时行为不一致](https://linux22.com/image/272612/%5CIfFileExists%20%E5%9C%A8%E4%B8%8E%20%5Cinput%20%E4%B8%80%E8%B5%B7%E6%B5%8B%E8%AF%95%E5%8F%A6%E4%B8%80%E4%B8%AA%E5%B8%83%E5%B0%94%E5%80%BC%E6%97%B6%E8%A1%8C%E4%B8%BA%E4%B8%8D%E4%B8%80%E8%87%B4.png)
我一直在重构一些代码并清除过时的命令。
我不明白这里发生了什么:
\begin{filecontents}{mkif}
\newif\ifaeRoughDraft
\def\testforRoughDraft
{\ifaeRoughDraft
\lfoot{testing}
\rfoot{proof}
\fi
}
\end{filecontents}
\documentclass{article}
\usepackage{fancyhdr}
\pagestyle{fancy}
\IfFileExists{.ae.proof}
{
\input{mkif}
\IfFileExists{.ae.draft}
{\aeRoughDrafttrue}
{}
\testforRoughDraft
%%\ifaeRoughDraft\lfoot{testing}\rfoot{proof}\fi
}{}
\begin{document}
testing
\end{document}
假设您创建.ae.proof
和.ae.draft
,则上面提供的 MWE 可以正常编译。但是,如果您尝试编译
\begin{filecontents}{mkif}
\newif\ifaeRoughDraft
\def\testforRoughDraft
{\ifaeRoughDraft
\lfoot{testing}
\rfoot{proof}
\fi
}
\end{filecontents}
\documentclass{article}
\usepackage{fancyhdr}
\pagestyle{fancy}
\IfFileExists{.ae.proof}
{
\input{mkif}
\IfFileExists{.ae.draft}
{\aeRoughDrafttrue}
{}
%%\testforRoughDraft
\ifaeRoughDraft\lfoot{testing}\rfoot{proof}\fi
}{}
\begin{document}
testing
\end{document}
我收到以下错误:
(/usr/local/texlive/2013/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty)
! Extra \else.
\IfFileExists ...ileonpath {#1}{#2}{#3}}\fi \else
\closein \@inputcheck \ede...
l.22 }{}
在我看来,代码是等效的。但是,显然 LaTeX 并不这么认为。
如果我改变输入文件的方式mkif
---比如从文件内部删除它\IfFileExists
---无论我何时使用\testforRoughDraft
或,事情都会再次起作用\ifaeRoughDraft
。
是什么赋予了?
答案1
的第二个参数中的代码在执行\IfFileExists
之前被吸收,因此 不正确地与 扩展派生的条件配对。让我们看看。\input{mkif}
\fi
\IfFileExists
扩展
\IfFileExists{.ae.proof}
{
\input{mkif}
\IfFileExists{.ae.draft}
{\aeRoughDrafttrue}
{}
\ifaeRoughDraft\lfoot{testing}\rfoot{proof}\fi
}{}
是
\openin\@inputcheck .ae.proof
\ifeof\@inputcheck
\ifx\input@path\@undefined
\def\reserved@a{}%
\else
\def\reserved@a{%
\@iffileonpath{.ae.proof}%
{\input{mkif}\IfFileExists{.ae.draft}{\aeRoughDrafttrue}{}%
\ifaeRoughDraft\lfoot{testing}\rfoot{proof}\fi}{}}%
\fi
\else
\closein\@inputcheck
\edef\@filef@und{.ae.proof }%
\def\reserved@a{%
\input{mkif}\IfFileExists{.ae.draft}{\aeRoughDrafttrue}{}%
\ifaeRoughDraft\lfoot{testing}\rfoot{proof}\fi
}%
\fi
\reserved@a
由于找到了,所以跳过了的.ae.proof
“真实”分支;它是第一个停止此分支的分支,而且是错误的分支。因此,下一个分支结束了的真正分支,并扫描了一个额外的分支。错误消息准确地说明了额外的分支就在之前。\ifeof
\fi
\fi
\ifeof
\else
\else
\closein
TeX 在跳过条件中的文本时不会跟踪括号。控制序列以 开头并不足以\if...
被视为条件:只有到原始条件的控制序列才会标有特殊标志,这使得 TeX在跳过条件分支中的标记时将它们与或\let
配对。因此,until未执行,只是一个未定义的控制序列。\else
\fi
\newif\ifaeRoughDraft
\ifaeRoughDraft
在另一种情况下,\fi
不存在,因为 TeX 在跳过条件中的标记时不会扩展宏,所以看到的只是\testforRoughDraft
。
mkif
一个更好的方法是始终输入;这样就不会冒条件未定义的风险,但这只是个人看法。或者使用更好的宏代替\testforRoughDraft
:
\begin{filecontents}{mkif}
\newif\ifaeRoughDraft
\makeatletter
\newcommand\doifaeRoughDraft{%
\ifaeRoughDraft
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
\makeatother
\end{filecontents}
所以你可以说
\IfFileExists{ae.proof}
{\input{mkif}%
\IfFileExists{ae.draft}{\aeRoughDrafttrue}{}%
\doifaeRoughDraft{\lfoot{testing}\rfoot{proof}}{}%
}{}
更加灵活。