A Document Class and A Package For Handling Multi-File Projects
A Document Class and A Package For Handling Multi-File Projects
2020/09/07 v2.0
Abstract
The subfiles package allows authors to split a document into one main
file and several subsidiary files (subfiles) akin to the \input command, with
the added benefit of making the subfiles compilable on their own. This is
achieved by reusing the preamble of the main file also for the subfiles.
Contents
1 Introduction 2
2 Basic usage 2
3 Advanced usage 3
3.1 Including files instead of inputting them . . . . . . . . . . . . . . . 3
3.2 Fixing pathes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.3 Conditional execution of commands . . . . . . . . . . . . . . . . . 4
3.4 Unusual locations for placing definitions and text . . . . . . . . . . 4
4 Use cases 5
4.1 Hierarchy of directories . . . . . . . . . . . . . . . . . . . . . . . . 5
4.2 Avoiding extra spaces . . . . . . . . . . . . . . . . . . . . . . . . . 6
5 Troubleshooting 6
6 Dependencies 6
7 Version history 7
8 The Implementation 8
8.1 The class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
8.2 The package . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1
1 Introduction
The LATEX commands \include and \input allow the user to split the TEX source
of a document into several input files. This is useful when creating documents with
many chapters, but also for handling large tables, figures and code samples, which
require a considerable amount of trial-and-errors.
In this process the rest of the document is of little use, and can even interfere.
For example, error messages may indicate not only the wrong line number, but
may point to the wrong file. Frequently, one ends up wanting to work only on the
new file:
• Create a new file, and copy-paste the preamble of the main file into it.
• Work on this file, typeset it alone as many times as necessary.
• Finally, when the result is satisfactory, delete the preamble from the file
(alongside with \end{document}!), and \include or \input it from the
main file.
It is desirable to reduce these three steps to the interesting, middle one. Each
new, subordinate file (henceforth ‘subfile’) should behave both as a self-sufficient
LATEX document and as part of the whole project, depending on whether it is
LATEXed individually or \included/\input from the main document. This is
what the class subfiles.cls and the package subfiles.sty are intended for.
2 Basic usage
subfiles.sty The main file, i.e., the file with the preamble to be shared with the subfiles, has
to load the package subfiles:
\documentclass[...]{...}
\usepackage{subfiles}
\begin{document}
\subfile Subordinate files (subfiles) are loaded from the main file or from other subfiles
with the command
\subfile{hsubfile namei}
subfiles.cls The subfiles have to start with the line
\documentclass[hmain file namei]{subfiles}
which loads the class subfiles. Its only ‘option’, which is actually mandatory,
gives the name of the main file. This name follows TEX conventions: .tex is the
default extension, the path has to be provided if the main file is in a different
directory, and directories in the path have to be separated by / (not \). Thus, we
have the following structure.
2
main file subfile
\documentclass[...]{...} \documentclass[hmain file namei]{subfiles}
hshared preamblei \begin{document}
\usepackage{subfiles} ...
\begin{document} \end{document}
...
\subfile{hsubfile namei}
...
\end{document}
3 Advanced usage
3.1 Including files instead of inputting them
\subfileinclude In plain LATEX, you can use either \input or \include to load a file. In most
cases the first is appropriate, but sometimes there are reasons to prefer the latter.
Internally, the \subfile command uses \input. For those cases where you need
\include, the package provides the command
\subfileinclude{hsubfile namei}
3
3.3 Conditional execution of commands
\ifSubfilesClassLoaded The command \ifSubfilesClassLoaded is useful to execute commands condi-
tionally, depending on whether the main file is typeset or a subfile.
\ifSubfilesClassLoaded{% then branch
. . . commands executed when the subfile is typeset . . .
}{% else branch
. . . commands executed when the main file is typeset . . .
}
As an example, this can be used to add the bibliography to the main document
or to the subdocument, whichever is typeset:
main file subfile
\documentclass[...]{...} \documentclass[hmain file namei]{subfiles}
\usepackage{subfiles} \begin{document}
\bibliographystyle{alpha} ...
\begin{document} \ifSubfilesClassLoaded{%
... \bibliography{bibfile}%
\subfile{hsubfile namei} }{}
... \end{document}
\bibliography{bibfile}
\end{document}
4
the subfile. The code after \end{document} behaves as if following the \subfile
command in the main file, except that it is still part of the group enclosing the
subfile. As a consequence, empty lines at the end of the subfile lead to a new
paragraph in the main document, even if the \subfile command is immediately
followed by text.
4 Use cases
4.1 Hierarchy of directories
Sometimes it is desirable to put a subfile together with its images and supplemen-
tary files into its own directory. The difficulty now is that these additional files
have to be addressed by different pathes depending on whether the main file or the
subfile is typeset. As of version 1.3, the subfiles package handles this problem
by using the import package.
As an example, consider the following hierarchy of files:
main.tex
mypreamble.tex
dir1/subfile1.tex
dir1/image1.jpg
dir1/text1.tex
dir1/dir2/subfile2.tex
dir1/dir2/image2.jpg
dir1/dir2/text2.tex
where main, subfile1, and subfile2 have the following contents:
main.tex subfile1.tex
\documentclass{article} \documentclass[../main]{subfiles}
\input{mypreamble} \begin{document}
\usepackage{graphicx} \input{text1}
\usepackage{subfiles} \includegraphics{image1.jpg}
\begin{document} \subfile{dir2/subfile2}
\subfile{dir1/subfile1} \end{document}
\end{document}
subfile2.tex
\documentclass[../../main]{subfiles}
\begin{document}
\input{text2}
\includegraphics{image2.jpg}
\end{document}
Then each of the three files can be typeset individually in its respective directory,
where LATEX is able to locate all included text files and images.
5
4.2 Avoiding extra spaces
Sometimes you may want to load the contents of a subfile without white space
separating it from the contents of the main file. In this respect, \subfile behaves
similar to \input. Any space or newline before and after the \subfile command
will appear in the typeset document, as will any white space between the last
character of the subfile and \end{document}. Therefore, to load the contents of
a subfile without intervening spaces, you have either to add comment signs:
main.tex sub.tex
... \documentclass[main.tex]{subfiles}
text before% \begin{document}
\subfile{sub.tex}% contents of subfile%
text after \end{document}
or to put everything on the same line:
5 Troubleshooting
Here are some hints that solve most problems.
1. Make sure to use the most recent version of the subfiles package, available
from CTAN1 and Github2 .
2. Make sure that \usepackage{subfiles} appears near the end of the main
preamble.
3. Make sure that the strings \begin{document} and \end{document} appear
on lines of their own and that there are no additional characters preceding
or trailing them.
4. If some external program that cooperates with TEX, like bibtex or biber,
complains about not being able to find a file, locate the name of the file in
the LATEX source and replace hfilenamei by \subfix{hfilenamei}.
5. If nothing of the above helps, ask the nice people on tex.stackexchange3 .
6 Dependencies
The subfiles package uses the import package by Donald Arsenau to load subfiles
from different directories. import.sty is part of the standard TEX distribution.
1 https://ctan.org/pkg/subfiles
2 https://github.com/gsalzer/subfiles
3 https://tex.stackexchange.com/
6
7 Version history
v1.1: Initial version by Federico Garcia. Subsequent versions by Gernot Salzer.
v1.2:
• Incompatibility with classes and packages removed that modify the
\document command, like the class revtex4.
v1.3:
• Use of import package to handle directory hierarchies.
• \ignorespaces added to avoid spurious spaces.
• Incompatibility with commands removed that expect \document to be
equal to \@onlypreamble after the preamble. Thanks to Eric Domen-
joud for analysing the problem.
v1.4:
• Incompatibility with memoir class and comment package removed.
• Bug ‘\unskip cannot be used in vertical mode‘ fixed.
v1.5:
• Command \subfileinclude added.
• Basic support for bibtex related bibliographies in subfiles added.
Seems to suffice also for sub-bibliographies with the package chapterbib.
• Support for sub-bibliographies with package bibunits added.
v1.6:
• Support for sub-bibliographies with package bibunits dropped, in fa-
vor of \subfix.
• Command \subfix added.
• Incompatibility with standalone class removed.
• The options of the main class are now also processed when typesetting
a subfile; before they were ignored. Thanks to Ján Kl’uka for analysing
the problem.
v2.0:
• Incompatibility with LATEX Oct. 2020 removed. Thanks to Ulrike
Fischer from the LATEX 3 team for the warning in time.
• By default, text after \end{document} as well as the preamble of sub-
files, when loaded with \subfile, are ignored now. The old behaviour
is available via the new package option v1.
7
• Command \ifSubfilesClassLoaded added and documentation re-
garding the use of the \bibliography command corrected. Thanks
to Github user alan-isaac for reporting the issue.
• Subfiles now can have the same name as the main file. Thanks to
Github user June-6th for reporting the issue.
• Problem with the search path for images resolved. Thanks to Github
user maxnick for reporting the issue.
8 The Implementation
8.1 The class
1 h∗classi
2 \NeedsTeXFormat{LaTeX2e}
3 \ProvidesClass{subfiles}[2020/09/07 v2.0 Multi-file projects (class)]
4 \DeclareOption*{%
5 \typeout{Preamble taken from file ‘\CurrentOption’}%
6 \let\preamble@file\CurrentOption
7}
8 \ProcessOptions
In earlier versions, we used \subimport to load the preamble of the main file,
which has the unwanted effect of undoing changes to the graphics path. Therefore
we use \input and initialize \import@path and \input@path to the path of the
main file. We use the internal LATEX macro \filename@parse to obtain this path.
16 \filename@parse{\preamble@file}
17 \edef\import@path{\filename@area}
18 \edef\input@path{{\filename@area}}
19 \input{\preamble@file}
After loading the preamble of the main file, we reset \import@path{}. Since
the preamble may have changed the catcode of the @ sign, we make it (again) a
letter. Better safe than sorry.
20 {\makeatletter
21 \gdef\import@path{}
8
22 }
23 h/classi
The package has one option, v1, which affects the way how the text after
\end{document} and in the preamble of subfiles is handled. With this option,
subfiles behaves like in version 1.x. To implement the retro behaviour, we need
a few definitions.
First, we define three macros containing the strings \begin{document},
\end{document} and document. We need them later to detect these strings in
the input.
27 \def\subfiles@DOCUMENT{document}
28 {\escapechar=-1\relax
29 \xdef\subfiles@BEGINDOCUMENT{\string\\begin\string\{document\string\}}%
30 \xdef\subfiles@ENDDOCUMENT{\string\\end\string\{document\string\}}%
31 }
9
49 }%
50 }
Now we set the default behaviour of the subfiles package: When loading the
main preamble in a subfile, everything after the preamble is ignored. Moreover,
when reading a subfile, its preamble as well as everything after \end{document}
is ignored.
51 \let\subfiles@handleMain\endinput
52 \let\subfiles@handleSubpreamble\subfiles@skipPreamble
53 \let\subfiles@handleTextAfterSubdocument\endinput
The option v1 restores the behaviour of the old subfiles package: When load-
ing the main preamble in a subfile, only the contents of the document environent is
ignored, but not the stuff following it. Moreover, when reading a subfile, only the
\documentclass command and the lines \begin{document} and \end{document}
are ignored, but the subfile preamble as well as everything after \end{document}
is retained.
54 \DeclareOption{v1}{%
55 \let\subfiles@handleMain\subfiles@skipDocument
56 \let\subfiles@handleSubpreamble\subfiles@skipDocumentclass
57 \let\subfiles@handleTextAfterSubdocument\relax
58 }
59 \DeclareOption*{\PackageWarning{subfiles}{Option ’\CurrentOption’ ignored}}
60 \ProcessOptions\relax
To skip everything until a specific string is read, we adapt code from the
verbatim package. The skipping of lines is controlled by two macros that have
to be set before calling \subfiles@skiplines. \subfiles@skiplinesend is the
string that marks the end of the skipped area; it has to appear on a line of its own,
as the only content of this line. \subfiles@skiplinescont contains the code to
be executed after skipping has ended.
61 \def\subfiles@skiplines{%
62 \begingroup
63 \let\do\@makeother\dospecials
64 \@makeother\^^L%
65 \endlinechar‘\^^M\relax \catcode‘\^^M=12\relax \subfiles@skipline}
66 {\catcode‘\^^M=12 \endlinechar=-1 %
67 \gdef\subfiles@skipline#1^^M{\def\subfiles@tmp{#1}%
68 \ifx\subfiles@tmp\subfiles@skiplinesend
69 \def\subfiles@tmp{\endgroup\subfiles@skiplinescont}%
70 \else\let\subfiles@tmp\subfiles@skipline
71 \fi \subfiles@tmp}
72 }
10
the filename into basename and extension. Unfortunately, concatenating base-
name and extension to recover the filename is not clean: Under Unix/Linux, the
filenames base and base. denote different entities, but after \filename@parse
both have the same basename and an empty extension. Therefore we redefine
the command \filename@simple temporarily; it is responsible for this unwanted
split.
74 \def\subfiles@split#1{%
75 \let\subfiles@filename@simple\filename@simple
76 \def\filename@simple##1.\\{\edef\filename@base{##1}}%
77 \filename@parse{#1}%
78 \let\filename@simple\subfiles@filename@simple
79 }%
11
Now we split the file name into path and base name and load the file.
102 \subfiles@split{#1}%
103 \subfiles@loadfile{\filename@area}{\filename@base}%
104 \endgroup
105 }
\subfix If some package provides a command that takes a filename as argument, then
it has to be prefixed with the current \import@path. This is what the \subfix
command tries to do. In order to succeed, the filename has to be expanded im-
mediately, such that the current value of \import@path is used.
106 \def\subfix#1{\import@path#1}
For patching a list of file or path names, we define two auxiliary macros, one
iterating over a comma-separated list of names and one processing a sequence of
names enclosed in braces.
107 \def\subfiles@fixfilelist#1{%
108 \def\subfiles@list{}%
109 \def\subfiles@sep{}%
110 \@for\subfiles@tmp:=#1\do{%
111 \edef\subfiles@list{\subfiles@list\subfiles@sep\subfix{\subfiles@tmp}}%
112 \def\subfiles@sep{,}%
113 }%
114 }
115 \def\subfiles@fixpathlist#1{%
116 \def\subfiles@list{}%
117 \@tfor\subfiles@tmp:=#1\do{%
118 \edef\subfiles@list{\subfiles@list{\subfix\subfiles@tmp}}%
119 }%
120 }
\ifSubfilesClassLoaded To add code or text conditionally, depending on whether the main document
or a subfile is typeset, we provide the command \ifSubfilesClassLoaded.
134 \newcommand\ifSubfilesClassLoaded{%
135 \expandafter\ifx\csname [email protected]\endcsname\relax
136 \expandafter\@secondoftwo
12
137 \else
138 \expandafter\@firstoftwo
139 \fi
140 }
The subfiles package is loaded near the end of the main preamble. If it is
loaded from a subfile, i.e., if subfiles.cls has been loaded, then we have to
prepare for skipping the main document. We do this be redefining the \begin
command. Normally, the first \begin after the subfiles package starts the main
document. To allow for the case that some other environment occurs before (does
it really happen?) we test whether we are dealing with \begin{document}. If not,
we execute the original definition of \begin; otherwise we skip the main document
as specified by \subfiles@handleMain.
141 \ifSubfilesClassLoaded{%
142 \let\subfiles@begin\begin
143 \def\begin#1{%
144 \def\subfiles@tmp{#1}%
145 \ifx\subfiles@tmp\subfiles@DOCUMENT
146 \let\begin\subfiles@begin
147 \let\subfiles@tmp\subfiles@handleMain
148 \else
149 \def\subfiles@tmp{\subfiles@begin{#1}}%
150 \fi
151 \subfiles@tmp
152 }%
153 }{}
154 h/packagei
13