# key values getting improperly passed through a property list getter function

I'm creating rather complicated diagram and would like to put all the controls all in one easy to find location and not scattered throughout the document. To do this, I've created setter and getter functions for a LaTeX3 property list. Here's the code:

\documentclass{article}
\usepackage{pstricks,pst-node}
\usepackage{xparse}
\ExplSyntaxOn
\prop_new:N \g__sunset_plist
\NewDocumentCommand{\setattr}{ mm }
{
\prop_gput:Nnn \g__sunset_plist {#1} {#2}
}
\DeclareExpandableDocumentCommand{\gettr}{ m }
{
\prop_get:Nn \g__sunset_plist { #1 }
}
\ExplSyntaxOff
\setattr{my_linestyle}{linestyle=dashed,linecolor=blue}
\setattr{my_line}{\psline[linestyle=dashed,linecolor=blue](A)(B)}
\pagestyle{empty}
\begin{document}

\begin{pspicture}(10,10)

\pnode(0,0){A}
\pnode(10,10){B}
\pnode(10,0){C}
\pnode(0,10){D}

\gettr{my_line}   %% <-- works as expected
\psline[\gettr{my_linestyle}](C)(D)  %% <-- not working

\end{pspicture}

\end{document}


The line

    \gettr{my_line}   %% <-- works as expected


works but I don't want to approach the problem this way. I'd prefer to write

    \psline[\gettr{my_linestyle}](C)(D)  %% <-- not working


because this line shows me exactly what I'm doing: drawing a line from point C to point D. What's hidden are the attributes to that line. I'd prefer this approach. But what seems to be happening is that when \gettr{my_linestyle} is expanded, LaTeX sees:

    \psline[{linestyle=dashed,linecolor=blue}](C)(D)  %% <-- not working


How do I get my getter function to expand without the surrounding {...}?

EDIT

Here's the error message

! Package xkeyval Error: linestyle=dashed,linecolor=blue' undefined in familie
s ,pstricks,pst-node'.

See the xkeyval package documentation for explanation.
Type  H <return>  for immediate help.


So it seems that some kind of expansion is happening before xkeyval is getting the keys.

-
You must feed \psline with the list of options, not with something that ultimately expands to a list of options. –  egreg Feb 6 at 18:51
@egreg. That's what I was afraid of hearing. :( –  A.Ellett Feb 6 at 18:55
@A.Ellett This is general: most TeX keyval implementations are very careful to avoid any expansion of their argument. –  Joseph Wright Feb 6 at 19:32
@JosephWright, I guess I might have suspected that. But my error seems to suggest that \gettr{...} is getting expanded, but then placed within its own group before getting passed as keys. I was hoping there would be a trick to remove the surrounding parentheses before keyval got ahold of anything. –  A.Ellett Feb 6 at 19:56
–  Marco Daniel Feb 6 at 20:35
show 2 more comments

## 1 Answer

You can define a "prefix" macro:

\documentclass{article}
\usepackage{pstricks,pst-node}
\usepackage{xparse}
\ExplSyntaxOn
\prop_new:N \g__ellett_sunset_plist
\NewDocumentCommand{\setattr}{ mm }
{
\prop_gput:Nnn \g__ellett_sunset_plist {#1} {#2}
}
\NewDocumentCommand{\gettr}{ m }
{
\prop_get:Nn \g__ellett_sunset_plist { #1 }
}
\NewDocumentCommand{\expandoptions}{mO{}}
{
\use:x { \exp_not:N #1 [ #2 ] }
}
\ExplSyntaxOff

\setattr{my_linestyle}{linestyle=dashed,linecolor=blue}
\setattr{my_line}{\psline[linestyle=dashed,linecolor=blue](A)(B)}

\pagestyle{empty}

\begin{document}

\begin{pspicture}(10,10)
\pnode(0,0){A}
\pnode(10,10){B}
\pnode(10,0){C}
\pnode(0,10){D}

\gettr{my_line}   %% <-- works as expected
\expandoptions\psline[\gettr{my_linestyle}](C)(D)  %% <-- not working

\end{pspicture}

\end{document}


Using \use:x is a "last resort", but four expansions of \gettr still are far from the final result. Beware of other options containing dangerous tokens; text and lengths are safe.

-
Thank you. I like the \expandoptions macro. I'd been trying something like \exp_after:wN with very little success. It hadn't occurred to me to combine \use:x with \exp_not:N. –  A.Ellett Feb 6 at 23:27
add comment