接下来lualatex MWE\newcommand\mySection{\section}
在lua端进行模拟。
% !TEX TS-program = lualatex
\documentclass{article}
\begin{document}
\directlua{
token.set_macro('mySection', '\\section')
}
\mySection{bar}
\end{document}
如何模拟\let\mySection\section
?
穷人的解决方案就像
\directlua{
token.set_macro(catcodetable, 'mySection', token.get_macro('section'))
}
catcodetable
只要正确设置,最终就会起作用,但如何操作呢?
答案1
一般来说你不能。tex.set_macro
是唯一允许从 Lua 分配 TeX 宏的 Lua 函数,并且它相当有限:不可能使用它来定义带有参数的宏,并且它不允许您定义包含具有不同 catcode 的相同字符的宏。
因此,从 Lua 执行等效操作的唯一可靠方法\let
是将\let\newname\oldname
(或等效标记)传回 TeX 并让 TeX 执行它。
即使您想将自己限制为具有一致 catcode 的无参数宏,您token.get_macro
也无法告诉您有关 catcode 的任何信息。因此,确定宏中使用的 catcode 的唯一方法是再次将其传回 TeX,在那里展开它,然后读回标记。
答案2
仅作为演示如何在 LuaTeX 中完成任务(可扩展!)
当然它仍然涉及将东西传递给 TeX 来执行。
%! TEX program = lualatex
\documentclass{article}
\begin{document}
% define some macros here.
% NOTE \a and \b should not be redefined in normal code
\def\a{123}
\def\b{456}
% the old value of \a is 123
\directlua{print("========", token.get_macro("a"))}
\edef\c{
\directlua{
--[[ the old value is 123 (use this comment style because new lines are stripped, this is directlua not luacode environment ]]
print(token.get_macro("a"))
--[[ create a table of tokens with content \let\a\b. Can use token.create as well ]]
local tokens=token.scan_toks(false, false)
--[[ run it ]]
tex.runtoks(function()
tex.sprint(tokens)
end)
--[[ look, the macro content really changed ]]
print(token.get_macro("a"))
}{\let\a\b}
}
% and outside too
\directlua{print(token.get_macro("a"))}
\end{document}
LuaTeX 文档中关于此代码的一些注释:
runtoks
您必须确保 TEX 最后处于正常状态,而这并不总是那么简单。
关于扫描令牌的一般信息
在扫描下一个标记时,您需要记住,我们的扫描方式与 TeX 不同:扩展、更改模式并随心所欲地执行操作。使用 Lua 进行扫描时,我们只会拾取标记。
\beginlocalcontrol
或者从中复制宏的定义https://tex.stackexchange.com/a/628874/250119我们可以做以下事情:
%! TEX program = lualatex
\documentclass{article}
\newluafunction\beginlocalcontrol
\directlua{lua.get_functions_table()[\the\allocationnumber] = function() return tex.runtoks(token.get_next) end} % define its meaning
\luadef\beginlocalcontrol\allocationnumber
\begin{document}
% define some macros here.
% NOTE \a and \b should not be redefined in normal code
\def\a{123}
\def\b{456}
% the old value of \a is 123
\directlua{print("========", token.get_macro("a"))}
\edef\c{
\beginlocalcontrol\let\a\b\endlocalcontrol
}
% the macro content changed
\directlua{print("======== changed", token.get_macro("a"))}
\end{document}
\newluafunction
作为使用/ 的替代方法\allocationnumber
,可以使用#lft+1
如下方法
1
2
3
但是在 Lua 5.2 中,当分配非连续时,存在未定义行为的风险(但实际上不太可能发生)