# Adding introspection to TikZ/pgf shapes

After digging into the output of \tracingmacros=1 during a while, I'll ask here... I am trying to add a bit of introspection to pgf shapes. The idea is to be able to "extract" a \savedmacro of a shape.

To be more specific: is it possible to define the following \whatamI macro so that it expands to the shape (passed as argument) internal \Iam?

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\pgfdeclareshape{myA}{
\savedmacro{\Iam}{\edef\Iam{A}}
\anchor{center}{\pgfpointorigin}
\behindbackgroundpath{
\pgfnode{circle}{center}{\Iam}{}{\pgfusepath{stroke}}
}
}
\pgfdeclareshape{myB}{
\savedmacro{\Iam}{\edef\Iam{B}}
\anchor{center}{\pgfpointorigin}
\behindbackgroundpath{
\pgfnode{rectangle}{center}{\Iam}{}{\pgfusepath{stroke}}
}
}
\def\whatamI#1{%
% extract the saved macro \Iam definition
% return \relax or -NoItem- or whatever if not defined in the shape
% ???
}
\begin{document}
They works: \begin{tikzpicture}
% \tracingmacros=1
\node [myA](A) at(0,0) {};
% \tracingmacros=1
\node [myB](B) at(1,0) {};
% ...more code
\edef\nodeAis{\whatamI{A}} % so now I can do different things dinamically
\node [draw, rectangle,red,right] at (2,0) {%
Node A is \nodeAis};
\end{tikzpicture}

\end{document}


Notice that I really do not need to retrieve the instance-specific savedmacro of a shape through its label/name. Even being able to retrieve the last one specified or to retrieve the value in the shape text would suffice to me.

• Try \def\whatamI#1{\csname pgf@sh@ma@#1\endcsname\message{^^J^^J I am \Iam^^J^^J}}. – Symbol 1 Jul 25 '19 at 9:51

It seems the main problem is that you do not know where are the saved things. For macros, they are in \pgf@sh@ma@NAMEOFNODE where NAMEOFNODE is to be replaced with the name of the node.

For instance, if I insert \show\pgf@sh@ma@A in your code, I get

> \pgf@sh@ma@A=macro:
->\def \Iam {A}.


If, instead, I insert \show\pgf@sh@ma@B, I get

> \pgf@sh@ma@B=macro:
->\def \Iam {B}.


There will be multiple things if there are more than one saved macros. For example for the shape regular polygon from shapes.geometric, there are its saved macros

> \pgf@sh@ma@NAMEOFPOLYGON=macro:


Back to your question. To extract the \Iam of node (A), just execute \pgf@sh@ma@A and then \Iam will be defined to be A. Similarly if you execute \pgf@sh@ma@B then \Iam will be defined to be B.

So the following works

\begin{tikzpicture}
\node [myA](A) at(0,0) {};
\node [myB](B) at(1,0) {};
\node [draw, rectangle,red] at (3,0) {%
Node A is \pgf@sh@ma@A\Iam};
\node [draw, rectangle,green,right] at (5,0) {%
Node B is \pgf@sh@ma@B\Iam};
\end{tikzpicture}


P.S. Here is a list

• pgf@sh@ns@#1: "node shape", such as rectangle or circle.
• pgf@sh@np@#1: saved anchors and dimensions.
• pgf@sh@nt@#1: transformation applied to the node; this affects the position of anchors so it is worth remembering.
• pgf@sh@pi@#1: the picture id; this is used for remember picture etc.
• pgf@sh@ma@#1: saved macros as in this answer.