# Create macros inside Lua block

How can I create a macro (re)definition directly inside a LuaTeX block?

e.g.,

\directlua{tex.print("\\mymacro{test}")}


would be the same as

\mymacro{test}


in TeX?

• You're missing \noexpand before \\  (and I'm pretty sure to have seen a similar question in the past --- no time to hunt for it, though). – Bruno Le Floch Mar 17 '12 at 23:04
• Thanks, I thought I tried that as I saw an example somewhere too but it didn't work. I think I put the noexpand in the wrong place. It should be tex.print("\noexpand\\mymacro{test}") – Uiy Mar 17 '12 at 23:12
• I tried it both with and without the \noexpand in ConTeXt, and it seems to work equally well. Am I missing something? – Esteis Mar 17 '12 at 23:22
• @Eris Ok, see my updated post on how to define and call a TeX macro in lua. See if you can reproduce those without using noexpand. – Uiy Mar 17 '12 at 23:38
• @Esteis: In ConTeXt, inside a luacode environment, \\  is unexpandable. In LaTeX, if you don't use any package, \\  is not redefined inside \directlua, so a \noexpand is needed to ensure that Lua sees \\ . – Aditya Mar 17 '12 at 23:46

While the other explanations are correct, I strongly suggest to use another way. Don't write any code in \directlua, except for a call to another file. See my lengthy answer at https://tex.stackexchange.com/a/33102/243

That way you can write tex.print("\\mymacro{test}") in your Lua file and TeX won't see it and thus you don't need to protect the string.

• It definitely is easier and better and I've started doing this simply because I get better error message locations and it is easier to maintain. I still like to use directlua for testing simple things. I guess I could make a "main" function in a separate file and call that from latex. The biggest problem I have is having to switch between files. (write in lua file, save, switch to latex file, compile... doesn't seem like much but those few tens of seconds add up) – Uiy Mar 21 '12 at 12:14

If I understand you and your example correctly, you want to (1) define a macro yourself in TeX; (2) generate some TeX code from LuaTeX that includes a call to your macro; (3) you want that TeX code to be expanded (evaluated). Something like this? (ConTeXt code.)

% Define the macro we're going to use
\def\betweenXY#1%
{ X#1Y }

% Either print the backslash directly (don't forget to escape it!) (options 1 and 3)
% or use the fact that any macro you define ends up in the context (option 2)
% namespace in LuaTeX
\startluacode
tex.print('\\betweenXY{jolly}')  % option 1
context.betweenXY('swagman')     % option 2
\stopluacode
\directlua{tex.print('\\betweenXY{swagman}')} % option 3

• I'm not sure if this works or not but as Bruno pointed out you have to not expand the macro(I guess luatex is expanding the macro inline instead of just passing it as text). The context I didn't know about and that is helpful as it is something I'll have to learn about eventually. – Uiy Mar 17 '12 at 23:22
• This works; I tested it. Can't see any behaviour change with the \noexpand. \directlua{print('\\betweenXY{camped}')} and \directlua{print('\noexpand\\betweenXY{camped}')} both print this to stdout: \betweenXY{camped}. – Esteis Mar 17 '12 at 23:52

Bruno answered this but here is the corrected code:

\def\mymacro#1{--#1--}
\directlua{tex.print("\noexpand\\mymacro{test}")}


The Lua code will call \mymacro with test as an argument.

The following code

\def\mymacro#1{-#1}
\mymacro{test}


is equivalent to

\directlua{tex.print("\noexpand\\def\noexpand\\mymacro\#1{-\#1-}")} % Same as using \def\mymacro#1{-#1-} in TeX
\directlua{tex.print("\noexpand\\mymacro{test}")} % Same as using \mymacro{test} in TeX
`

It seems one must use \noexpand on all TeX macros to prevent TeX from interpreting them(basically to use them as a text string. If not, TeX will see \def in the above string and try to define a macro instead of passing \def to the tex.print function.