2

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 05 '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. – Alicia Garcia-Raboso Nov 05 '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 07 '15 at 02: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. – Alicia Garcia-Raboso Nov 07 '15 at 03:07
  • I guess if you're sure that \parse@label etc. are unique. – cfr Nov 07 '15 at 03:36
  • Shouldn't label/options be a style if you want to pass a key-value list? – cfr Nov 07 '15 at 03:42
  • @cfr: I guess it should, but I've tried that and TeX gives the unhelpful error message I don't know the key /branch cut jump... – Alicia Garcia-Raboso Nov 07 '15 at 03:45
  • @cfr: \parse@label and company are unique. I checked using the first answer in http://tex.stackexchange.com/questions/30483/how-can-i-check-in-latex-or-plain-tex-whether-a-command-exists-by-name – Alicia Garcia-Raboso Nov 07 '15 at 03:45
  • Can you provide a more minimal example? What exactly is wrong with the output of your code? It isn't very clear what the code isn't doing which it should or what it shouldn't do that it is. At least, not to me. Or at least annotate the code to indicate the node which demonstrates the problem. – cfr Nov 07 '15 at 03:51
  • @cfr: I describe in the question what is wrong (it doesn't compile the moment I give options that are more than just a value). I'll try to come up with a more minimal example. – Alicia Garcia-Raboso Nov 07 '15 at 03:54
  • You only really need a single node, don't you? To demonstrate the issue? And you want the code to produce the error. Or at least to include code to produce the error commented out. – cfr Nov 07 '15 at 04:05
  • @cfr: I figured it out! As you suggested, I should have been using /branch cut jump/label/.style to set the default value instead of /branch cut jump/label/.initial. Then the macro parsing the label can just call \pgfkeys{/branch cut jump/label/options/.append style={#1}}, and I can do node[/branch cut jump/label/options/]. Thanks for all your help. – Alicia Garcia-Raboso Nov 07 '15 at 07:34
  • You should write that as an answer. – cfr Nov 07 '15 at 13:44

1 Answers1

2

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}

node

cfr
  • 198,882
  • 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 07 '15 at 04:06
  • Not exactly sure why, but these leaks styles up to the whole tikzpicture: change thick to scale=3 and the whole tikzpicture expands! – Alicia Garcia-Raboso Nov 07 '15 at 07:37
  • Hmmm.... That's odd. I guess it is a good thing that the style suggestion worked ;). – cfr Nov 07 '15 at 13:42