创建带有用于输入内容的界面的 LaTeX 模板

创建带有用于输入内容的界面的 LaTeX 模板

我想创建一个模板,提供某种用于输入内容的界面。一些内容应该在最终文档的多个位置重复,但我不想在代码中编写重复的内容。事实上,我想让模板决定如何构造我提供的内容。让我举个例子来尝试一下。这是我想象中的模板:

\begin{document}
\section*{Products}
\begin[itemize}
  % for each product in the list of products
  %   \item product.name - product.description
\end{itemize}

\section*{Prices}
\begin{itemize}
  % for each product in list of products
  %  \item product.name: product.price
\end{itemize}
\end{document}

我希望模板提供用于定义产品列表的界面,并在我的主 tex 文件中像这样使用它:

\begin{products}
  \product{Product 1}{description for product 1}{\$10}
  \product{Product 2}{description for product 2}{\$20}
\end{products}

最终文件看起来应如下:

\begin{document}
\section*{Products}
\begin[itemize}
  \item Product 1 - description for product 1
  \item Product 2 - description for product 2
\end{itemize}

\section*{Prices}
\begin{itemize}
  \item Product 1: \$10
  \item Product 2: \$20
\end{itemize}
\end{document}

我可能需要另一个以不同方式构建产品的模板。理想情况下,我只需更改模板文件即可。换句话说,定义产品列表的主文件不应该关心产品的结构,它只提供数据。

我可能想要一个可以显示如下数据的模板:

\section*{Products}
\begin{itemize}
  % for each product in the list of products
  %  \item product.name \(product.price\) - product.description
\end{itemize}

或者

\begin{tabular}{lll}
  % for each product in the list of products
  %  product.name & product.price & product.description \\
\end{tabular}

或者

\section*{Products}
\begin{itemize}
  % for each product in list of products
  %   \item.product.name - product.description
\end{itemize}

% some other sections here that have nothing to do with products

\section*{Prices}
...

并且它们都应该使用相同的数据文件。想象一下 REST API 如何提供数据,不同的应用程序可以以不同的方式显示它。这就是我在这里试图实现的事情 - 有一个文件,我在其中提供可以以模板定义的不同方式显示的数据。

我只使用 LaTeX 进行一些基本操作,所以我不知道这是否可行。

答案1

使用 LaTeX 可以轻松实现这一点。在这里我使用 pgfkeys,因为除其他外,它使在描述中留空格变得容易,并且它具有非常方便的迭代列表的语法。为了方便那些想要使用此代码的人,我将所有内容放在一个文件中,但在实际应用中,您可能需要将数据文件与模板文件分开。

\documentclass{article}
\usepackage{pgffor}
% this creates a data file which you can separate this from the template file
\begin{filecontents*}{ProductData.tex}  
\pgfkeys{/products/.cd,
name/.initial={},
description/.initial={},
price/.initial={},
1/.style={name=iPad,description=Medium-sized tablet,price={\$1,000}},
2/.style={name=iPhone,description=Smartphone,price=\$8000},
3/.style={name=goat cheese,description=cheese made from goat milk,price=\$10},
4/.style={name=Emmentaler,description=Swiss cheese made from cow milk,price=\$8},
product description/.code={\item \pgfkeys{/products/.cd,#1}\pgfkeysvalueof{/products/name} --- \pgfkeysvalueof{/products/description}},
descriptions/.code={\section*{Products}
\begin{itemize}
    \pgfkeys{/products/product description/.list={#1}}
\end{itemize}},
product price/.code={\item \pgfkeys{/products/.cd,#1}\pgfkeysvalueof{/products/name}: \pgfkeysvalueof{/products/price}},
prices/.code={\section*{Prices}
\begin{itemize}
    \pgfkeys{/products/product price/.list={#1}}
\end{itemize}}}
\end{filecontents*}
\input{ProductData.tex}
\begin{document}
\pgfkeys{/products/.cd,
descriptions={1,2},
prices={1,...,4}}    
\end{document}

在此处输入图片描述

一旦您有了数据文件,您只需要一个非常短的模板文件。

\documentclass{article}
\usepackage{pgffor}
\input{ProductData.tex}
\begin{document}
\pgfkeys{/products/.cd,
descriptions={1,2},
prices={1,...,4}}    
\end{document}

此外,您稍后还可以轻松添加密钥。

答案2

在我发现expl3可以解决这个问题之后,这件事就相对容易实现了。

模板文件提供了文档的界面和结构,如下所示:

% template1.sty
\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn
\tl_new:N \l_product_name_tl
\tl_new:N \l_product_price_tl
\tl_new:N \l_product_description_tl

\newcommand{\product}[3]{
  \tl_put_right:Nn \l_product_name_tl {{#1}}
  \tl_put_right:Nn \l_product_price_tl {{#2}}
  \tl_put_right:Nn \l_product_description_tl {{#3}}
}

\newcommand{\productdesc}{
    \int_step_inline:nn {\tl_count:N \l_product_description_tl}{
      \subsection*{\tl_item:Nn \l_product_name_tl {##1}}
      \tl_item:Nn \l_product_description_tl {##1}
      \int_compare:nNnTF {##1} = {\tl_count:N \l_product_description_tl} {} {}
    }
}

\newcommand{\productprice}{
  \begin{itemize}
    \int_step_inline:nn {\tl_count:N \l_product_price_tl}{
      \item \tl_item:Nn \l_product_name_tl {##1}:~ \tl_item:Nn \l_product_price_tl {##1}
      \int_compare:nNnTF {##1} = {\tl_count:N \l_product_price_tl} {} {}
    }
  \end{itemize}
}
\ExplSyntaxOff

\newcommand{\unrelateddata}[1]{
  \newcommand{\getunrelateddata}{#1}
}

\newcommand{\makedoc}{
  \begin{document}

  \section*{Products}
  \productdesc

  \section*{Now Something Completely Different}
  This is completely unrelated to products.

  \getunrelateddata

  \section*{Prices}
  \productprice

  \end{document}
}

主(数据)文件可能如下所示:

\include{template1.sty}
\usepackage{lipsum}

\product{Product 1}{\$10.00}{
  \lipsum[1][1-4]
}
\product{Product 2}{\$20.00}{
  \lipsum[1][5-8]
}
\product{Product 3}{\$30.00}{
  \lipsum[1][9-12]
}
\product{Product 4}{\$40.00}{
  \lipsum[1][13-16]
}

\unrelateddata{
  \lipsum[2][1-10]
}

\makedoc

如果我需要以不同的形式呈现相同的数据,我可以创建一个提供相同界面的新模板:

% template2.sty
\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn
\tl_new:N \l_product_name_tl
\tl_new:N \l_product_price_tl
\tl_new:N \l_product_description_tl

\newcommand{\product}[3]{
  \tl_put_right:Nn \l_product_name_tl {{#1}}
  \tl_put_right:Nn \l_product_price_tl {{#2}}
  \tl_put_right:Nn \l_product_description_tl {{#3}}
}

\newcommand{\productdesc}{
    \int_step_inline:nn {\tl_count:N \l_product_description_tl}{
      \textbf{\tl_item:Nn \l_product_name_tl {##1}}
      \begin{quote}
        \tl_item:Nn \l_product_description_tl {##1}
      \end{quote}
      \int_compare:nNnTF {##1} = {\tl_count:N \l_product_description_tl} {}{}
    }
}

\newcommand{\productdata}{
  \begin{tabular}{|l|l|p{8cm}|}
    \textbf{Product} & \textbf{Price} & \textbf{Description} \\
    \hline
    \int_step_inline:nn {\tl_count:N \l_product_name_tl}{
      \tl_item:Nn \l_product_name_tl {##1} & \tl_item:Nn \l_product_price_tl {##1} & \tl_item:Nn \l_product_description_tl {##1}
      \int_compare:nNnTF {##1} = {\tl_count:N \l_product_name_tl} {} {\\}
    }
  \end{tabular}
}
\ExplSyntaxOff

\newcommand{\unrelateddata}[1]{
  \newcommand{\getunrelateddata}{#1}
}

\newcommand{\makedoc}{
  \begin{document}

  \section*{Products}
  \productdesc

  \section*{Products in Table View}
  \productdata

  \section*{Now Something Completely Different}
  This is completely unrelated to products.

  \getunrelateddata

  \end{document}
}

而我在主文件中要做的就是更改包含的文件。

相关内容