# How to create a variable number of arguments as PGF key?

Many interfaces use a variable number of arguments, for example in CSS

 margin:1pt 1pt 1pt 1pt


The clip functions of the graphics package also have similar examples.

Is this possible with PGF keys?

Please note that this should not be a comma delimited list.

\documentclass{article}
\usepackage{pgfkeys}
\begin{document}
\pgfkeyssetvalue{/test/test}{1pt 2pt 3pt 4pt}
\pgfkeysgetvalue{/test/test}{\test}
\end{document}


Essentially I am looking for a parser to grub a variable number of arguments and place them in individual macros.

A few ways...

Probably the simplest:

\documentclass[varwidth, border=5]{standalone}
\usepackage{tikz}

\tikzset{%
border/.style args={#1 #2 #3}{
border width=#1,
border style=#2,
border color=#3,
},
border width/.store in=\borderwidth,
border style/.store in=\borderstyle,
border color/.store in=\bordercolor,
}

\begin{document}
\ttfamily
\tikzset{border=20pt solid blue}
border: \borderwidth\ \borderstyle\ \bordercolor;

\tikzset{border=5pt dotted green}
border: \borderwidth\ \borderstyle\ \bordercolor;

\tikzset{border=15pt dashed red}
border: \borderwidth\ \borderstyle\ \bordercolor;
\end{document}


A bit more complicated, but allows partial specification...

\documentclass[varwidth, border=5]{standalone}
\usepackage{tikz}

\def\empty{}
\pgfkeys{utils/.cd,
set if not empty/.code 2 args={%
\def\arg{#2}%
\ifx\arg\empty%
\else%
\pgfkeys{#1={#2}}%
\fi%
}
}
\tikzset{%
border/.style={border ..=#1 {} {} {}},
border ../.style args={#1 #2 #3 #4}{
/utils/set if not empty={/tikz/border width}{#1},
/utils/set if not empty={/tikz/border style}{#2},
/utils/set if not empty={/tikz/border color}{#3}%,
},
border width/.store in=\borderwidth,
border style/.store in=\borderstyle,
border color/.store in=\bordercolor,
}

\def\borderwidth{1pt}
\def\borderstyle{solid}
\def\bordercolor{blue}

\begin{document}
\ttfamily
\tikzset{border=20pt}
border: \borderwidth\ \borderstyle\ \bordercolor;

\tikzset{border=5pt dotted}
border: \borderwidth\ \borderstyle\ \bordercolor;

\tikzset{border=15pt dotted red}
border: \borderwidth\ \borderstyle\ \bordercolor;
\end{document}


This final version is probably not exactly what is required but anyway but illustrates a general method for extracting space separated values in to separate keys...

\documentclass[varwidth, border=5]{standalone}
\usepackage{tikz}
\def\at{@}
\pgfkeys{/utils/.cd,
set keys/.style 2 args={
/utils/set keys ..={{0}{#1}#2 @ @}
},
set keys ../.code args={#1#2#3 #4}{%
\def\tmp{#3}%
\ifx\tmp\at%
\pgfkeys{#2\space n/.initial=\pgfmathresult}%
\else%
\pgfmathparse{int(#1+1)}%
\pgfkeys{#2\space\pgfmathresult/.initial=#3}%
\pgfkeys{/utils/set keys ..={\pgfmathresult}{#2}#4}%
\fi%
}
}
\tikzset{
test/.style={/utils/set keys={/tikz/test}{#1}}
}

\begin{document}
\tikzset{test={20pt 30pt 40pt 100pt}}
\pgfkeysgetvalue{/tikz/test n}\n
There were \n\ values
\foreach \i in {1,...,\n}{
\par\leavevmode
The value of test \i' is \pgfkeysvalueof{/tikz/test \i}
}
\end{document}


This gives:

• It is close to what I am looking for, however I am not really sure how you got the result. Do you mind adding some explanatory notes? How would you handle a different case say: border=1px solid blue where the values are not dimensions? Mar 28 '15 at 9:41
• @YiannisLazarides it doesn't matter whether the values are dimensions or not. I've provided a slightly different version which is a bit more relevant to your use-case. Mar 28 '15 at 10:15
• Thanks. This is perfect. What does the border ..= does? I mean the ..` I don't seem to fid anuything related in the manual. Mar 28 '15 at 10:37
• Brilliant! I see its just a string. Thanks for the help. Mar 28 '15 at 10:44