So you've defined
\newcommand{\drawaxes}{%
\directlua{%
tex.sprint("\draw[thick,red] (-1,0) -- (1,0)")
}
}
Later, when TeX encounters \drawaxes, it replaces it with
\directlua {tex.sprint("\draw [thick,red] (-1,0) -- (1,0)") }
and goes to work again. It now encounters \directlua. If you look up the documentation of the \directlua primitive in the LuaTeX manual, it says:
The primitive \directlua is used to execute Lua code immediately. The syntax is
\directlua ⟨general text⟩
\directlua ⟨16-bit number⟩ ⟨general text⟩
The ⟨general text⟩ is expanded fully, and then fed into the Lua interpreter. …
So TeX takes the sequence of tokens tex.sprint("\draw [thick,red] (-1,0) -- (1,0)") and starts expanding it. Each token up to tex.sprint(" remains as it is (does not expand), but the \draw expands to \path [draw]. And \path expands to
\let \tikz@signal@path=\tikz@signal@path \pgfutil@ifnextchar [{\tikz@check@earg }{\pgfutil@ifnextchar <{\tikz@doopt }{\tikz@@command@path }}
in which \tikz@signal@path is defined as a macro that expands to… \tikz@signal@path, itself! By the time you interrupt, TeX is still repeatedly expanding \tikz@signal@path.
If you like, you could see all this if you add something like \errorcontextlines=100 in your .tex file, to see more context in the error message than you saw:
! Interruption.
\path ->\let \tikz@signal@path
=\tikz@signal@path \pgfutil@ifnextchar [{\tikz@check@earg }{\pgfutil@ifnextchar <{\tikz@doopt }{\tikz@@command@path }}
\draw ->\path
[draw]
\drawaxes ->\directlua {tex.sprint("\draw
[thick,red] (-1,0) -- (1,0)") }
l.16 \drawaxes
;
?
(The convention is that in each pair of lines, the first line is everything that TeX has read, and the second line is what is yet to come. It's a dump of TeX's internal input stack.)
Add \tracingmacros=1 \tracingonline=1 to see TeX working hard.
You can reproduce this error without LuaTeX, with a document like:
\documentclass{standalone}
\usepackage{tikz}
\makeatletter
\edef\haha{\tikz@signal@path}
on any other engine (pdfTeX or XeTeX) too.
(I don't know why \tikz@signal@path is defined to expand to itself; it's come up before.)
Anyway, the solution is to make sure that \directlua gets the actual Lua code you want. There are some tricks with TeX macros, but the easiest is to put as much Lua code as possible in a separate file. (My rule of thumb is: the contents of \directlua{...} should contain only alphanumeric characters, (), and single quotes.)
For example, put the following in draw.lua:
function drawaxes()
tex.sprint([[ \draw[thick,red] (-1,0) -- (1,0) ]])
end
(note the [[ ... ]] to treat the string literally, without having to escape backslashes)
and your .tex file can be:
\documentclass{standalone}
\usepackage{luatex85}
\usepackage{tikz}
\directlua{dofile('draw.lua')}
\newcommand{\drawaxes}{\directlua{drawline()}}
\begin{document}
\begin{tikzpicture}
\drawaxes;
\end{tikzpicture}
\end{document}
(Or you could put just the tex.sprint line in the draw.lua file and have
\newcommand{\drawaxes}{\directlua{dofile('draw.lua')}}
but I imagine you'd like to put multiple functions in the same file.)
\directluatries to fully expand its argument and\drawgets so expanded at the wrong time. – egreg Mar 02 '18 at 23:18