我正在尝试使用它foreach
来简化下面 MN(ot)WE 中的第一个环境代码。
第二段代码中可选参数存在扩展问题。输出如下。
我怎样才能解决这个问题 ?
\documentclass[12pt]{article}
\RequirePackage{forest}
\usetikzlibrary{calc}
\useforestlibrary{linguistics}
\newcommand\ptreeComment[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}
另一方面,下面的代码可以正常运行。
\documentclass[12pt]{article}
\RequirePackage{tikz}
\newcommand\test[2][black]{
Option: #1 et Arg: #2\par
}
\newcommand\colorize[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}
答案1
在选择局部变量的名称时应该更加小心\foreach
:
% xcolor.sty, line 756:
\def\textcolor#1#{\@textcolor{#1}}
% xcolor.sty, line 757:
\def\@textcolor#1#2#3{\protect\leavevmode{\color#1{#2}#3}}
您正在使用\textcolor
,其内部使用\color
:如果您重新定义,\color
您不能指望`\textcolor 起作用;实际上您清楚地看到了为什么打印颜色名称。
还有一种不同的方法来解决这个问题,无需使用局部变量。
\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
\newcommand\ptreeComment[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}
该宏\lforeach
有一个可选参数,用于说明选项;可能的选项包括
single
(默认),当您只想循环标准逗号分隔列表时;double
如果列表的形式为1/a,2/b,...
,并且之前和之后的项目用和/
来引用;#1
#2
triple
如果列表的形式为“1 / a / i,2 / b / ii,... ”(在示例中使用);format
选择您想要的任何分隔符,并使用任意数量的参数(当然最多九个);例如,triple
与 相同format=#1/#2/#3
。
*-variant 会扩展第一个强制参数(如果列表存储在宏中)。第一个强制参数包含列表,第二个包含要执行的代码,其中您使用 而不是“变量” #1
,#2
依此类推。
例如,使用以下命令可获得相同的输出
\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}}
(这只是为了展示可能性)。
答案2
我不知道为什么要定义一个函数来改变节点,而你所要做的只是创建一种样式。
在这里,我创建了my note
具有 3 个参数的样式:颜色、名称和文本。
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}
%\newcommand\ptreeComment[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}
答案3
问题确实来自于名称的使用\color
。使用\col
使一切正常……:-)