在对象编程语言中,通常存在结构体,它可以帮助您重复使用代码两次或多次,但只需编写一次该代码。
如果作者不想深入研究 Latex,那么编写 Latex 代码的一种方便方法就是简单地使用模板。
这里的用例是作者想要包含独立于模板的共享组件。对于章节和子节,我认为这很常见。但作者希望将元素的代码(例如图形和标题的代码)共享到书籍模板和演示模板中。
一份文件示例图.tex有内容
\begin{figure}[h!]
\includegraphics[width=0.6\paperwidth]{examplePath/exampleFigure.png}
\caption{Example Section.}
\end{figure}
并纳入示例BookSection.tex
The example BlaBla shows the ... and we can see in figure:
\include{exampleFigure}
but on the other hand ...
以及示例PresentationSlide.tex
\begin{frame}{ExampleSlide}
\framesubtitle{Random Bla}%
\include{exampleFigure}
\end{frame}
如果我们想替换命名用例,那么命名用例已经变得相当复杂了示例图.tex [宽度=0.6\纸张宽度]到[宽度=0.8\纸张宽度]例如包括在示例PresentationSlide.tex。在编程中,我们可以通过将变量作为参数来简单地重用代码片段。
在我发现的每一个例子中包括机制一儿童.tex仅包含一次父类。这些示例具有树状结构。我的用例允许儿童.tex包括父母双方父级1.tex和父级2.tex。我甚至想要多个根(模板文件)。
- 这样的结构是否可以维护?
- 如果可维护的话,是否存在有用的 Latex IDE?
- 这里是否有一个有用的指南可供参考,以建议如何解决上述参数化问题?
如何解决参数化问题?
答案1
LaTex 中的“库”称为包,并通过以下方式包含
\usepackage{mystuff}
例如,使用以下代码访问\myfig{fig:zz}{myfigure}{my caption}
在这种情况下,mystuff.sty
应该有
\newcommand\myfig[4][htp]{%
\begin{figure}[#1]%
\includegraphics[width=0.6\paperwidth]{#3}%
\caption{#4\label{#2}}%
\end{figure}}
注意,我将位置参数设为可选,以便您可以\myfig[!ht]
在需要时使用。您不应该经常添加,!
因为它用于覆盖文档范围设置的特殊用途,设置文档范围设置然后始终忽略它们是没有意义的。另外,h
单独使用它通常是一个错误,LaTeX 会对此发出警告并进行更改,因此htp
更好的默认值是默认设置。
答案2
我可以提供一个模板文件模式的界面
\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
使用以下命令输入模板文件
\inputfilesection{⟨name of template-file⟩}%
{⟨name of section⟩}%
[⟨replacement for the token \default⟩]
这⟨代码⟩仅当 -command\inputfilesection
和\filesection
-comand 具有相同的⟨部分名称⟩-争论。
在这种情况下⟨代码⟩将在 verbatim-catcode-régime 下读取,并且序列\default
将被替换:如果\inputfilesection
-command 指定⟨代币的替代品\default
⟩-argument,则替换将来自该参数。
否则替换将来自\filesection
-command 的⟨代币的替代品\default
⟩-争论。
结果被传递\scantokens
以进行重新标记和正常处理。
多个\filesection
s 可以有相同的⟨部分名称⟩。在这种情况下,模板文件中出现的所有相关名称的文件部分都由 提供\inputfilesection
。在这种情况下,如果\inputfilesection
- 提供⟨代币的替代品\default
⟩-argument,该参数将用来替代\default
已传递的所有文件部分的令牌。
我知道的注意事项:
!!!不要在被!!!\inputfilesection
调用的文件中执行操作\inputfilesection
!!!\inputfilesection
尝试读取⟨代币的替代品\default
⟩-verbatim-catcode-régime 下的参数。因此\inputfilesection
不应在其他宏等的参数内使用。!!!
%
% 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}
答案3
一些勇敢的尝试已经实现这一点(参见将参数传递给 \input{text} (包含的文本文件)作为起点),但我发现它通常不值得。
但是,您可以做的是在父文档中使用变量/宏(甚至可以动态地更改它们),并在子文档中引用它们。
\begin{figure}[h!]
\includegraphics[width=\mywidth]{\myfigure}
\caption{\mycaption}
\end{figure}
… 结合,比如说,
\def\mywidth{.6\paperwidth}
\def\myfigure{examplePath/exampleFigure} % usually best to omit the .png etc suffix
\def\mycaption{This is a caption!}
\input{exampleFigure.tex}
% using the same width, so no need to redefine
\def\myfigure{examplePath/exampleFigure2}
\def\mycaption{Another caption!}
\input{exampleFigure.tex}
如您所见,在编写代码片段之前,您必须\input
根据需要重新定义变量。话虽如此,在处理这些事情时,我自己就是一个复制粘贴的人。在我看来,最乏味的部分是序言(不要让我开始设置字体),我肯定会重复使用它们。