12

I am using listings to display source code. I would like to label/bracket certain lines of this source code so that I can call out each section and describe what they do.

Here is an example of what I'd like to do:

enter image description here

Here some latex containing example code. The /**** SECTION X ****/ comments within the code are just there to denote where I'd like the sections in this particular listing.

    \documentclass{article}

\usepackage{listings}

\begin{document}

\begin{lstlisting}
List<Point2D> data = // ...

/**** SECTION A ****/
val x = scaleBand<Int> {
    rangeRound(listOf(0.0, width))
    domain(data.indices.toList())
    padding(0.1)
}

/**** SECTION B ****/
val y = scaleLinear<Double> {
  domain(listOf(height, 0))
  range(listOf(0, data.maxBy { it.y })
}

/**** SECTION C ****/
val bar = rect<Point2D> {
    width(x.bandwidth)
    height { d, _ -> height - y(d.y) }
    fill(Color.STEELBLUE)
}

/**** SECTION D ****/
val root = Group()
root.selectAll<Point2D>(".bar")
    .data(data)
    .enter()
    .append { d, _, _ -> bar(d) }
    .translateX { _, i, _ -> x(i) }
    .translateY { d, _, _ -> y(d.y) }
\end{lstlisting}


\end{document}
  • Please post a minimal compilable example (without the nice new markup you want) so that folks here can just cut and paste to get started on an answer. – Ethan Bolker Mar 15 '17 at 12:49
  • Tikzmark combine with escape inside should work – cmhughes Mar 15 '17 at 17:06
10

Based on cmhughes comment sugessting the use of tikzmark, and the multiline bracket solution found here, I was able to come up with the following:

\documentclass{article}

\usepackage{enumitem}
\usepackage{tikz}
\usepackage{listings}
\usepackage{xparse}

\usetikzlibrary{calc,decorations.pathreplacing}

\newcommand{\tikzmark}[1]{%
  \tikz[overlay,remember picture,baseline] \node [anchor=base] (#1) {};}

\newcommand*{\BracektStubSize}{0.5em}%
\NewDocumentCommand\LeftBracket{%
    O{}% #1 = draw options
    O{0pt}% #2 = shift to be applied (optional, for use with nested braces)
    m% #3 = top \tikzmark name
    m% #4 = bottom \tikzmark name
    m% #5 = node text
}{%
    \begin{tikzpicture}[overlay,remember picture,baseline]
        \coordinate (Top Start of Bracket) at ([shift={(#2-15pt,5pt)}]#3.north east);
        \coordinate (Bottom Start of Bracket) at ([shift={(#2-15pt,2pt)}]#4.south east);
        \draw[thick, #1] 
            (Top Start of Bracket) --++(-\BracektStubSize,0) 
                |-(Bottom Start of Bracket) ;

        \node[xshift=-5pt, align=left, anchor=east, #1]
            at ($(Bottom Start of Bracket)!0.5!(Top Start of Bracket)$) {#5};
    \end{tikzpicture}    
}

\begin{document}

\begin{lstlisting}[escapechar=\&]
List<Point2D> data = // ...

&\tikzmark{Mark A}&val x = scaleBand<Int> {
    rangeRound(listOf(0.0, width))
    domain(data.indices.toList())
    padding(0.1)
&\tikzmark{End A}&}


&\tikzmark{Mark B}&val y = scaleLinear<Double> {
  domain(listOf(height, 0))
  range(listOf(0, data.maxBy { it.y })
&\tikzmark{End B}&}

&\tikzmark{Mark C}&val bar = rect<Point2D> {
    width(x.bandwidth)
    height { d, _ -> height - y(d.y) }
    fill(Color.STEELBLUE)
&\tikzmark{End C}&}

&\tikzmark{Mark D}&val root = Group()
root.selectAll<Point2D>(".bar")
    .data(data)
    .enter()
    .append { d, _, _ -> bar(d) }
    .translateX { _, i, _ -> x(i) }
&\tikzmark{End D}&    .translateY { d, _, _ -> y(d.y) }
\end{lstlisting}

\LeftBracket[black][0pt]{Mark A}{End A}{a}
\LeftBracket[black][0pt]{Mark B}{End B}{b}
\LeftBracket[black][0pt]{Mark C}{End C}{c}
\LeftBracket[black][0pt]{Mark D}{End D}{d}

\end{document}

Which produces:

enter image description here

  • Great job! Really well done :) – cmhughes Mar 17 '17 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.