10

I need to store tikz option in a \csdef{}:

\csdef{My Node Option}{draw=red, thick, fill=yellow}

How do I use this definition to define a style via \tikzset? I attempted to use .expand once as per How do I define tikz styles with a xkeyval command?:

\tikzset{Node Options/.style/.expand once=\csuse{My Node Option}}

but that leads to a

Package pgfkeys Error: I do not know the key '/tikz/draw=red, thick, fill=yellow' and I am going to ignore it. Perhaps you misspelled it.

The desired result is to modify only the \tikzset in the MWE and obtain:

enter image description here

Notes:

  • As egreg commented, spaces in names of commands should be avoided. However, in my actual use case, the command names defined by the csdef{} are named after file names with paths which include spaces, slashes, numbers, periods.

Code:

\documentclass{article}

\usepackage{tikz}
\usepackage{etoolbox}

\begin{document}


\csdef{My Node Option}{draw=red, thick, fill=yellow}

\noindent
\begin{tikzpicture}
    \tikzset{Node Options/.style/.expand once=\csuse{My Node Option}}%% ????

    \node [Node Options] at (0,0) {Node Text};
\end{tikzpicture}%
\end{document}
1
  • 2
    You'd need /.expand thrice, which doesn't exist. But /.expand twice=\csname My Node Option\endcsname works. I know that spaces in names of commands and options is bad. ;-)
    – egreg
    Oct 30, 2018 at 0:03

3 Answers 3

10

You can use expanded instead of expand once in your MWE:

\tikzset{Node Options/.style/.expanded=\csuse{My Node Option}}%% ????

1
  • 2
    +1 It's better to give a complete minimal working example as an answer to show that your solution works, but I agree that this does work and hence that this is probably the preferred tikz solution.
    – user30471
    Oct 29, 2018 at 23:34
8

\csuse{...} is not quite the same as \csname...\endcsname:

% etoolbox.sty, line 883:
\newcommand*{\csuse}[1]{%
  \ifcsname#1\endcsname
    \csname#1\expandafter\endcsname
  \fi}

If you expand once in your context you get

\ifcsname My Node Option\endcsname\csname My Node Option\endcsname\fi

A further expansion step will remove the conditional, leaving

\csname My Node Option\endcsname\fi

which requires two expansion steps in order to deliver

draw=red, thick, fill=yellow\fi

but then the \fi kicks in, because it is shuffled around at the wrong place.

You can do

\tikzset{Node Options/.style/.expand twice=\csname My Node Option\endcsname}

that avoids the problem of the dangling \if.

However, the best strategy, in my opinion, is to use styles all around:

\documentclass{article}

\usepackage{tikz}

\begin{document}

\tikzset{My Node Option/.style={draw=red, thick, fill=yellow}}

\begin{tikzpicture}
\tikzset{Node Options/.style=My Node Option}

\node [Node Options] at (0,0) {Node Text};
\end{tikzpicture} 

\end{document}
6

You can use the \begingroup\edef\x{\endgroup <stuff to expand>}\x expansion trick:

\documentclass{article}

\usepackage{tikz}
\usepackage{etoolbox}

\begin{document}

\csdef{My Node Option}{draw=red, thick, fill=yellow}

\noindent
\begin{tikzpicture}
  \begingroup\edef\x{\endgroup
    \noexpand\tikzset{Node Options/.style={\csuse{My Node Option}}}}%
  \x

  \node [Node Options] at (0,0) {Node Text};
\end{tikzpicture}%

\end{document}

Note the additional braces around the \csuse.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .