Como passar argumentos de macro (# 1, # 2, ..) para variáveis Lua
Esta pergunta é provavelmente trivial, mas comecei a explorar Lua (La) TeX algumas horas atrás, então tenha paciência comigo.
O MWE é o seguinte:
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("}")
Eu sei que poderia colocar \newcommando texarquivo e, em seguida, chamar directluadentro da definição de comando, mas no meu caso de uso real, estou fazendo um loop em uma tabela onde as chaves são os nomes dos comandos, então preciso deixar como está.
EDITAR : Como minha pergunta inicial pode ter sido um pouco um problema XY, estou postando meu caso de uso real abaixo.
Meu objetivo é: dado um monte de ambientes de teoremas definidos pelo thmtoolspacote, redefina-os incorporando-os em um tcolorboxambiente.
Comecei a fazer isso via, expl3mas fiquei frustrado muito rapidamente, em parte por causa da minha incompetência na forma de programação LaTeX3, em parte porque a programação em LaTeX é tão dolorosa em comparação com qualquer outra linguagem de programação "normal" (para loops, declarações if, etc. ), que é o motivo pelo qual começou a mergulhar mais fundo em LuaTeX.
Agora para o código. Eu tenho esta mesa
boxed_theorems = {
definition = "definition",
example = "example",
lemma = "theorem",
theorem = "theorem",
corollary = "theorem",
proof = "proof",
}
onde as chaves são nomes de ambiente (de novo, vindos de thmtools), e os valores são tcolorboxopções (aqui definition, example, theoreme proofsão um bando de estilos tcolorbox.
A maneira como faço um loop sobre essa tabela (e o resto do arquivo .lua incluído via \directlua) é a seguinte:
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")
Respostas
Eu acho que é mais simples configurar macros LaTeX no arquivo .tex e agrupar o código Lua em funções que podem aceitar e retornar argumentos.
Por exemplo, test.texpode ser o seguinte:
\documentclass{article}
\directlua{require("test.lua")}
\newcommand\foo[1]{\directlua{foo("#1")}}
\begin{document}
\foo{bar}
\end{document}
enquanto test.luapode conter
function foo ( s )
tex.sprint ( "\\textit{"..s.."}" )
end
Observe que as strings acumuladas por tex.printnão são retornadas ao TeX até que o trecho Lua seja concluído, portanto, não há Lua ativa no ponto que #1é processado como o argumento bar. Portanto, para responder à sua pergunta da forma como foi escrita, você precisa entrar novamente em Lua nesse ponto, conforme mostrado aqui.
isso imprime
arg is: barbaz
De Lua, mostrar a string barfoi passado para Lua.
e compõe isso, que acho que é a saída pretendida
No entanto, quase certamente essa não é a melhor maneira de abordar seu 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("}")