Cómo pasar argumentos macro (# 1, # 2, ..) a variables Lua

Oct 05 2020

Esta pregunta probablemente sea trivial, pero comencé a explorar Lua (La) TeX hace un par de horas, así que tengan paciencia conmigo.

El MWE es el siguiente:

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("}")

Sé que podría ingresar \newcommandel texarchivo y luego llamar directluadentro de la definición del comando, pero en mi caso de uso real, estoy recorriendo una tabla donde las claves son los nombres de los comandos, así que necesito dejar eso como está.

EDITAR : Como mi pregunta inicial podría haber sido un problema XY, a continuación publico mi caso de uso real.

Mi objetivo es: dado un montón de entornos de teoremas definidos por el thmtoolspaquete, redefinirlos incrustándolos en un tcolorboxentorno.

Comencé a hacer esto a través de, expl3pero me frustré muy rápidamente, en parte debido a mi incompetencia en la forma de programación LaTeX3, en parte porque programar en LaTeX es tan doloroso en comparación con cualquier otro lenguaje de programación "normal" (bucles for, declaraciones if, etc. ), por lo que se comienza a profundizar en LuaTeX.

Ahora al código. Tengo esta mesa

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

donde las claves son los nombres de entorno (de nuevo, procedentes de thmtools), y los valores son tcolorboxopciones (en este caso definition, example, theoremy proofson un montón de estilos tcolorbox.

La forma en que recorro esa tabla (y el resto del archivo .lua incluido a través de \directlua) es la siguiente:

tex.print("\\ExplSyntaxOn")

for theorem,tcolorbox_theorem in pairs(boxed_theorems) do
  -- copy <theorem_name> in a new environment inner<theorem_name>
  tex.print("\\let\\inner" .. theorem .. "\\" .. theorem)
  tex.print("\\let\\endinner" .. 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")

Respuestas

1 Mico Oct 05 2020 at 20:05

Creo que es más sencillo configurar macros LaTeX en el archivo .tex y agrupar el código Lua en funciones que pueden aceptar y devolver argumentos.

Por ejemplo, test.texpodría ser el siguiente:

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

mientras que test.luapodría contener

function foo ( s )
   tex.sprint ( "\\textit{"..s.."}" )
end
DavidCarlisle Oct 05 2020 at 20:34

Tenga en cuenta que las cadenas acumuladas por tex.printno se devuelven a TeX hasta que se completa el fragmento de Lua, por lo que no hay Lua activo en el punto que #1se procesa como argumento bar. Entonces, para responder a su pregunta tal como está escrita, debe volver a ingresar Lua en ese punto, como se muestra aquí.

esto imprime

arg is: barbaz

De Lua, mostrando la cuerda barse pasó a Lua.

y escribe esto, que creo que es su salida prevista.

Sin embargo, es casi seguro que esta no es la mejor manera de abordar su caso de uso real.

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

\directlua{
texio.write_nl('arg is: ' .. arg .. '\string\n')
}
\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("}")