使用低级 Expl3 语法进行参数拆分

使用低级 Expl3 语法进行参数拆分

使用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}

但是,我不确定这是否比具有两个强制参数的先前版本更好,因为这两个参数的含义不同(起始节点和终止节点)。

另一种策略是将它们添加到键值对列表中,不同之处在于键startend 必须必须具体说明。

\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}

现在整个参数是强制性的,因为必须同时存在startend。尝试省略其中一个,您将看到错误消息弹出。

在此处输入图片描述

答案2

这个答案与@egreg的答案大致相同,即它使用\SplitArgument,但它也用于expkv-cskey = 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}

相关内容