5

I'd like to define a new listings environment where the listing has an \hrule before and after the listing itself. In order to do this I've defined this environment:

\lstnewenvironment{haskell}[1][]
    {
        \vspace{0.4cm}
        \mathligsoff
        \hrule
        \lstset{language=haskell, basicstyle=\small, #1}
    }{
        \hrule
        \mathligson
        \vspace{0.4cm}
}

The problem is that sometimes, when a listing ends up at the bottom of a page, the closing \hrule moves to the next page:

image showing the extra rule at the start of the new page

As you can see the highlighted rule ended up at the start of the new page, which is just ugly.

How can I avoid to produce a pagebreak between the listing and the rule at the end? I have already tried to add a \nopagebreak before \hrule but it didn't solve the problem.

Bakuriu
  • 2,218
  • related: http://tex.stackexchange.com/questions/140314/how-to-undo-the-feasible-breakpoints-of-lstlisting – jub0bs Sep 27 '14 at 12:08
  • 1
    You may want to use tcolorbox to draw the surrounding "box". The general consensus is that tcolorbox handles that kind of situation better than the native mechanism implemented in listings. – jub0bs Sep 27 '14 at 12:09

1 Answers1

1

Like indicated in the comments by Jubobs I'd use tcolorbox for this. The following code mimicks the layout outlined in the question but with tcolorbox a lot fancier layouts easily are possible.

\documentclass{article}
\usepackage{tcolorbox,listings}
\tcbuselibrary{listings,xparse}
\tcbset{listing engine=listings}

\NewTCBListing{haskell}{O{}}{%
  % colors:
  colback = white , colframe = black , coltitle = black ,
  % rules:
  boxrule = 0pt , toprule = 1pt , bottomrule = 1pt , arc = 0pt ,
  % spacing:
  boxsep = 0pt , left = 0pt , right = 0pt ,
  % listing options:
  listing options = {
    language = haskell ,
    basicstyle = \small ,
    gobble = 2 ,%
    #1%
  } ,
  listing only
}

\begin{document}

\begin{haskell}
  sums = zipWith (\x y -> x + y) numbers1 numbers2
  products = zipWith (\x y -> x * y) numbers1 numbers2
  pairs = zipWith (\x y -> (x, y)) numbers1 numbers2
\end{haskell}

\end{document}

Unless you specify the breakable option of tcolorbox (needs the breakable library) the complete listing will stay on one page.

enter image description here

cgnieder
  • 66,645