tikz add tag
samcarter
Inspired by [this question](https://topanswers.xyz/tex?q=2028), I wanted to add pics for the TikZlings. Some code like


\documentclass{standalone}
\usepackage{tikzlings}

\tikzset{
anteater/.pic={\anteater},
anteater/.search also={,/tikz,/pgf,/thing},
bear/.pic={\bear},
bear/.search also={,/tikz,/pgf,/thing},
cat/.pic={\cat},
cat/.search also={,/tikz,/pgf,/thing},
% ...
}

\tikzset{
thing/.search also={,/tikz,/pgf},
}

\begin{document}
\begin{tikzpicture}[scale=2]
\draw(0,0) grid(4,4);
\draw(0,0) --++(0.5,0.5) pic{bear}
--++(1,1)     pic[cat/body=red,scale=0.5]{cat}
--++(1,1)     pic[thing/hat=red]{bear};
\end{tikzpicture}
\end{document}


seems to work fine, but having a long hard coded list of tikzlings makes adding new ones error prone.

So I thought that maybe one could use something similar to

https://github.com/samcarter/tikzlings/blob/main/tikzlings.sty#L68-L90

which would iterate over a list that looks similar to this:


\def\tikzling@list{
anteater/anteaters,
bear/bears,
cat/cats%
}


I tried to modify the code, but I must do something horrible wrong because it exploded quite spectacularly:


\documentclass{standalone}
\usepackage{tikzlings}

\makeatletter
\ExplSyntaxOn

\cs_new:Npn \tikzlings_iterate_pic:N #1 {
\clist_map_function:NN #1 \__tikzlings_pic_items:n
}

\cs_new:Npn \__tikzlings_pic_items:n #1 {
\exp_not:N {
\__tikzlings_before_slash:w #1 / \s_stop
}
/.pic{
\exp_not:c {
\__tikzlings_before_slash:w #1 / \s_stop
}
},
\exp_not:N {
\__tikzlings_before_slash:w #1 / \s_stop
}
/.search also={,/tikz,/pgf,/thing},
}
\cs_new_eq:NN \tikzling@iterate_pic \tikzlings_iterate_pic:N

\ExplSyntaxOff

\ExpArgsNnx\tikzset{\tikzling@iterate_pic\tikzling@list}
\makeatother

\begin{document}
\begin{tikzpicture}[scale=2]
\draw(0,0) grid(4,4);
\draw(0,0) --++(0.5,0.5) pic{bear};
\end{tikzpicture}
\end{document}


Top Answer
Phelype Oleinik
The first error:

! Undefined control sequence.
\pgfkeyscurrentkey ->\tikzling@iterate
_pic\tikzling@list
l.32 \makeatother

?

is because you are mixing expl3 syntax with 2e syntax in \tikzset{\tikzling@iterate_pic\tikzling@list}, but you did \ExplSyntaxOff just before that, so \tikzling@iterate_pic is seen as \tikzling@iterate _pic.  Avoid mixing syntaxes; use \tikzling@iterate@pic here.

---

After fixing that, the next error is more cryptic:

! Argument of \reserved@a has an extra }.
<inserted text>
\par
l.32 \makeatother

?

which shows the error in the \makeatother line, but it is actually because of \ExpArgsNnx.  It takes three arguments:  an N argument (a single token which will not be expanded), an n argument (a braced group of tokens which will not be expanded), and an x argument (a braced group of tokens that will be x-(\edef-)expanded).  If you look at the code (newlines added for clarity):


\makeatother                            % x

you can see that what is actually being x-expanded is \makeatother, and not \tikzling@iterate@pic as you wanted (that's why the error shows in the \makeatother line).

Here you want \ExpArgsNx, so you can do \cs_new_eq:NN \ExpArgsNx \exp_args:Nx or if you don't care about compatibility with older LaTeX you can use the newly added \ExpArgs{x} (the first argument is always N so it is assumed for \ExpArgs):


\ExpArgs{x}\tikzset{\tikzling@iterate@pic\tikzling@list}
% or \cs_new_eq:NN \ExpArgsNx \exp_args:Nx then
% \ExpArgsNx\tikzset{\tikzling@iterate@pic\tikzling@list}


---

After that, the error is because you wrote:

\exp_not:N {
\__tikzlings_before_slash:w #1 / \s_stop
}
/.pic{
\exp_not:c {
\__tikzlings_before_slash:w #1 / \s_stop
}
}

If you replace \__tikzlings_before_slash:w #1 / \s_stop by (say) anteater, you get:

\exp_not:N { anteater } /.pic{ \exp_not:c { anteater } }

The \exp_not:N here is doing nothing because it's acting on {, which doesn't expand anyway, so it can go.  Then you have {anteater} as a key, but keys don't go in braces, so you can remove those too.  Then you are missing a = after .pic.

---

Finally you have an easy one:

! Package pgfkeys Error: I do not know the key '/tikz/anteater/.searchalso', to
which you passed ',/tikz,/pgf,/thing', and I am going to ignore it. Perhaps yo
u misspelled it.

Remember that spaces matter in PGF keys, but not in expl3 syntax, so you have to write .search~also, and after that the code will work.

---

You can make your code easier to read if you first expand \__tikzlings_before_slash:w #1 / \s_stop to get the TikZling name, and pass that to an auxiliary:

\cs_new:Npn \__tikzlings_pic_items:n #1
{
\exp_args:No \__tikzlings_pic_items_aux:n
{ \__tikzlings_before_slash:w #1 / \s_stop }
}
\cs_new:Npn \__tikzlings_pic_items_aux:n #1
{
#1/.pic = { \exp_not:c {#1} },
#1/.search~also = {,/tikz,/pgf,/thing},
}


---

Full code:

\documentclass{standalone}
\usepackage{tikzlings}

\makeatletter
\ExplSyntaxOn

\cs_new:Npn \tikzlings_iterate_pic:N #1
{ \clist_map_function:NN #1 \__tikzlings_pic_items:n }

\cs_new:Npn \__tikzlings_pic_items:n #1
{
\exp_args:No \__tikzlings_pic_items_aux:n
{ \__tikzlings_before_slash:w #1 / \s_stop }
}
\cs_new:Npn \__tikzlings_pic_items_aux:n #1
{
#1/.pic = { \exp_not:c {#1} },
#1/.search~also = {,/tikz,/pgf,/thing},
}
\cs_new_eq:NN \tikzling@iterate@pic \tikzlings_iterate_pic:N

\ExplSyntaxOff

\ExpandArgs{x}\tikzset{\tikzling@iterate@pic\tikzling@list}
% or \cs_new_eq:NN \ExpArgsNx \exp_args:Nx then
% \ExpArgsNx\tikzset{\tikzling@iterate@pic\tikzling@list}
\makeatother

\begin{document}
\begin{tikzpicture}[scale=2]
\draw(0,0) grid(4,4);
\draw(0,0) --++(0.5,0.5) pic{bear};
\end{tikzpicture}
\end{document}


Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.