答案1
更熟悉 Lua 的人几乎肯定会有更好的想法……
评论中 egreg 的想法让事情变得稍微简单一些:考虑使用[[...]]
字符串语法,这样你就不需要转义字符串(但如果字符串本身包含]]
等,仍然会出现问题),并使用 eTeX,\unexpanded
这样你就不必太担心到处放置\noexpand
。另请参阅一些\directlua
关于另一个问题的建议。
正如我之前在评论中提到的,绕过/模拟 LaTeX 命令可能不是一个好主意。LaTeX 的命令比您最初想象的要复杂一些,并且可能会被修补/挂入。即使在 Lua 中重写 LaTeX(例如用\PackageWarning
调用 Lua 脚本/函数的东西替换)也不一定有助于后一种情况。
我认为你能做的最好的事情就是编写自己的 Lua 函数来调用 LaTeX 的\PackageWarning
,注意适当地转义参数等。(抱歉,我没有足够的能力去尝试这一点。)
比较以下终端输出:
\documentclass{article}
\PackageWarningNoLine{mypackage}{Hello, I am a warning}
\PackageWarning{mypackage}{Hello, I am a warning}
\directlua{
texio.write_nl("term and log", [[\unexpanded{Package mypackage Warning: Hello, I am a warning.}]]);
tex.print([[\unexpanded{\PackageWarning{mypackage}{Hello, I am a warning}}]]);
}
\begin{document}
\end{document}
我在这里使用是"term and log"
因为(正如 egreg 解释的),LaTeX 通常会写入\@unused
从未打开的流,因此输出同时出现在终端和日志文件中。
输出为
Package mypackage Warning: Hello, I am a warning.
Package mypackage Warning: Hello, I am a warning on input line 3.
Package mypackage Warning: Hello, I am a warning.
Package mypackage Warning: Hello, I am a warning on input line 1.
\PackageWarning
还要注意,即使调用真实命令,Lua 版本的行号也是错误的。
作为参考,一些相关定义来自latex.ltx
:
\def\set@display@protect{\let\protect\string}
\def\@spaces{\space\space\space\space}
\ifnum\inputlineno=\m@ne
\let\on@line\@empty
\else
\def\on@line{ on input line \the\inputlineno}
\fi
\DeclareRobustCommand{\GenericWarning}[2]{%
\begingroup
\def\MessageBreak{^^J#1}%
\set@display@protect
\immediate\write\@unused{^^J#2\on@line.^^J}%
\endgroup
}
\def\PackageWarning#1#2{%
\GenericWarning{%
(#1)\@spaces\@spaces\@spaces\@spaces
}{%
Package #1 Warning: #2%
}%
}
\def\PackageWarningNoLine#1#2{%
\PackageWarning{#1}{#2\@gobble}%
}