# Processing complex label-like expressions with pgfkeys

I would like to use pgfkeys to process expressions like

label={[scale=.8,pos=.9]above right:$-2\pi i$}


(which typically appear as labels in nodes), and extract from them three parameters according to the pattern [#1]#2:#3. I would also like to make #1 and #2 optional (again, as labels in nodes), so that things like #2:#3, [#1]#3 and #3 are valid patterns.

Update: I've been reading the tikz code that does this parsing, and have come up with code that works for many cases (it even allows for #3 being optional). The code is attached below (it is a working example, but is far from minimal: sorry!).

So what is it that doesn't work? Well, the options (argument #1). If I just specify a value (e.g. label={[blue]above:hola}), it works. But if I try to make it into a list (label={[blue,thick]above:hola}) or a key-value pair (label={[scale=.8]above:hola}), the code breaks (I get an error like I do not know the key /tikz/scale=.8). What do I have to modify to get that working?

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{arrows.meta,shapes.misc,decorations.pathmorphing,calc,bending}

\pgfdeclarelayer{top}
\pgfsetlayers{main,top}

\tikzset{
branch point/.style={cross out,draw=black,fill=none,minimum size=2*(#1-\pgflinewidth),inner sep=0pt,outer sep=0pt},
branch point/.default=5,
branch cut/.style={
decorate,decoration=snake
}
}

\makeatletter
\catcode\$=11\relax% \gdef\parse@label[#1]#2:#3\empty{% % Extract options \if\relax\detokenize{#1}\relax \relax% \else \pgfkeyssetvalue{/branch cut jump/label/options}{#1}% \fi% % Do we have an angle? \if\relax\detokenize{#3}\relax % Nope! \if\relax\detokenize{#2}\relax % We also don't have a label text \relax% \else % But we do have a label text, so let's extract it \pgfkeyssetvalue{/branch cut jump/label/text}{#2}% \fi% \else % Yup! \parse@@label#2:#3\empty% \fi% } \gdef\parse@@label#1:#2:\empty{% % Do we have an angle? \if\relax\detokenize{#1}\relax \relax% \else \pgfkeyssetvalue{/branch cut jump/label/angle}{#1}% \fi% % Do we have a label text? \if\relax\detokenize{#2}\relax \relax% \else \pgfkeyssetvalue{/branch cut jump/label/text}{#2}% \fi% } \catcode\$=3\relax%
\pgfkeys{/branch cut jump/.cd,
pos/.initial = .8,
amplitude/.initial = 10,
color/.initial = green!60!black,
label/.code    = {
\@ifnextchar[%
{\parse@label}%
{\parse@label[]}#1:\empty%
},
label/options/.initial = green!60!black,
label/angle/.initial   = above right,
label/text/.initial    = $-2\pi i$
}
\tikzset{
place arrow/.style={
to path={
(\tikztostart) -- (\tikztotarget) \tikztonodes
},
execute at begin to={
\coordinate (A) at ($(\tikztostart)!\pgfkeysvalueof{/branch cut jump/pos}!-\pgfkeysvalueof{/branch cut jump/amplitude}:(\tikztotarget)$);
\coordinate (B) at ($(\tikztostart)!\pgfkeysvalueof{/branch cut jump/pos}!\pgfkeysvalueof{/branch cut jump/amplitude}:(\tikztotarget)$);
\coordinate (AB/3) at ($(A)!1/3!(B)$);
\coordinate (2AB/3) at ($(A)!2/3!(B)$);
\coordinate (C) at ($(AB/3)!2/(3*sqrt(3))!-90:(B)$);
\coordinate (D) at ($(2AB/3)!4/(3*sqrt(3))!-90:(B)$);
\begin{pgfonlayer}{top}
\draw[thick,\pgfkeysvalueof{/branch cut jump/color},-{Stealth[]}] (A) .. controls (C) and (D) .. (B) node[\pgfkeysvalueof{/branch cut jump/label/options},\pgfkeysvalueof{/branch cut jump/label/angle}]{\pgfkeysvalueof{/branch cut jump/label/text}};
\end{pgfonlayer}
}
},
branch cut jump/.style={
/branch cut jump/.cd,#1,
/tikz/.cd,place arrow
}
}
\makeatother

\begin{document}

\begin{tikzpicture}[x=90pt,y=90pt]
\begin{scope}
% Axes
\draw[thin,gray,->] (-1,0) -- (1,0) node[right] {$x$};
\draw[thin,gray,->] (0,-1) -- (0,1) node[above] {$y$};
% Branch point
\draw[thick] (0,0) node[branch point,draw=red,thick] {};
% Branch cut
\draw[thick,red,branch cut,branch cut jump] (0,0) to (0:1.2);
\draw[thick,red,branch cut,branch cut jump={label={hola}}] (0,0) to (30:1.2);
\draw[thick,red,branch cut,branch cut jump={label={:}}] (0,0) to (60:1.2);
\draw[thick,red,branch cut,branch cut jump={label={:adios}}] (0,0) to (90:1.2);
\draw[thick,red,branch cut,branch cut jump={label={left:}}] (0,0) to (120:1.2);
\draw[thick,red,branch cut,branch cut jump={label={below:$\times (-1)$}}] (0,0) to (150:1.2);
\draw[thick,red,branch cut,branch cut jump={label={[blue]hola}}] (0,0) to (180:1.2);
\draw[thick,red,branch cut,branch cut jump={label={[blue]:}}] (0,0) to (210:1.2);
\draw[thick,red,branch cut,branch cut jump={label={[blue]:adios}}] (0,0) to (240:1.2);
\draw[thick,red,branch cut,branch cut jump={label={[blue]left:}}] (0,0) to (270:1.2);
\draw[thick,red,branch cut,branch cut jump={label={[blue]below:$\times (-1)$}}] (0,0) to (300:1.2);
\end{scope}
\end{tikzpicture}

\end{document}

• You can just copy the label code. – percusse Nov 5 '15 at 17:06
• @percusse: I'm looking at the code right now. It does way more than just extract the three values I want. Also, I find it very difficult to understand. I don't think I have the knowledge to isolate what I need from the rest. – Alberto Garcia-Raboso Nov 5 '15 at 17:10
• You are currently overwriting TikZ's definitions of things. This seems like a Bad Idea. It would be better to use something like xabel={[scale=.8,pos=.9]above right:$-2\pi i$}. Apart from anything else, you can then pass it onto label if you actually want a label. – cfr Nov 7 '15 at 2:31
• @cfr: I don't think I'm overwriting TikZ definitions, am I? I have label inside /branch cut jump. Also, I do want something that acts as a label, but it is, in fact, a node: see the code inside the execute at begin to block. – Alberto Garcia-Raboso Nov 7 '15 at 3:07
• I guess if you're sure that \parse@label etc. are unique. – cfr Nov 7 '15 at 3:36

Maybe this helps:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{arrows.meta,shapes.misc,decorations.pathmorphing,calc,bending}

\pgfdeclarelayer{top}
\pgfsetlayers{main,top}

\tikzset{
branch point/.style={cross out,draw=black,fill=none,minimum size=2*(#1-\pgflinewidth),inner sep=0pt,outer sep=0pt},
branch point/.default=5,
branch cut/.style={
decorate,decoration=snake
}
}

\makeatletter
\catcode\$=11\relax% \gdef\parse@label[#1]#2:#3\empty{% % Extract options \if\relax\detokenize{#1}\relax \relax% \else \tikzset{/branch cut jump/label/options=#1}% \fi% % Do we have an angle? \if\relax\detokenize{#3}\relax % Nope! \if\relax\detokenize{#2}\relax % We also don't have a label text \relax% \else % But we do have a label text, so let's extract it \pgfkeyssetvalue{/branch cut jump/label/text}{#2}% \fi% \else % Yup! \parse@@label#2:#3\empty% \fi% } \gdef\parse@@label#1:#2:\empty{% % Do we have an angle? \if\relax\detokenize{#1}\relax \relax% \else \pgfkeyssetvalue{/branch cut jump/label/angle}{#1}% \fi% % Do we have a label text? \if\relax\detokenize{#2}\relax \relax% \else \pgfkeyssetvalue{/branch cut jump/label/text}{#2}% \fi% } \catcode\$=3\relax%
\pgfkeys{/branch cut jump/.cd,
pos/.initial = .8,
amplitude/.initial = 10,
color/.initial = green!60!black,
label/.code    = {
\@ifnextchar[%
{\parse@label}%
{\parse@label[]}#1:\empty%
},
label/options/.store in = \branch@label@options,
label/options=green!60!black,
label/angle/.initial   = above right,
label/text/.initial    = $-2\pi i$
}
\tikzset{
place arrow/.style={
to path={
(\tikztostart) -- (\tikztotarget) \tikztonodes
},
execute at begin to={
\coordinate (A) at ($(\tikztostart)!\pgfkeysvalueof{/branch cut jump/pos}!-\pgfkeysvalueof{/branch cut jump/amplitude}:(\tikztotarget)$);
\coordinate (B) at ($(\tikztostart)!\pgfkeysvalueof{/branch cut jump/pos}!\pgfkeysvalueof{/branch cut jump/amplitude}:(\tikztotarget)$);
\coordinate (AB/3) at ($(A)!1/3!(B)$);
\coordinate (2AB/3) at ($(A)!2/3!(B)$);
\coordinate (C) at ($(AB/3)!2/(3*sqrt(3))!-90:(B)$);
\coordinate (D) at ($(2AB/3)!4/(3*sqrt(3))!-90:(B)$);
\begin{pgfonlayer}{top}
\draw[thick,\pgfkeysvalueof{/branch cut jump/color},-{Stealth[]}] (A) .. controls (C) and (D) .. (B) node[\branch@label@options,\pgfkeysvalueof{/branch cut jump/label/angle}]{\pgfkeysvalueof{/branch cut jump/label/text}};
\end{pgfonlayer}
}
},
branch cut jump/.style={
/branch cut jump/.cd,#1,
/tikz/.cd,place arrow
}
}
\makeatother

\begin{document}

\begin{tikzpicture}
\draw[thick,red,branch cut,branch cut jump={label={[blue,thick]above:hola}}] (0,0) to (30:1.2);
\end{tikzpicture}

\end{document}


• Not that the thick makes a difference here since it is a node which is not drawn but it doesn't produce an error.... – cfr Nov 7 '15 at 4:06
• Not exactly sure why, but these leaks styles up to the whole tikzpicture: change thick to scale=3 and the whole tikzpicture expands! – Alberto Garcia-Raboso Nov 7 '15 at 7:37
• Hmmm.... That's odd. I guess it is a good thing that the style suggestion worked ;). – cfr Nov 7 '15 at 13:42