使用egreg
的答案这里我尝试使用 -style 可选参数拆分创建自己的高级命令key=value
,并成功了。
现在我该如何整合强制的论点,即
\mycoolcommand[...,...,...]{arg1,arg2}
代替
\mycoolcommand[...,...,...]{arg1}{arg2}
?
在下面的 MWE 中,我寻求的命令是:
\newcoolbrace[...,...,...]{polp,root}
我通常使用\SplitArgument
,但我猜这里会有点不同。
我知道这可能重复了如何在“expl3”[而不是“xparse”]的上下文中拆分参数?但由于我不熟悉Expl3
语法,因此很难根据我的例子调整答案。
平均能量损失
\documentclass{article}
\usepackage[linguistics]{forest}
\usetikzlibrary{decorations.pathreplacing,decorations.text}
\NewDocumentCommand{\newcoolbraceaux}{mmmmm}{
\draw[decorate,semithick,decoration={brace,amplitude=10pt,raise=#1pt}](#4)--(#5);
\draw[decorate,semithick,decoration={raise=#2pt,text along path,text align=center,text=#3}](#4)--(#5);}
\ExplSyntaxOn
\NewDocumentCommand{\newcoolbrace}{O{}mm}
{
\group_begin:
\keys_set:nn { krebs/newcoolbrace } { #1 }
\krebs_newcoolbrace:VVVnn
\l__krebs_newcoolbrace_braise_tl
\l__krebs_newcoolbrace_traise_tl
\l__krebs_newcoolbrace_text_tl
{#2}
{#3}
\group_end:
}
\keys_define:nn { krebs/newcoolbrace }
{
braise .tl_set:N = \l__krebs_newcoolbrace_braise_tl,
traise .tl_set:N = \l__krebs_newcoolbrace_traise_tl,
text .tl_set:N = \l__krebs_newcoolbrace_text_tl,
braise .initial:n = 36,
traise .initial:n = 54,
text .initial:n = ~,
}
\cs_set_eq:NN \krebs_newcoolbrace:nnnnn \newcoolbraceaux
\cs_generate_variant:Nn \krebs_newcoolbrace:nnnnn { VVV }
\ExplSyntaxOff
\begin{document}
\begin{forest}
[nP[~][n
[n][asp
[~][asp
[asp][pol,name=polp
[~][pol
[pol][vP
[\textit{x},name=v][v′
[v][root,name=root]]]]]]]]]
\newcoolbrace[braise=26,traise=44,text=Unaccusative]{polp}{root}
\end{forest}
\end{document}
答案1
你可以这样做:
\documentclass{article}
\usepackage[linguistics]{forest}
\usetikzlibrary{decorations.pathreplacing,decorations.text}
\NewDocumentCommand{\newcoolbraceaux}{mmm>{\SplitArgument{1}{,}}m}{%
\newcoolbraceauxa{#1}{#2}{#3}#4%
}
\NewDocumentCommand{\newcoolbraceauxa}{mmmmm}{%
\draw[
decorate,
semithick,
decoration={brace,amplitude=10pt,raise=#1pt},
](#4)--(#5);%
\draw[
decorate,
semithick,
decoration={
raise=#2pt,
text along path,
text align=center,
text={#3},
},
](#4)--(#5);%
}
\ExplSyntaxOn
\NewDocumentCommand{\newcoolbrace}{O{}m}
{
\group_begin:
\keys_set:nn { krebs/newcoolbrace } { #1 }
\krebs_newcoolbrace:VVVnn
\l__krebs_newcoolbrace_braise_tl
\l__krebs_newcoolbrace_traise_tl
\l__krebs_newcoolbrace_text_tl
{#2}
\group_end:
}
\keys_define:nn { krebs/newcoolbrace }
{
braise .tl_set:N = \l__krebs_newcoolbrace_braise_tl,
traise .tl_set:N = \l__krebs_newcoolbrace_traise_tl,
text .tl_set:N = \l__krebs_newcoolbrace_text_tl,
braise .initial:n = 36,
traise .initial:n = 54,
text .initial:n = ~,
}
\cs_set_eq:NN \krebs_newcoolbrace:nnnnn \newcoolbraceaux
\cs_generate_variant:Nn \krebs_newcoolbrace:nnnnn { VVV }
\ExplSyntaxOff
\begin{document}
\begin{forest}
[nP[~][n
[n][asp
[~][asp
[asp][pol,name=polp
[~][pol
[pol][vP
[\textit{x},name=v][v'
[v][root,name=root]]]]]]]]]
\newcoolbrace[braise=26,traise=44,text=Unaccusative]{polp,root}
\end{forest}
\end{document}
但是,我不确定这是否比具有两个强制参数的先前版本更好,因为这两个参数的含义不同(起始节点和终止节点)。
另一种策略是将它们添加到键值对列表中,不同之处在于键start
和end
必须必须具体说明。
\documentclass{article}
\usepackage[linguistics]{forest}
\usetikzlibrary{decorations.pathreplacing,decorations.text}
\NewDocumentCommand{\newcoolbraceaux}{mmmmm}{%
\draw[
decorate,
semithick,
decoration={brace,amplitude=10pt,raise=#1pt},
](#4)--(#5);%
\draw[
decorate,
semithick,
decoration={
raise=#2pt,
text along path,
text align=center,
text={#3},
},
](#4)--(#5);%
}
\ExplSyntaxOn
\NewDocumentCommand{\newcoolbrace}{m}
{
\group_begin:
\keys_set:nn { krebs/newcoolbrace } { #1 }
\bool_lazy_or:nnTF
{ \quark_if_nil_p:V \l__krebs_newcoolbrace_start_tl }
{ \quark_if_nil_p:V \l__krebs_newcoolbrace_end_tl }
{
\msg_error:nn { krebs/newcoolbrace } { missing-bounds }
}
{
\krebs_newcoolbrace:VVVVV
\l__krebs_newcoolbrace_braise_tl
\l__krebs_newcoolbrace_traise_tl
\l__krebs_newcoolbrace_text_tl
\l__krebs_newcoolbrace_start_tl
\l__krebs_newcoolbrace_end_tl
}
\group_end:
}
\keys_define:nn { krebs/newcoolbrace }
{
braise .tl_set:N = \l__krebs_newcoolbrace_braise_tl,
traise .tl_set:N = \l__krebs_newcoolbrace_traise_tl,
text .tl_set:N = \l__krebs_newcoolbrace_text_tl,
start .tl_set:N = \l__krebs_newcoolbrace_start_tl,
end .tl_set:N = \l__krebs_newcoolbrace_end_tl,
braise .initial:n = 36,
traise .initial:n = 54,
text .initial:n = ~,
start .initial:n = \q_nil,
end .initial:n = \q_nil,
}
\cs_set_eq:NN \krebs_newcoolbrace:nnnnn \newcoolbraceaux
\cs_generate_variant:Nn \krebs_newcoolbrace:nnnnn { VVVVV }
\msg_new:nnnn { krebs/newcoolbrace } { missing-bounds }
{
Missing~start~or~end
}
{
You~must~specify~'start=<label>'~and~'end=<label>'
}
\ExplSyntaxOff
\begin{document}
\begin{forest}
[nP[~][n
[n][asp
[~][asp
[asp][pol,name=polp
[~][pol
[pol][vP
[\textit{x},name=v][v'
[v][root,name=root]]]]]]]]]
\newcoolbrace{braise=26,traise=44,text=Unaccusative,start=polp,end=root}
\end{forest}
\end{document}
现在整个参数是强制性的,因为必须同时存在start
和end
。尝试省略其中一个,您将看到错误消息弹出。
答案2
这个答案与@egreg的答案大致相同,即它使用\SplitArgument
,但它也用于expkv-cs
key = value参数。如果您只想使用它来将值转发给另一个宏,那么设置key = value接口会容易得多。
定义之后,所有\newcoolbracekv
键将按照指定键的顺序\ekvcSplitAndForward
转换为的参数。\newcoolbraceaux
\documentclass{article}
\usepackage[linguistics]{forest}
\usetikzlibrary{decorations.pathreplacing,decorations.text}
\NewDocumentCommand{\newcoolbraceaux}{mmmmm}{
\draw[decorate,semithick,decoration={brace,amplitude=10pt,raise=#1pt}](#4)--(#5);
\draw[decorate,semithick,decoration={raise=#2pt,text along path,text align=center,text={#3}}](#4)--(#5);}
\usepackage{expkv-cs}
\NewDocumentCommand\newcoolbrace { O{} >{\SplitArgument{1}{,}}m }
{\newcoolbracekv{#1}#2}
\ekvcSplitAndForward\newcoolbracekv\newcoolbraceaux
{
braise = 36
,traise = 54
,text = {} % defaults to an empty value
}
\begin{document}
\begin{forest}
[nP[~][n
[n][asp
[~][asp
[asp][pol,name=polp
[~][pol
[pol][vP
[\textit{x},name=v][v′
[v][root,name=root]]]]]]]]]
\newcoolbrace[braise=26,traise=44,text=Unaccusative]{polp,root}
\end{forest}
\end{document}