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}
  • 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 '18 at 0:03
10

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

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

  • 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. – Andrew Oct 29 '18 at 23:34
7

\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.

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.