在C
,我可以写#pragma once
作为头文件顶部的预处理器指令,它告诉支持它的任何编译器在每个编译周期最多包含一次该文件,而不管#include
在其他源文件中我使用了多少次该头文件。它是#ifndef
//#define
包括#endif
守卫,尽管它不是该标准的官方记录/支持的部分。
La(TeX) 有几种所谓的“包含保护”功能,其中许多功能在以下问题的答案中进行了概述:条件排版/构建。
我的问题是:(La)TeX 中是否存在(或有可能存在)类似于#pragma once
该C
语言的构造;也就是说,在文件的一行上设置一个指令,导致该文件在编译期间只输入一次?
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>