tcolorbox 、 tikzmark 和到 tcolorbox 边界的距离

tcolorbox 、 tikzmark 和到 tcolorbox 边界的距离

下面最后一段代码效果很好。输出如下。

在此处输入图片描述

但是 API 效率不高。我想像下面的代码一样定义我的标记。

\begin{coding-python}{Basic loop Python}
def oneloop(n):       |\tikzmark{top}|          
    for i in range(n):
        print(i**2)   |\tikzmark{down}|

print(oneloop(n))
\end{coding-python}

以下是我的问题。

  1. 为此,我需要计算tcolorbox从一个标记到左边距的距离。这可能吗?
  2. 我还可以计算到右边距的距离吗?

这是我的 MWE。

\documentclass[12pt,a4paper]{article}

\usepackage[skins, many, minted, breakable, hooks]{tcolorbox}
\usetikzlibrary{tikzmark,calc,fit}


\makeatletter


% Source: http://tex.stackexchange.com/a/50054/3954

\newcommand\myframe[4][-1ex]{%
    \tikz[remember picture,overlay,pin distance=0cm]{
        \draw[draw=#4,line width=1pt,fill=#4!20,rectangle,rounded corners, opacity=0.2]
        ( $ (pic cs:#2) + (-1ex,2ex) $ ) rectangle ( $ (pic cs:#3) + (1ex,#1) $ );
        \draw[draw=#4,line width=1pt,rectangle,rounded corners, opacity=1]
        ( $ (pic cs:#2) + (-1ex,2ex) $ ) rectangle ( $ (pic cs:#3) + (1ex,#1) $ );
    }
}


% Source: https://tex.stackexchange.com/a/124688/6880

\newcommand{\mynewminted}[3]{%
    \newminted[#1]{#2}{#3}%
    \tcbset{myminted/#1/.style = {
        minted language = #2, 
        minted options  = {#3}
    }}
}


\newcommand{\create@new@coding@env@title}[4]{%
    \mynewminted{for-coding-#1}{python}{escapeinside=||}

    \newtcblisting[]{coding-#1}[2][1]{%
        listing only,
        width        = ##1\linewidth,
        title        = ##2,
        myminted/for-coding-python,
    }
}

\create@new@coding@env@title{python}{\Large\faPython}{2mm}{1.8mm}

\makeatother


\begin{document}

\begin{coding-python}{Basic loop Python}
|\tikzmark{topleft}|def oneloop(n):            
    for i in range(n):
        print(i**2)   |\tikzmark{downright}|

print(oneloop(n))
\end{coding-python}

\myframe{topleft}{downright}{red}

\end{document}

答案1

是的,这是可以做到的。实现这一点的一种方法是存储框架的坐标,tcolorbox以便我们可以将它们用于框架。这可以通过三个键来实现enhanced,remember,overlay={...}。然后这些坐标将用作框架的水平坐标。

\documentclass[12pt,a4paper]{article}

\usepackage[skins, many, minted, breakable, hooks]{tcolorbox}
\usetikzlibrary{tikzmark,calc,fit}


\makeatletter


% Source: http://tex.stackexchange.com/a/50054/3954

\newcommand\myframe[4][-1ex]{%
    \tikz[remember picture,overlay]{
        \path ([yshift=2ex]pic cs:#2) coordinate (aux1) 
        ([yshift=-1ex]pic cs:#3) coordinate (aux2);
        \draw[draw=#4,line width=1pt,fill=#4!20,rectangle,rounded corners, opacity=0.2]
        ([xshift=1ex]current tcb-NW|-aux1)  rectangle 
        ([xshift=-1ex]current tcb-SE|-aux2);
        \draw[draw=#4,line width=1pt,rectangle,rounded corners, opacity=1]
         ([xshift=1ex]current tcb-NW|-aux1)  rectangle 
        ([xshift=-1ex]current tcb-SE|-aux2);
    }
}


% Source: https://tex.stackexchange.com/a/124688/6880

\newcommand{\mynewminted}[3]{%
    \newminted[#1]{#2}{#3}%
    \tcbset{myminted/#1/.style = {
        minted language = #2, 
        minted options  = {#3}
    }}
}


\newcommand{\create@new@coding@env@title}[4]{%
    \mynewminted{for-coding-#1}{python}{escapeinside=||}

    \newtcblisting[]{coding-#1}[2][1]{%
        listing only,
        width        = ##1\linewidth,
        title        = ##2,
        myminted/for-coding-python,enhanced,%<-added
        remember,%<-added
        overlay={%<-added
        \path[overlay,remember picture] 
        (frame.north west) coordinate (current tcb-NW)
        (frame.south east) coordinate (current tcb-SE);}
    }
}

\create@new@coding@env@title{python}{\Large\faPython}{2mm}{1.8mm}

\makeatother


\begin{document}

\begin{coding-python}{Basic loop Python}
def oneloop(n):       |\tikzmark{top}|          
    for i in range(n):
        print(i**2)   |\tikzmark{down}|

print(oneloop(n))
\end{coding-python}

\myframe{top}{down}{red}

\end{document}

在此处输入图片描述

tcolorbox 的边框和红框之间的距离被认为是1ex但当然可以修改(或存储在 pgf 键中)。

附录: 一些方法可以与这个答案

\documentclass[12pt,a4paper]{article}

\usepackage[skins, many, minted, breakable, hooks]{tcolorbox}
\usetikzlibrary{tikzmark}
\tikzset{projetframe/.cd,pstyle/.style={draw=red,line width=1pt,fill=red!20,
rectangle,rounded corners},style/.code={\tikzset{projetframe/pstyle/.append
style={#1}}},frame sep/.initial=1ex,to/.initial={}}%
\newcounter{projetframe}
\newcounter{projetbcframe}
\makeatletter
\newcommand\projetframe[1]{%
    \stepcounter{projetframe}%
    \tikzmark{pframestart-\number\value{projetframe}}%
    \tikzset{projetframe/.cd,#1}%
    \tikz[remember picture,overlay,pin distance=0cm]{
        \@ifundefined{save@pt@\tikzmark@pp@name{pframestart-\number\value{projetframe}}}{%
        %    
        }{%
        \path ([yshift=2ex]pic cs:pframestart-\number\value{projetframe}) coordinate (aux1) 
        ([yshift=-1ex]pic cs:\pgfkeysvalueof{/tikz/projetframe/to}) coordinate (aux2)
        (pic cs:current tcb-NW-\number\value{projetbcframe}) coordinate(aux3)
        (pic cs:current tcb-SE-\number\value{projetbcframe}) coordinate (aux4);
         \draw[projetframe/pstyle]
        ([xshift=\pgfkeysvalueof{/tikz/projetframe/frame sep}]aux3|-aux1)  rectangle 
        ([xshift=-\pgfkeysvalueof{/tikz/projetframe/frame sep}]aux4|-aux2);
        }
    }%
}

% Source: http://tex.stackexchange.com/a/50054/3954




% Source: https://tex.stackexchange.com/a/124688/6880

\newcommand{\mynewminted}[3]{%
    \newminted[#1]{#2}{#3}%
    \tcbset{myminted/#1/.style = {
        minted language = #2, 
        minted options  = {#3}
    }}
}


\newcommand{\create@new@coding@env@title}[4]{%
    \mynewminted{for-coding-#1}{python}{escapeinside=||}

    \newtcblisting[]{coding-#1}[2][1]{%
        listing only,
        width        = ##1\linewidth,
        title        = ##2,
        myminted/for-coding-python,enhanced,%<-added
        overlay={%<-added
        \path[overlay,remember picture] 
        (frame.north west) node{\tikzmark{current tcb-NW-\number\value{projetbcframe}}}
        (frame.south east) node{\tikzmark{current tcb-SE-\number\value{projetbcframe}}};}
        \stepcounter{projetbcframe}%
    }
}

\create@new@coding@env@title{python}{\Large\faPython}{2mm}{1.8mm}

\makeatother


\begin{document}

\begin{coding-python}{Basic loop Python}
|\projetframe{to=down}|def oneloop(n):        
    for i in range(n):
        print(i**2)   |\tikzmark{down}|

print(oneloop(n))
\end{coding-python}

\tikzset{projetframe/.cd,style={draw=blue,fill=blue!20},frame sep=1.5ex}
\begin{coding-python}{Another basic loop Python}
|\projetframe{to=downB}|def oneloop(n):        
    for i in range(n):
        print(i**2)    |\tikzmark{downB}| 

print(oneloop(n))
\end{coding-python}

\end{document}

如您所见,现在所有内容都存储在 pgf 键中,因此您可以更轻松地创建框。但是,可以考虑通过将所有选项传递给参数来使其更加优雅,这将允许您摆脱 。我\tikzset试图使其更优雅时的主要问题是我对 了解不多minted。似乎有一些禁用字符,我不知道这些是什么,也不知道如何解决这个问题。

在此处输入图片描述

相关内容