11

I have a LaTeX code set up as so:

\documentclass[a4paper,10pt]{report}

\usepackage[utf8]{inputenc}
\usepackage{fullpage}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{float}
\usepackage{parcolumns}
\usepackage{qtree}
\usepackage{url}

\usepackage{color}
\usepackage{xcolor}
\usepackage{caption}
\usepackage{textcomp}
\usepackage{todonotes}

\lstset{
    language=C,
    keywordstyle=\bfseries\ttfamily\color[rgb]{0,0,1},
    identifierstyle=\ttfamily,
    commentstyle=\color[rgb]{0.133,0.545,0.133},
    stringstyle=\ttfamily\color[rgb]{0.627,0.126,0.941},
    showstringspaces=false,
    basicstyle=\small,
    numberstyle=\footnotesize,
    stepnumber=1,
    numbersep=10pt,
    tabsize=2,
    breaklines=true,
    prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}},
    breakatwhitespace=false,
    aboveskip={1.5\baselineskip},
    columns=fixed,
    upquote=true,
    extendedchars=true,
    frame=single
}

\begin{document}

\begin{parcolumns}[nofirstindent]{2}
 \colchunk{
  \noindent\begin{minipage}{.45\textwidth}

\begin{lstlisting}[language={[x86masm]Assembler},caption={Original code},label={lst:OrigCode}]
  1
  2
  3
  4
  5
  ..
  12
\end{lstlisting}

  \end{minipage}
 }
 \colchunk{
  \begin{minipage}{.45\textwidth}

\begin{lstlisting}[language={[x86masm]Assembler},caption={Code after insertion of detour},label={lst:AfterDetour}]
  86
  4
  5
  ..
  12
\end{lstlisting}

  \end{minipage}
 }
 \colplacechunks
\end{parcolumns}

\end{document}

This produces two side-by-side code listings as follows:

Before

I want to more clearly illustrate the changes by drawing lines between changed parts of the code to produce something like this:

After

Is this possible? My alternative is to alter the image then attach it to the document as an image but this is undesirable for if I decide to modify the listing.

Werner
  • 603,163
Mike Kwan
  • 307

2 Answers2

13

You can use the overlay and remember picture attributes of tikz/pgf to mark elements within your listings, and draw the lines after typesetting them. To do this, you can momentarily "escape" the listing formatting via mathescape=true to mark a specific location. Here's a minimal example:

Lines connecting lines of code in separate listings

\documentclass[a4paper,10pt]{report}
\usepackage{fullpage}% http://ctan.org/pkg/fullpage
\usepackage{listings}% http://ctan.org/pkg/listings
\usepackage{parcolumns}% http://ctan.org/pkg/parcolumns
\usepackage{textcomp}% http://ctan.org/pkg/textcomp
\usepackage{tikz}% http://ctan.org/pkg/pgf
\usetikzlibrary{calc}

% http://tex.stackexchange.com/questions/1559/adding-a-large-brace-next-to-a-body-of-text/1570#1570
\newcommand{\tikzmark}[1]{\tikz[overlay,remember picture] \node (#1) {};}

\lstset{
    language=C,
    keywordstyle=\bfseries\ttfamily\color[rgb]{0,0,1},
    identifierstyle=\ttfamily,
    commentstyle=\color[rgb]{0.133,0.545,0.133},
    stringstyle=\ttfamily\color[rgb]{0.627,0.126,0.941},
    showstringspaces=false,
    basicstyle=\small,
    numberstyle=\footnotesize,
    stepnumber=1,
    numbersep=10pt,
    tabsize=2,
    breaklines=true,
    prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}},
    breakatwhitespace=false,
    aboveskip={1.5\baselineskip},
    columns=fixed,
    upquote=true,
    extendedchars=true,
    frame=single,
    mathescape % Allows escaping to (La)TeX mode within $..$
}

\begin{document}

\begin{parcolumns}[nofirstindent]{2}
 \colchunk{
  \noindent\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language={[x86masm]Assembler},caption={Original code},label={lst:OrigCode}]
  1 $\tikzmark{L1line1}$
  2
  3
  4 $\tikzmark{L1line4}$
  5
  ..
  12
\end{lstlisting}
  \end{minipage}
 }
 \colchunk{
   \begin{minipage}{.45\textwidth}
\begin{lstlisting}[language={[x86masm]Assembler},caption={Code after insertion of detour},label={lst:AfterDetour}]
 $\tikzmark{L2line1}$ 86
 $\tikzmark{L2line4}$ 4
  5
  ..
  12
\end{lstlisting}
   \end{minipage}
 }
 \colplacechunks
\end{parcolumns}

\tikz[overlay,remember picture] \draw[color=red] ($(L1line1)+(0pt,0.7ex)$) -- ($(L2line1)+(0pt,0.7ex)$);
\tikz[overlay,remember picture] \draw[color=blue] ($(L1line4)+(0pt,0.7ex)$) -- ($(L2line4)+(0pt,0.7ex)$);
\end{document}

While in "math escape mode", you can execute any (La)TeX commands. We just use this opportunity to set the \tikzmark that we use later.

The placement and alignment of the nodes are up to you. A similar approach is possible using pst-node from the pstricks bundle, but would require a latex->dvips->ps2pdf or xelatex compiling sequence. Here is a duplication of the above approach using pstricks, which produces the identical output:

\documentclass[a4paper,10pt]{report}
\usepackage{fullpage}% http://ctan.org/pkg/fullpage
\usepackage{listings}% http://ctan.org/pkg/listings
\usepackage{parcolumns}% http://ctan.org/pkg/parcolumns
\usepackage{textcomp}% http://ctan.org/pkg/textcomp
\usepackage{pst-node}% http://ctan.org/pkg/pst-node

\lstset{
    language=C,
    keywordstyle=\bfseries\ttfamily\color[rgb]{0,0,1},
    identifierstyle=\ttfamily,
    commentstyle=\color[rgb]{0.133,0.545,0.133},
    stringstyle=\ttfamily\color[rgb]{0.627,0.126,0.941},
    showstringspaces=false,
    basicstyle=\small,
    numberstyle=\footnotesize,
    stepnumber=1,
    numbersep=10pt,
    tabsize=2,
    breaklines=true,
    prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}},
    breakatwhitespace=false,
    aboveskip={1.5\baselineskip},
    columns=fixed,
    upquote=true,
    extendedchars=true,
    frame=single,
    mathescape % Allows escaping to (La)TeX mode within $..$
}

\begin{document}

\begin{parcolumns}[nofirstindent]{2}
 \colchunk{
  \noindent\begin{minipage}{.45\textwidth}
\begin{lstlisting}[language={[x86masm]Assembler},caption={Original code},label={lst:OrigCode}]
  1 $\rnode[r]{L1line1}{\strut}$
  2
  3
  4 $\rnode[r]{L1line4}{\strut}$
  5
  ..
  12
\end{lstlisting}
  \end{minipage}
 }
 \colchunk{
   \begin{minipage}{.45\textwidth}
\begin{lstlisting}[language={[x86masm]Assembler},caption={Code after insertion of detour},label={lst:AfterDetour}]
 $\rnode[l]{L2line1}{\strut}$ 86
 $\rnode[l]{L2line4}{\strut}$ 4
  5
  ..
  12
\end{lstlisting}
   \end{minipage}
 }
 \colplacechunks
\end{parcolumns}

\psline[linecolor=red](L1line1)(L2line1)
\psline[linecolor=blue](L1line4)(L2line4)
\end{document}
Werner
  • 603,163
0

Update on Werner's answer: I had to use \renewcommand instead of \newcommand. Else it wouldn't work because \tikzmark is already defined.

Edit: I was able to extend the command a little bit. So now it also works inline.

\renewcommand{\tikzmark}[1]{\tikz[overlay,remember picture,baseline=(#1.base)] \node (#1) {};}
enter image description here
Cyrill
  • 11
  • That's presumably because you are already loading the tikzmark library, in which case just omit that definition altogether as you can use the tikzmark command defined in that library. There's also an extension of the tikzmark library that automatically adds tikzmarks to listings code so you don't need to add them yourself. – Andrew Stacey Jan 01 '24 at 01:35
  • Thank you. Can you send the link to this library? That would be very helpful. Been trying to get this to work for 2 hours. – Cyrill Jan 01 '24 at 01:57
  • Nevermind, figured it out... – Cyrill Jan 01 '24 at 02:35