6

I would like to draw vertical rules at a specific location in the left margin of a listing in a listings environment. Is it possible ?

======= PSEUDO EXAMPLE =======

for i in range(5):
# One comment
    if i == 2:
# One comment
        print(i)

print("Finished....")

======= OUTPUT WISHED (this is ASCII art ! ) =======

   for i in range(5):
    # One comment
|      if i == 2:
|   # One comment
|          print(i)

    print("Finished....")   
projetmbc
  • 13,315

1 Answers1

8

You may use TikZ and it’s overlay function …

Here’s my solution.

Code

\documentclass{article}

\usepackage{xparse}
\usepackage{listings}
    \lstset{%
        escapechar=§% or what fits to your code
    }
\usepackage{tikz}
    \usetikzlibrary{calc}
    \tikzstyle{every lst line}=[line width=3pt, gray]
    % command for setting a TikZ anchor
    \newcommand{\tanc}[1]{%
        \begin{tikzpicture}[remember picture]
            \coordinate (#1) at (0,0);
%           \fill circle (0.5pt);% this line is for testing only
        \end{tikzpicture}%
    }
    % some parameters
    \def\DeltaX{4cm}
    \def\DeltaYi{6pt}
    \def\DeltaYii{0pt}
    % command for drawing the lines
    \NewDocumentCommand{\makeline}{O{0pt} m m O{}}{%
        \begin{tikzpicture}[remember picture, overlay, transform canvas={xshift=#1}]
            \draw [every lst line,#4] %
                let\p1=(#2), \p2=(#3), \p3=(current page.west) in%
                (\x3+\DeltaX,\y1+\DeltaYi) -- (\x3+\DeltaX,\y2+\DeltaYii);
            ;
        \end{tikzpicture}%
    }

\usepackage{lipsum}% for testing

\begin{document}
\lipsum[1]
%
\begin{lstlisting}
for i in range(5):
# Pu§\tanc{one}§t the anchor somewhere in the line
if i == 2:
# One comment §\tanc{two}§
    print(i) §\tanc{three}§
print("Finished....")§\tanc{four}§
\end{lstlisting}
\makeline{one}{two}\makeline{three}{four}[red]
\makeline[-7pt]{one}{four}[blue]
%
\lipsum[2]
\end{document}

Settings

  • Choose an escape character that is never part of your listings. I choosed §.
  • Adjust the every lst line style to fit your taste. This is the style applied to each line drawn with \makeline
  • Adjust the parameters to fit you font and layout. \DeltaX = distance to left page border, \DeltaYi = shift between baseline of the anchored row in your listing an the start of the line and \DeltaYii same for second row.

Usage

  • Put an anchor somewhere in the row you want the line to start with \tanc{<name 1>}
    # Pu§\tanc{one}§t the anchor somewhere in the line

  • Put a second anchor with \tanc{<name 2>}. The names should be unique at least for on listing.
    print(i) §\tanc{two}§

  • Draw the line with \makeline{<name 1>}{<name 2>}.
    \makeline{one}{two}

    You may change the line style of the line using the second optional argument and shift the line horizontally using the first one:
    \makeline[<x shift>]{<name 1>}{<name 2>}[<style>]
    \makeline[-7pt]{one}{four}[blue]

    If you load a decoration library you can also add big curly braces or whatever by using the <style> argument.

  • run LaTeX twice otherwise TikZ can’t get the right positions of the remember picture nodes.

Result

result

Tobi
  • 56,353
  • Thanks for this... I will start soon how to use TiKz for enhancing my documents. – projetmbc Feb 05 '12 at 23:03
  • @projetmbc: I improved my answer and extend the code. If you want to learn TikZ you may consider the pgfmanual containing some great tutorials. – Tobi Feb 06 '12 at 13:52
  • Thanks for the possibilty to indicate two lines, or more. That will help for producing documents to start programmation. PS : could you remove \start{fold} et \end{fold} in the example because they don't belong to the listing ? – projetmbc Feb 06 '12 at 18:44
  • @projetmbc I removed them. Don’t know why they where there … I also added a not that the example needs two latex runs – Tobi Feb 06 '12 at 18:58
  • Indeed I've puted \start{fold} et \end{fold} to materialze where I wanted to place the LaTeX commands to draw the rules. This corresponds to your §\tanc{...}§. – projetmbc Feb 06 '12 at 19:40
  • @projetmbc Ahh … I see … :-) – Tobi Feb 06 '12 at 20:04
  • I'm trying to adapt this code for my question on adding circled numbers (annotations) to listings: http://tex.stackexchange.com/questions/51597/how-to-add-numerical-ala-no-starch-press-listing-notes-without-xetex It would be nice if you could check that one and see how it fits your code. – blahblahblahdev Apr 13 '12 at 18:59
  • @soze: I’m sorry, but I didn’t understand what you want me to do … could you pleas explain what you’re expecting …? – Tobi Apr 13 '12 at 21:23