为什么 SplitArgument 在这里不能按预期工作?

为什么 SplitArgument 在这里不能按预期工作?

我正在尝试定义宏来根据应该放入其中的文本设置 TikZ 节点的大小和位置。由于存在多个相似但不完全相同且复杂程度不同的节点,我尝试将它们的共同点提取到内部宏中,但不知何故,xparse\SplitArgument无法按预期工作。

以下是 MWE:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{varwidth}
\usepackage{xparse}
\newsavebox\testTempBox
\NewDocumentCommand{\commonFunction}{+m}{%
    \begin{lrbox}{\testTempBox}%
    \begin{varwidth}{6cm}%
        #1%
    \end{varwidth}%
    \end{lrbox}%
    \the\wd\testTempBox;\the\ht\testTempBox
    %Function is simplified a lot; has more inputs and outputs
}
\NewDocumentCommand{\variationA}{+m}{%
    \variationAInternal{#1}{\commonFunction{#1}}
}
\NewDocumentCommand{\variationAInternal}{+m >{\SplitArgument{1}{;}}m}{%
    \variationAInternalInternal{#1}#2\\
}
\NewDocumentCommand{\variationAInternalInternal}{m m m}{%
    #2%
    %\node[trapezium, ...] at (#4, #5) {\parbox{#3}{\centering #1}};
}
\NewDocumentCommand{\variationB}{+m}{%
    \variationBInternal{#1}{\commonFunction{#1}}
}
\NewDocumentCommand{\variationBInternal}{+m >{\SplitArgument{1}{;}}m}{%
    #2
    %\node[rectangle, ...] at (#4,#5) {\parbox{#3}{\centering #1}};
}
\begin{document}
\begin{tabular}{l}
\variationA{Test 1:\\Some Test}\\
\variationB{Test 2:\\Second Test}
\end{tabular}
\end{document}

分裂失败

我也尝试过使用标识符和\csname类似的东西,但我不知道为什么高度有效但宽度无效:

\documentclass[a7paper,landscape]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage{varwidth}
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric, arrows}
\newsavebox\tmpBox
\NewDocumentCommand{\commonFunction}{m +m}{%
    %still less complex than the original
    \expandafter\newsavebox\csname box#1\endcsname%
    \begin{lrbox}{\csname box#1\endcsname}
    \begin{varwidth}{6cm}
        #2
    \end{varwidth}
    \end{lrbox}
    \expandafter\newlength\csname tw#1\endcsname%
    \expandafter\newlength\csname w#1\endcsname%
    \expandafter\newlength\csname h#1\endcsname%
    \expandafter\setlength\csname tw#1\endcsname{\expandafter\wd\csname box#1\endcsname}%
    \expandafter\setlength\csname w#1\endcsname{\dimexpr\expandafter\wd\csname box#1\endcsname + 4ex\relax}%
    \expandafter\setlength\csname h#1\endcsname{\dimexpr\expandafter\ht\csname box#1\endcsname + 2ex\relax}%
}
\NewDocumentCommand{\startstop}{m +m}{%
    \commonFunction{#1}{#2}%
    \node[draw, rectangle, rounded corners, minimum width=\csname w#1\endcsname, minimum height=\csname h#1\endcsname, fill=red!30] at (0,0) {\parbox{\csname tw#1\endcsname}{\centering #2}};
}
\begin{document}
\begin{tikzpicture}
\startstop{FlowStart}{Start:\\Test}
\end{tikzpicture}
\end{document}

csname 失败

答案1

你的第二个论点\variationAInternal是。其中\commonFunction{Test 1:\\Some Test}没有。;

在不知道您的实际用例有多复杂的情况下,我会先执行lrbox前面的操作\variationAInternal,然后将\thes 转发到内部函数(然后您就已经可以使用正常的ms 了)。

\exp_args:Nnff什么也不做,只是f在将其转发给第一个参数之前扩展了它的第三和第四个参数。(这可能不是必需的,但谁知道在访问其维度\testTempBox之前还发生了什么\variationAInternal。)

由于 PGF/TikZ 会卸载图片中的常规字体(并为节点或重新安装它们\pgftext),因此您需要在或环境\pgfutil@selectfont开始时使用。这显然会忽略节点的任何字体选择,但会拾取之前对字体所做的任何其他更改。lrboxvarwidth\variationA

代码

\documentclass{standalone}
\usepackage{tikz}
\usepackage{varwidth}
\newsavebox\testTempBox

\makeatletter % for \pgfutil@selectfont
\NewDocumentCommand{\commonFunction}{+m}{%
    \begin{lrbox}{\testTempBox}%
    \begin{varwidth}{6cm}%
        \pgfutil@selectfont#1%
    \end{varwidth}%
    \end{lrbox}%
    %Function is simplified a lot; has more inputs and outputs
}
\makeatother
\ExplSyntaxOn % for \exp_args
\NewDocumentCommand{\variationA}{+m}{
    \commonFunction{#1}
    \exp_args:Nnff \variationAInternal { #1 } % no expand
                                       { \the\wd\testTempBox } % fully expand
                                       { \the\ht\testTempBox } % fully expand
}
\ExplSyntaxOff
\NewDocumentCommand{\variationAInternal}{+m m m }{
    \node[draw, align=center,
      label={[node font=\tiny,xscale=.5]#2${}\times{}$#3}]{#1};
}
\begin{document}
\begin{tikzpicture}
\variationA{Test 1:\\Some Test}
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案2

如果你有

\NewDocumentCommand{\foo}{>{\SplitArgument{;}{1}}m}{...#1...}

调用如下

\foo{a;b}

会导致

...{a}{b}...

然而

\foo{a}

会导致

...{a}{-NoValue-}...

通常情况下

\NewDocumentCommand{\foo}{>{\SplitArgument{;}{1}}m}{%
  ...\fooaux#1...%
}

其中\fooaux是一个带有两个强制参数的命令,您可以检查\IfNoValueTF{#2}是否-NoValue-传递了该参数。

让我们看看当你调用时会发生什么

\variationA{Test 1:\\Some Test}

根据定义,

\variationAInternal{Test 1:\\Some Test}{\commonFunction{Test 1:\\Some Test}}

现在你\variationAInternal有参数说明符

+m
>{\SplitArgument{1}{;}}m

还有分号。因此你得到

\variationAInternalInternal{Test 1:\\Some Test}{\commonFunction{Test 1:\\Some Test}}{-NoValue}\\

所以你最终得到的是

\commonFunction{Test 1:\\Some Test}\\

现在让我们检查一下

\variationB{Test 2:\\Second Test}

这转化为

\variationBInternal{Test 2:\\Second Test}{\commonFunction{Test 1:\\Second Test}}

这变成了

{\commonFunction{Test 1:\\Second Test}}{-NoValue-}

这解释了输出。我不确定您期望得到什么;但是如果您不使用分号,则无法进行拆分,并且您始终会得到一-NoValue-对括号组中的第二项。

相关内容