[Tex/LaTex] Macro that inserts arguments into an environment

environmentsmacrosparameterspython

I'm having a bit of an issue trying to get a piece of code up and running. I'm working on extending python.sty file for embedding python into a LaTex document (adding persistent data and the ability to pass the results of LaTex commands to Python). At the high level, this style file provides functions that let you do:

\begin{python}
print r"Raw output, goes right into the Tex file."
\end{python}

I'm looking to make a simple function that allows passing data from Tex/Latex to the body of that python code but I'm running into real fun times with fragility issues. Foolishly, I assumed that something along these lines would work:

\xdef\internalSetPythonVariable#1#2{\PythonPersistenceInternalName["#1"] = r"#2"}
\xdef\setPythonVariable#1#2{\begin{python}\internalSetPythonVariable{#1}{#2}\end{python}}

Clearly, that one wouldn't work because the python environment messes with all the commands inside- so that was out. But I thought, "Fine, I'll just make sure that the stuff inside the python environment is all text by the time we even START that stupid environment." So I tried something like this:

\xdef\internalSetPythonVariable#1#2{\PythonPersistenceInternalName["#1"] = r"#2"}
\xdef\setPythonVariable#1#2{\expandafter\begin{python}\internalSetPythonVariable{#1}{#2}\end{python}}

However, the expandafter doesn't seem to want to work on the \begin stuff and now I'm a bit stuck. I keep getting the ever-so-helpful "! Argument of \reserved@a has an extra }" error. In general, I think this is a fairly simple issue in concept: I want to be able to evaluate everything inside an environment to text before the environment ever starts.

To note, there don't seem to be many other ways to accomplish this. By the time the environment is running in full gear, it's treating everything as fully text-only (no macros, no anything). Additionally, since I'm using these functions to read/write variables, I need them to be one-liners that take arguments. And it would seem rather silly to have to make a whole new environment that accepts optional params just for this purpose.

So does anybody know how to get those args fully expanded before things start? I've tried fiddling with it like crazy and gotten nowhere. With that said, if I can accomplish this- I'm hoping avoid having to ever do mundane junk with TeX again (see: conditionals, loops, non-typesetting macros).

Best Answer

You need to make sure that the \begin and \end macros aren't expanded in the \xdef. You need to use \noexpand not \expandafter for this. The latter only affects the order of expansion.

\xdef\setPythonVariable#1#2{\noexpand\begin{python}\internalSetPythonVariable{#1}{#2}\noexpand\end{python}}
Related Question