2

I try to draw on a listing with tikz overlay. but the image only show the listing, then the part out side of that region has been cut out.

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{listings}
\begin{document}
\definecolor{lbcolor}{rgb}{1,1,1} 
\newcounter{m}
\lstset{%
  frame            = tb,
  tabsize          = 1,
  numbers          = left,
  framesep         = 3pt,
  framerule        = 0.4pt,
  commentstyle     = \color{Green},
  keywordstyle     = \color{blue},
  stringstyle      = \color{DarkRed},
  backgroundcolor  = \color{WhiteSmoke},
  showstringspaces = false,
}
\newcommand\makenode[2]{%
  \tikz[baseline=0pt, remember picture] { 
    \node[fill=gray!50,anchor=base,#1/.try,inner sep=0] (m-\the\value{m}) {#2}; }%
    \stepcounter{m}%
}
\lstdefinelanguage{MYLANG}{
    backgroundcolor=\color{lbcolor},
    alsoletter=0123456789,
    keywords={
        5479,3802,1677,29,14,3787,1692,3071,469,2602
    },
    keywordstyle=\makenode{keyword},
    sensitive=false, %not case-sensitive
} %
\begin{lstlisting}[language=MYLANG,numbers=none,escapechar=!,
    basicstyle=\ttfamily\bfseries, linewidth=\linewidth] 
$ adb shell free -m
        total      used      free     shared   buffers
Mem:    5479       3802      1677     29       14
-/+ buffers/cache: 3787      1692
Swap:   3071       469       2602
\end{lstlisting}
\begin{tikzpicture}[remember picture, overlay,
    font=\tiny,
    every edge/.append style = {
      ->, thick, >=stealth,
      DimGray, dashed, line width = 1pt },
    every node/.append style={
      align=center,anchor=north,minimum height=1pt,
      font=\bfseries,fill=green!10,inner sep=0},
    %text width=5pt
  ]
  \def\dy{-50pt}
  \draw (m-0.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N1) {total(MB)};
  \draw (m-7.west) -- ++(-5pt,0);

  \draw (m-1.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N2) {used(MB)};
  \draw (m-5.west) -- ++(-5pt,0);  
  \draw (m-8.west) -- ++(-5pt,0);

  \draw (m-2.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N3) {free(MB)};
  \draw (m-6.west) -- ++(-5pt,0);  
  \draw (m-9.west) -- ++(-5pt,0);  

  \draw (m-3.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N4) {shared(MB)};

  \draw (m-4.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N5) {buffer(MB)};
\end{tikzpicture} 
\end{document}

Output: enter image description here

Update

@Qrrbrbirlbel's answer is perfect, but when I try to replace the tikz with tikzpicture, but looks like not work as expected. the offset of each annotation line shift to left a little bit.

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usepackage{varwidth}
\usetikzlibrary{positioning}
\usepackage{listings}
\begin{document}
\definecolor{lbcolor}{rgb}{1,1,1}
\newcounter{m}
\lstset{%
  frame            = tb,
  tabsize          = 1,
  numbers          = left,
  framesep         = 3pt,
  framerule        = 0.4pt,
  commentstyle     = \color{Green},
  keywordstyle     = \color{blue},
  stringstyle      = \color{DarkRed},
  backgroundcolor  = \color{WhiteSmoke},
  showstringspaces = false,
}
\newcommand\makenode[2]{%
  \hspace{-.15em}%
  \tikz[baseline=0pt, remember picture]
    \node[fill=gray!50, anchor=base, inner sep=+.15em,
          text depth=+0pt, outer sep=+0pt, #1/.try] (m-\the\value{m}) {#2};%
  \hspace{-.15em}%
  \stepcounter{m}%
}
\lstdefinelanguage{MYLANG}{
  backgroundcolor=\color{lbcolor},
  alsoletter=0123456789,
  keywords={5479,3802,1677,29,14,3787,1692,3071,469,2602},
  keywordstyle=\makenode{keyword},
  sensitive=false, %not case-sensitive
} %
\begin{varwidth}{\linewidth}
\begin{lstlisting}[language=MYLANG,numbers=none,escapechar=!,
    basicstyle=\ttfamily\bfseries, linewidth=\linewidth]
$ adb shell free -m
        total      used      free     shared   buffers
Mem:    5479       3802      1677     29       14
-/+ buffers/cache: 3787      1692
Swap:   3071       469       2602
\end{lstlisting}

\begin{tikzpicture}[
  remember picture, baseline=+0pt,
  font=\tiny,
  every node/.append style={font=\bfseries, fill=green!10, text depth=+0pt},
  vh/.style={to path=|-(\tikztotarget)},
  every edge/.append style={vh, gray!50, overlay},
  n 4/.style={yshift=-\baselineskip-2*(\pgfkeysvalueof{/pgf/inner ysep})},
]
  \foreach[count=\i] \t/\n/\ns in {
  total/0/7, used/1/{5, 8}, free/2/{6, 9}, shared/3, buffer/4}{
  \node[anchor=base, n \i/.try] (n) at ([xshift=-5pt]m-\n.west|-0,0) {\t(MB)}
  edge (m-\n)
  \unless\ifx\n\ns foreach \N in \ns {edge (m-\N)} \fi;
   }
\end{tikzpicture}
\end{varwidth}
\end{document}

Output: enter image description here

2 Answers 2

3

Only the edges need to be overlayed.

Instead of overlaying the whole diagram, we'll just let PGF/TikZ find the right horizontal position itself by setting trim left = 0pt. On the second compilation run, the green nodes will be placed correctly in relation to x = 0pt, i.e. the left side of the picture.

The vertical position of the green nodes is setup as if they would have been placed as normal TeX text in a new paragraph below the listing. This is done by a combination of baseline = 0pt and setting the y value of the node's base anchor to 0pt as well (this is the - part in the at specification).

The entries of the loop are setup so that \t specifies the content of the green nodes while \n specifies the number of the upper gray node while thet \ns macro should contain all other gray nodes below that. Leave it out (which makes it default to the same as \n) if there's only one gray node for that column. This is caught by the \ifx test.

The varwidth option of standalone makes it possible to actually use multiple paragraphs in the first place.

Code

\documentclass[border=2pt, varwidth]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{listings}
\begin{document}
\definecolor{lbcolor}{rgb}{1,1,1}
\newcounter{m}
\lstset{%
  frame            = tb,
  tabsize          = 1,
  numbers          = left,
  framesep         = 3pt,
  framerule        = 0.4pt,
  commentstyle     = \color{Green},
  keywordstyle     = \color{blue},
  stringstyle      = \color{DarkRed},
  backgroundcolor  = \color{WhiteSmoke},
  showstringspaces = false,
}
\newcommand\makenode[2]{%
  \hspace{-.15em}%
  \tikz[baseline=0pt, remember picture]
    \node[fill=gray!50, anchor=base, inner sep=+.15em,
          text depth=+0pt, outer sep=+0pt, #1/.try] (m-\the\value{m}) {#2};%
  \hspace{-.15em}%
  \stepcounter{m}%
}
\lstdefinelanguage{MYLANG}{
  backgroundcolor=\color{lbcolor},
  alsoletter=0123456789,
  keywords={5479,3802,1677,29,14,3787,1692,3071,469,2602},
  keywordstyle=\makenode{keyword},
  sensitive=false, %not case-sensitive
} %
\begin{lstlisting}[language=MYLANG,numbers=none,escapechar=!,
    basicstyle=\ttfamily\bfseries, linewidth=\linewidth]
$ adb shell free -m
        total      used      free     shared   buffers
Mem:    5479       3802      1677     29       14
-/+ buffers/cache: 3787      1692
Swap:   3071       469       2602
\end{lstlisting}

\begin{tikzpicture}[
  remember picture, baseline=+0pt, trim left=+0pt,
  font=\tiny,
  every node/.append style={font=\bfseries, fill=green!10, text depth=+0pt},
  vh/.style={to path=|-(\tikztotarget)},
  every edge/.append style={vh, gray!50, overlay},
  n 4/.style={yshift=-\baselineskip-2*(\pgfkeysvalueof{/pgf/inner ysep})},
]
\foreach[count=\i] \t/\n/\ns in {
  total/0/7, used/1/{5, 8}, free/2/{6, 9}, shared/3, buffer/4}
  \node[anchor=base, n \i/.try] (n) at ([xshift=-5pt]m-\n.west|-0pt,0pt) {\t(MB)}
  edge (m-\n) \unless\ifx\n\ns foreach \N in \ns {edge (m-\N)} \fi;
\end{tikzpicture}
\end{document}

Output

enter image description here

9
  • +1 Although I do not understand this. The nodes themselves are also referencing to be placed correctly and though needs overlay (to prevent the ever increasing size of the tikzpicture for every compile). As I can see, your solution only seems stable because of varwidth (I do fully understand this option). Is your solution truly stable from one compilation to the next? Commented Sep 5 at 11:31
  • @hpekristiansen standalone is a black box for me, but the manual says: “The resulting effect [of varwidth] is […] that multiple paragraphs can be included as part of the content.” The TikZ picture that places the green nodes is now on its own paragraph which is, of course, under the listing. The solution appears to be stable for varwidth/standalone as well as for article. The green nodes should not be overlayed because we want their size to matter. Commented Sep 5 at 12:18
  • The size ever increasing only happens because TikZ can't “reach” a coordinate from another diagram because something is in the way (that would happen, if we would reference the gray nodes without overlay (here it is in every edge). \tikz[remember picture]\draw (0,0) -- (current page.center);` in article works without problem because TikZ can enhance the bounding box to include current page.center. Commented Sep 5 at 12:19
  • Awesome, can we still keep tikzpicture environment?
    – lucky1928
    Commented Sep 5 at 13:43
  • 1
    @hpekristiansen Yes and no. Of course, it is referenced but only the x part of it is used to find a point that is not occupied by something else. This is done by taking the vertical part of 0,0 and aligning it to the baseline of this TeX line (baseline=0pt). Why this also needs separatly 0,0 on the path may need some investigating (the x part of this is irrelevant as long as it is the same). Commented Sep 5 at 15:33
1

overlay TikZ pictures does not take up space. Here is a solution where vertical space is added manually at the end.

\documentclass[border=2pt, preview]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{listings}
\begin{document}
\definecolor{lbcolor}{rgb}{1,1,1} 
\newcounter{m}
\lstset{%
  frame            = tb,
  tabsize          = 1,
  numbers          = left,
  framesep         = 3pt,
  framerule        = 0.4pt,
  commentstyle     = \color{Green},
  keywordstyle     = \color{blue},
  stringstyle      = \color{DarkRed},
  backgroundcolor  = \color{WhiteSmoke},
  showstringspaces = false,
}
\newcommand\makenode[2]{%
  \tikz[baseline=0pt, remember picture] { 
    \node[fill=gray!50,anchor=base,#1/.try,inner sep=0] (m-\the\value{m}) {#2}; }%
    \stepcounter{m}%
}
\lstdefinelanguage{MYLANG}{
    backgroundcolor=\color{lbcolor},
    alsoletter=0123456789,
    keywords={
        5479,3802,1677,29,14,3787,1692,3071,469,2602
    },
    keywordstyle=\makenode{keyword},
    sensitive=false, %not case-sensitive
} %
\begin{lstlisting}[language=MYLANG,numbers=none,escapechar=!,
    basicstyle=\ttfamily\bfseries, linewidth=\linewidth] 
$ adb shell free -m
        total      used      free     shared   buffers
Mem:    5479       3802      1677     29       14
-/+ buffers/cache: 3787      1692
Swap:   3071       469       2602
\end{lstlisting}
\begin{tikzpicture}[remember picture, overlay,
    font=\tiny,
    every edge/.append style = {
      ->, thick, >=stealth,
      DimGray, dashed, line width = 1pt },
    every node/.append style={
      align=center,anchor=north,minimum height=1pt,
      font=\bfseries,fill=green!10,inner sep=0},
    %text width=5pt
  ]
  \def\dy{-50pt}
  \draw (m-0.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N1) {total(MB)};
  \draw (m-7.west) -- ++(-5pt,0);

  \draw (m-1.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N2) {used(MB)};
  \draw (m-5.west) -- ++(-5pt,0);  
  \draw (m-8.west) -- ++(-5pt,0);

  \draw (m-2.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N3) {free(MB)};
  \draw (m-6.west) -- ++(-5pt,0);  
  \draw (m-9.west) -- ++(-5pt,0);  

  \draw (m-3.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N4) {shared(MB)};

  \draw (m-4.west) -- ++(-5pt,0) -- ++(0,\dy) node[pos=1,below] (N5) {buffer(MB)};
\end{tikzpicture} 
\vspace{0.5cm}
\end{document}

A table with some labels under

You must log in to answer this question.

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