0

I'm trying to implement filesystem based file includes for a paper I'm writing and have previously asked a question on this topic. The accepted answer seems to work in the case that I only have a single discovery loop. However, If I try and nest these, it behaves weirdly.


So to replicate some details from the original question:

My filesystem looks like this:

article.tex
sections/
|-- 00-introductions.tex
|-- 10-data.tex
|-- 20-analysis.tex
|-- 90-conclusions.tex
|-- data/
|   |-- 00-xxx.tex 
|   |-- NN-xxx.tex
|
|-- analysis/
    |-- 00-xxx.tex
    |-- NN-xxx.tex

And my article.tex now looks like:

\documentclass[twocolumn, a4paper]{article}

\input{packages.tex}

\addbibresource{bibliography.bib}

\title{xxx}

\author{xxx}
\date{\today}

\newread\sections
\openin\sections=build/sections.list

\newread\data
\openin\data=build/data.list

\begin{document}
\twocolumn[
  \begin{@twocolumnfalse}
    \maketitle
    \begin{abstract}
     {\lipsum[1-2]}
     \bigskip
    \end{abstract}
  \end{@twocolumnfalse}
]


\loop
{\endlinechar=-1 \global\read\sections to \next}
\ifx\next\empty\else
\input{sections/\next}
\repeat

\printbibliography

\end{document}

So, as things stand, this includes all of the files in /sections quite well.

However, I'd also like to include everything in /sections/data into 10-data.tex, so I've added this to the file:

\section{Data}

\loop
{\endlinechar=-1 \global\read\data to \next}
\ifx\next\empty\else
\input{sections/data/\next}
\repeat

However, this results in the introduction and data sections being discovered and all of the subsections in /data/sections but then it stops. For some reason, the outer loop doesn't then seem to add 20-analysis.tex or 90-conclusions.tex to article.tex. The outer loop just seems to stop.

What's going on here? Does LaTex just not support nested loops? Is there a way around this?

3
  • It's in build/data.list and opened at the top of article.tex, right below where I do it for sections. It's generated in exactly the same way as sections. The fact that it's including the data sections would imply to me that it's being opened and read just fine Nov 27, 2022 at 18:25
  • 1
    you probably want {\input{sections/\next}} to keep the inner loop local (or use a different loop macro}) Nov 27, 2022 at 18:50
  • 1
    That's done it, thank you! Do you want me to write up an answer or leave it for you? Nov 27, 2022 at 19:18

2 Answers 2

0

It seems as though \input{} doesn't create a new scope on its own.

To fix this, you can just wrap it in braces like so:

\loop
{\endlinechar=-1 \global\read\sections to \next}
\ifx\next\empty\else
{\input{sections/\next}}
\repeat

As a side note, if you're planning on re-using this functionality, it can be wrapped up in a newcommand:

% Include every file in a directory based on an externally generated list of file-names.
% #0 - Iterator name
% #1 - List of files to include
% #2 - Directory the files are in
\newcommand{\IncludeFromDirectory}[3]{%
\newread#1
\openin#1=#2

\loop
{\endlinechar=-1 \global\read#1 to \next}
\ifx\next\empty\else
{\input{#3/\next}}
\repeat
}

And then used like:

\IncludeFromDirectory{\sections}{build/sections.list}{sections}
0

Doing \input inside a group may not be the best idea.

Here's the structure I built:

├── article.aux
├── article.log
├── article.pdf
├── article.tex
├── data.list
├── sections
│   ├── 00-introductions.tex
│   ├── 10-data.tex
│   ├── 20-analysis.tex
│   ├── 90-conclusions.tex
│   ├── analysis
│   └── data
│       ├── 00-xxx.tex
│       └── NN-xxx.tex
└── sections.list

The file sections.list is

00-introductions.tex
10-data.tex
20-analysis.tex
90-conclusions.tex

and data.list is

00-xxx.tex 
NN-xxx.tex

The .tex files just contain I'm \textt{<filename>} with the exception of 10-data.tex that has

I'm \texttt{10-data.tex}

\inputfromlist[sections/data]{data.list}

and, of course, article.tex that has

\documentclass[twocolumn, a4paper]{article}

\ExplSyntaxOn

\NewDocumentCommand{\inputfromlist}{O{.}m}
 {% #1 = prefix (default current directory)
  % #2 = file list
  \scottishtapwater_lists:nn { #1 } { #2 }
 }

\ior_new:N \g_scottishtapwater_lists_files_ior
\int_new:N \g_scottishtapwater_lists_level_int

% syntactic sugar
\cs_new:Nn \__scottishtapwater_lists_level:
 {
  g_scottishtapwater_lists_files_ \int_eval:n { \g_scottishtapwater_lists_level_int } _seq
 }

\cs_new_protected:Nn \scottishtapwater_lists:nn
 {
  \int_gincr:N \g_scottishtapwater_lists_level_int
  \seq_gclear_new:c { \__scottishtapwater_lists_level: }
  \ior_open:Nn \g_scottishtapwater_lists_files_ior { #2 }
  \ior_str_map_inline:Nn \g_scottishtapwater_lists_files_ior
   {
    \seq_gput_right:cn { \__scottishtapwater_lists_level: } { ##1 }
   }
  \ior_close:N \g_scottishtapwater_lists_files_ior
  \seq_map_inline:cn { \__scottishtapwater_lists_level: }
   {
    \tl_if_empty:nF { ##1 } { \input{#1/##1} \par }
   }
  \int_gdecr:N \g_scottishtapwater_lists_level_int
 }

\ExplSyntaxOff

\begin{document}

\inputfromlist[sections]{sections.list}

\end{document}

enter image description here

The idea is to read the lists line by line and to populate with them a sequence that depends on the level provided by the integer variable \g_scottishtapwater_lists_level_int. Thus we can nest as many \inputfromlist commands as we want without introducing unwanted grouping.

1
  • Could you please elaborate on why that first sentence is the case? Nov 28, 2022 at 11:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .