总结• lua 是否是处理存储在外部文本文件中的元数据并输出 TeX 片段以用于前言的好选择?解决以下子问题的最小 lua 示例将是理想的选择:
编程问题
给定一个外部文本文件(下面的完整示例),其中包含任意数量(N)的作者和所属机构的列表,如何以编程方式生成以下文本片段?
\author[1,2,3]{Author One}
\author[2,*]{Author Two}
\affil[1]{First address}
\affil[2]{Second address}
\affil[3]{Third address}
\affil[*]{Corresponding author: [email protected]}
该计划需要执行以下任务:
- 解析作者和所属机构的输入(可选来自外部文件,但此处不是关键功能)
- 从完整列表中隔离唯一地址
- 生成 N
\author[]{}
条指令及其对应的唯一指令\affil[]{}
这是实现下文所述更一般目标的一项非平凡任务的一个很好的例子;其他宏会更直接(不需要for
循环或条件编程结构)。注意:我们可以假设宏\author
和\affil
是在类中定义的,无需担心编译结果。问题在于如何使用 lua 生成这些片段。
背景• 我已经厌倦了学术期刊出版商定义的 LaTeX 宏的丛林。这浪费了大量的时间——每当有人提交稿件时,他们都必须解读作者姓名、所属机构、关键字、地址等所需的特定宏集,而各个期刊之间的一致性非常低。下面是一个例子:
\title{Manuscript Title}
\dates{Compiled \today}
\author[1,2,3]{Author One}
\author[2,*]{Author Two}
\affil[1]{First address}
\affil[2]{Second address}
\affil[3]{Third address}
\affil[*]{Corresponding author: [email protected]}
\ociscodes{(140.3490) Lasers, distributed feedback; (060.2420) Fibers.}
另一个:
\title{Manuscript title}
\date{\today}
\author{Author One}
\affiliation{First address}
\alsoaffiliation{Second address}
\email{[email protected]}
\author{Author Two}
\phone{+123456789}
\fax{+123456789}
\email{[email protected]}
\affiliation{First address}
\alsoaffiliation{Second address}
\alsoaffiliation{Third address}
\abbreviations{IR,NMR,UV}
\keywords{American Chemical Society}
通常需要付出巨大的努力来改变格式以便重新提交给另一个期刊;我怀疑它有时会影响特定期刊的选择,只是为了尽量减少这个障碍!
没有人会让出版商考虑采用一套一致的宏——如果有的话,这样的尝试只会增加现有的“标准”。
我一直在考虑的是开发一个实用工具解决这种情况。受启发pandoc
,元数据稿件所需的数据将以外部的、上下文无关的、人类可读的格式存储;该工具将处理这些数据以填充特定于期刊的模板,从而生成可直接注入文档的 LaTeX 代码。
为说明起见,请考虑以下示例:
_元数据.yaml
title: "Here and there again: harnessing non-locality in invisibility cloaks"
date: "\\today"
authors:
- name: Bilbo Baggins
affiliation: ["Bag End, Bagshot Row, Private Bag, Hobbiton, the Shire",
"Rivendell, West of the Misty Mountains, Eriador"]
email: [email protected]
note: Currently on leave in Mordor
corresponding: false
collaboration: The Fellowship of the Ring
- name: Lord Elrond
affiliation: "Rivendell, West of the Misty Mountains, Eriador"
email: [email protected]
corresponding: true
- name: Lady Galadriel
affiliation: ["Caras Galadhon, The Naith of Lórien, Lothlórien"]
email: [email protected]
corresponding: true
- name: Gandalf The Grey
affiliation: ["Middle-earth, Arda"]
email: [email protected]
corresponding: true
collaboration: The Fellowship of the Ring
thanks: Frodo Baggins, Gollum
keywords: [ring, invisibility, cloaking]
abbreviations: [LOTR]
pacs: [123, 456, 789] # https://publishing.aip.org/publishing/pacs
ociscodes: [123, 456, 789] # https://www.osapublishing.org/submit/ocis
preprint: APS/123-ABC
abstract: >
All that is gold does not glitter. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
脚本读取并处理此 yaml 元数据,并将生成的 LaTeX 宏插入到稿件中。脚本包含各种指令,用于根据期刊的规范选择和格式化不同部分。在期刊之间切换不需要更改元数据文件;只需要一组字符串处理指令即可输出特定于期刊的宏:根据选择author
和address
字段,
\author{Author One}
\affiliation{First address}
\alsoaffiliation{Second address}
\email{[email protected]}
或者
\author[1,2,*]{Author One}
\affil[1]{First address}
\affil[2]{Second address}
\affil[*]{Corresponding author: [email protected]}
其余字段也是如此(其中一些字段未使用)。然后 LaTeX 照常处理手稿,并将此标题注入 TeX 文件中(\input{}
或以其他方式)。
例如,这是由脚本生成的最简手稿,用于特定期刊的类别:
\documentclass[aip,graphicx]{revtex4-1}
\usepackage[]{lipsum}
\begin{document}
\title{Here and there again: harnessing non-locality in invisibility cloaks}
\author{Bilbo Baggins}
\affiliation{Bag End, Bagshot Row, Private Bag, Hobbiton, the Shire}
\affiliation{Rivendell, West of the Misty Mountains, Eriador}
\author{Lord Elrond}
\affiliation{Rivendell, West of the Misty Mountains, Eriador}
\email{[email protected]}
\author{Lady Galadriel}
\affiliation{Caras Galadhon, The Naith of Lórien, Lothlórien}
\email{[email protected]}
\author{Gandalf The Grey}
\affiliation{Middle-earth, Arda}
\email{[email protected]}
\date{\today}
\pacs{123,456,789}
\keywords{ring,invisibility,cloaking}
\begin{abstract}
All that is gold does not glitter. Lorem ipsum dolor sit amet.
\end{abstract}
\maketitle
\lipsum[2-6]
\end{document}
另一个,
\documentclass[9pt,twocolumn,twoside]{optica}
\usepackage[]{lipsum}
\title{Here and there again: harnessing non-locality in invisibility cloaks}
\author[1,2]{Bilbo Baggins}
\author[2]{Lord Elrond}
\author[3]{Lady Galadriel}
\author[4]{Gandalf The Grey}
\affil[1]{Bag End, Bagshot Row, Private Bag, Hobbiton, the Shire}
\affil[2]{Rivendell, West of the Misty Mountains, Eriador}
\affil[3]{Caras Galadhon, The Naith of Lórien, Lothlórien}
\affil[4]{Middle-earth, Arda}
\dates{\today}
\ociscodes{123, 456, 789}
\begin{abstract}
All that is gold does not glitter. Lorem ipsum dolor sit amet.
\end{abstract}
\begin{document}
\maketitle
\lipsum[2-6]
\end{document}
一些输出示例:
笔记• 由于熟悉 R 语言,我用 R 编写了一个原理证明,但这不是一个很好的选择。我考虑使用 lua,因为它是 luatex 的首选语言 - 大多数 TeX 发行版都提供该语言,并且可能具有良好的功能来进行这种类型的字符串处理和与 TeX 的交互。
答案1
(删除了一些关于问题质量的评论。)
下面是一个示例,可以帮助您开始在 Lua 中执行相同的操作。这是一个粗略的概念验证,但您应该能够根据自己的需要进行调整。(例如,为了简单起见,它对元数据使用了简单的键值格式,而元数据恰好是实际有效的 Lua 代码,而不是从 YAML/JSON/XML/whatever 等纯数据格式进行解析。这类似于 Emacs 对仅是 elisp 代码的配置文件所做的操作,类似于 Django 等各种 Python 项目对配置文件只是 Python 代码所做的操作,等等。但如果您确实需要,将其更改为从 YAML 解析应该很简单。)
文件gen.lua
包含模板(当然您需要将它们移动到单独的文件中)和一个非常基本的模板替换函数:
journal1 = [[
\documentclass[9pt,twocolumn,twoside]{osajnl}
\journal{ol}
\setboolean{shortarticle}{true}
\title{$<title>}
\author[1,2,3]{$<author1>}
\author[2,*]{$<author2>}
\affil[1]{$<address11>, $<address12>, $<address13>}
\affil[2]{$<address21>, $<address22>, $<address23>}
\affil[*]{Corresponding author: $<email1>}
\dates{Compiled \today}
\ociscodes{(140.3490) Lasers, distributed feedback; (060.2420) Fibers}
\begin{abstract}
$<abstract>
\end{abstract}
\setboolean{displaycopyright}{true}
\begin{document}
]]
journal2 = [[
\documentclass[aip,graphicx]{revtex4-1}
\begin{document}
\title{$<title>}
\author{$<author1>}
\affiliation{$<address11>, $<address12>, $<address13>}
\email{$<email1>}
\author{$<author2>}
\affiliation{$<address21>, $<address22>, $<address23>}
\email{$<email2>}
\date{\today}
\pacs{123,456,789}
\keywords{$<keywords>}
\begin{abstract}
$<abstract>
\end{abstract}
]]
function substitute(template, variables)
ret = template:gsub('($%b<>)', function(var) return variables[var:sub(3, -2)] end)
tex.print(string.split(ret, '\n'))
end
对于特定情况,您可以编写一个实际.tex
文件,如下所示(如果愿意,可以将其移至data =
单独的文件中):
\directlua{dofile('gen.lua')}
\directlua{
data = {
title = 'Here and there again: harnessing non-locality in invisibility cloaks',
author1 = 'Bilbo Baggins',
address11 = 'Bag End',
address12 = 'Bagshot Row',
address13 = 'Private Bag',
email1 = '[email protected]',
author2 = 'Lord Elrond',
address21 = 'Rivendell',
address22 = 'West of the Misty Mountains',
address23 = 'Eriador',
email2 = '[email protected]',
abstract = 'All that is gold does not glitter. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
keywords = 'ring,invisibility,cloaking',
}
}
% Contains \documentclass and even \begin{document}
\directlua{substitute(journal1, data)}
\maketitle
Hello world
\end{document}
处理上述文件需要以下文件osajnl.cls和风格/ol.sty来自问题中链接的 GitHub 存储库。它生成:
如果您在文件中更改journal1
为(删除文件后),则会产生:journal2
.aux