TransWikia.com

Restructuring multiple files with inputs and macros in it

TeX - LaTeX Asked by 63rrit on November 12, 2021

i have a multifile document, that is weirdly structured and i want to improve the structure.

the hierarchy looks like this:

dir0
├──header.tex
├──dir1
|  ├──main1.tex
|  └──img1.png
├──dir2
|  ├──main2.tex
|  └──img2.png
└──dir3
   └──sharedtext.tex

the files look like this:

header.tex:

    usepackage[...]{...} % packages used in both main1 and main2 go here
    ... 
    newcommand{textblockForBoth}[]{textblock that is used in both main1 and main2}
    ...

main1.tex:

    documentclass[a4paper,oneside]{scrbook}
    usepackage[...]{...} % packages only used in main1
    ...
    input{../header.tex}
    newcommand{textblockForMain1}[]{textblock that is used only in main1}
    ...
    begin{document}
    input{../dir3/sharedtext.tex}
    end{document}

main2.tex:

documentclass[a4paper,oneside]{scrbook}
usepackage[...]{...} % packages only used in main2
...
input{../header.tex}
newcommand{textblockForMain2}[]{textblock that is used only in main2}
...
begin{document}
input{../dir3/sharedtext.tex}
end{document}

sharedtext.tex:

tableofcontents
chapter{chapter1}
sharedtext is written here and commands put some stuff here:
textblockHere % textblocks or just words from main1 or main2 are added

so basically the preambel is located in the header.tex,
shared text by all main files is stored in sharedtext.tex
and document specific words/textblocks are added with macros that are defined in the respective main.tex and are called in the sharedtext.tex

another thing is that graphics are in the directory of the main.tex files and need to be referenced correctly. but i think this can be done easily using the following:

graphicspath{...}

is there a better way to structure this?
and which commands do you suggest using?
i think import or include are better suited here then input.
The "subfile" package might also be an option

kind regards
63rrit

One Answer

When counting how many times shared.tex was input, then you can combine shared.tex and header.tex:

File structure:

dir0
├──shared.tex
├──main1.tex
├──img1.png
├──main2.tex
└──img2.png

shared.tex

csname @ifxinputcountundefined firstelse secondfi oftwoendcsname{%
  gdefinputcount{0}%
}{%
  xdefinputcount{numbernumexprinputcount+1relax}%
}%
%%
ifnuminputcount=0 %
  % This has formerly been header.tex:
  usepackage[...]{...} % packages used in both main1 and main2 go here
  ... 
  newcommand{textblockForBoth}[]{textblock that is used in both main1 and main2}
  ...
  %%%%%%%%%%
  expandafterendinput
fi
%%
ifnuminputcount=1 %
  % This has formerly been shared.tex:
  tableofcontents
  chapter{chapter1}
  sharedtext is written here and commands put some stuff here:
  textblockHere % textblocks or just words from main1 or main2 are added
  %%%%%%%%%%
  expandafterendinput
fi

main1.tex

documentclass[a4paper,oneside]{scrbook}
usepackage[...]{...} % packages only used in main1
...
% This time inputcount will be defined 0...
input{./shared.tex}
newcommand{textblockForMain1}[]{textblock that is used only in main1}
...
begin{document}
% This time inputcount will be incremented to 1...
input{./shared.tex}
end{document}

main2.tex

documentclass[a4paper,oneside]{scrbook}
usepackage[...]{...} % packages only used in main2
...
% This time inputcount will be defined 0...
input{./shared.tex}
newcommand{textblockForMain2}[]{textblock that is used only in main2}
...
begin{document}
% This time inputcount will be incremented to 1...
input{./shared.tex}
end{document}

With the things proposed in the following it is relied on the commandline-option --jobname not(!) being used when compiling a .tex-file. This implies that the things proposed in the following do not(!) work out on online-platforms like overleaf where the commandline-option --jobname is used by the underlying "machinery".

The following is similar to my first answer to the question shared common text across many documents.

The concept of counting how many times a file is loaded via input is useful also when creating many documents of the same pattern.

It is possible

  • to have TeX stop reading an input-file at a specific point. This is done via endinput. You need to make sure that if....fi are balanced before applying endinput. You can use expandafter for having TeX process fi (and thus balance things) before processing endinput.
  • to input an input-file several times, hereby increasing a counter-macro with each input for deciding which portion of the file to process with the current call to input.

When loading the same file several times you can keep all things ("variables", sequences of text) specific to a document within the same file.

Loading that same file several times can be done outgoing from a "framework" common to all documents.

In order to get the jobname/the name of the resulting .pdf-file right, that framework can be loaded from the file which afterwards is to be loaded several times by the framework.

With the following templates all files main⟨K⟩.tex are of the same pattern.

Compiling main⟨K⟩.tex yields defining the counter-macro inputcount and loading framework.tex.
framework.tex contains the framework (preamble, text-snippets etc) common to all documents.

As framework.tex is loaded by main⟨K⟩.tex, jobname will yield the phrase "main⟨K⟩".
framework.tex in turn can—via input—load jobname.tex = main⟨K⟩.tex again and again, each time incrementing inputcount and therefore processing another portion of main⟨K⟩.tex.
The first portion of main⟨K⟩.tex might contain definitions(=values specific to the document main⟨K⟩) for macros that serve as variables.
The second portion of main⟨K⟩.tex might contain a snippet of text specific to the document main⟨K⟩.
The third portion of main⟨K⟩.tex might contain another snippet of text specific to the document main⟨K⟩.
Etc...

With the following template you can compile the file main1.tex and the file main2.tex.

Each of these loads framework.tex which in turn provides the framework for all documents and reloads main1.tex respective file main2.tex twice.
The first time only the portion with the definitions of macros that serve as variables is processed.
The second time only the text-snippet specific to main1.tex respective main2.tex is processed.

File: framework.tex:

% This file is input from within main1.tex or main2.tex, thus
% jobname will be "main1" or "main2"...

documentclass{article}
%usepackage...
%...

% The value of inputcount will be increased to 1, thus 
% Portion 1 will be processed and
% VariableA, VariableB and VariableC will be defined:
inputjobname.tex

begin{document}

tableofcontents

section{A section which all documents have in common}

This is a section which all documents have in common.

Now let's within the section which all documents have in common
use the variables specific to each document:

begin{itemize}
item verb|VariableA| is: VariableA
item verb|VariableB| is: VariableB
item verb|VariableC| is: VariableC
end{itemize}

section{Another section which all documents have in common}
This is another section which all documents have in common.

Now let's come to a snippet of text which differs from document
to document:
% The value of inputcount will be increased to 2, thus 
% Portion 2 will be processed.

inputjobname.tex

end{document}

File: main1.tex:

csname @ifxinputcountundefined firstelse secondfi oftwoendcsname{%
  % You could move the following newcommand to framework.tex.
  newcommandinputcount{0}%
  %%%%%%%%%
  input framework.tex
}{%
  xdefinputcount{numbernumexprinputcount+1relax}%
}%
%%
%% Portion 1 - Variables:
%%
ifnuminputcount=1  %
  makeatletter
  newcommandVariableA{%
    This is Variable A with main1.tex.
  }%
  newcommandVariableB{%
    This is Variable B with main1.tex.
  }%
  newcommandVariableC{%
    This is Variable C with main1.tex.
  }%
  %...
  makeatother
  expandafterendinput
fi 
%%
%% Portion 2 - First text snippet:
%%
ifnuminputcount=2 %
  section{A section that is produced by processing 
           Portion 2 of texttt{main1.tex}}

  Compiling texttt{main1.tex} yields a nice document.\
  Compiling texttt{main1.tex} yields a nice document.\
  Compiling texttt{main1.tex} yields a nice document.\
  Compiling texttt{main1.tex} yields a nice document.\

  That's the end of the section coming from Portion 2 of texttt{main1.tex}.
  expandafterendinput
fi

File: main2.tex:

csname @ifxinputcountundefined firstelse secondfi oftwoendcsname{%
  % You could move the following newcommand to framework.tex.
  newcommandinputcount{0}%
  %%%%%%%%%
  input framework.tex
}{%
  xdefinputcount{numbernumexprinputcount+1relax}%
}%
%%
%% Portion 1 - Variables:
%%
ifnuminputcount=1  %
  makeatletter
  newcommandVariableA{%
    This is Variable A with main2.tex.
  }%
  newcommandVariableB{%
    This is Variable B with main2.tex.
  }%
  newcommandVariableC{%
    This is Variable C with main2.tex.
  }%
  %...
  makeatother
  expandafterendinput
fi 
%%
%% Portion 2 - First text snippet:
%%
ifnuminputcount=2 %
  section{A section that is produced by processing 
           Portion 2 of texttt{main2.tex}}

  Compiling texttt{main2.tex} yields a nice document.\
  Compiling texttt{main2.tex} yields a nice document.\
  Compiling texttt{main2.tex} yields a nice document.\
  Compiling texttt{main2.tex} yields a nice document.\

  That's the end of the section coming from Portion 2 of texttt{main2.tex}.
  expandafterendinput
fi

When compiling main1.tex I get main1.pdf which looks like this:

enter image description here

When compiling main2.tex I get main2.pdf which looks like this:

enter image description here

All files are kept in the same directory.

If necessary you can have files with images/whatsoever content specific to each document in a separate sub-directory whose name somehow can be deduced from the result of expanding jobname. E.g.,
images for document main1 in subdirectory main1_images,
images for document main2 in subdirectory main2_images,
...

This way evaluating jobname can be a "generic" way of specifying sub-directories with files belonging to one of the documents—e.g., within the graphicspath-directive or within file-paths directly.

Therefore again:

With the things just proposed it is relied on the commandline-option --jobname not(!) being used when compiling a .tex-file. This implies that the things just proposed do not(!) work out on online-platforms like overleaf where the commandline-option --jobname is used by the underlying "machinery".

On such platforms/in situations where you cannot rely on jobname delivering the name of the main .tex-input-file you could within each file main⟨K⟩.tex define a macro jobfile right before the command input framework.tex to expand to the phrase main⟨K⟩ and within framework.tex use that jobfile-macro instead of the jobname-primitive.
The disadvantage with this approach is that renaming a file main⟨K⟩.tex implies the need of editing that file for changing the definition of the jobfile-macro.

Answered by Ulrich Diez on November 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP