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'm working on a package that allows Python code to be entered within certain commands and environments, saves the Python code to external files and executes it, and brings back the results via \input. Similar to SympyTeX and SageTeX, but with additional features.

As a trivial example, \pylab{print 1+1} would save the text string print 1+1 to a file, Python executes this file to obtain 2 and saves this in a second file, and this second file is brought back into the original document with \input.

This is a minimal example. (It will give errors after the first run, before Python is run to create infile.tex.)

\newcommand{\pylab}[1]{
    \newwrite\outputstream
    \immediate\openout\outputstream=outfile.py
    \immediate\write\outputstream{#1}
    \immediate\closeout\outputstream
    \input{infile.tex}
}

The problem is that in more complex cases, the argument for \pylab could contain special characters, for example \pylab{print 3%2} (modulus operator). What's the best way to deal with this? Ideally, my command would act like \verb, so that it would take anything but * as the switch, so as to be able to work around almost any special code characters. I've been reading about verbatim, catcodes, \gdef, etc., but I haven't been able to get anywhere with those yet.

SympyTeX and SageTeX use

\catcode`\%=12
\newcommand{\percent}{%}
\catcode`\%=14

to define a replacement for %, but I want to avoid that route if possible since it means that I can't just directly paste in valid Python code.

share|improve this question
    
Hi, I don't know if it is going to help you, but perhaps you would like to have a look at python.sty‌​. You may find the code here or at the internet archives. –  pmav99 May 28 '11 at 19:28
    
About your code example: \newwrite\outputstream must be outside of \pylab and only executed once. And the percent character is already defined as \@percentchar. –  Martin Scharrer May 28 '11 at 19:34

1 Answer 1

up vote 4 down vote accepted

You can read the argument verbatim using the follow technique. However this keeps { and } normal so they need to be matched inside the argument.

\documentclass{article}

\makeatletter
\newwrite\@pyout
\newcommand{\pylab}{%
    \begingroup
    % deactivate special characters
    \let\do\@makeother
    \dospecials
    % change '{' and '}' back to normal
    \catcode`\{=1
    \catcode`\}=2
    \@pylab
}
\def\@pylab#1{%
    \endgroup
    \immediate\openout\@pyout=\jobname.py
    \immediate\write\@pyout{#1}%
    \immediate\closeout\@pyout
    \immediate\write18{python \jobname.py > \jobname-py.tex}%
    \input{\jobname-py}%
}

\makeatother


\begin{document}

\pylab{print 3%2}

\end{document}

If you want the behavior of \verb use the following code which is inspired by the actual \verb code.

\documentclass{article}

\makeatletter

\newwrite\@pyout

\newcommand{\pylab}[1]{%
    \begingroup
    \verb@eol@error
    \let\do\@makeother
    \dospecials
    \catcode`#1\active
    \lccode`\~`#1%
    \lowercase{\def\@@pylab##1~}{\endgroup\@pylab{##1}}%
    \@@pylab
}

\def\@pylab#1{%
    \immediate\openout\@pyout=\jobname.py
    \immediate\write\@pyout{#1}%
    \immediate\closeout\@pyout
    \immediate\write18{python \jobname.py > \jobname-py.tex}%
    \input{\jobname-py}%
}

\makeatother

\begin{document}

\pylab|print 3%2|

\end{document}

Update:

With the new version 2011/07/23 of my newverbs package you can simplify the \pylab macro to \newcommand{\pylab}{\begingroup\Collectverb{\@pylab}}.

share|improve this answer
1  
It's possible to avoid writing the \jobname-py.tex file by changing the two lines before the final brace into \@@input|"python \jobname.py" (it still requires shell-escape enabled). –  egreg May 28 '11 at 20:52
    
Thanks! The first solution does everything I wanted--seems to handle everything I've thrown at it, and since I'm dealing with code, matched braces isn't an issue. –  G.P. May 29 '11 at 3:28

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.