You define parallel foreach
as being a style with parameter text #1in#2via#3
, with no spaces, and then you use:
parallel foreach = \x in {test} via \c
so the arguments to parallel foreach
are ␣\x␣
, ␣{test}␣
, and ␣\c
, then when you pass it to \getitem
, you have:
\clist_gset:Nn\g_list_clist␣{test}␣
The first space token is consumed by TeX when grabbing the second argument to \clist_gset:Nn
, but the second space is typeset in your node.
There are several possibilities here, for instance \tl_trim_spaces:n
:
\clist_gset:Nx \g_list_clist { \tl_trim_spaces:n {#1} }
(actually, the implementation is a bit more complicated to check for braces around the argument to parallel foreach
; see the code at the bottom of this answer). However expl3
provides \clist_item:nn
, so you can take items from a comma-separated list without storing it in a variable, which makes things simpler here:
\exp_args:Nx \clist_item:nn
{ \tl_trim_spaces:n {#1} } {#2}
Though this doesn't cope with the possibility of multiple items in the list because of the extra braces. You need to check if the argument to parallel foreach
is within braces, and if so remove them, with something like:
\NewDocumentCommand {\getitem} {m O{1}} {
\exp_args:Nx \clist_item:nn
{ \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n } {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
{
\tl_if_head_is_group:nTF {#1}
{ \exp_not:n #1 }
{ \exp_not:n {#1} }
}
With that, your code produces the expected output:
\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand {\getitem} {m O{1}} {
\exp_args:Nx \clist_item:nn
{ \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n } {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
{
\tl_if_head_is_group:nTF {#1}
{ \exp_not:n #1 }
{ \exp_not:n {#1} }
}
\ExplSyntaxOff
\pgfset{
foreach/parallel foreach/.style args={#1in#2via#3}{
evaluate=#3 as #1 using "before\getitem{#2}[#3]"
},
}
\begin{document}
\begin{tikzpicture}
\foreach \i [
count = \c,
parallel foreach = \x in {test,another} via \c,
] in {1,2}
\node at (1, \i) {blank\x};
\node at (1, -1) {no blank\getitem{{test}}[1]};
\end{tikzpicture}
\end{document}
And here's the code using a clist
variable rather than \clist_item:nn
:
\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}
\ExplSyntaxOn
\clist_new:N \g_list_clist
\NewDocumentCommand {\getitem} {m O{1}} {
\use:x
{
\clist_gset:Nx \exp_not:N \g_list_clist
{ \tl_trim_spaces_apply:nN {#1} \zhiyuan_remove_braces:n }
}
\clist_item:Nn \g_list_clist {#2}
}
\cs_new:Npn \zhiyuan_remove_braces:n #1
{
\tl_if_head_is_group:nTF {#1}
{ \exp_not:n #1 }
{ \exp_not:n {#1} }
}
\ExplSyntaxOff
\pgfset{
foreach/parallel foreach/.style args={#1in#2via#3}{
evaluate=#3 as #1 using "before\getitem{#2}[#3]"
},
}
\begin{document}
\begin{tikzpicture}
\foreach \i [
count = \c,
parallel foreach = \x in {test,another} via \c,
] in {1,2}
\node at (1, \i) {blank\x};
\node at (1, -1) {no blank\getitem{{test}}[1]};
\end{tikzpicture}
\end{document}