自动修复 catcode 输出

自动修复 catcode 输出

使用以下宏重新定义 lua 块的 catcode,使 tex 文件内部的 lua 编程更加自然,但存在缺陷:

\def\lua{%
  \bgroup
  \catcode`\\=12
  \catcode`\{=12
  \catcode`\}=12
  \catcode`\^^M=12
  \catcode`\#=12
  \catcode`\~=12
  \catcode`\%=12
  \catcode`\_=12
  \catcode`\@=12
  \doluacode
}

\bgroup
\catcode`\|=0
\catcode`\^^M=12 %
\catcode`\\=12 %
|long|gdef|doluacode#1^^M#2\endlua{|directlua{#2}|egroup}%
|egroup

因为它重新定义了代码,所以它也会重新定义 tex.print 输出的代码。以下代码将失败

\lua
    tex.print("\\mymacro")
\endlua

因为\被解释为 catcode 为 12。

有什么方法可以让 tex.print 恢复使用原始 tex catcodes,这样打印 tex 内容就可以了没有必须手动重新定义每个字符(当您在 lua 中以编程方式生成 tex 代码时这显然不起作用)。

也就是说,我只想简单地运行上面的代码并进行少量修改并使其正常工作,而不必执行诸如 tex.print(0, "\") tex.print("mymacro") 之类的操作,这对于以编程方式生成的 tex 再次不起作用。

我所拥有的唯一方法是创建一个新的打印函数,扫描字符串并转换 cat 代码,但希望有更好的方法?

答案1

ConTeXt 提供\startluacode\stopluacode宏,它们提供的功能与您的\lua...\endlua宏相同。这两个宏之间的主要区别在于,ConTeXt 宏在调用之前会切换到正常的 catcode \direclua。以下代码是从luat-ini.mkiv

%D A few more goodies:

\unexpanded\def\startlua    {\luat_start_lua     } \let\stoplua    \relax % tex catcodes
\unexpanded\def\startluacode{\luat_start_lua_code} \let\stopluacode\relax % lua catcodes

% It might makes sense to have a \type {\directelua} so that we can avoid
% the \type {\normalexpanded} around \type {\directlua}. Something to discuss
% in the team.

\def\luat_start_lua
  {\begingroup
   \obeylualines
   \luat_start_lua_indeed}

\def\luat_start_lua_indeed#1\stoplua
  {\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}

\def\luat_start_lua_code
  {\begingroup
   \obeylualines
   \obeyluatokens
   \luat_start_lua_code_indeed}

\def\luat_start_lua_code_indeed#1\stopluacode
  {\normalexpanded{\endgroup\noexpand\directlua\zerocount{#1}}}

其中\obeylualines等于\relax(从以前的定义中遗留下来的?)并且\obeyluatokens定义为

\appendtoks
   \let\\\lualetterbackslash
   \let\|\lualetterbar       \let\-\lualetterdash
   \let\(\lualetterlparent   \let\)\lualetterrparent
   \let\{\lualetterlbrace    \let\}\lualetterrbrace
   \let\'\lualettersquote    \let\"\lualetterdquote
   \let\n\lualettern         \let\r\lualetterr
   \let\f\lualetterf         \let\t\lualettert
   \let\a\lualettera         \let\b\lualetterb
   \let\v\lualetterv         \let\s\lualetters
   \let\1\lualetterone       \let\2\lualettertwo
   \let\3\lualetterthree     \let\4\lualetterfour
   \let\5\lualetterfive      \let\6\lualettersix
   \let\7\lualetterseven     \let\8\lualettereight
   \let\9\lualetternine      \let\0\lualetterzero
\to \everyluacode

\def\obeyluatokens
  {\setcatcodetable\luacatcodes
   \the\everyluacode}

答案2

请参阅我的回答我应该将哪个 Lua 环境与 LuaTeX(LuaLaTeX)一起使用?。精髓在于:不要用于\directlua编写 Lua 代码。为什么?因为你遇到了你遇到的问题和其他一些问题(例如错误消息上的行号)。你可以查看软件包luacode以了解如何正确执行 catcode,但如果你只是想编写 Lua 代码,那就没有必要了。

答案3

通过使用\beginblock包装 catcode 并\endblock在实际传递给 lua 之前恢复它们。允许参数\lua由 catcode 修复,但由于\endblock发生在\directlua调用之前,因此 catcode 被恢复,因此 lua 代码的输出使用原始 catcode。

% defines a \lua ... \endlua block for executing luacode
\def\lua{%
  %\directlua{print("\noexpand\n")}% Print out a new line character each time a new lua block is used to force starting on a new line(else it may not)
  \bgroup
  \begingroup
  \catcode`\\=12
  \catcode`\{=12
  \catcode`\}=12
  \catcode`\^^M=12
  \catcode`\#=12
  \catcode`\~=12
  \catcode`\%=12
  \catcode`\_=12
  \catcode`\@=12
  \catcode`\|=0
  \doluacode
}

\bgroup
\catcode`\|=0
\catcode`\^^M=12 %
\catcode`\\=12 %
|long|gdef|doluacode#1^^M#2\endlua{|endgroup|directlua{#2}|egroup}%
|egroup

相关内容