Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In C, I can write #pragma once as a preprocessor directive at the top of a header file, which tells any compiler that supports it to include the file a maximum of one time per compilation cycle, regardless of how many times I #include that header file in the other source files. It is a common alternative to #ifndef/#define/#endif include guards, despite not being an officially documented/supported part of the standard.

La(TeX) has several facilities for so-called "include guards", many of which are outlined in the answers to Conditional typesetting / build.

My question is: Does there exist (or is there a possibility of) a construct in (La)TeX analogous to #pragma once in the C language; that is, a directive set on one line of a file which causes that file to be input only one time during the compilation?

MWE for Testing:

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

Note:

You might say to just use \providecommand and be done with it, which is a valid answer. But I would like to know if what I've proposed is possible with (La)TeX, for science!

share|improve this question
    
You could use a flag, and wrap the \input command to test first. –  Ethan Bolker Aug 6 at 16:15
3  
You know that's what \usepackage does, I suppose? If you want to do things 'by hand' it's normal to do \csname myresevedname\endcsname\let\myreservedname\endinput (if it's not been defined, the \csname construct will do nothing important, and on a second pass it will be set up equal to \endinput). –  Joseph Wright Aug 6 at 16:23
2  
Well, you can use gpp on LaTeX files. –  Raphael Aug 6 at 20:58

2 Answers 2

up vote 9 down vote accepted

May be you needn't to deal with the name of the file or with another special identifier at the start ot such file. If I understand your question, you need only simply type \pragmaonce at the start of the file. I've looked to the LaTeX internals and I've found that: if the \input is followed by {, i. e. \input{filename}, then the \@iinput{filename} macro is processed. Thus I redefined this macro:

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

Of course, you have to respect the discipline and to type the \input only with braces around filename.

share|improve this answer
    
Very nice! This is basically what I was looking for. –  Paul Gessler Aug 7 at 14:19

If you load mydefs with \usepackage, giving it the .sty extension, LaTeX will load it only once. But it will not be available after \begin{document}.

The analog of #pragma once could be

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

<code in mydefs.tex>
share|improve this answer
    
shouldn't it be \gdef instead of \global\let? –  cgnieder Aug 6 at 17:08
    
@cgnieder Yes, wrong code. Fixed –  egreg Aug 6 at 17:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.