我刚刚读了一篇精彩的文章LaTeX 模板并意识到我尝试过这种方法,但有一个技术方面我不知道如何解决。我说的是如何真正使用这些预先准备好的模板。主要问题是当人们开始编写新文档时如何轻松加载它们。最简单的方法是有一个本地中央模板存储库(以及它们的修订版,正如 Stefan Kottwitz 在他的帖子)以及任何template.tex
需要的时候复制将其移至专用于新文档的新目录。但是,这缺少了 LaTeX 的一些模块化,不是吗?
当使用存储在 TeX 可以找到的某个地方的文档个性化类文件时,用户只需指定类的名称,它就可以供他使用,而不管类存储在何处。模板不是这种情况。所以我的问题基本上是这样的:使用 LaTeX 模板的最佳方法是什么?我应该如何存储它们?我应该将它们存储在哪里?我应该如何在一天结束时使用它们?模板不应该“导出”到类文件中吗?如果是这样,那么实现此目的的最简单方法是什么?
答案1
片段管理器
使用模板的一种灵活而强大的方法是使用代码片段管理器。在将 `$$ ... $$` 宏替换为 `\[ ... \]` 宏?——更喜欢 LaTeX 的布局方式,但 `$` 写起来更快您会发现一个关于代码片段管理器工作原理的简单解释。您要做的就是将每个模板存储为单独的代码片段,然后使用代码片段管理器的功能在扩展时对其进行修改。
YASnippet
下面是一个例子YASnippet,Emacs 的一个代码片段管理器。以下步骤是如何创建一个简单的文章模板:
- 输入您想要的片段模式。在这种情况下,我猜它是 LaTeX 模式。
- 做M-x
yas/new-snippet
。 - 输入片段的名称。
- 现在您将有机会编辑代码片段。通过 标记所有内容C-x h,然后通过 终止它C-w。
现在您将得到一个空的代码片段。将以下内容粘贴到其中,并确保代码片段在之后
\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}
执行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
上面提到的包则支持。但你可以很好地结合这两者。