# How to pass a macro as a value for a key?

I want to pass a macro to a showgrid key. The macro can be redefined later. Its possible values are top, bottom, false, true.

The following MWE produces a blank page. How to fix it?

\documentclass[border=12pt,pstricks]{standalone}
\usepackage{pstricks}

\def\status{true}

\begin{document}

\begin{pspicture}[showgrid=\status](3,3)
\end{pspicture}

\end{document}

-

The reason is the definition of the key. The value of the key isn't expanded and the resulting test fails. You can use the following redefinition:

\makeatletter
\define@key[psset]{pstricks}{showgrid}[b]{\expandafter\pst@@showgrid#1\@nil}
\makeatother


The expansion above works only once. To expand the value of the key you can use:

\makeatletter
\define@key[psset]{pstricks}{showgrid}[b]{\begingroup\edef\x{\endgroup\noexpand\pst@@showgrid#1\noexpand\@nil}\x}
\makeatother


Here the example:

\documentclass[border=12pt,pstricks]{standalone}
\usepackage{pstricks}

\def\status{true}
\makeatletter
\define@key[psset]{pstricks}{showgrid}[b]{\expandafter\pst@@showgrid#1\@nil}
\makeatother

\begin{document}
\def\status{true}
\begin{pspicture}[showgrid=\status](3,3)
\end{pspicture}

\end{document}

-
This gives ! Undefined control sequence. <recently read> \pst@@showgrid. Do I have to update something? – Ahmed Musa Aug 9 '12 at 0:40
@AhmedMusa: I working with TeX Live 2012 and it works without any problems. – Marco Daniel Aug 9 '12 at 5:28

Unlike pgfkeys, the xkeyval package has no provision for expanding the value of a key at \setkeys. However, Marco Daniel's solution is so specific for a particular key as to be inapplicable for other keys, even within pstricks. Here is a general solution, which I have adapted from the development version of the keyreader package to suit the existing code of xkeyval. The idea is to use pointers to indicate the user's desire to expand (fully or partially) the value of a key.

\documentclass{article}
\usepackage{pstricks}

\makeatletter
\def\XKV@s@tkeys#1#2{%
\XKV@sp@deflist\XKV@na{#2}%
\XKV@for@n{#1}\CurrentOption{%
\XKV@expandvalueasneeded
\expandafter\XKV@s@tk@ys\CurrentOption==\@nil
}%
}
\def\XKV@expandvalueasneeded{%
\begingroup
\def\reserved@a##1##2\@nil##3{%
\def\reserved@a####1##1####2####3\@nil{%
\ifx\@nnil####2\else
\edef\CurrentOption{##3=####2{##2}}%
\fi
}%
\reserved@a
\expanded\@iden\expandonce{\unexpanded\expandafter}%
##1\@nnil\@nil
}%
\def\reserved@b##1=##2=##3\@nil{%
\if\relax\detokenize{##2}\relax\else
\reserved@a##2\@nil{##1}%
\fi
}%
\expandafter\reserved@b\CurrentOption==\@nil
\edef\x{\endgroup\edef\noexpand\CurrentOption
{\noexpand\unexpanded{\unexpanded\expandafter{\CurrentOption}}}}\x
}
\makeatother

\begin{document}
\def\status{true}
\def\sstatus{\status}

\newpsstyle{gridstyle}{subgriddiv=2}
\begin{pspicture}[showgrid=\expandonce{\status}](-1,0)(2,2)
%\begin{pspicture}[showgrid=\expanded{\sstatus}](-1,0)(2,2)
\end{pspicture}

\end{document}


On this site I have seen people trying to use keys defined as macros. So here is a solution that will accept even macros as keys.

\documentclass{article}
\usepackage{pstricks}

\makeatletter
\def\XKV@g@tkeyname#1=#2\@nil#3{%
\XKV@ifcmd{#1}\savevalue#3{%
\XKV@rkvtrue\XKV@sgfalse
}{%
\XKV@ifcmd{#1}\gsavevalue#3{%
\XKV@rkvtrue\XKV@sgtrue
}{%
\XKV@rkvfalse\XKV@sgfalse
}%
}%
\expandafter\XKV@ifcmd\expandafter{#3}\xkvexpanded#3{%
\edef#3{#3}%
}{%
\expandafter\XKV@ifcmd\expandafter{#3}\xkvexpandonce#3{%
\edef#3{\unexpanded\expandafter{#3}}%
}{}%
}%
}
\def\XKV@s@tkeys#1#2{%
\XKV@sp@deflist\XKV@na{#2}%
\XKV@for@n{#1}\CurrentOption{%
\begingroup
\@tempcnta\z@
\XKV@expandkvasneeded
\edef\x{\endgroup\edef\noexpand\CurrentOption
{\noexpand\unexpanded{\unexpanded\expandafter{\CurrentOption}}}}\x
\expandafter\XKV@s@tk@ys\CurrentOption==\@nil
}%
}
\def\XKV@expandkvasneeded{%
\def\reserved@a##1##2\@nil##3{%
\def\reserved@a####1##1####2####3\@nil{%
\ifx\@nnil####2\else
\ifnum\@tempcnta=\z@
\edef\CurrentOption{####2{##2}=\unexpanded{##3}}%
\else
\edef\CurrentOption{##3=####2{##2}}%
\fi
\fi
}%
\reserved@a
\xkvexpanded\@iden\xkvexpandonce{\unexpanded\expandafter}##1\@nnil\@nil
}%
\def\reserved@b##1=##2=##3\@nil{%
\ifnum\@tempcnta=\z@
\reserved@a##1\@nil{##2}%
\else
\if\relax\detokenize{##2}\relax\else
\reserved@a##2\@nil{##1}%
\fi
\fi
}%
\expandafter\reserved@b\CurrentOption==\@nil
\ifnum\@tempcnta=\@ne\else
\@tempcnta\@ne
\expandafter\XKV@expandkvasneeded
\fi
}
\let\xkvexpanded\relax
\let\xkvexpandonce\relax
\makeatother

\begin{document}
\def\status{true}
\def\sstatus{\status}
\def\showgrid{showgrid}

\newpsstyle{gridstyle}{subgriddiv=2}
\begin{pspicture}[\xkvexpanded{\showgrid}=\xkvexpandonce{\status}](-1,0)(2,2)
%\begin{pspicture}[showgrid=\xkvexpanded{\sstatus}](-1,0)(2,2)
\end{pspicture}
\end{document}

-