4

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.

5

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}

enter image description here

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}

enter image description here

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:

enter image description here

  • 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? – Yiannis Lazarides 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. – Mark Wibrow 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. – Yiannis Lazarides Mar 28 '15 at 10:37
  • Brilliant! I see its just a string. Thanks for the help. – Yiannis Lazarides Mar 28 '15 at 10:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.