> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/zh-cn/shen-ru-wen-zhang/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md).

# LuaTeX 简介（第 1 部分）：它是什么——又是什么让它如此不同？

LuaTeX 是一个 *工具包*——它包含复杂的软件工具和组件，借助它们你可以构建（排版）各种各样的文档。本文的副标题还提出了两个关于 LuaTeX 的问题：它是什么——以及它为何如此不同？对“它是什么？”的回答似乎很明显：“它是一个 TeX 排版引擎！”确实如此，但从更广泛的角度看，而本文作者也赞同这一点，LuaTeX 是一个极其多功能的、基于 TeX 的 *文档构建与工程系统*.

### 解读 LuaTeX：从哪里开始？

本文第一篇关于 LuaTeX 的文章，旨在为理解这个 TeX 引擎提供一个背景，说明它提供了什么，以及为什么/如何它的设计使用户能够构建/设计/创建各种复杂排版与设计问题的解决方案——也许还能在某种程度上提供“面向未来的保障”，因为用户越来越需要能够适应不断变化的技术生态系统的基于 TeX 的软件。在作者看来，在建立对 LuaTeX 的能力和潜力的理解时，列举并描述其特性/功能并不一定是最佳起点。对于不熟悉其他 TeX 引擎的读者来说，这种方式不会特别有帮助，而基于特性的比较对他们而言也未必有特别意义。

在有可能耗尽读者耐心的风险下（“快说重点！”），我将采用一种更“整体”的方法，希望能提供有用的背景，但代价是需要额外阅读一些内容——并深入探讨若干编程主题以帮助理解。在 [第2部分](/latex/zh-cn/shen-ru-wen-zhang/09-an-introduction-to-luatex-part-2-understanding-directlua.md) 我们探讨使用 `\directlua` 不过，目前我们先尝试为理解 LuaTeX 奠定基础。

本文强烈反映了作者在建立对 LuaTeX 的理解和欣赏过程中的个人“旅程”：先了解 LuaTeX 发展背后的理念，并将其视为一个软件工具容器，你就会更好地理解这款令人惊叹的软件所开启的广阔解决方案领域。

## LuaTeX：不只是为了学术界，或数学！

LuaTeX 内置的丰富特性和功能，不仅能够通过传统的 LaTeX 提供极高质量的排版，还为开发定制的、非 LaTeX 的解决方案来处理复杂的文档生产和工程问题提供了巨大空间。LuaTeX 内嵌了强大的 Lua 脚本语言，这意味着例如你可以使用 Lua 将“插件”（外部软件库）加载到 LuaTeX 中；这进一步支持高度自动化、与现有软件系统或工作流的集成，以及借助专门的软件来处理数据、文本或图形。

从历史上看，TeX 一直与学术写作/出版相关，尤其是在数学领域，但 LuaTeX 尤其具有在许多其他领域中的应用潜力——包括商业 PDF 文档生产。其中一个例子是 [speedata publisher](https://speedata.github.io/publisher/) 它在基于 XML 的工作流中纯粹把 LuaTeX 作为 PDF 生成引擎使用——它完全不使用 LaTeX。事实上，speedata publisher 几乎不包含任何 TeX 代码——我询问了 [Patrick Gundlach](https://twitter.com/patrickgundlach)，speedata publisher 的开发者，他确认总共只用了大约三行 TeX 代码。它强大的排版能力是用 Lua 代码设计和实现的，借助 LuaTeX 的 Lua API（这是我们在本文后面要讨论的话题）。

## 一个简短的个人故事：我是如何第一次发现 LuaTeX 的

我第一次了解到 LuaTeX 是在 2009 年末/2010 年初，那时它还处于中期测试版阶段（0.50 版）。当时我正在寻找基于 TeX 的软件来排版我为学习一些阿拉伯语而写的手写笔记。通过 Google 搜索，我发现了 TUG 2009 大会的一组视频（[现在在 YouTube 上](https://www.youtube.com/playlist?list=PL2D4DD50DC9C0BA0E)），其中包括高质量阿拉伯语排版的演示（使用 Hans Hagen 的 [ConTeXt 宏包](http://wiki.contextgarden.net/Main_Page)）。这些视频还包括一个题为 [LuaTeX 项目：向 1 版迈进一半](https://youtu.be/AKv4po9PGW0).

当时用于生成那种精美阿拉伯语排版的 TeX 引擎叫做“LuaTeX”。那时我在科学（物理）出版领域工作，虽然对 TeX/LaTeX 很熟悉，却从未听说过 LuaTeX：这引起了我的兴趣，我想进一步了解这个新的 TeX 引擎。由于 LuaTeX 当时仍处于测试开发阶段，而且发展迅速，我希望始终跟进最新更新，所以对我来说最好的办法就是自己动手从源代码构建（编译）LuaTeX 可执行程序。除了 LuaTeX 可执行程序之外，你还需要一个“TeX 安装环境”来提供运行 LuaTeX 的环境（例如 texmf.cnf、宏包、字体等）。与其下载并安装庞大的 [TeX Live](https://www.tug.org/texlive/) 发行版，我选择创建一个绝对最小化的自定义 TeX 安装，以便探索 LuaTeX（这是一个“有趣”的练习，我 [已在我的个人博客上记录下来](http://www.readytext.co.uk/?cat=30)）。LuaTeX 的每个新版本都会附带其参考手册（例如，针对[1.0.4 版](https://www.tug.org/svn/texlive/tags/texlive-2017.1/Master/texmf-dist/doc/luatex/base/luatex.pdf?revision=44591\&view=co)），其中记录了该软件的最新特性和功能。然而，这是一部 *参考* 手册，因此（不可避免地）对想要入门这款令人惊叹的 TeX 引擎的初学者来说，解释较为简略——它假定读者对底层 TeX 概念有一定了解。鉴于我是在 LuaTeX 发展相对早期阶段发现它的，当时很难找到好的入门材料，因此我花了一些时间去探索、试验（以及一些挫败感……），直到各个部分开始逐渐拼接起来。不用说，随着我对这款惊人软件着迷，我的阿拉伯语学习也戛然而止，最后转而编写用于阿拉伯语排版的 LuaTeX [插件](http://www.readytext.co.uk/?p=3143) ！

我自己的“LuaTeX 之旅”当然非常非线性，但在这个过程中，它提供了一个从“底层”学习（Lua）TeX（以及 TeX 安装环境）的机会：我的博客收录了一系列杂而有趣的 [文章](http://www.readytext.co.uk/?cat=3) ，内容基于我当时探索和处理的各种主题。希望本文能恰当地利用那段时间和经验，帮助其他人开始对 LuaTeX 的能力产生兴趣并进行探索。LuaTeX 仍在持续开发中，在撰写本文时，它已经达到 1.0.4 版，该版本随 TeX Live 2017 发布。开发者们非常活跃，发现的任何 bug 通常都会在报告后不久得到修复——例如，通过 [dev-luatex 邮件列表](https://mailman.ntg.nl/mailman/listinfo/dev-luatex) 或通过 [在线 LuaTeX bug 跟踪器](http://tracker.luatex.org/my_view_page.php)。在它达到 1.0 版之前很久，LuaTeX 就已经具备生产可用能力——当然，你需要接受其特性在持续演进，且偶尔某些变更可能会破坏你现有的 TeX 代码。如今，LuaTeX 当然也受到 Overleaf 和 ShareLaTeX 平台的支持（以 LuaLaTeX 形式）。

## 变化世界中的 TeX：新技术与工作流

显然，TeX 引擎并不是运行在一个技术静止不变的世界里，偶尔会出现一些创新，而这些创新会立即并显然成为 TeX 引擎的候选加入项——其中一个这样的创新就是 OpenType 可变字体，我们将在下文简要讨论。尽管几乎毫无疑问，基于 TeX 的排版软件极其多功能，但 TeX 引擎如今是在一个快速变化且高度多样化的软件生态系统中运行——新的工作流更加凸显了集成需求以及实现广泛文档/排版解决方案的灵活性，而 TeX 可能只是其中的一个组成部分。

TeX 不仅必须对现有用户保持相关性，还要通过支持内容创建解决方案来吸引新用户——这些方案对新一代用户仍然有用，他们未必想把 TeX 作为独立工具使用，而可能作为整体工作流的一部分，通过诸如 Overleaf 之类的在线协作平台来使用。

即便是对 [tex.stackexchange](https://tex.stackexchange.com/) 略作浏览，也能看出基于 TeX 的软件正在生成和实现的文档与解决方案种类极其丰富——人们常常展现出惊人的创造力，不断发现新的用例和希望生成的内容类型。此外，能够处理基于 TeX 的标记/内容并生成非 PDF（也非 DVI）输出的工作流需求从未如此强烈——例如 MathML/XML 和 HTML。比如，将 TeX“转换”为 [JATS XML](https://jats.nlm.nih.gov/) 格式（长期用于学术期刊出版），以及更近一些时候在电子书出版中使用的 epub 的兴起。

### 可变字体技术——时代在变

2016 年 9 月 14 日，Microsoft、 [Google](https://opensource.googleblog.com/2016/09/introducing-opentype-font-variations.html), [Adobe](https://blog.typekit.com/2016/09/14/variable-fonts-a-new-kind-of-font-for-flexible-design/) 和 Apple 宣布了一种新字体技术： [OpenType 可变字体](https://medium.com/@tiro/https-medium-com-tiro-introducing-opentype-variable-fonts-12ba6cd2369)。我们不会详细探讨这项技术，只需说像 [Thomas Phinney](https://twitter.com/ThomasPhinney) 和 [John Hudson](https://twitter.com/TiroTypeworks) 这样的高度权威字体专家已经观察到（[在 Twitter 上](https://twitter.com/ThomasPhinney/status/917087509342851072)）可变字体技术的采用速度远快于许多早期字体创新——这很可能是由网页设计师的需求推动的，他们需要能够适应移动设备上各种不同屏幕尺寸/分辨率的响应式设计。

显然，OpenType 可变字体是字体技术中的一个有趣且令人兴奋的发展，TeX 用户无疑可以从中受益——事实上，这个问题不可避免地已经被 [在 tex.stackexchange 上提出](https://tex.stackexchange.com/questions/355104/tex-luatex-xetex-fontspec-support-for-opentype-variable-fonts) ，并在 LuaTeX 的 [邮件列表](https://www.tug.org/pipermail/luatex/2016-September/006204.html).

顺带一提，值得注意的是，建立在“参数化”字体创建基础上的字体技术并不是一个全新的想法：Knuth 的 METAFONT 和 Adobe 的 Multiple Master 技术在某种程度上都是早期先驱，尽管其实现细节相当不同。

### 可变字体：我们什么时候需要它们——现在！

任何新的且有用的技术标准/规范都需要时间“融入”其目标开发者和实现者生态——这还包括厘清规范文本本身中的任何歧义或措辞解释。开发者必须阅读并理解文档，并将其转化为真正可运行的软件——在这里，这还包括创建字体及使用它们的技术：兼容的浏览器和排版引擎。TeX 开发者显然需要高质量的可变字体，以便将其作为实现（编程）可变字体技术支持的可靠“基准”。

在 TeX 中实现任何新技术，例如可变字体，都会带来 *潜在的* 需要修改 TeX 引擎内部结构——当然，是否需要这样做取决于该技术的性质，以及至关重要的，是 TeX 行为的哪个方面正在被改变。并不总是需要修改 TeX 引擎本身，也许只需对支持/辅助软件进行修改，包括这些程序中使用的任何“组件”（第三方代码库）。从内部看，TeX 引擎是 *极其* 复杂的——要对 TeX 源代码形成足够的理解并做出可靠修改，需要相当高深且高度专业的知识（而这样的人才非常稀缺）。此外，任何修改都必须确保不会对 TeX 引擎的长期稳定性/兼容性产生负面影响——这对 TeX 社区以及之后处理作者（La）TeX 文件的人员至关重要：最显著的是学术出版商，以及像 Overleaf 和 ShareLaTeX 这样的云服务。

许多 TeX 用户很可能希望利用可变字体；例如，实现新的设计可能性或解决棘手的排版问题。所以，从某种意义上说，这里存在一个两难：TeX 用户希望获得新技术，但其实现又依赖于一项非常有限的资源：具备资格并有能力推动实现的开发者数量。修改 TeX 的内部结构很困难，而且通常在可能的情况下最好避免，那么还有没有别的办法来为 TeX 添加（某些类别的）新特性/功能呢？有！LuaTeX 选择了这条路。

#### 早期实验：OpenType 可变字体与 LuaTeX

LuaTeX 的设计使得对可变字体技术的快速实验成为可能。早在 2017 年 4 月，使用 LuaTeX 的 ConTeXt TeX 格式就已经有了一个 [测试版](https://mailman.ntg.nl/pipermail/ntg-context/2017/088343.html) 实现了 OpenType 可变字体。之所以能够做到这一点，是因为 ConTeXt 的字体支持是用 Lua 代码构建的（而且 ConTeXt 还有自己用 Lua 编写的 fontloader）。

## LuaTeX：背景与历史

就 TeX 而言，LuaTeX 尽管已经处于积极开发超过 10 年，但它仍然是“新来的”。LuaTeX 网站 [记录了](http://www.luatex.org/roadmap.html) LuaTeX 在 2005 年诞生，而（我认为）从 2006 年开始进入持续且积极的开发。由于其内在的复杂性，以及构建者的勤勉，LuaTeX 确实花了 10 年开发才达到 1.0 版，该版本是由其开发者 [宣布的](https://mailman.ntg.nl/pipermail/dev-luatex/2016-September/005882.html) （Hans Hagen、Hartmut Henkel、Taco Hoekwater、Luigi Scarso）于 2016 年 9 月 27 日。

在那次发布公告中有一个重要的原则声明：

> “我们的主要目标是提供一种 TeX 变体，使其允许用户扩展，而无需适配其内部工作机制。”

这句话完美概括了 LuaTeX 开发背后的理念，并指出了一条路径，使基于 TeX 的软件能够应对我们已经提到的挑战：采用新技术，并保持对新一代用户的相关性。

现在该来回答本文副标题中的第二个问题了：“它为何如此不同”。通过探讨“……允许用户扩展，而无需适配内部工作机制”这句话的含义，我们可以更好地理解 LuaTeX“带来了什么”。

## LuaTeX：打开 TeX 的“黑箱”

Knuth 最初的 TeX 程序是今天所有现代 TeX 引擎的共同祖先，而 LuaTeX 实际上是最新的演化一步：它源自 pdfTeX 程序，但增加了一些强大的软件组件，带来了大量额外功能。Knuth 编写原始版本的 TeX 软件时，也提供了 TeX 语言作为控制和编程其排版行为的方式：大约 320 条底层命令（原语）对 TeX 宏包的用户和开发者开放。这些命令在控制或影响 TeX 排版行为的某些方面提供了不同程度的能力，但 TeX 的许多内部功能、算法、决策过程、数据和数据结构对用户而言都是隐藏的。可以说，Knuth 的 TeX 程序并不是一个完全的“黑箱”，但它确实是非常深的灰色——不可否认，源代码是开放的，但对绝大多数人来说，那同样也是一个难以理解的黑箱。

我们把 TeX 内部的处理过程称为某种“黑箱”；然而，LuaTeX 打开了其基于 TeX 的内部机制，为用户/开发者提供了对许多过去隐藏在 TeX 引擎深处的过程更大的访问与控制。LuaTeX 还增加了许多新的原语命令，用于控制这些新特性。

### LuaTeX：源自 pdfTeX，但不使用 pdfTeX 的代码

为了准确起见，需要指出的是，虽然我们把 LuaTeX 描述为源自 pdfTeX，但 LuaTeX 并不直接使用 pdfTeX 的原始程序代码。LuaTeX 的一位开发者（Taco Hoekwater）承担了真正 *赫拉克勒斯式的* 任务：用干净、现代的 C 代码（CWEB）重写 LuaTeX 的核心 TeX 引擎。

#### 历史注记

部分由于 Knuth 最初的 TeX 源代码年代久远——现代的后代程序都由它演化而来——修改它以适配或创建新的基于 TeX 的排版引擎是一个复杂而曲折的过程。该过程的一部分需要将 Pascal 代码转换为 C 代码——这并非没有 [一定程度的复杂性](http://www.readytext.co.uk/?p=2529)。最终生成的机器代码 C 代码极其冗长，也非常难以阅读或理解。显然，将 LuaTeX 的代码完全重写，绕开了整个 Pascal 到 C 的转换过程。

## LuaTeX 的构建模块

在引言中，我们提到 LuaTeX 是一个“工具包”，并将其描述为“文档构建与工程系统”。我们已经看到，在 LuaTeX 1.0 的公告中，其开发者声称：

> “我们的主要目标是提供一种 TeX 变体，使其允许用户扩展，而无需适配其内部工作机制。”

现在是时候把这些线索和想法汇总起来，聚焦于这一切究竟 *实际意味着什么* 在实践中。

### LuaTeX 拼图

如果你“打开引擎盖”去看，就会发现 LuaTeX 软件，也就是实际的可执行程序，是由一组软件组件构成的，这些组件组合在一起提供了 LuaTeX 的整体功能。当然，这并不新鲜，大多数软件都是这样构成的。然而，LuaTeX 与其他 TeX 引擎不同之处在于，这些组件的组合方式使用户能够更深入地访问 TeX 内部功能的许多方面：TeX 的排版算法、决策过程、数据和数据结构。对 TeX 内部机制的这种开放，使用户能够在无需修改实际 TeX 引擎本身的情况下构建新的排版解决方案。

### LuaTeX 中的 Lua：打开“黑箱”的关键

Lua 是一种非常强大、但又容易学习的脚本语言， [起源于巴西](https://www.lua.org/about.html)——它创建于 1993 年，至今仍在积极开发中。Lua 的优势之一是它可作为一种编程语言，用于将分散的软件组件“粘合”在一起，使你能通过一种简单而多功能的脚本语言来使用它们。Lua 在打开 LuaTeX TeX 引擎内部工作机制方面起着核心作用，但为了更好地理解这是如何实现的，值得稍作绕道，简要讨论两个编程概念：

* 应用程序编程接口（API）；
* 编程语言绑定。

如果你对这些概念已经很熟悉，可以跳过这一节。这里不会对这两个主题做详细展开——我们的目标不是追求严格的技术严谨性，而是提供足够的背景，让你知道这些概念的含义及其与 LuaTeX 的相关性。

### 应用程序编程接口（API）

设想你是一名程序员，写了一些代码，其他用户（程序员）可能会觉得很有用，但你的代码很复杂，你又不希望使用者去操心那些底层细节。注意，这些程序员/开发者使用的是与你编写代码时相同的编程语言。此外，假设你打算重写代码的某些部分——例如，让它更快、占用更少内存等等。你代码的现有用户不应为此担心：你计划做的任何改动都不应破坏他们的程序。那么，解决方案是什么？

答案在于一种叫做 API 的东西：一种 *应用程序编程接口*。你不会要求用户（其他程序员）去接触你的代码中可能会改变的底层细节，而是提供一组特定的 *函数* ，供其他程序员使用。这些函数是你代码的一个 *接口* ，其他开发者可以通过它构建 *应用程序* ，而无需对你程序的内部工作机制有深入了解。从某种意义上说，你可以把它想成围绕代码的一层附加层，它将用户与那些凌乱的底层细节“隔离”开来。

只要你不改变这些函数（即接口），你就可以自由修改并更新软件的底层细节，而不会影响（破坏）那些依赖你的代码来构建其应用程序的人的工作：这就是“应用程序编程接口”这一术语的由来。

#### API：一个 LaTeX 宏包类比

当你使用 LaTeX 宏包提供的命令时，可以把这些命令看作一种 API。作为用户，你未必关心这些命令背后的 TeX 和 LaTeX 魔法（也就是宏包代码）：你真正想要的只是使用它们提供的功能。

### 编程语言绑定

我们已经看到，编写/发布一套有用代码的程序员（称为一个 *库*）可以提供一个所谓的应用程序编程接口（一组函数），通过它，使用 *相同* 编程语言的其他程序员可以使用该库（代码集合）。当库开发者和其用户双方都使用 *相同* 编程语言时，这很好，但如果使用 *不同* 编程语言的程序员也想使用那个库，会怎样？例如，你可能会用 Lua 语言编写脚本，但又想使用用例如 C/C++ 等编程语言编写的库。某种程度上，两种不同的编程语言（Lua 和 C/C++）需要能够相互“沟通”。解决这个问题的一种方案就是所谓的 [语言绑定](https://en.wikipedia.org/wiki/Language_binding).

讨论语言绑定的技术细节超出了本文范围，因此我们给出一个简明概述。其本质上是，通过向原始库添加一个合适的附加“层”代码，它就可以与另一种编程语言（例如 Lua）“通信”：这层代码称为一个 *绑定*。它使两种语言能够通过 API 互操作，第二种语言（例如 Lua）的程序员可以借此访问该库提供的功能/服务。

![用于展示语言绑定概念的示意图。](/files/a1aa8ed73ea9bcb3c1163c8f54d047a97297012e)

**图 1**：用于展示语言绑定概念的示意图：使一个用 Lua 编写的程序能够使用用另一种编程语言编写的外部库。正是通过 Lua 绑定，LuaTeX 的内部组件，以及因此 LuaTeX 很大一部分内部排版功能，才得以向用户开放，用来开发复杂排版问题的解决方案。

## LuaTeX：两种编程选择——TeX 和 Lua

从本质上说，LuaTeX 是一个支持两种编程语言的 TeX 引擎：传统的基于 TeX 的语言，以及 Lua 脚本语言。当然，你可以在同一个 TeX 文档中同时使用这两种语言，或者如果你愿意，也可以继续只走纯 TeX 的路线：例如，通过 LaTeX（LuaLaTeX）宏包。TeX（或 LaTeX）并不是一种容易使用或学习的编程语言，很少有人真正掌握了 TeX 的许多怪癖——TeX 中的 [记号](https://www.overleaf.com/blog/522-what-is-a-tex-token) 与展开概念，与大多数人对编程语言的预期和经验都相当陌生。

加入 Lua 使得可以通过一种更易接近且更传统的编程语言来使用基于 TeX 的排版——正如本文开头所指出的，借助 Lua API，你几乎无需任何 TeX 代码就能进行 [复杂排版](http://wiki.luatex.org/index.php/TeX_without_TeX).

### LuaTeX 增加了许多新的原语

每个 TeX 引擎都提供数百个所谓的原语命令：这些是每个单独排版引擎所支持的基于 TeX 语言的基本构建块。Donald Knuth 发布的 TeX 原始版本提供了大约 320 条命令，而较新的 TeX 引擎（pdfTeX、XeTeX 和 LuaTeX）都各自增加了许多新的原语，以便让用户能够使用各引擎附加的特性和功能。LuaTeX 新增的大量原语记录在其 [参考手册](https://www.tug.org/svn/texlive/tags/texlive-2017.1/Master/texmf-dist/doc/luatex/base/luatex.pdf?revision=44591\&view=co).

在 LuaTeX 引入的许多新原语中，有一个叫做 `\directlua{...}` 的原语，它是使用 Lua 代码的入口：通过访问 LuaTeX 引擎内部来构建复杂的排版工具和解决方案。

### \directlua{...}：通往 Lua 编程的入口

如前所述，Lua 脚本语言可以被视为提供了一层“通道”，通过它可以访问 LuaTeX 的基于 TeX 的排版引擎以及构成 LuaTeX 的诸多组件所提供的功能。Lua 语言也是实现 LuaTeX 可扩展性的机制——借助 Lua 加载专门的外部软件/代码库。

总体而言，LuaTeX 提供的 Lua 接口（Lua 基函数集合）被称为其 *Lua API*：它是 LuaTeX 内部引擎/组件与用户文档之间的“通信链路”。

### 一个简单的 \directlua{...} 示例

以下 *极其简单的* 这个示例远不足以触及冰山一角。然而，它确实展示了通过“TeX 方式”和“Lua 方式”访问 TeX 参数之间相互作用的基本思想。

请注意：

* `\hsize` 是一个 TeX 原语（命令），它设置一个决定排版行宽度的内部参数的值——例如，你通常会将其设为一个合适的值，位于一个 `\vbox{...}`. `\hsize` 只是 *许多* 你可以通过 Lua 代码访问和/或修改的 TeX 参数之一。
* 访问 TeX 参数只是 LuaTeX 的 Lua API 中一个 *极其微小的* 方面：还有太多其他内容！

```latex

\documentclass{article}
\begin{document}
\let\\\relax % 重新定义 \\ 的含义，以避免展开问题
这是 {\ttfamily\string\hsize} 的当前值（通过 \LaTeX）：
\the\hsize\par
\directlua{
% 使用 Lua API 获取 \hsize 的当前值
local hs=tex.hsize
% 使用一个 Lua API 函数打印一些
% LaTeX 代码以及 \hsize 的值
tex.print("这是 {\\ttfamily\\string\\hsize} 的值
，由 Lua 代码报告（以缩放点为单位）：")
tex.print(hs.."\\par")
% 使用 Lua API 为 \hsize 设置一个新值
tex.hsize="400pt" % 或使用 tex.hsize=400*65536（以缩放点计）
}%
% 在 \directlua 执行完毕后，请求 LaTeX
% 告诉我们 \hsize 的新值
这是 {\ttfamily\string\hsize} 的值，
由 \LaTeX{} 在 {\tt\string\directlua} 完成后报告：
\the\hsize\par
\end{document}
```

这里有一张图片展示 LuaTeX 排版上述 LaTeX 代码的结果：

![运行 LuaTeX 的结果](/files/35781119e94bb10606c18c58427b3ffa81920717)

请注意， `\let\\\relax` 的 TeX“小技巧”是为了避免 LuaTeX 对 Lua 代码进行“展开”时引发的问题：我们在下文会简要提到这一点。

### 使用 Lua 代码

在你的 TeX/LaTeX 文档中使用 Lua 代码主要有两种方式：

1. **内联**：直接在你的 `.tex` 文档中编写 Lua 代码（如上例所示）；
2. **外部**：将 Lua 代码存放在外部 `.lua` 代码文件中，并使用 Lua 的机制加载并运行它们。

选项（1）最适合较短的 Lua 代码片段。选项（2）用于较大的程序或 Lua 代码库。它有一个明显的优势，就是你可以避开涉及 TeX 所谓的棘手问题 `\catcode` 值（这可能会“相当令人沮丧”）。这些 `\catcode` 问题的原因是，在将 Lua 代码送入 LuaTeX 内置 Lua 解释器之前，它会先经历“展开”。这种展开可能很难理解，因此我们将在后续文章中进一步探讨。

当然，也有一些 LaTeX 宏包可以帮助你在 .tex 文件中使用 Lua 代码——例如，你可以使用 [luacode 宏包](https://ctan.org/pkg/luacode?lang=en).

## 本文总结及第 2 部分介绍

构成 LuaTeX 的软件组件，再加上内嵌的 Lua 脚本语言，为构建能够解决各种复杂排版问题的解决方案提供了强大的组合——也可用于设计能从与基于 TeX 的排版引擎紧密集成中受益的文档制作工作流程。在 [本文第二部分](/latex/zh-cn/shen-ru-wen-zhang/09-an-introduction-to-luatex-part-2-understanding-directlua.md) 我们将深入探讨 LuaTeX 提供的最强大的命令： `\directlua`.

在那之前，祝你 LuaTeX 使用愉快！

## 致谢

作者非常感谢 [Luigi Scarso](https://twitter.com/luigi_scarso)，LuaTeX 的开发者之一，抽出时间阅读了本文的草稿，并提出了许多非常有帮助的意见和建议。文中若仍有任何事实错误或遗漏，当然都由作者负责。此外，我还要感谢 [Patrick Gundlach](https://twitter.com/patrickgundlach)，开发者 [speedata publisher](https://speedata.github.io/publisher/)，感谢他抽出时间回答我的问题。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/zh-cn/shen-ru-wen-zhang/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
