I'm trying to use this answer to put my lstlistings environments inside a tikz node. So I want to define a new listings environment, with \lstnewenvironment
.
My final goal, to be precise, is to ensure the proper framing of two-column listings generated through the multicol
package using the multicols
option of listings (ยง5.8 of the listings manual). Tikz comes in because 2-columns framing is ugly with the frame argument of listings, see the end of this pdf for an example.
But I also have single-column listings in my document that I'd like to decorate with tikz, and I'd love to have a single command to typeset both 2-columns and single-column listings. Fortunately, the listings manual suggests something: simply copying an optional argument of the new listings environment inside an lstset
command (p.41).
That's what I tried to do:
\documentclass{minimal}
\usepackage{listings}
\usepackage{tikz}
\usepackage{multicol}
\tikzstyle{sourcecodebox} = [
fill=white, draw=black, inner sep=1em, rectangle
]
\makeatletter
\lstnewenvironment{lstfigurelisting}[1][]{%
\lstset{frame=none,#1}%
\setbox\@tempboxa=\hbox\bgroup\color@setgroup
}%
{%
\color@endgroup\egroup
\begin{tikzpicture}
\node[sourcecodebox] (box)
{\makebox[.75\linewidth][l]{\box\@tempboxa}};
\end{tikzpicture}
}
\makeatother
\begin{document}
Some code here:
\begin{lstfigurelisting}[multicols=2]
#!/usr/bin/env python
def main():
print "Hello, World!"
if __name__ == '__main__':
main()
\end{lstfigurelisting}
\end{document}
Unfortunately, I get a Something's wrong--perhaps a missing \item
pointing at multicols=2
.
If I remove that optional argument, or change it to something innocuous (e.g. breaklines=true
, everything works (so at least I get the framing for single-column listings). I've read the FAQ on the missing \item
error, but I don't understand how this would apply, here. I do understand that the plain TeX \setbox
is used to save the whole environment content in a TeX box register, but I don't see how the multi-column environment, specifically, would insert a list inside that box.
Does anybody have an idea of what's going on ? Any other alternatives to suggest as to reaching my final goal (1 and 2-column listings inside a tiks node) ?
Best Answer
I don't really know anything about
listings
ormulticol
and particularly haven't a clue as to why they complain so much about being put in a box (presumably to do with howmulticol
works its magic). So I went back to the original specification: to get alistings
listing in a columnar setup within a TikZ node. I came up with the following solution. What seemed to be the key was to avoid precisely that situation that your code lands in: that something reads in the listing ahead of time and then resets it somewhere else. Several of the commands that I chose to use had a "read ahead" version, and I found that the code did not work if I chose that one. For example, I had to use aminipage
instead of a\parbox
.Anyway, this will need tweaking I'm sure - particularly with regard to line widths - but it does seem to do the basic "put a 2-column listing in a TikZ node".
Result: