使用模板

使用模板

我刚刚读了一篇精彩的文章LaTeX 模板并意识到我尝试过这种方法,但有一个技术方面我不知道如何解决。我说的是如何真正使用这些预先准备好的模板。主要问题是当人们开始编写新文档时如何轻松加载它们。最简单的方法是有一个本地中央模板存储库(以及它们的修订版,正如 Stefan Kottwitz 在他的帖子)以及任何template.tex需要的时候复制将其移至专用于新文档的新目录。但是,这缺少了 LaTeX 的一些模块化,不是吗?

当使用存储在 TeX 可以找到的某个地方的文档个性化类文件时,用户只需指定类的名称,它就可以供他使用,而不管类存储在何处。模板不是这种情况。所以我的问题基本上是这样的:使用 LaTeX 模板的最佳方法是什么?我应该如何存储它们?我应该将它们存储在哪里?我应该如何在一天结束时使用它们?模板不应该“导出”到类文件中吗?如果是这样,那么实现此目的的最简单方法是什么?

答案1

片段管理器

使用模板的一种灵活而强大的方法是使用代码片段管理器。在将 `$$ ... $$` 宏替换为 `\[ ... \]` 宏?——更喜欢 LaTeX 的布局方式,但 `$` 写起来更快您会发现一个关于代码片段管理器工作原理的简单解释。您要做的就是将每个模板存储为单独的代码片段,然后使用代码片段管理器的功能在扩展时对其进行修改。

YASnippet

下面是一个例子YASnippet,Emacs 的一个代码片段管理器。以下步骤是如何创建一个简单的文章模板:

  1. 输入您想要的片段模式。在这种情况下,我猜它是 LaTeX 模式。
  2. M-x yas/new-snippet
  3. 输入片段的名称。
  4. 现在您将有机会编辑代码片段。通过 标记所有内容C-x h,然后通过 终止它C-w
  5. 现在您将得到一个空的代码片段。将以下内容粘贴到其中,并确保代码片段在之后\end{document}结束不是在新行上:

    # -*- mode: snippet -*-
    # name: article
    # key: arttemp
    # --
    \documentclass{article}
    
    \usepackage[${1:english}]{babel}
    
    \title{${2:Title}}
    \author{${3:Author}}
    
    \begin{document}
    
    \maketitle
    
    $0
    
    \end{document}
    
  6. 执行C-c C-c保存并加载代码片段。

现在,您可以在 LaTeX 模式下使用该代码片段,方法是先书写,arttemp然后按Tab。请注意$1$2和定义制表位,并且前三个具有可以覆盖的默认值。以下动画显示了该代码片段的工作原理:$3$0

上述片段的动画

显然,示例中的代码片段是一个非常简单的代码片段。我用作文章模板的一个代码片段长达 172 行。它包含\usepackage我常用的包、包配置和我常用的宏的宏定义。有关如何编写代码片段的更多信息,请参阅文档

使用 YASnippet,你的代码片段将以文件形式存储。手册介绍了如何整理片段我将代码片段保存在 ~/.emacs.d/mysnippets 中,并通过以下命令在我的 .emacs 中加载它们:

(setq yas/root-directory "~/.emacs.d/mysnippets"); Develop and keep personal snippets under ~/emacs.d/mysnippets
(yas/load-directory yas/root-directory); Load the snippets

通过在计算机之间同步 ~/.emacs.d/mysnippets,我可以在所有的计算机上获得相同的片段。

答案2

您可以使用 lua 设置简单的模板系统。

示例模板sample.tpl

---
title = "Sample document",
extra_packages = "cmap",
encoding="utf8",
class = "article"
---
\documentclass{${class}}
\usepackage[${encoding}]{inputenc}
\usepackage{${extra_packages}}
\title{${title}}
\begin{document}
\maketitle
${content}
\end{document}

在用字符串分隔的标题中---,设置了默认变量。然后将它们包含在代码中${variable_name}。您可以在文档中覆盖变量:

---
title = "Hello world",
extra_packages="lipsum"
---
\section{First one}

\lipsum[1-4]

现在脚本luatextemplating.lua

kpse.set_program_name("luatex")
-- Helper functions
-- interp: simple templating
-- usage: print( "${name} is ${value}" % {name = "foo", value = "bar"} )
function interp(s, tab)
  return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
end
getmetatable("").__mod = interp

-- Parse page variables
function table.unserialize(s)
        local getTableFromString = loadstring('return '..s)
        local t = assert(getTableFromString())
        if type(t) ~= 'table' then return end
        return t
end

function string:split(pat)
  pat = pat or '%s+'
  local st, g = 1, self:gmatch("()("..pat..")")
  local function getter(segs, seps, sep, cap1, ...)
    st = sep and seps + #sep
    return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
  end
  return function() if st then return getter(st, g()) end end
end
-- 
function parseInputFile(filename)
  local f=io.open(filename)
  local s = f:read("*a")
  f:close()
  return parseInput(s)
end
function parseInput(s)
  local start = s:find("---") + 3
  local header_end= s:find("---",start)
  local header= s:sub(start,header_end-1)
  local content= s:sub(header_end+3)
  return table.unserialize("{"..header.."}"),content
end

-- Execution

local arg_message=[[
luatextemplating - generate TeX files from simple templates
usage: 
  luatextemplating templatefile inputfile
result is printed to the stdout
]]


if #arg < 2 then
  texio.write_nl(arg_message)
  return 0
end

local main_header, template = parseInputFile(arg[1])
local file_header, content= parseInputFile(arg[2])

for k, v in pairs(file_header) do
  main_header[k]=v
end

main_header["content"]=content
print(template % main_header)

运行后,texlua luatextemplating.lua path/to/templates/sample.tpl sample.tex您会在标准输出中看到此文档

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{lipsum}
\title{Hello world}
\begin{document}
\maketitle

\section{First one}

\lipsum[1-4]

\end{document}

答案3

启用模板的一种方法是使用不同 IDE 提供的功能。

例如:在 TexMaker 中,您希望将模板全部保存在与工作文件夹分开的单个文件夹结构中。然后使用 file-new for already file 选项获取模板。然后将其保存到工作文件夹中。我让我的学生以这种方式开发和保存单个项目模板。

此外,IDE TexnicCenter 具有类似的功能,但您需要仔细按照手册中的说明才能使用模板功能。最重要的说明是必须在结构中为模板文件创建一个新目录。(编辑:TexnicCenter 中的模板功能可防止您在另存为时意外更改模板。)

我希望其他 IDE 也能提供类似的功能。

答案4

关于 Emacs 和文件模板(只是为了完整性):我使用auto-insert-tkld-Package 已经很久了。你可以在GitHub

基本上,这个包用于提供不同的文件模板,每当您在 Emacs 中打开不存在的文件时,这些模板就会被插入。这个包以通常的 emacs 方式通过 elisp 变量进行配置。也就是说,您定义哪种文件类型由哪种模板填充。Auto-Insert-TKLD 还管理搜索路径,让您有机会为同一类型的文件的不同项目使用不同的模板。

当打开一个不存在的文件时,如果该文件定义了适当的模板,则模板将插入到缓冲区中。插入时,会识别一些特殊代码;例如,%U将被完整用户名替换,%a将被用户的电子邮件地址替换,实际运行的 Emacs 等等。

此外,Auto-Insert TKLD 能够在 Emacs minibuffer 中询问用户定义的问题,并将答案插入模板,进一步自定义。这是一种非常简单的方法,可以实现功能强大的自定义模板。

但是,你还可以更进一步,使用特殊字符%(%)封装普通的 elisp 代码,当模板插入缓冲区时,这些代码会被求值。这样可以制作出非常强大的模板,但是当然,你必须处理 Emacs Lisp 编码!

此包明确处理模板,当您开始处理不存在的文件。它不支持将代码片段插入现有缓冲区,而YASnippet上面提到的包则支持。但你可以很好地结合这两者。

相关内容