\IfFileExists 在与 \input 一起测试另一个布尔值时行为不一致

\IfFileExists 在与 \input 一起测试另一个布尔值时行为不一致

我一直在重构一些代码并清除过时的命令。

我不明白这里发生了什么:

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

更加灵活。

相关内容