I need to determine if a TeX macro is already defined or not via a Lua function. Any ideas?
function IsTeXMacroDefined(macroname)
if defined(macroname) then return true end
return false
end
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It only takes a minute to sign up.
Sign up to join this communityI don't know how robust it is but the following seems to work.
\documentclass{standalone}
\def\test{}
\begin{document}
\directlua{%
function is_defined(s)
local undef = 'undefined_cs'
if token.command_name(token.create(s)) == undef then
return false
else
return true
end
end
if is_defined('test') then tex.sprint('test is defined\noexpand\\par') else
tex.sprint('test is not defined\noexpand\\par') end
if is_defined('testa') then tex.sprint('testa is defined\noexpand\\par') else
tex.sprint('testa is not defined\noexpand\\par') end}
\end{document}
Updated
I added a TeX
wrapper. It takes as an argument the name of the control sequence to be tested or the control sequence itself (this is done by removing the backslash at lua level with the help of lpeg
). The TeX
wrapper uses the expandability of \directlua
to define on the fly a TeX
\iftrue
or \iffalse
statement inside a \csname
.
As pointed out in comments, one should always write lua code in a separate lua file.
First the lua file (save it as is_def.lua
).
local lpeg = require('lpeg')
local P, C, Cs, V, match = lpeg.P, lpeg.C, lpeg.Cs, lpeg.V, lpeg.match
function is_cs_defined (s)
s = match(Cs(P({(C('\\') / '' + 1) * V(1) + true})),s)
local undef = 'undefined_cs'
return not(token.command_name(token.create(s)) == undef)
end
Then the .tex
file.
\documentclass{standalone}
\directlua{dofile('is_def.lua')}
\def\iscsdefined#1{%
\texttt{\string#1}
\csname if\directlua{if is_cs_defined('\luatexluaescapestring{#1}')
then tex.sprint('true') else tex.sprint('false') end}\endcsname
is defined
\else
is not defined
\fi}
\def\test{}
\begin{document}
\iscsdefined{test}
\iscsdefined{\test}
\iscsdefined{testa}
\end{document}
\\par
for the example to work though.
token.get_macro
and/or token.get_meaning
Feb 23, 2018 at 2:34