# How to raise a LaTeX warning from within Lua code?

I want to raise a warning from within Lua code. With advice from the LuaTeX wiki and LaTeX 2𝜀 for class and package writers, I arrived at the following (working) solution:

\documentclass{article}
\begin{document}
Foo
\directlua{
myvar = "\noexpand\\PackageWarning{mypackage}{Hello, I am a warning.}"
tex.print(myvar)
}
\end{document}


This seems unnecessarily complex, considering that raising an error is as easy as:

\directlua{
tex.error("Hi, I'm an error!")
}


While I'm aware that tex.error is a generic TeX error and the warning I'm producing is a package-specific warning, I still think for both generic LaTeX warnings (if that exists?) and package-specific warnings (as well as package-specific errors, probably), there should be an easier way. Is there one?

-
@cyberSingularity: Indeed, I wasn't sure whether that was a TeX or LaTeX thing. I edited my question, please let me know if there are still any imprecise statements in it. –  doncherry Nov 10 '12 at 22:01
tex.print("\noexpand\\PackageWarning{pack}{Text}") seems easier. –  egreg Nov 10 '12 at 22:04
@cyberSingularity Better yet, tex.print([[\unexpanded{\PackageWarning{pack}{Text}}]]) so that macros in Text will be expanded only on the TeX side. –  egreg Nov 10 '12 at 22:13
@doncherry The warning mechanism in LaTeX uses \write on an output string that is never open, so by rule the contents is written both to the terminal and in the log file. –  egreg Nov 10 '12 at 22:15
@cyberSingularity My last comment was just to explain how LaTeX treats warnings. What about tex.iowrite? My knowledge of Lua is rather primitive, so I can't see if and how it could help. –  egreg Nov 10 '12 at 22:27

Someone who is more familiar with Lua will almost certainly have better ideas...

egreg's idea from the comments makes things slightly easier: consider using the [[...]] string syntax so you don't need to escape the string (but there will still be issues if the string itself contains a ]] etc), and use eTeX's \unexpanded so you don't need to worry so much about putting \noexpand everywhere. See also some of the suggestions about \directlua on a different question.

As I previously mentioned in a comment, bypassing/emulating the LaTeX commands for this is probably not a good idea. LaTeX's commands for this are slightly more complicated than you might first think, and might get patched/hooked into. Even rewriting LaTeX in Lua (replacing eg \PackageWarning with something that invokes a Lua script/function) wouldn't necessarily help in the latter situation.

I think the best you could do would be to write your own Lua function that invokes LaTeX's \PackageWarning, taking care to escape parameters etc as appropriate. (Sorry, I'm not proficient enough to attempt that.)

Compare the terminal output from the following:

\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}


I have used "term and log" here because (as egreg explained), LaTeX normally writes to an \@unused stream that is never open, so the output appears both on the terminal and in the log file.

The output is

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.


Note also that the line numbers from the Lua version are wrong, even when the real \PackageWarning command is invoked.

For reference, some relevant definitions from 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}%
}

-
From what I see, texio.write is quite similar to TeX's \message –  egreg Nov 10 '12 at 23:38
@egreg: Agreed, though the LuaTeX reference manual doesn't make that comparison so they may behave differently in some ways... –  cyberSingularity Nov 10 '12 at 23:48
With term and log it is the same as \message; with log it's the same as \wlog; it has no counterpart with term. –  egreg Nov 10 '12 at 23:54