下面最后一段代码效果很好。输出如下。
但是 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}
以下是我的问题。
- 为此,我需要计算
tcolorbox
从一个标记到左边距的距离。这可能吗? - 我还可以计算到右边距的距离吗?
这是我的 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
。似乎有一些禁用字符,我不知道这些是什么,也不知道如何解决这个问题。