I can offer an interface where template-files are of pattern
\filesection{⟨name of section⟩}{⟨replacement for the token \default⟩}
⟨code⟩
\endfilesection
%-------------------------------------------------------------
\filesection{⟨name of section⟩}{⟨replacement for the token \default⟩}
⟨code⟩
\endfilesection
%-------------------------------------------------------------
\filesection{⟨name of section⟩}{⟨replacement for the token \default⟩}
⟨code⟩
\endfilesection
%-------------------------------------------------------------
\endinput
You input the template-files with the command
\inputfilesection{⟨name of template-file⟩}%
{⟨name of section⟩}%
[⟨replacement for the token \default⟩]
The ⟨code⟩ of a file-section will be executed only if both the \inputfilesection-command and the \filesection-comand have the same ⟨name of section⟩-argument.
In this case ⟨code⟩ will be read under verbatim-catcode-régime and the sequence \default will be replaced:
If the \inputfilesection-command specifies a ⟨replacement for the token \default⟩-argument, then the replacement will come from that argument.
Otherwise the replacement will come from the \filesection-command's ⟨replacement for the token \default⟩-argument.
The result is passed to \scantokens for re-tokenization and normal processing.
Several \filesections can have the same ⟨name of section⟩. In this case all file-sections of the name in question occurring in the template-file are delivered by \inputfilesection. In this case if the \inputfilesection-provides a ⟨replacement for the token \default⟩-argument, this argument will be used as replacement for the token \default with all file-sections delivered.
CAVEATS I AM AWARE OF:
!!!Don't do \inputfilesection inside files that are called by \inputfilesection!!!
!!!\inputfilesection attempts to read the ⟨replacement for the token \default⟩-argument under verbatim-catcode-régime. Therefore \inputfilesection should not be used inside arguments of other macros and the like.!!!
%
% A exemplary template-file:
%
\begin{filecontents*}[overwrite]{MyTemplates.tex}
%\begin{filecontents*}{MyTemplates.tex}
\filesection{example-image-a}{width=0.6\textwidth}
\begin{figure}[!ht]
\centering
\includegraphics[\default]{example-image-a}
\caption{Example Section.}
\end{figure}
\endfilesection
%-------------------------------------------------------------
\filesection{example-image-b}{width=0.6\textwidth}
\begin{figure}[!ht]
\centering
\includegraphics[\default]{example-image-b}
\caption{Example Section.}
\end{figure}
\endfilesection
%-------------------------------------------------------------
\filesection{example-image-c}{width=0.6\textwidth}
\begin{figure}[!ht]
\centering
\includegraphics[\default]{example-image-c}
\caption{Example Section.}
\end{figure}
%\show\defaultABC %% This yields \show\defaultABC
% , resulting in > \defaultABC=undefined.
% This is a test to make sure that replacing
% is not done if the sequence \default is
% trailed by a character whose catcode at the
% time of replacing is 11.
\endfilesection
%-------------------------------------------------------------
\endinput
\end{filecontents*}
\documentclass{article}
\usepackage{graphicx}
\makeatletter
%///// start of code that could go into a package / .sty-file//////////////////
\newcommand\UD@ifnextcharspace[3]{%
\let\reserved@d= #1%
\edef\reserved@a{\unexpanded{#2}}%
\edef\reserved@b{\unexpanded{#3}}%
\futurelet@let@token\UD@ifnch
}%
\newcommand\UD@ifnch{%
\ifx@let@token\reserved@d\expandafter\reserved@a\else\expandafter\reserved@b\fi
}%
\NewDocumentCommand\inputfilesection{mm}{%
% Use \UD@ifnextcharspace for ensuring the next token is read under
% normal catcode-régime:
\begingroup
\UD@ifnextcharspace[{%
\let\do@makeother\dospecials
\do^^I%
\do^^M%
@inputfilesection{#1}{#2}%
}{%
\let\do@makeother\dospecials
\do^^I%
\do^^M%
@inputfilesection{#1}{#2}%
}%
}%
\NewDocumentCommand@inputfilesection{mm!o}{%
\endgroup
\def@stringincommand{#2}%
\IfNoValueF{#3}{\def\default{#3}}%
\input{#1}%
\global\let\default\UndeFinEd
}%
\newcommand@stringincommand{}%
\newcommand@stringinfile{}%
\NewDocumentCommand\filesection{m}{%
\begingroup@makeother^^I\relax
@filesection{#1}%
}%
\NewDocumentCommand@filesection{mv}{%
\endgroup
\begingroup
\let\do@makeother\dospecials
\do^^I%
\do^^M%
@@filesection{#1}{#2}%
}%
\begingroup
\newcommand@@filesection[3]{%
\endgroup
\def@@filesection##1##2##3#1{%
\def@stringinfile{##1}%
\expandafter\endgroup
\ifx@stringinfile@stringincommand\expandafter@firstofone\else\expandafter@gobble\fi
{%
\begingroup
@ifundefined{default}{\def\default{##2}}{}%
\newlinechar=\endlinechar
\scantokens
\expandafter\expandafter
\expandafter\expandafter
\expandafter\expandafter
\expandafter{\expandafter\UD@Replacedefault\expandafter{\default}{##3}{#3}#2}%
}\ignorespaces
}%
}%
@firstofone{%
\let\do@makeother\dospecials
\do^^I%
\catcode\{=1 % \catcode}=2 %
@@filesection
}{\endfilesection}{%}{\endgroup\ignorespaces }%
%
%
%%/////////// code for \UD@Replacedefault /////////////////////////////////////
%%=============================================================================
%% PARAPHERNALIA:
%% \UD@firstoftwo, \UD@secondoftwo, \UD@PassFirstToSecond, \UD@Exchange,
%% \UD@stopromannumeral, \UD@CheckWhetherNull, \UD@ExtractFirstArg
%%=============================================================================
\newcommand\UD@firstoftwo[2]{#1}%
\newcommand\UD@secondoftwo[2]{#2}%
\newcommand\UD@firstoftwobraced[2]{{#1}}%
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=\^^00}% %%----------------------------------------------------------------------------- %% Check whether argument is empty: %%............................................................................. %% \UD@CheckWhetherNull{<Argument which is to be checked>}% %% {<Tokens to be delivered in case that argument %% which is to be checked is empty>}% %% {<Tokens to be delivered in case that argument %% which is to be checked is not empty>}% %% %% The gist of this macro comes from Robert R. Schneck's \ifempty-macro: %% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J> \newcommand\UD@CheckWhetherNull[1]{% \romannumeral\expandafter\UD@secondoftwo\string{\expandafter \UD@secondoftwo\expandafter{\expandafter{\string#1}\expandafter \UD@secondoftwo\string}\expandafter\UD@firstoftwo\expandafter{\expandafter \UD@secondoftwo\string}\expandafter\UD@stopromannumeral\UD@secondoftwo}{% \expandafter\UD@stopromannumeral\UD@firstoftwo}% }% %%----------------------------------------------------------------------------- %% Extract first inner undelimited argument: %%............................................................................. %% \UD@ExtractFirstArg{ABCDE} yields {A} %% %% \UD@ExtractFirstArg{{AB}CDE} yields {{AB}} %% %% Due to \romannumeral-expansion the result is delivered after two %% expansion-steps/after "hitting" \UD@ExtractFirstArg with \expandafter %% twice. %% %% \UD@ExtractFirstArg's argument must not be blank. %% This case can be cranked out via \UD@CheckWhetherBlank before calling %% \UD@ExtractFirstArg. %% %% Use frozen-\relax as delimiter for speeding things up. %% Frozen-\relax is chosen because David Carlisle pointed out in %% <https://tex.stackexchange.com/a/578877> %% that frozen-\relax cannot be (re)defined in terms of \outer and cannot be %% affected by \uppercase/\lowercase. %% %% \UD@ExtractFirstArg's argument may contain frozen-\relax: %% The only effect is that internally more iterations are needed for %% obtaining the result. %%............................................................................. \@ifdefinable\UD@RemoveTillFrozenrelax{% \expandafter\expandafter\expandafter\UD@Exchange \expandafter\expandafter\expandafter{% \expandafter\expandafter\ifnum0=0\fi}% {\long\def\UD@RemoveTillFrozenrelax#1#2}{{#1}}% }% \expandafter\UD@PassFirstToSecond\expandafter{% \romannumeral\expandafter \UD@PassFirstToSecond\expandafter{\romannumeral \expandafter\expandafter\expandafter\UD@Exchange \expandafter\expandafter\expandafter{% \expandafter\expandafter\ifnum0=0\fi}{\UD@stopromannumeral#1}% }{% \UD@stopromannumeral\romannumeral\UD@ExtractFirstArgLoop }% }{% \newcommand\UD@ExtractFirstArg[1]% }% \newcommand\UD@ExtractFirstArgLoop[1]{% \expandafter\UD@CheckWhetherNull\expandafter{\UD@firstoftwo{}#1}% {\UD@stopromannumeral#1}% {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillFrozenrelax#1}}% }% %%============================================================================= %% \UD@ForkDefaultPhrase{<tokens to check>} %% {<tokens in case <tokens to check> equal \default>} %% {<tokens in case <tokens to check> are sub-phrase of \default>} %% {<tokens in other cases>} %%============================================================================= \@ifdefinable\UD@gobbletoexclam{\long\def\UD@gobbletoexclam#1!{}}% \begingroup \newcommand\UD@ForkDefaultPhrase[8]{% \endgroup \newcommand\UD@ForkDefaultPhrase[1]{% \expandafter\UD@CheckWhetherNull\expandafter{\UD@gobbletoexclam##1!}% {% \UD@DefaultPhraseFork !##1!#2!#3!#4!#5!#6!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!##1!#3!#4!#5!#6!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!##1!#4!#5!#6!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!#3!##1!#5!#6!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!#3!#4!##1!#6!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!#3!#4!#5!##1!#7!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!#3!#4!#5!#6!##1!#8!{\expandafter\UD@firstoftwo\UD@firstoftwo{}}% !#1!#2!#3!#4!#5!#6!#7!##1!{\expandafter\UD@firstoftwo\UD@firstoftwobraced}% !#1!#2!#3!#4!#5!#6!#7!#8!{\expandafter\UD@secondoftwo\UD@firstoftwo{}}% !!!!% }{\expandafter\UD@secondoftwo\UD@firstoftwo{}}% }% \@ifdefinable\UD@DefaultPhraseFork{% \long\def\UD@DefaultPhraseFork##1!#1!#2!#3!#4!#5!#6!#7!#8!##2##3!!!!{##2}% }% }% \@firstofone{% \let\do\@makeother\dospecials \do\^^I \catcode{=1 %
\catcode\}=2 % \UD@ForkDefaultPhrase }{\}{\d}{\de}{\def}{\defa}{\defau}{\defaul}{\default}% %%============================================================================= %% \UD@Replacedefault{<Replacement>}% %% {<List of character-tokens where the sequence %% \default is to be replaced>}% %% {<tokens to prepend to result>}% %%============================================================================= \newcommand\UD@Replacedefault[3]{% % #1 - <Replacement> % #2 - <List where the token \default is to be replaced> % #3 - <tokens to prepend to result> \romannumeral\UD@Replacedefaultloop{}{}{\UD@secondoftwo}{#2}{#3}{#1}% }% \newcommand\UD@Replacedefaultloop[6]{% % #1 - <Result collected so far> % #2 - <sub-phrase of \default collected so far> % #3 - <flag for checking catcode of subsequent character if phrase \default is collected> % #4 - <List of character-tokens> % #5 - <tokens to prepend to result> % #6 - <Replacement> \UD@CheckWhetherNull{#4}{% \UD@ForkDefaultPhrase{#2}\UD@firstoftwo\UD@secondoftwo\UD@secondoftwo {\UD@stopromannumeral#5#1#6}{\UD@stopromannumeral#5#1#2}% }{% \expandafter\UD@PassFirstToSecond\expandafter{\UD@firstoftwo{}#4}{% \expandafter\expandafter\expandafter\UD@PassFirstToSecond\UD@ExtractFirstArg{#4}{% \UD@defaultreplace{#5}{#6}{#1}{#2}{#3}% }% }% }% }% \newcommand\UD@defaultreplace[7]{% % #1 - <tokens to prepend to result> % #2 - <Replacement> % #3 - <Result collected so far> % #4 - <sub-phrase of \default collected so far> % #5 - <flag for checking catcode of subsequent character if phrase \default is collected> % #6 - <Character in this iteration> % #7 - <Remaining List of character-tokens> \expandafter\UD@firstoftwo\expandafter{% \expandafter\UD@Replacedefaultloop\romannumeral #5{% \ifnum\the\catcode\expandafter\csname\string#6\endcsname=11 %
\expandafter\UD@firstoftwo\else\expandafter\UD@secondoftwo\fi
{\UD@stopromannumeral{#3#4}}{\UD@stopromannumeral{#3#2}}{}{\UD@secondoftwo}{#6#7}%
}{%
\UD@ForkDefaultPhrase{#4#6}%
{\UD@stopromannumeral{#3}{#4#6}{\UD@firstoftwo}}%
{\UD@stopromannumeral{#3}{#4#6}{\UD@secondoftwo}}%
{\UD@stopromannumeral{#3#4#6}{}{\UD@secondoftwo}}%
{#7}%
}%
}{}{#1}{#2}%
}%
%%/////////// end of code for \UD@Replacedefault //////////////////////////////
%///// end of code that could go into a package / .sty-file////////////////////
\makeatother
\begin{document}
\inputfilesection{MyTemplates.tex}{example-image-a}
\inputfilesection{MyTemplates.tex}{example-image-b}
\inputfilesection{MyTemplates.tex}{example-image-c}
\inputfilesection{MyTemplates.tex}{example-image-a}[width=.3\textwidth]
\inputfilesection{MyTemplates.tex}{example-image-b}[width=.3\textwidth]
\inputfilesection{MyTemplates.tex}{example-image-c}[width=.3\textwidth]
\end{document}

\includeand\inputagain. Thanks for pointing that out. I'll delete the comments (too late to edit them now :-(). – moewe Dec 24 '21 at 08:21