(La)TeX 中是否有与 #pragma once 类似的内容?

(La)TeX 中是否有与 #pragma once 类似的内容?

C,我可以写#pragma once作为头文件顶部的预处理器指令,它告诉支持它的任何编译器在每个编译周期最多包含一次该文件,而不管#include在其他源文件中我使用了多少次该头文件。它是#ifndef//#define包括#endif守卫,尽管它不是该标准的官方记录/支持的部分。

La(TeX) 有几种所谓的“包含保护”功能,其中许多功能在以下问题的答案中进行了概述:条件排版/构建

我的问题是:(La)TeX 中是否存在(或有可能存在)类似于#pragma onceC语言的构造;也就是说,在文件的一行上设置一个指令,导致该文件在编译期间只输入一次?

MWE 测试:

\documentclass{article}
\usepackage{filecontents}

\begin{filecontents*}{mydefs.tex}
%<-- insert magic *#pragma once*-like line here to prevent errors
\newcommand{\foo}{foo}
\newcommand{\baz}{baz}
\end{filecontents*}

\begin{document}
\input{mydefs}
\input{mydefs}
\foo\ \baz\ test.
\end{document}

笔记:

你可能会说,只要使用\providecommand它就可以了,这是一个有效的答案。但我想知道我所提出的建议是否适用于 (La)TeX,为了科学!

答案1

也许您不需要处理文件的名称或此类文件开头的另一个特殊标识符。如果我理解您的问题,您只需要在\pragmaonce文件开头键入。我查看了 LaTeX 内部并发现:如果后面\input跟着{,即\input{filename},则\@iinput{filename}处理宏。因此我重新定义了这个宏:

\documentclass{article}
\usepackage{filecontents}

\makeatletter
\let\pragma@iinput=\@iinput
\def\@iinput#1{\xdef\@pragmafile{#1}\pragma@iinput{#1}}
\def\@pragmafile{default}
\def\pragmaonce{%
   \csname pragma@\@pragmafile\endcsname
   \global\expandafter\let \csname pragma@\@pragmafile\endcsname = \endinput
}
\makeatother

\begin{filecontents*}{mydefs.tex}
\pragmaonce %<-- insert magic *#pragma once*-like line here to prevent errors
\newcommand{\foo}{foo}
\newcommand{\baz}{baz}
\end{filecontents*}

\begin{document}
\input{mydefs}
\input{mydefs}
\foo\ \baz\ test.
\end{document}

当然,您必须尊重纪律并仅用\input括号括住文件名。

答案2

如果你使用 加载mydefs\usepackage并为其添加.sty扩展名,LaTeX 将只加载一次。但在 之后它将不可用\begin{document}

类似地#pragma once可以是

\ifcsname mydefs.tex\endcsname
  \expandafter\endinput
\fi
\expandafter\gdef\csname mydefs.tex\endcsname{loaded}

<code in mydefs.tex>

相关内容