如何结合使用 listing、tikz 和 tikzmark 包来注释源代码列表?

如何结合使用 listing、tikz 和 tikzmark 包来注释源代码列表?

我想注释代码列表如下:

在此处输入图片描述

以下是我迄今为止尝试过的方法。我有点担心必须使用 raisebox,这样箭头尖端就不会指向线的底部。我该如何避免这种硬编码?我也很感激任何有关改进的建议,以便更容易处理屏幕截图中所示的几种注释。

如果我能指定以下内容,就能获得所需的结果,那就太好了:

  • 源线末端与箭头尖端之间的距离

  • 箭头的水平线长度和垂直线长度(以及垂直线是向上还是向下)

  • 以及文本节点的位置(垂直线的右侧或左侧以及文本节点与顶部或底部的垂直对齐。

\documentclass[twoside, openright, 10pt]{book}
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, tikzmark}

\begin{document}
  
\chapter{TiKz}

\begin{lstlisting}[caption={[MeetKarel]{MeetKarel}}, label={lst:meet_karel}, escapechar=ß]
import stanford.karel.Karel;
public class MeetKarel extends Karel { 
        public void run() {
                move();
                move();
                move();
                ß\tikzmark{b}ßpickBeeper();ß\raisebox{2.6pt}{\tikzmark{a}}ß                             
                turnLeft();
                move();
                move();
                turnLeft();
                turnLeft();
                turnLeft();ß\raisebox{2.6pt}{\tikzmark{c}}ß 
                move();
                putBeeper();
                move();
        }        
}
\end{lstlisting}
\begin{tikzpicture}[remember picture,overlay]
\draw([shift={(12ex,10ex)}] pic cs:a) ++ (0.05, 0) % shift just a little to the right
  % set inner and outer to 0 so that text is alighed with the beginning of the vertical line
  node[inner sep=0,outer sep=0, fill=yellow!80!black,text width=5cm, anchor= north west] 
  {Shifted a little above so that the arrow head points to the middle of the line.};
\draw[thin, gray, arrows = {-Stealth[inset=0pt, angle=45:7pt]}]
  ([shift={(12ex,10ex)}] pic cs:a) -- 
  ([shift={(12ex,0ex)}] pic cs:a) -- 
  ([shift={(0ex,0ex)}] pic cs:a);
\draw([shift={(12ex,-10ex)}] pic cs:c) ++ (0.05, -0.05) % shift just a little to the right and down
  % set inner and outer to 0 so that text is alighed with the beginning of the vertical line
  node[inner sep=0,outer sep=0, fill=yellow!80!black,text width=5cm, anchor= south west] 
  {I want to align base line of this text to the `c` node nicely. };
\draw[thin, gray, arrows = {-Stealth[inset=0pt, angle=45:7pt]}]
  ([shift={(12ex,-10ex)}] pic cs:c) -- 
  ([shift={(12ex,0ex)}] pic cs:c) -- 
  ([shift={(0ex,0ex)}] pic cs:c);
\end{tikzpicture}
\end{document}

结果: 在此处输入图片描述

答案1

这是您的代码的稍微简化的版本。

  1. 通过使用 tikzmark 特殊列表库,您不需要在代码中指定 tikzmarks,它们都为您提供了。
  2. 箭头(0.5,.5ex)从相应的 tikzmarks 处开始。.5ex的高度是 的一半x,并且对我来说看起来垂直高度很好。
  3. 线条和节点一起绘制,并-|使用路径构造使线条很好地弯曲。
  4. 在标签节点上添加一点点outer xsep,使它们远离连接线。实现相同效果的其他方法似乎会导致箭头放置问题。

所有这些都是为了使代码更短。各种数字可以硬编码到样式中,使其更简单、更灵活。

\documentclass[twoside, openright, 10pt]{book}
%\url{https://tex.stackexchange.com/q/657375/86}
\usepackage{listings}
\usepackage{tikz}
\usetikzlibrary{
  arrows.meta,
  tikzmark,
  calc,
  positioning
}
\usetikzmarklibrary{listings}


\begin{document}
  
\chapter{Ti\emph{k}Z}

\begin{lstlisting}[
  caption={[MeetKarel]{MeetKarel}},
  label={lst:meet_karel},
  name=karel,
  escapechar=ß
]
import stanford.karel.Karel;
public class MeetKarel extends Karel { 
        public void run() {
                move();
                move();
                move();
                pickBeeper();
                turnLeft();
                move();
                move();
                turnLeft();
                turnLeft();
                turnLeft();
                move();
                putBeeper();
                move();
        }        
}
\end{lstlisting}


\begin{tikzpicture}[
  remember picture,
  overlay,
  annotation/.style={
    inner sep=0pt,
    outer sep=0pt,
    outer xsep=1mm,
    fill=yellow!80!black,
    text width=5cm
  },
  >={Stealth[inset=0pt, angle=45:7pt]}
]
\draw[<-] (pic cs:line-karel-7-end)  ++(.5,.5ex) -| ++(2,1.5)
node[annotation, below right]
{Shifted a little above so that the arrow head points to the middle of the line.};

\draw[<-] (pic cs:line-karel-13-end) ++(0.5,.5ex) -| ++(2,-1)
node[annotation, above right]
{I want to align base line of this text to the `c` node nicely. };
\end{tikzpicture}
\end{document}

使用 tikzmark 注释的代码

相关内容