TeX - LaTeX Asked on September 20, 2020
I am trying to use foreach
to simplify the 1st env. code in my MN(ot)WE below.
There is an expansion problem regarding the optional argument in the 2nd code. Here is the output.
How can I fix this ?
documentclass[12pt]{article}
RequirePackage{forest}
usetikzlibrary{calc}
useforestlibrary{linguistics}
newcommandptreeComment[3][black]{
node [anchor=mid west] at (#2.mid -| ptreecomment coord) {%
textcolor{#1}{#3}%
};
}
begin{document}
begin{forest}
for tree = {%
sn edges,
grow' = 0,
l = 2.5cm,
s sep = 1.2cm,
anchor = parent,
},
tikz+={
coordinate (ptreecomment coord) at (current bounding box.east);
},
[
[$A$
[$B$, name = nB]
[$C$, name = nC]
]
[$D$
[$E$, name = nE]
[$F$, name = nF]
]
]
%
ptreeComment{nB}{$X = 1$}
ptreeComment[red]{nC}{$X = 3$}
ptreeComment[orange]{nE}{$X = 3$}
ptreeComment[black!60!green]{nF}{$X = 5$}
end{forest}
begin{forest}
for tree = {%
sn edges,
grow' = 0,
l = 2.5cm,
s sep = 1.2cm,
anchor = parent,
},
tikz+={
coordinate (ptreecomment coord) at (current bounding box.east);
},
[
[$A$
[$B$, name = nB]
[$C$, name = nC]
]
[$D$
[$E$, name = nE]
[$F$, name = nF]
]
]
%
foreach color/name/text in {black/nB/$X = 1$,
red/nC/$X = 3$,
orange/nE/$X = 3$,
black!60!green/nF/$X = 5$}
{
ptreeComment[color]{name}{text}
}
end{forest}
end{document}
On the other hand, the following code works without problem.
documentclass[12pt]{article}
RequirePackage{tikz}
newcommandtest[2][black]{
Option: #1 et Arg: #2par
}
newcommandcolorize[2][black]{
textcolor{#1}{#2}par
}
begin{document}
foreach opt/arg in {black/nB,red/nC,orange/nE,green/nF}{
test[opt]{arg}
}
bigskip
foreach opt/arg in {black/nB,red/nC,orange/nE,green/nF}{
colorize[opt]{arg}
}
end{document}
The problem comes indeed from the use of the name color
. The use of col
makes all things work... :-)
Answered by projetmbc on September 20, 2020
I don't know why you define a function to change nodes when all you have to do is create a style.
Here, I created the my note
style which has 3 arguments : color, name, and text.
my note/.style n args={3}{text=#1,name=#2,label={[#1]right:#3}},
my note/.default={black}{}{},
documentclass[12pt]{article}
RequirePackage{forest}
usetikzlibrary{calc}
useforestlibrary{linguistics}
%newcommandptreeComment[3][black]{
% node [anchor=mid west] at (#2.mid -| ptreecomment coord) {%
% textcolor{#1}{#3}%
% };
%}
begin{document}
begin{forest}
my note/.style n args={3}{text=#1,name=#2,label={[#1]right:#3}},
my note/.default={black}{}{},
for tree = {%
sn edges,
grow' = 0,
l = 2.5cm,
s sep = 1.2cm,
anchor = parent,
},
tikz+={
coordinate (ptreecomment coord) at (current bounding box.east);
},
[
[$A$
[$B$,my note]
[$C$,my note ={red}{nC}{$X=3$}]
]
[$D$
[$E$,my note ={blue}{nE}{$X=3$}]
[$F$,my note ={black!60!green}{nF}{$X=5$}]
]
]
%
% ptreeComment{nB}{$X = 1$}
% ptreeComment[red]{nC}{$X = 3$}
% ptreeComment[orange]{nE}{$X = 3$}
% ptreeComment[black!60!green]{nF}{$X = 5$}
end{forest}
end{document}
Answered by AndréC on September 20, 2020
You should be more careful when choosing names for local variables in foreach
:
% xcolor.sty, line 756:
deftextcolor#1#{@textcolor{#1}}
% xcolor.sty, line 757:
def@textcolor#1#2#3{protectleavevmode{color#1{#2}#3}}
You're using textcolor
, which internally uses color
: if you redefine color
you can't expect that `textcolor works; actually you clearly see why the color name is printed.
There is a different way to cope with the problem, without using local variables.
documentclass[12pt]{article}
usepackage{forest}
usetikzlibrary{calc}
useforestlibrary{linguistics}
usepackage{xparse}
ExplSyntaxOn
NewDocumentCommand{lforeach}{ s O{} m +m }
{
IfBooleanTF{#1}
{
manual_lforeach:non { #2 } { #3 } { #4 }
}
{
manual_lforeach:nnn { #2 } { #3 } { #4 }
}
}
int_new:N g__manual_foreach_map_int
cs_new_protected:Nn manual_lforeach:nnn
{
keys_set:nn { manual/lforeach } { single }
keys_set:nn { manual/lforeach } { #1 }
clist_set:Nn l__manual_lforeach_list_clist { #2 }
int_gincr:N g__manual_foreach_map_int
__manual_lforeach_define:n { #3 }
clist_map_inline:Nn l__manual_lforeach_list_clist
{
use:c { __manual_lforeach_ int_use:N g__manual_foreach_map_int _action:w } ##1 q_stop
}
int_gdecr:N g__manual_foreach_map_int
}
cs_generate_variant:Nn manual_lforeach:nnn { no }
cs_new_protected:Nn __manual_lforeach_define:n
{
exp_last_unbraced:NcV
cs_set:Npn
{ __manual_lforeach_ int_use:N g__manual_foreach_map_int _action:w }
l__manual_lforeach_format_tl
q_stop
{#1}
}
keys_define:nn { manual/lforeach }
{
format .tl_set:N = l__manual_lforeach_format_tl,
single .code:n = tl_set:Nn l__manual_lforeach_format_tl { ##1 },
double .code:n = tl_set:Nn l__manual_lforeach_format_tl { ##1/##2 },
triple .code:n = tl_set:Nn l__manual_lforeach_format_tl { ##1/##2/##3 },
}
ExplSyntaxOff
newcommandptreeComment[3][black]{%
node [anchor=mid west] at (#2.mid -| ptreecomment coord) {%
textcolor{#1}{#3}%
};
}
begin{document}
begin{forest}
for tree = {%
sn edges,
grow' = 0,
l = 2.5cm,
s sep = 1.2cm,
anchor = parent,
},
tikz+={
coordinate (ptreecomment coord) at (current bounding box.east);
},
[
[$A$
[$B$, name = nB]
[$C$, name = nC]
]
[$D$
[$E$, name = nE]
[$F$, name = nF]
]
]
%
lforeach[triple]% triple means #1/#2/#3
{
black/nB/$X = 1$,
red/nC/$X = 3$,
orange/nE/$X = 3$,
black!60!green/nF/$X = 5$
}
{ptreeComment[#1]{#2}{#3}}
end{forest}
end{document}
The macro lforeach
has an optional argument for stating options; the possible ones are
single
(default), when you only want to cycle over a standard comma separated list;double
if the list is of the form 1/a,2/b,...
and the items before and after the /
are referred to with #1
and #2
;triple
if the list is of the form `1/a/i,2/b/ii,... (used in the example);format
to choose whatever delimiters you wish, with any number of arguments (up to nine, of course); for instance, triple
is the same as format=#1/#2/#3
.The *-variant expands once the first mandatory argument (if the list is stored in a macro). The first mandatory argument has the list, the second one has the code to be executed, where instead of “variables” you use #1
, #2
and so on.
For instance, you get the same output with
lforeach[format=C(#1)N(#2)T(#3)]
{
C(black)N(nB)T($X = 1$),
C(red)N(nC)T($X = 3$),
C(orange)N(nE)T($X = 3$),
C(black!60!green)N(nF)T($X = 5$)
}
{ptreeComment[#1]{#2}{#3}}
(this is just for showing the possibilities).
Answered by egreg on September 20, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP