TransWikia.com

How to pass macro arguments (#1, #2, ..) to Lua variables

TeX - LaTeX Asked on February 12, 2021

This question is probably trivial, but I started exploring Lua(La)TeX a couple of hours ago so bear with me.

The MWE is the following:

test.tex:

documentclass{article}
directlua{require("test.lua")}
begin{document}
foo{bar}
end{document}

test.lua:

tex.print("newcommand{foo}[1]{")
tex.print("texttt{#1}")
-- arg = ?? how do I pass #1 to arg ??
-- arg = arg .. " baz"
-- tex.print("textit{" .. arg .. "}")
tex.print("}")

I know I could put newcommand in the tex file and then call directlua inside the command definition, but in my actual use case I’m looping over a table where the keys are the command names, so I need to leave that as is.

EDIT: As my initial question might have been a bit of an XY problem, I’m posting my real use case below.

My goal is: given a bunch of theorem environments defined by the thmtools package, redefine them by embedding them in a tcolorbox environment.

I started doing this via expl3 but got frustrated very quickly, partly because of my incompetence in the LaTeX3 way of programming, partly because programming in LaTeX is so painful compared to every other "normal" programming language (for loops, if statements, etc..), which is why is started diving deeper into LuaTeX.

Now to the code. I have this table

boxed_theorems = {
  definition = "definition",
  example = "example",
  lemma = "theorem",
  theorem = "theorem",
  corollary = "theorem",
  proof = "proof",
}

where the keys are environment names (again, coming from thmtools), and the values are tcolorbox options (here definition, example, theorem and proof are a bunch of tcolorbox styles.

The way I loop over that table (and the rest of the .lua file included via directlua) is the following:

tex.print("ExplSyntaxOn")

for theorem,tcolorbox_theorem in pairs(boxed_theorems) do
  -- copy <theorem_name> in a new environment inner<theorem_name>
  tex.print("letinner" .. theorem .. "" .. theorem)
  tex.print("letendinner" .. theorem .. "end" .. theorem)

  tex.print("RenewDocumentEnvironment{ " .. theorem .. " }{ O{} }{")

  -- I want to be able to call the new environment like this:
  --
  -- begin{theorem}[name={foo}, label={bar}, tcolorbox={baz}]
  --
  -- where 'name={foo}, label={bar}' is the argument of the
  -- innertheorem and should be assigned to 'theorem_options',
  -- while '{baz}' is an argument of the embedding tcolorbox and
  -- should be assigned to 'tcolorbox_local'.
 
  -- I haven't got that far yet (I need to create a function that
  -- parses #1, hence the original post), so for now they are just
  -- left empty.
  theorem_options = ""
  tcolorbox_local = ""

  -- The rest is pretty self-explanatory
  tex.print("begin{tcolorbox}[" .. tcolorbox_theorem .. ","
                                  .. tcolorbox_local .. "]")
  if theorem_options == "" then
    tex.print("begin{inner" .. theorem .. "}")
  else
    tex.print("begin{inner" .. theorem .. "}[" .. theorem_options .. "]")
  end
  tex.print("}{")
  tex.print("end{inner" .. theorem .. "}")
  tex.print("end{tcolorbox}")
  tex.print("}")
end

tex.print("ExplSyntaxOff")

2 Answers

I think it's more straightforward to set up LaTeX macros in the .tex file and to group the Lua code in functions that can accept and return arguments.

E.g., test.tex might be as follows:

documentclass{article}
directlua{require("test.lua")}
newcommandfoo[1]{directlua{foo("#1")}}
begin{document}
foo{bar}
end{document}

while test.lua might contain

function foo ( s )
   tex.sprint ( "textit{"..s.."}" )
end

Answered by Mico on February 12, 2021

Note that the strings accumulated by tex.print are not returned to TeX until the Lua chunk completes so there is no Lua active at the point that #1 is processed as the argument bar. So to answer your question as written you need to re-enter Lua at that point as shown here.

this prints

arg is: barbaz

From Lua, showing the string bar was passed to Lua.

and typesets this, which is I think your intended output.

enter image description here

However this is almost certainly not the best way of approaching your real use case.

documentclass{article}
directlua{require("test.lua")}
begin{document}
foo{bar}

directlua{
texio.write_nl('arg is: ' .. arg .. 'stringn')
}
end{document}

test.lua

tex.print("newcommand{foo}[1]{")
tex.print("texttt{#1}")
tex.print("directlua{arg='#1' arg = arg .. 'baz' tex.print('\textit{' .. arg .. '}')}")
tex.print("}")

Answered by David Carlisle on February 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP