[Tex/LaTex] Arguments for TikZ style

macrospgfkeystikz-pgftikz-styles

Motivation

To put arrows inside of a TikZ path I have defined myself a TikZ style arrow inside. To make it even more portable I want it to take arguments like this

\draw[arrow inside={pos = 0.1, end = |}] (1,-0.5) -- (1,1.5);

such that I can define the position of the arrow using pos and the type of the arrow by end. If no arguments are given it should fall back to the defaults.

enter image description here

What I have tried so far

To achive the above picture, I wrote the following snippet. The problem is that the values are properly stored in the macros I defined, but are not being updated, nor do I now, how to retain the defaults.

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{
    arrow inside/pos/.store in = \arrow@inside@pos,
    arrow inside/end/.store in = \arrow@inside@end,
    arrow inside/pos = 0.5,
    arrow inside/end = >,
    arrow inside/.style = {
        postaction = {
            decorate,
            decoration={
                markings,
                mark=at position \arrow@inside@pos with {\arrow{\arrow@inside@end}}
            }
        }
    },
}
\makeatother
\begin{document}
\[ \int_{
    \tikz[scale=0.3]{
        \path[fill=lightgray] (0,0) rectangle (1,1);
        \draw (1.5,1) -- (0,1) -- (0,0) -- (1.5,0);
        \draw[arrow inside={pos = 0.1, end = |}] (1,-0.5) -- (1,1.5);
    }
} \vec{B} \cdot \vec{n} \, df \]
\end{document}

Possibly related:

Best Answer

Jake is correct in his now deleted answer. The options you pass to arrow inside are not applied as they are simply grabbed and not used (i.e. “gobbled”) similar to #1 in:

\newcommand*{\myCommand}[1]{Foobar Rhubarb}% no "#1" in its definition

You need to add #1 in your .style definition.

But instead of using the .store in handler, consider using .initial keys which simply store a value. This way, you don’t add another layer of abstraction (PGFkeys already use a specific “namespace”), no need to add your own \arrow@inside@… macros if PGFkeys already uses /tikz/arrow inside/….

To also avoid troubles with /.cd inside a .style, I’d use a specific key set arrow inside that sets the path to /tikz/arrow inside.

References

Code

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\tikzset{
  set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
  set arrow inside={pos/.initial=.5, end/.initial=>},
  arrow inside/.style={
    set arrow inside={#1},
    postaction={
      decorate,
      decoration={
        markings,
        mark=at position \pgfkeysvalueof{/tikz/arrow inside/pos}
             with \arrow{\pgfkeysvalueof{/tikz/arrow inside/end}}
      }
    }
  },
}
\begin{document}
\[ \int_{
    \tikz[scale=0.3]{
        \path[fill=lightgray] (0,0) rectangle (1,1);
        \draw (1.5,1) -- (0,1) -- (0,0) -- (1.5,0);
        \draw[arrow inside={pos = 0.1, end = |}] (1,-0.5) -- (1,1.5);
    }
} \vec{B} \cdot \vec{n} \, df \]
\end{document}

Output

enter image description here

But why stop there?

Sometimes users want to use more than one arrow tip along a (part of a) path which I realized in a comment should be made better.

The following solution doesn’t use a pos key anymore (this can be changed) but applies the options end and opt to a list of arrow-tip marks in a decoration.

(Note that for regular intervals, the library also provides mark=between positions <start> and <end> step <step> with <marking>.)

Code

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{decorations.markings}
\tikzset{
  set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
  set arrow inside={end/.initial=>, opt/.initial=},
  /pgf/decoration/Mark/.style={
    mark/.expanded=at position #1 with
    {\noexpand\arrow[\pgfkeysvalueof{/tikz/arrow inside/opt}]
      {\pgfkeysvalueof{/tikz/arrow inside/end}}}},
  arrow inside/.style 2 args={
    set arrow inside={#1},
    postaction={decorate,decoration={
        markings,Mark/.list={#2}}}},
}
\begin{document}
\tikz[thick]
  \draw[
    arrow inside={
      end=|,
      opt=red!\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}0!blue
    }{0, .05, .15, .3, .5, .7, .85, .95, 1},
  ] (0,0) to[bend left] (4,0);
\end{document}

Output

enter image description here