11

This is what I want to do:

\documentclass{beamer}

\begin{document}

\begin{frame}[fragile]{Frame 1}

    Some \structure{Python} code here:

    % I want to define a new "pythoncode" environment, so I can use it like this:
    \begin{pythoncode}[hello.py]
    #!/usr/bin/env python
    def main():
        print "Hello, World!"
    if __name__ == '__main__':
        main()
    \end{pythoncode}

\end{frame}

\end{document}

But I want to customize the source-code box beyond what listings package allow me. Jan Hlavacek suggested me to use tikz package for that, and pointed me to a few examples.

Okay, that's great! Tikz gives me enough power and freedom for customization! All I need now is creating a new environment, so that I can use this environment just like in the code above.

However, I'm having trouble mixing tikz with listings inside a new environment. I've tried the following code, but it doesn't work (I get Missing \endcsname inserted.):

\usepackage{listings}
\usepackage{tikz}
\usepackage{environ}

\tikzstyle{sourcecodebox} = [
    draw=blue, very thick,
    rectangle, rounded corners,
    inner sep=10pt
]
\tikzstyle{sourcecodetitle} = [
    fill=black, text=white,
    rectangle, rounded corners
]
\NewEnviron{pythoncode}[1]{
    \begin{tikzpicture}
    \node[sourcecodebox](box){
        \begin{lstlisting}[
            language=Python,
            basicstyle=\ttfamily\footnotesize,
            escapeinside={(*@}{@*)},
            %numbers=left,
            breaklines=true,
            breakatwhitespace=true,
            showspaces=false,
            showstringspaces=false,
            frame=shadowbox,
            frameround=rrrt,
            rulecolor=\color{black},
            rulesepcolor=\color{gray}
        ]
        \BODY
        \end{lstlisting}
    };
    \node[sourcecodetitle] at (box.north west) {#1};
    \end{tikzpicture}
}

Related questions:

7
  • 1
    Not really answering your question, but how about actually having a hello.py file with the code, and then use \lstinputlisting{hello.py}. You avoid the problem altogether because you don't need to define an environment anymore. Commented Jan 20, 2011 at 14:52
  • 1
    @Denilson Use the listings environment command to create the environment \lstnewenvironment
    – yannisl
    Commented Jan 20, 2011 at 15:16
  • @Juan: No, I don't want to put an external file because I'm going to use several snippets of source code throughout several slides, so it's a lot better to have them inline with the slide text. Also, sometimes I'll want to highlight some lines from the source code, and thus I need the source inline, mixed with TeX. See this question: tex.stackexchange.com/questions/8851/… Commented Jan 21, 2011 at 2:06
  • @Yiannis: Before writing the code from my question, I've tried using \lstnewenvironment, but I failed completely, because I needed to open \begin{tikzpicture} inside the first pair of braces and then close it inside another set of braces. Since that is not possible, another question from this site suggested using the environ package. Anyway, if you have a working solution, please share with us! Commented Jan 21, 2011 at 2:08
  • @Denilson, this question looks like a duplicate of your earlier question. In order to avoid duplicating efforts trying to answer your question, perhaps you would like to delete this question and update the earlier one with any new information, the things you have tried and why they didn't work? Commented Jan 24, 2011 at 13:59

2 Answers 2

7

Note that \NewEnviron does not support verbatim. The documentation should point that out. As already commented the \lstnewenvironment must be used for this. Alternatively place the verbatim files into external files which are then read using \listinputlisting.

Find below my solution which stores the resulting listings first into a box which is then used inside the TikZ node. IMHO you should not mix the listings frame argument with additional frames from TikZ. You should produce all framing using TikZ (not to be confused with beamers \frame macro/environment). Beamer provides some nice framed boxes as well!

I had to add the linewidth argument and a \makebox, otherwise the listings frame is to wide. You might want to adjust that.

Best Regards, Martin

\documentclass{beamer}

\usepackage{listings}
\usepackage{tikz}

\tikzstyle{sourcecodebox} = [
    draw=blue, very thick,
    rectangle, rounded corners,
    inner sep=10pt
]
\tikzstyle{sourcecodetitle} = [
    fill=black, text=white,
    rectangle, rounded corners
]

\makeatletter
\lstnewenvironment{pythoncode}[1][]{%
    \def\pythoncodetitle{#1}%
    \lstset{%
        language=Python,
        basicstyle=\ttfamily\footnotesize,
        escapeinside={(*@}{@*)},
        %numbers=left,
        breaklines=true,
        breakatwhitespace=true,
        showspaces=false,
        showstringspaces=false,
        frame=shadowbox,
        frameround=rrrt,
        linewidth=.75\linewidth,
        rulecolor=\color{black},
        rulesepcolor=\color{gray}
    }%
    \setbox\@tempboxa=\hbox\bgroup\color@setgroup
}%
{%
    \color@endgroup\egroup
    \begin{tikzpicture}
        \node[sourcecodebox] (box)
            % Makebox is needed to take the frame added by listings into account
            {\makebox[.75\linewidth][l]{\box\@tempboxa}};
        \node[sourcecodetitle] at (box.north west) {\pythoncodetitle};
    \end{tikzpicture}
}

\begin{document}

\begin{frame}[fragile]{Frame 1}

    Some \structure{Python} code here:
    \begin{pythoncode}[hello.py]
    #!/usr/bin/env python
    def main():
        print "Hello, World!"
    if __name__ == '__main__':
        main()
    \end{pythoncode}

\end{frame}

\end{document}
0
6

tcblisting environments from tcolorbox package are a good tool to define fancy boxes around source code. tcolorbox provides the surrounding box and it works with listings and minted packages to format source code.

Next it's just an example which shows some customization options:

\documentclass{beamer}

\usepackage[most]{tcolorbox}

\newtcblisting{pythoncode}[2][]{%
    enhanced, title=#2, colframe=blue!50!black, 
    colback=blue!10!white, sharp corners,
    fonttitle=\ttfamily, coltitle=white,
    attach boxed title to top left = {yshift=-.5mm} ,
    boxed title style={sharp corners, size=small, colback=blue!75!black},
    listing only,listing options={language=python},#1}

\begin{document}

\begin{frame}[fragile]{Frame 1}

    Some \structure{Python} code here:

    % I want to define a new "pythoncode" environment, so I can use it like this:
    \begin{pythoncode}{hello.py}
    #!/usr/bin/env python
    def main():
        print "Hello, World!"
    if __name__ == '__main__':
        main()
    \end{pythoncode}

\end{frame}

\end{document}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .