在directlua中传递要由lua函数解析的宏

在directlua中传递要由lua函数解析的宏

我有类似的东西

\directlua{X = "width=0.5*\linewidth"} <-- invalid escape sequence

\directlua{X = "width=0.5*\\linewidth"} <-- Error

! Undefined control sequence.
\\->\let \reserved@e 
                     \relax \let \reserved@f \relax \@ifstar {\let \reserved...

l.254 ...X = "width=0.5*\\linewidth";}

X 在 lua 函数中使用,例如

function doX()
    --X = "width=0.5*\\linewidth"; --works fine
    tex.print("\includegraphics["..X.."]{...}");
end

因此问题不在于函数或我传递的内容,而在于转义问题。这是 catcode 问题吗?基本上,我想将字符串中的 LaTeX 宏传递给 lua,然后这些宏最终被 lua 代码原封不动地吐出,但\l在 Lua 中被解释为转义序列\\,我猜,这对 LaTeX 来说很奇怪。

答案1

\directlua原语在将结果字符串传递给 Lua 之前对其参数进行完全扩展。一般来说,它只应用于小的“片段”或加载单独的专用 Lua 文件

\directlua{dofile("name-of-file")}

因为这样就避免了担心 TeX<-> Lua 问题。

当你使用\directlua除“文本”以外的任何内容时,你必须留意将要发生的 TeX 扩展。

\directlua{X = "width=0.5*\linewidth"}

因为\linewidth不是可扩展标记,所以文字字符串被传递给 Lua。然后它看到\l,正如错误所说,这不是有效的转义序列。

\directlua{X = "width=0.5*\\linewidth"}

你有 TeX 控制序列\\:这通常意味着 LaTeX 中的行尾,并且有一个定义,它将扩展但不是“正确”。因此,你会得到一个奇怪的错误,就像你尝试

\edef\foo{\\}

正确的方法这里是为了确保 Lua 看到价值\linewidth

\directlua{X = "width=0.5*\the\linewidth"}

如果你想在这里进行计算,你需要考虑到这\linewidth是一个维度,所以也许

\directlua{X = "width=\the\dimexpr0.5\linewidth\relax"}

可能会更好。

如果你想让 Lua 返回 TeX 控制序列,你需要将文字放入\\字符串中:这是使用 完成的\noexpand。因此,如果你希望持有X一个字符串以返回 TeX,那么

\directlua{X = "width=0.5*\noexpand\\linewidth"}

是正确的方法。


对于较长的块,可以考虑使用luacode包。它定义了一个环境,在这个环境中进行了一些 catcode 更改,以便“更轻松地”将 Lua 代码直接放入 LaTeX 文档中。有几件事需要注意

  • Catcode 更改和分组使luacode不可扩展
  • 像(几乎)所有 LaTeX 环境一样,luacode是一个 TeX 组,因此 TeX 端的任何定义都需要是全局的才能“转义”

使用luacode一个可能会

\RequirePackage{luacode}
\begin{luacode}
X = "width=0.5*\\linewidth"
\end{luacode}

相关内容