我正在尝试定义宏来根据应该放入其中的文本设置 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}
答案1
你的第二个论点\variationAInternal
是。其中\commonFunction{Test 1:\\Some Test}
没有。;
在不知道您的实际用例有多复杂的情况下,我会先执行lrbox
前面的操作\variationAInternal
,然后将\the
s 转发到内部函数(然后您就已经可以使用正常的m
s 了)。
它\exp_args:Nnff
什么也不做,只是f
在将其转发给第一个参数之前扩展了它的第三和第四个参数。(这可能不是必需的,但谁知道在访问其维度\testTempBox
之前还发生了什么\variationAInternal
。)
由于 PGF/TikZ 会卸载图片中的常规字体(并为节点或重新安装它们\pgftext
),因此您需要在或环境\pgfutil@selectfont
开始时使用。这显然会忽略节点的任何字体选择,但会拾取之前对字体所做的任何其他更改。lrbox
varwidth
\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-
对括号组中的第二项。