Archive for the ‘Linux’ Category.

The Ultimate Python – LaTeX Environment

Many times while creating LaTeX documents I’ve thought “Wouldn’t it be great if I could write an inline python script to generate some LaTeX code here.” In this post I describe how to embed python scripts in LaTeX, how to get Vim to correctly syntax highlight the embedded python, and the modifications required to get rubber to compile LaTeX that uses python.sty. All of the code and scripts mentioned in this post are available on bitbucket.

I have already built a system where python generated .tex files are \input into my documents (script execution is managed by makefiles). I want to take this a step further—allowing python source to sit in a .tex file alongside LaTeX source.

In 2007 Martin R. Ehmsen released a LaTeX package python.sty that allows such python embedding. python.sty defines a new python environment in which arbitrary python code can be placed. Everything that is written to stdout by the embedded python code is interpreted as LaTeX in the final document.

example1

For example, this sequence of identity matrices is generated with the mixture of LaTeX and python code below.

$N \times N$ element identity matrices for $N \in \{1,2,\ldots,5\}$:

\begin{python}
def identity(n):
    """
    Generates and returns the LaTeX code for
    a n x n identity matrix.

    """
    return '\n'.join([
        r'\left[',
        r'\begin{array}{%s}' % (n*'c',),
        '\\\\'.join('&'.join('1' if i==j else '0' for j in range(n))
                        for i in range(n)),
        r'\end{array}',
        r'\right]',
    ])

# Displays identity matrices for
# n \in {1, 2, ..., 5}.
print '\n'.join([
    r'\begin{equation*}',
    r'\begin{array}{%s}' % (5*'c',),
    '&'.join(identity(i) for i in range(1,6)),
    r'\end{array}.',
    r'\end{equation*}',
])
\end{python}

What improvements can we make to python.sty?

By default when python.sty encounters \begin{python} the following actions are executed:

  1. All text up to the closing \end{python} is output to outfile.py; outfile is the basename of the .tex document being processed;
  2. outfile.py is piped to the python executable with the resulting stdout and stderr stored to outfile.py.out and outfile.py.err;
  3. outfile.py.out is included in the LaTeX document using \input{outfile.py.out}.

This is great when a document contains a single python script, however since every environment overwrites outfile.py{.out,.err} it is impossible to view the python output and errors of all script executions. An updated python.sty fixes this by writing each environment to a different outfileN.py where N is a counter that is incremented each environment.

The updated python.sty also stores python’s return code to outfileN.rc. If python fails with a return code other than 0 the traceback and any other stderr output is included with red text in the document.

For example, if we deliberately throw an exception the traceback is included in the document body.

\begin{python}
# Create a deliberate exception.
print 'This text will be displayed.'
print 1/0
print 'This text won\'t be displayed.'
\end{python}

example2

Can Vim correctly syntax highlight LaTeX embedded python?

Python syntax-highlighted as LaTeX isn’t pretty. A stackoverflow question and answer describes how to get Vim to correctly highlight .tex as LaTeX while using the python syntax highlighter for \begin{python}\end{python} blocks. A condensed series of steps is

  1. Create a new Vim syntax file ~/.vim/syntax/pytex.vim containing:
    " Syntax for LaTeX files with embedded Python
    " environments.
    let b:current_syntax = ''
    unlet b:current_syntax
    runtime! syntax/tex.vim
    
    let b:current_syntax = ''
    unlet b:current_syntax
    syntax include @TeX syntax/tex.vim
    
    let b:current_syntax = ''
    unlet b:current_syntax
    syntax include @Python syntax/python.vim
    syntax region pythonCode matchgroup=Snip start="\\begin{python}" end="\\end{python}" containedin=@TeX contains=@Python
    
    hi link Snip SpecialComment
    let b:current_syntax = 'pytex'
        
  2. Add the following line to your .vimrc:
        au BufRead *.tex set syntax=pytex
        

The LaTeX code snippits in this post were generated using this syntax highlighting setup and the :TOhtml command.

Rubber can’t compile documents that use the python.sty package!

Rubber is a python command line tool that greatly simplifies compiling LaTeX documents. Unfortunately it provides no simple way to pass additional command line arguments to the underlying latex and pdflatex executables.

python.sty uses the \write18 command that executes an arbitrary shell command from within LaTeX. This is, by default, restricted for security reasons. Full \write18 functionality can be enabled by passing the –shell-escape argument to latex or pdflatex.

I’ve created a branch of Rubber that accepts and passes on the –shell-escape command line argument. You should download and install this latest version if you wish to use Rubber in concert with python.sty.

With this shell-escape Rubber branch the example.tex file can be compiled using:

mkdir .build
rubber -d --shell-escape --into=.build example.tex
cp .build/example.pdf .

Links of Interest

  1. https://bitbucket.org/brotchie/python-sty/ – python.sty source, Vim syntax scripts, and an example .tex file.
  2. http://stackoverflow.com/questions/5176972/trouble-using-vims-syn-include-and-syn-region-to-embed-syntax-highlighting – stackoverflow question detailing how to syntax python within LaTeX documents.
  3. https://code.launchpad.net/~brotchie/rubber/shell-escape – shell-escape enabled branch of Rubber.
  4. http://thewikiblog.appspot.com/blog/python-inside-latex – where I found a copy of the original python.sty.

Scrolling with the Zoom Slider on a Microsoft Natural Ergonomic Desktop 7000 in Ubuntu

Microsoft Natural Ergonomic Desktop 7000

Microsoft Natural Ergonomic Desktop 7000

The keyboard component of the Natural Ergonomic Desktop 7000 has a conveniently placed “zoom” slider in the centre. My desire to utilize this for scrolling web pages in Ubuntu lead me to some Google searching followed by downloading, patching, and compiling evrouter; a utility that allows you to transcode unhandled input events arriving from peripherals into key codes and mouse actions more suitable for applications. The steps described in this post have been tested on Ubuntu 11.04 64bit, if you’re using an earlier version of Ubuntu YMMV.

The initial step is to download and install evrouter. For completeness here’s a copy-paste of my bash history whilst I was fetching, compiling, and installing evrouter(with large swathes of deletions).

1
2
3
4
5
6
7
8
9
cd /var/tmp/
sudo apt-get install git libxtst-dev
git clone https://github.com/larsmagne/evrouter.git
wget https://raw.github.com/gist/754395/872183805da1da0b1d7703b0995dc755f8b815ad/evrouter-0.4_with_key_repeats_option.patch
cd evrouter
patch -p1 <../evrouter-0.4_with_key_repeats_option.patch
./configure
make
sudo make install

To do anything useful evrouter requires privileged access to devices linked to from /dev/input/by-id/. Adding

**REPLACE WITH YOUR ACCOUNT NAME** ALL=NOPASSWD: /usr/bin/evrouter

to the end of your /etc/sudoers file (remember to use visudo) will let your specific user account execute evrouter as root without a password.

We can ask evrouter to query all our connected input devices using

1
sudo evrouter -D /dev/input/by-id/*

Running this with 7000’s wireless dongle plugged in should display some resembling

device 0: /dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-kbd: Microsoft Microsoft® 2.4GHz Transceiver V1.0
device 1: /dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse: Microsoft Microsoft® 2.4GHz Transceiver V1.0
device 2: /dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-if01-event-mouse: Microsoft Microsoft® 2.4GHz Transceiver V1.0

Contrary to expectation the device that generates zoom sliders events is the event-mouse source

/dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse

All the events arriving from this device can be viewed in real-time using

1
sudo evrouter -d /dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse

which outputs

Window "(null)": # Window title
# Window "(null)": # Resource name
# Window "(null)": # Class name
"Microsoft Microsoft® 2.4GHz Transceiver V1.0" "/dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse" none key/418 "fill this in!"

Window "(null)": # Window title
# Window "(null)": # Resource name
# Window "(null)": # Class name
"Microsoft Microsoft® 2.4GHz Transceiver V1.0" "/dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse" none key/419 "fill this in!"

as we zoom up and down. Given are some lines that we can paste directly into our ~/.evrouterrc config file, changing “fill this in!” to mouse-wheel up and down (XButton/4 and XButton/5)

"Microsoft Microsoft® 2.4GHz Transceiver V1.0" "/dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse" none key/418 "XButton/4"
"Microsoft Microsoft® 2.4GHz Transceiver V1.0" "/dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse" none key/419 "XButton/5"

With the above two lines in ~/.evrouterrc you should be able to start proxying zoom slides into mouse-wheel movements using

1
sudo evrouter -r /dev/input/by-id/usb-Microsoft_Microsoft®_2.4GHz_Transceiver_V1.0-event-mouse

Happy scrolling!