如何将宏参数(#1、#2、..)传递给 Lua 变量

如何将宏参数(#1、#2、..)传递给 Lua 变量

这个问题可能微不足道,但我几个小时前就开始探索 Lua(La)TeX,所以请耐心等待。

MWE 如下:

test.tex

\documentclass{article}
\directlua{require("test.lua")}
\begin{document}
\foo{bar}
\end{document}

test.lua

tex.print("\\newcommand{\\foo}[1]{")
tex.print("\\texttt{#1}")
-- arg = ?? how do I pass #1 to arg ??
-- arg = arg .. " baz"
-- tex.print("\\textit{" .. arg .. "}")
tex.print("}")

我知道我可以将其放入文件\newcommandtex,然后directlua在命令定义中调用,但在我的实际用例中,我循环遍历一个表,其中的键是命令名称,所以我需要保持原样。

编辑:由于我最初的问题可能有点像 XY 问题,因此我在下面发布了我的真实用例。

我的目标是:给定一组由thmtools包定义的定理环境,通过将它们嵌入到环境中来重新定义它们tcolorbox

我开始通过这种方式做事expl3,但很快就感到沮丧,部分原因是我对 LaTeX3 编程方式的无能,部分原因是与其他所有“正常”编程语言(for 循环、if 语句等)相比,用 LaTeX 编程太痛苦了,这就是我开始深入研究 LuaTeX 的原因。

现在来看看代码。我有这张表

boxed_theorems = {
  definition = "definition",
  example = "example",
  lemma = "theorem",
  theorem = "theorem",
  corollary = "theorem",
  proof = "proof",
}

其中的键是环境名称(同样来自 thmtools),值是tcolorbox选项(这里definition,,和example是一堆 tcolorbox 样式。theoremproof

我循环遍历该表(以及通过包含的其余.lua文件\directlua)的方式如下:

tex.print("\\ExplSyntaxOn")

for theorem,tcolorbox_theorem in pairs(boxed_theorems) do
  -- copy <theorem_name> in a new environment inner<theorem_name>
  tex.print("\\let\\inner" .. theorem .. "\\" .. theorem)
  tex.print("\\let\\endinner" .. theorem .. "\\end" .. theorem)

  tex.print("\\RenewDocumentEnvironment{ " .. theorem .. " }{ O{} }{")

  -- I want to be able to call the new environment like this:
  --
  -- \begin{theorem}[name={foo}, label={bar}, tcolorbox={baz}]
  --
  -- where 'name={foo}, label={bar}' is the argument of the
  -- innertheorem and should be assigned to 'theorem_options',
  -- while '{baz}' is an argument of the embedding tcolorbox and
  -- should be assigned to 'tcolorbox_local'.
 
  -- I haven't got that far yet (I need to create a function that
  -- parses #1, hence the original post), so for now they are just
  -- left empty.
  theorem_options = ""
  tcolorbox_local = ""

  -- The rest is pretty self-explanatory
  tex.print("\\begin{tcolorbox}[" .. tcolorbox_theorem .. ","
                                  .. tcolorbox_local .. "]")
  if theorem_options == "" then
    tex.print("\\begin{inner" .. theorem .. "}")
  else
    tex.print("\\begin{inner" .. theorem .. "}[" .. theorem_options .. "]")
  end
  tex.print("}{")
  tex.print("\\end{inner" .. theorem .. "}")
  tex.print("\\end{tcolorbox}")
  tex.print("}")
end

tex.print("\\ExplSyntaxOff")

答案1

我认为在 .tex 文件中设置 LaTeX 宏并将 Lua 代码分组到可以接受和返回参数的函数中更为直接。

例如,test.tex可能如下:

\documentclass{article}
\directlua{require("test.lua")}
\newcommand\foo[1]{\directlua{foo("#1")}}
\begin{document}
\foo{bar}
\end{document}

虽然test.lua可能包含

function foo ( s )
   tex.sprint ( "\\textit{"..s.."}" )
end

答案2

请注意, 积累的字符串 直到 Lua 块完成才会返回到 TeX,因此在作为参数处理的tex.print点处没有 Lua 处于活动状态。因此,要回答您的问题,您需要在该点重新输入 Lua,如下所示。#1bar

这将打印

arg is: barbaz

来自Lua,显示字符串bar被传递给Lua。

并对其进行排版,我认为这就是您想要的输出。

在此处输入图片描述

然而,这几乎肯定不是解决实际用例的最佳方法。

\documentclass{article}
\directlua{require("test.lua")}
\begin{document}
\foo{bar}

\directlua{
texio.write_nl('arg is: ' .. arg .. '\string\n')
}
\end{document}

测试.lua

tex.print("\\newcommand{\\foo}[1]{")
tex.print("\\texttt{#1}")
tex.print("\\directlua{arg='#1' arg = arg .. 'baz' tex.print('\\\\textit{' .. arg .. '}')}")
tex.print("}")

相关内容