TikZ - foreach,扩展问题,可选参数和节点

TikZ - foreach,扩展问题,可选参数和节点

我正在尝试使用它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使一切正常……:-)

相关内容