Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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
share|improve this question
add comment

1 Answer

up vote 9 down vote accepted

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

enter image description here

share|improve this answer
    
Thanks. This will probably work good enough. You'll need to use no expand on the \\par for the example to work though. –  Uiy Apr 10 '12 at 12:21
    
... Or better put it into a Lua file :-) –  topskip Apr 10 '12 at 14:03
    
Thanks for your comments. See my updated answer. –  cjorssen Apr 11 '12 at 7:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.