0

In an ideal world latex-ing this document

\documentclass{article}
\usepackage{tikz}
\begin{document}
  \pgfkeys{/a/.code=(a)}
  \pgfkeys{/a}
  \def\b{\pgfkeys{/a}}
  \b
  \edef\c{\pgfkeys{/a}}
  \c
\end{document}

would create a document containg "(a)(a)(a)"... but in the real world the line "\edef\c{\pgfkeys{/a}}" puts PGF in a loop, and if I interrupt pdflatex or lualatex with a C-c I get this message:

! Interruption.
\pgfkeys@parse ...uturelet \pgfkeys@possiblerelax 
                                                  \pgfkeys@parse@main 
l.33 \edef\c{\pgfkeys{/a}
                       }
? 

What is the recommended workaround?

Note: this is a minimal version of this other question: How do I send the result of \pgfkeys to Lua?

1
  • 1
    You cannot have \pgfkeys in an \edef. Well, strictly speaking you can, but this will never set the key, because \edef doesn't perform assignments.
    – egreg
    Nov 1, 2022 at 9:27

3 Answers 3

4

\pgfkeys is not expandable. There is no way to get your \edef working.

The expkv package offers expandable key-value commands. With it your example works:

\documentclass{article}
\usepackage{expkv}
\begin{document}
\ekvdefNoVal{fam}{a}{(a)}

\ekvset{fam}{a}

\def\b{\ekvset{fam}{a}}
\b

\edef\c{\ekvset{fam}{a}}
\c
\end{document}

But be aware that it depends a lot on the actual action of your keys. If your code does more complicated things than priting (a) it can break again if you don't protect it properly.

2

As I've explained somewhere else the \pgfkeys macro and its derivatives do a lot more than just call the .code you've defined.

You're going to have to use the internal macro that is actually called by PGFkeys when it is done parsing a key-value pair:

\edef\c{\pgfkeysvalueof{/a/.@cmd}\pgfeov}

(Every .code key is internally defined as the macro \pgfk@/full/path to/key/.@cmd delimited by \pgfeov where \pgfkeysvalueof is a fancy way to call \csname pgfk@#1.)

If you need to use this often, you might want to define your own macro \pgfkeyscall:

\newcommand\pgfkeyscall[2]{\pgfkeysvalueof{#1/.@cmd}#2\pgfeov}

which you can then use as

\edef\c{\pgfkeyscall{/a}{}}

Though, in this simple case where /b doesn't do anything, you might just want to use a value-key that just stores the content which is also fully expandable by using \pgfkeysvalueof{/b} (which should be able to be forwarded to Lua without edefing it).

\pgfkeys{/b/.initial=(b)}
\edef\c{\pgfkeysvalueof{/b}}
\c
% or
\pgfkeysgetvalue{/b}\c % no edef
\c

Code

\documentclass{article}
\usepackage{pgfkeys}
\newcommand\pgfkeyscall[2]{\pgfkeysvalueof{#1/.@cmd}#2\pgfeov}
\pgfkeys{
  /a/.code=(a),
  /b/.initial=(b)}
\begin{document}
  \pgfkeys{/a,/b}
  
  \edef\c{\pgfkeyscall{/a}{}}%
  \c
  \pgfkeysgetvalue{/b}\c
  \c
\end{document}

Output

(a)(b)
(a)(b)

1

The answer given below is wrong, see this question and answer for why and how.

Original answer here:

I assume what you are trying to do is set \c to have the same value as the expansion of \pgfkeys{/a}, but doing so with \edef causes an infinite loop (someone with much more experience than me can probably tell you why).

The following works (spaces may not quite be right, you can adjust and fiddle as needed)

\documentclass{article}
\usepackage{tikz}
\begin{document}
  \pgfkeys{/a/.code=(a)}
  \pgfkeys{/a}
  \def\b{\pgfkeys{/a}}
  \b
  \expandafter\def\c{\pgfkeys{/a}}
  \c
\end{document}

The result is (a) (a) (a) (my PDF appears to have more space between the first and second than between the second and third, which is why you may need to adjust something somewhere. I don't know where. Sprinkling % at line ends appropriately will possibly fix it.)

1
  • sorry this is completely wrong \expandafter\def\c accidentally fails to give an error as \c is defined as cedilla so it does not define \c but \T1-cmd (so breaks accents) Nov 1, 2022 at 8:15

You must log in to answer this question.

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