概括

概括

我对 LuaTeX 完全陌生,对此我有几个问题。首先,我了解到在 LuaTeX 中可以使用“token filter”回调跟踪所有 TeX 标记。是否可以在回调函数中获取一些其他信息,例如输入文件中的当前位置和当前组级别。我要做的是编写如下所示的回调函数:

\directlua{
  function foo ()
    t = token.get_next()
    if someTestFunction(t) then
       poz = currentPositionTexEyesAreLookingAtSourceFile()
       level = currentGroupLevel()
       mode = isMathMode()
       table.insert(someTable, {poz, level, mode})
    end
  end
  callback.register('token_filter',foo)
}

答案1

是的,所有这些项目都可以在回调中获取token_filter 。不过,其中一些项目需要一些准备。

概括

为了回答你的问题的各个部分:

  • token_filter您可以使用和库的组合来“跟踪”经过 TeX 的所有标记token。但是,由于这意味着每个标记至少要调用一次 C API,因此效率也相当低。我怀疑这种方法\tracingall在实用性方面是否胜出,因此无论您真正想要实现什么,它可能都不是最初想要的。

  • tex.currentgrouplevel可以使用与 eTeX 原语相对应的 寄存器来查询当前嵌套深度 \currentgrouplevel

  • 为了测试数学模式,tex.nest必须访问 TeX 的内部嵌套堆栈 ( )。 tex.nest.ptr包含堆栈指针,以便 tex.nest [tex.nest.ptr]返回堆栈顶部(当前状态)。如果字段mathstyle为非负数,则我们实际上处于数学模式。此外,可以通过检查字段是否mode为负数来区分内联和显示数学。(理论上,mode仅凭字段就足以检测数学模式——\ifmmode就是这样实现的——但参考中给出的值似乎不正确。无论如何,请咨询 来源 了解更多详情。

  • 跟踪输入文件和行号需要付出更多努力。由于这种信息不能通过引擎直接获得,因此我们必须自己管理。幸运的是,Luatex 提供了所有必要的先决条件:要跟踪主输入文件中的行,您可以使用回调 process_input_buffer。此外,由于open_read_line回调,您可以精确控制 TeX 文件的读取方式。(使用启动脚本时,后者本身就足够了。不过,我没有测试过。)

例子

以下是结合以上所有内容的演示: https://gist.github.com/phi-gamma/6745931。结果是一个包含有关收集到的代币信息的表格:

排版结果

TeX 文件定义了几个用户级宏。前两个控制回调状态:

\enabletokenpos [<number>]  %% enable position tracking
\disabletokenpos            %% disable

主文件的行数将从以下行开始计算: \enabletokenpos发生该行开始计算。它需要一个强制的论点,即当前行号据我所知,除非使用单独的初始化脚本(超出了当前问题的范围),否则无法自动确定该点的输入线。

然后有用于访问当前状态的宏:

\printcurrentfile      %% name of the file being read
\printcurrentpos       %% position in the file being read
\printcurrentfilepos   %% name and position in the customary “<name>:<line>” format

显然,回调必须到位才能使它们工作。

跟踪通过这些宏进行控制:

\collecttoken          %% add a single token to the tracing table
\startcollecttokens    %% start adding tokens (environment)
\stopcollecttokens     %% stop adding tokens

使用环境时要小心:由于多级扩展,它会很快炸毁结果表。不过,它足够聪明,不会将自己包含在内。

最后,为了输出令牌集合的内容,您需要另一个宏:

\collectedtokens

它建立一个简单的表格并将其打印在文档中。

笔记

跟踪文件仅限于输入(即 TeX)文件。在 TeX 运行期间触及的其他文件(Lua 代码、位图、编码等)不受影响。该表file_stack有助于跟踪各个文件内的行号。process_input_bufferopen_read_file回调均被使用。这对于实现正确的行数是必要的,因为当前实现允许在处理文档时加载 Lua 代码。如上所述,应该可以通过open_read_line在打开主输入之前使用初始化脚本安装过滤器来避免这种情况。

挂接到的函数token_filter有两种变体: grabtoken()将使用单个标记,将其添加到集合中,然后从回调中移除自身。 grabtokens()(复数)基本上是相同的函数,但它将保留在原处,直到通过调用将其禁用stopcollecting()。 作为一个好东西,它将在遇到控制序列后避免收集任何标记,\stopcollecttokens以免我们用不需要的项目污染集合。

令牌以具有以下键的表形式添加:

  • filename遇到该标记的输入文件的名称;

  • position该输入文件的行号;

  • grouplevel的价值tex.currentgrouplevel;

  • mathmode如果在显示数学中遇到则为正数,如果在内联数学中遇到则为负数,错误的否则;

  • csname相关的控制序列(如果适用);

  • token返回的标记表token.get_next();值的含义在参考中进行了解释。

例如\input如下所示:

{
  ["csname"]="input",
  ["file"]="tokenposition.tex",
  ["grouplevel"]=2,
  ["mathmode"]=false,
  ["position"]=32,
  ["token"]={ 119, 0, 3360 },
},

相关内容