对于 TeX 实现来说,Lua 与其他脚本语言相比有哪些优势?

对于 TeX 实现来说,Lua 与其他脚本语言相比有哪些优势?

这个问题的灵感来自马丁·施罗德对我是 TeX 新手。我应该使用 LaTeX、XeLaTeX 等吗?以及我之前在这个论坛上提出的两个问题:

  1. 自动文档更新
  2. 使用 Python Cheetah 生成 LaTeX 真值表

回想起来,我真的很惊讶没有 LuaTeX 用户回答我的问题,因为在我看来,通过在 LuaTeX 中将 Lua 脚本嵌入到 LaTeX 代码中,这很容易实现。这真的可以做到吗(仅针对 LuaTeX 用户的问题)?这容易吗?

我的第二个问题是由于,如果我已经了解 Python(如果你愿意,你可以用 Perl 代替)只是为了使用 TeX,我非常讨厌学习另一种脚本/通用编程语言(Lua)。是否有人为 TeX 制作 Python 接口,简称为 PythonTeX(PerlTeX 确实存在)?据我所知,PythonTeX 并不存在。有一种叫做PyTeX但它看起来只是一个为那些想使用 Python 语法输入 TeX 文档的人准备的工具。

与 Python 相比,使用 Lua 作为 TeX 的嵌入式脚本语言是否有优势(除了开始使用 LuaTeX 的人可能更熟悉 Lua 这一事实之外)?

答案1

LuaTeX 的开发人员在他们的主页

嵌入解释器是一回事,而且对于 Python 来说显然没什么意思。另一件事是让 TeX 的内部结构对嵌入解释器可见。虽然很多通信代码可能以某种方式从 LuaTeX 改编为 PythonTeX,但这仍然需要大量工作。

更好的方法可能是稍微作弊,简单地搭载 LuaTeX 解释器。有一个名为“嵌入”Python 的 Lua 桥疯狂蟒蛇,也许还可以让它与 LuaTeX 配合使用。但是,使用 XML-RPC 可能更简单:让 LuaTeX 生成一个 Python 进程,充当 XML-RPC 服务器。然后 LuaTeX 命令可以调用 Python 进程。附加功能:一旦在 LuaTeX 端实现此功能,它就可以与任何其他脚本语言一起使用,而不仅仅是 Python。

答案2

我从去年 5 月开始编写“PythonTeX”,计划在下周末到 3 月初之间发布第一个公开版本。我实际上打算将其命名为 PythonTeX,类似于 PerlTeX 和 SageTeX。

我创建了一个 LaTeX 包和随附的 Python 脚本,它们提供了 python.sty、SageTeX 和 SympyTeX 的大部分功能,但更注重速度和可用性。以下是 PythonTeX 将带来什么的简要概述。

  • 命令和环境之间的持久性。例如,每个环境\begin{pythoncode} ... \end{pythoncode}都会从上一个中断的地方继续,因此所有变量、函数等都会保留下来。您可以选择命名命令和环境,然后只有同名的命令和环境之间才会保留。例如,\begin{pythoncode}[name] ... \end{pythoncode}只与名为 的其他命令和环境共享持久性name

  • 自动包含印刷内容。例如,

    \begin{pythoncode}
    print(1+1)
    \end{pythoncode}
    

    2在编译后的文档中会自动替换为。

  • 速度。使用 Python 的多处理包,每组命名的命令和环境都在其自己的进程中执行。此外,每组都经过哈希处理,因此代码仅在更改时才执行。运行代码的结果会被保存,并在未检测到更改时重新使用。

  • 代码排版。所有执行的代码都可以使用 fancyvrb 及其内部函数进行排版。也可以选择使用 Pygments 排版代码,Pygments 是一个可以进行语法高亮的 Python 包(minted 包使用 Pygments)。使用 Pygments 时,所有代码都会被散列,排版结果也会保存,因此在后续运行中,只有更改的代码才需要由 Pygments 处理。这有助于防止 Pygments 减慢速度。

  • 有意义的错误消息。所有错误消息都由代码解析,该代码确定发生错误的文档行(而不是实际执行的 *.py 文件的行)。因此,您可以准确地知道文档中哪里出了问题。

  • 最少文件。代码会自行清理,因此 Python 创建的永久文件数量将保持在最低限度,并且每次运行后都会删除所有临时文件。

PythonTeX 发布后我就可以发布链接。我还将在首次公开发布后不久将其提交给 CTAN。

答案3

以下是通过 JSON-RPC 从 LuaTeX 调用持久 Python 进程的一种方法。1)

所需设置:

  1. 下载并安装jsonrpclib. 这提供了 Python 服务器。

  2. 下载 Lua json-rpc 客户端。我改编了在网上找到的一些 Lua 模块,然后将它们压缩并放在我的服务器. 解压到此答案中指定的目录之一: “Lua 树”(texmf 树的类似物)

现在,我们可以编写一个公开一些功能的 Python 服务器:

import sys
from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer

server = SimpleJSONRPCServer(('localhost', 8080))

server.register_function(lambda: "Hello from Python!", 'ping')
server.register_function(lambda *args: sum(args), 'add')

# the counter generator shows that the server can be used
# to preserve state between requests, and even across multiple
# LaTeX compiler runs (which we may not want)
counter = iter(xrange(sys.maxint))
server.register_function(lambda: counter.next(), 'count')

server.serve_forever()

将其保存为testserver.py并运行。

以下是展示如何调用服务器的测试文档:

\documentclass{article}

\directlua{ % make the running python server available as a proxy
    require "jsonrpc"
    pythonserver = jsonrpc.proxy("http://localhost:8080")
}

\newcommand{\python}[2][]{\directlua{%
    result = pythonserver.#2(#1)
    tex.print(result)
}}

\begin{document}

\python{ping}

The sum of 1,2,3,4,5,6,2,4,5,6 is \python[1,2,3,4,5,6,2,4,5,6]{add}

\directlua{%
    for x=0,100,1 do
        result = pythonserver.count()
        tex.print(result)
    end
}

\end{document}

回答关于如何实现 pythontex 的原始问题,现在所需的只是一个 shell 脚本,该脚本首先启动服务器,然后调用 LuaTeX,然后再次关闭服务器。这留给读者练习 ;)

1) 我之所以使用 JSON-RPC 而不是 XML-RPC,是因为我找不到只支持 Lua 的 XML-RPC 客户端;我找到的那个客户端使用 C 扩展库,而我却不知道如何将其加载到 LuaTeX 中(脸红)。JSON-RPC 模块更简单,经过一番努力(就我而言)后,我终于说服它合作了。也许有一天我也能弄清楚如何让 XML-RPC 也能工作。

答案4

实际上,将 Python 代码转换为(纯)TeX 代码的一个好方法是:

  1. 对于排版工作(方框、粘连和惩罚),仅使用 TeX;
  2. 对于计算、数据库接口等,您可以构建 Python 模块,然后通过 TeX 程序调用这些模块\write18。Python 模块必须将输出保留到文件中,然后通过常规方式读取这些文件\newread,然后将其用于 TeX 代码。此解决方案在 Linux 上效果最佳,因为 Linux 上原生安装了 Python。

作为示例,尝试以下操作:按如下方式准备模块“adder.py”:

#!/usr/bin/env python
# file 'adder.py'

import sys

def save(data):
    tempFile = open("temp.dat","w")
    tempFile.write(str(data))
    tempFile.close()

def double(x):
    result = x * 2
    save(result)


if __name__ == "__main__":
    n = int(sys.argv[1])
    double(n)
    sys.exit

现在,在同一个目录中,您可以输入这样的 TeX 文件:

% file `doubler.tex'
\newread\tempfile
%
\def\double#1{%
    \immediate\write18{python adder.py #1}\relax
    \immediate\openin\tempfile=temp.dat
    \read\tempfile to \var
    \var}%
%
Double 2 is \double2\par
Double 3 is \double3\par
Double 4 is \double4\par
Double 5 is \double5\par
Double 6 is \double6\par
\bye

这个 TeX 文件必须用 shell-escape 进行编译,例如:

tex -shell-escape doubler

pdftex -shell-escape doubler

xetex -shell-escape doubler

相关内容