使用 Latex 代码块作为库 - 用于在多种表示中重复使用 Latex 元素(例如图形)

使用 Latex 代码块作为库 - 用于在多种表示中重复使用 Latex 元素(例如图形)

在对象编程语言中,通常存在结构体,它可以帮助您重复使用代码两次或多次,但只需编写一次该代码。

如果作者不想深入研究 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以进行重新标记和正常处理。

多个\filesections 可以有相同的⟨部分名称⟩。在这种情况下,模板文件中出现的所有相关名称的文件部分都由 提供\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根据需要重新定义变量。话虽如此,在处理这些事情时,我自己就是一个复制粘贴的人。在我看来,最乏味的部分是序言(不要让我开始设置字体),我肯定会重复使用它们。

相关内容