自定义符号 - 简化方式

自定义符号 - 简化方式

我有一个名为的自定义符号\trident,我对它的编程有点笨拙。

我想使用一种更优雅的方法,例如@egreg\commonroot在这篇文章中为我的符号建议的方法:

https://tex.stackexchange.com/a/711580/262813

如 MWE 所示,智能\coolsource命令必须能够根据传递的参数自动选择应该使用两个符号中的哪一个。

平均能量损失

\documentclass{article}

\usepackage{fontspec}

\usepackage{xparse}

\usepackage{graphicx}

\setmainfont{Times New Roman}

\newfontface{\arrows}{STIX Two Math}[Scale=0.7]


\NewDocumentCommand{\lex}{>{\SplitArgument{1}{,}}m}{\lexAUX#1}

\NewDocumentCommand{\lexAUX}{mm}{%
    \textit{#1}%
    \IfValueT{#2}{\textup{\textsubscript{\textsc{#2}}}}%
}


\NewDocumentCommand{\commonroot}{}{%
    \raisebox{\depth}{%
        \normalfont\arrows
        \kern0.225em
        \symbol{"2199}\kern-0.236em\symbol{"2198}%
        \kern0.225em
    }%
}



\newcommand{\trident}{%
    \raisebox{-0.6ex}{\rotatebox{45}{\textleftarrow\!\!}}%
    \kern0.025em%
    \makebox[0pt][c]{\kern0.05em\raisebox{-0.9ex}{\rotatebox{90}{\textleftarrow}}}%
\raisebox{0.453ex}{\rotatebox{-45}{\!\!\textrightarrow}}}
    
    

\NewDocumentCommand{\coolsource}{ommg}{%
    \IfValueTF{#1}{%
        $\hspace*{-1pt}\left\{\begin{array}{@{}c@{}}}{%
            \IfValueTF{#4}{$\hspace*{-1pt}\left\{\begin{array}{@{}c@{}}}{\textup{\{}}}%
            \lex{#2}%
            \kern0.25em%
            \IfValueTF{#4}{
                \trident%
                \raisebox{-2ex}{\kern-0.8em\makebox[0pt][c]{\lex{#4}}}% Adjust the -2ex as needed to position the text
            }{%
                % If the third argument is not provided, just use \commonroot
                \commonroot%
            }%
            \IfValueT{#1}{\IfValueF{#4}{\kern-0.8em}\raisebox{2.25ex}{\makebox[0pt][c]{\lex{#1}}}}%
            \IfValueTF{#4}{\kern1.05em}{\IfValueTF{#1}{\kern1.05em}{\kern0.25em}}%
            \lex{#3}%
            \IfValueTF{#1}{%
            \end{array} \right\}$}{%
            \IfValueTF{#4}{\end{array}\right\}$}{\textup{\}}}}}

\begin{document}
    
    \coolsource{contracter,v}{contraction,n}{contracture,n}
    
        \vspace*{2ex}
        
    \coolsource[contraire,v]{contracter,v}{contraction,n}{contracture,n}
    
        \vspace*{2ex}
        
    \coolsource[contraire,v]{contracter,v}{contraction,n}
    
        \vspace*{2ex}
        
    \coolsource{contracter,v}{contraction,n}
    
\end{document}


在此处输入图片描述

另外,我会使用\tetradent,这样就可以在底部有两个导数,而不是 1 个(而不是垂直向南的箭头,我们会得到两个箭头,即 SSW 箭头和 SSE 箭头;#4/#5 可选参数将被逗号分成两部分,并\IfValueT{#5}会触发四齿兽)。我再次可以以 67.5 和 112.5 度角旋转一个向右箭头,但也许我们STIX Two也可以在这种情况下使用。

\newcommand{\tetradent}{%
    \raisebox{-0.5ex}{\rotatebox{45}{\textleftarrow\!\!}}%
    \kern0.025em%
    \makebox[0pt][c]{\kern-0.267em\raisebox{-0.845ex}{\rotatebox{67.5}{\textleftarrow}}}%
    \makebox[0pt][c]{\kern0.36em\raisebox{-0.41ex}{\rotatebox{112.5}{\textleftarrow}}}%
    \raisebox{0.553ex}{\rotatebox{-45}{\!\!\textrightarrow}}}

在此处输入图片描述

如果我尝试包含\tetradent大小写,以及一个布尔值,以便通过将源词素括在框架内来以某种方式区分源词素,我会得到一个命令,该命令在可能性树的向右移动以及要计算和添加的补偿字距方面处理起来非常复杂。

平均能量损失

\documentclass{article}

\usepackage{fontspec}

\usepackage{xparse}

\usepackage{graphicx}

\usepackage{tcolorbox}

\setmainfont{Times New Roman}

\newfontface{\arrows}{STIX Two Math}[Scale=0.7]


\NewDocumentCommand{\lex}{>{\SplitArgument{1}{,}}m}{\lexAUX#1}

\NewDocumentCommand{\lexAUX}{mm}{%
    \textit{#1}%
    \IfValueT{#2}{\textup{\textsubscript{\textsc{#2}}}}%
}


\NewDocumentCommand{\commonroot}{}{%
    \raisebox{\depth}{%
        \normalfont\arrows
        \kern0.225em
        \symbol{"2199}\kern-0.236em\symbol{"2198}%
        \kern0.225em
    }%
}


\newcommand{\trident}{%
    \raisebox{-0.5ex}{\rotatebox{45}{\textleftarrow\!\!}}%
    \kern0.025em%
    \makebox[0pt][c]{\kern0.0518em\raisebox{-0.67ex}{\rotatebox{90}{\textleftarrow}}}%
    \raisebox{0.553ex}{\rotatebox{-45}{\!\!\textrightarrow}}}% Right arrow

\newcommand{\tetradent}{%
    \raisebox{-0.5ex}{\rotatebox{45}{\textleftarrow\!\!}}%
    \kern0.025em%
    \makebox[0pt][c]{\kern-0.267em\raisebox{-0.845ex}{\rotatebox{67.5}{\textleftarrow}}}%
    \makebox[0pt][c]{\kern0.36em\raisebox{-0.41ex}{\rotatebox{112.5}{\textleftarrow}}}%
    \raisebox{0.553ex}{\rotatebox{-45}{\!\!\textrightarrow}}}

\NewDocumentCommand{\coolsource}{sommgg}{%
    \IfValueTF{#2}{%
        $\hspace*{-1pt}\left\{\begin{array}{@{}c@{}}}{%
            \IfValueTF{#5}{$\hspace*{-1pt}\left\{\begin{array}{@{}c@{}}}{\textup{\{}}}%
            \IfValueTF{#6}{\lex{\footnotesize#3}}{\lex{#3}}%
            \kern0.25em%
            \IfValueTF{#5}{
                \IfValueTF{#6}{%
        \tetradent
    \raisebox{-2.5ex}{\kern-3em\makebox[0pt][c]{\lex{\footnotesize#5}}}%
    \raisebox{-2.5ex}{\kern4.5em\makebox[0pt][c]{\lex{\footnotesize#6}}}%
            }{%
                \trident%
            \raisebox{-2.5ex}{\kern-0.8em\makebox[0pt][c]{\lex{#5}}}%
            }}{%
                % If the third argument is not provided, just use \commonroot
                \commonroot%
            }%
            \IfValueT{#2}{\IfValueF{#5}{\kern-0.8em}{%
                    \IfValueT{#6}{\kern-2.2em}
                        \IfBooleanTF{#1}{\raisebox{3ex}{\makebox[0pt][c]{%
                            \tcbox[nobeforeafter, tcbox raise base,
                        colframe=black, boxrule=0.12ex, arc=0mm, 
                        boxsep=0pt, left=2pt, right=2pt, top=2pt, bottom=2pt]{\lex{#2}}}}}{%
                            \raisebox{2.5ex}{\makebox[0pt][c]{\lex{#2}}}}%
                        }}%
            \IfValueTF{#5}{\IfValueTF{#2}{\kern1.05em}{\IfValueTF{#6}{\kern-1.15em}{\kern1.05em}}}{\IfValueTF{#2}{\kern1.05em}{\kern0.25em}}%
                    \IfValueTF{#6}{\lex{\footnotesize#4}}{\lex{#4}}%%
            \IfValueTF{#2}{%
            \end{array}\right\}$}{%
            \IfValueTF{#5}{\end{array}\right\}$}{\textup{\}}}}}

\begin{document}
    
    \coolsource{contracter,v}{contraction,n}{contracture,n}
    
            \vspace*{2ex}
    
    \coolsource[contraire,v]{contracter,v}{contraction,n}{contracture,n}
        
            \vspace*{2ex}
    
    \coolsource[contraire,v]{contracter,v}{contraction,n}{contracture,n}{contracteur,n}
    
            \vspace*{2ex}
    
    \coolsource{contracter,v}{contraction,n}
    
            \vspace*{2ex}
    
    \coolsource{contracter,v}{contraction,n}{contracture,n}
    
            \vspace*{2ex}
    
    \coolsource{contracter,v}{contraction,n}{contracture,n}{contracteur,n}
    
            \vspace*{2ex}
    
    \coolsource*[contraire,v]{contracter,v}{contraction,n}{contracture,n}{contracteur,n}
    
\end{document}

在此处输入图片描述

答案1

不完全是答案,但我可能会选择 Expl 口味的 TiZ 解决方案使绘制箭头和定位不同部分变得更加容易。我还将使用逗号分隔列表(我将内部分隔符更改为冒号):

\documentclass[tikz, border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing, fit}

\ExplSyntaxOn

% if the code does not compile try to uncomment the following line
% \cs_generate_variant:Nn \tl_set:Nn { Ne }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nee }
\seq_new:N \l_vincentkrebs_coolsource_deriv_parts_seq
\cs_new:Npn \vincentkrebs_coolsource_format #1 {
    \seq_set_split:Nee \l_vincentkrebs_coolsource_deriv_parts_seq { \c_colon_str } { #1 }
    \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 1 } }
    \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 2 } } 
    \textit{\tl_use:N \l_tmpa_tl} \tl_if_empty:NF \l_tmpb_tl {\textup{\textsubscript{\textsc{\tl_use:N \l_tmpb_tl}}}}
}

\clist_new:N \l_vincentkrebs_coolsource_derivs_clist
\clist_new:N \l_vincentkrebs_coolsource_fitspec_clist
\NewDocumentCommand{\coolsource}{ o O{} m }{
    \clist_set:Nn \l_vincentkrebs_coolsource_derivs_clist { #3 }
    \clist_clear:N \l_vincentkrebs_coolsource_fitspec_clist
    \begin{tikzpicture}[baseline=(a)]
        \coordinate (a) at (0,0);
        \IfValueT{#1}{
            \node[anchor=south, #2] (A) at (a) { \vincentkrebs_coolsource_format { #1 } };
            \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (A) }
        }
        \coordinate (b) at (-1em,-0.6em);
        \coordinate (c) at (1em,-0.6em);
        \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 1 } }
        \tl_set:Ne \l_tmpb_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 2 } }
        \node[anchor=east] (B) at (b) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
        \node[anchor=west] (C) at (c) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } };
        \draw[<->] (b.west) -- (a.south) -- (c.east);
        \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (B), (C) }

        \int_compare:nNnT { \clist_count:N \l_vincentkrebs_coolsource_derivs_clist } > { 2 } {
            \int_compare:nNnTF { \clist_count:N \l_vincentkrebs_coolsource_derivs_clist } > { 3 } {
                \coordinate (d) at (0em,-1.2em);
                \coordinate (e) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 3 } }
                \tl_set:Ne \l_tmpb_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 4 } }
                \node[anchor=north ~ east] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
                \node[anchor=north ~ west] (E) at (e) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } }; 
                \draw[->] (a.south) -- ([xshift=-0.5em]d.north);
                \draw[->] (a.south) -- ([xshift=0.5em]e.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D), (E) }
            } {
                \coordinate (d) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 3 } }
                \node[anchor=north] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };  
                \draw[->] (a.south) -- (d.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D) }
            }
        } 
        
        \node[fit={ \clist_use:Nn \l_vincentkrebs_coolsource_fitspec_clist { } }] (frame) {};
        \draw[decorate, decoration={brace, mirror}] (frame.north ~ west) -- (frame.south ~ west);
        \draw[decorate, decoration={brace}] (frame.north ~ east) -- (frame.south ~ east);
    \end{tikzpicture}
}

\ExplSyntaxOff

\begin{document}

\coolsource{contracter:v,contraction:n}

\coolsource{contracter:v,contraction:n,contracture:n}

\coolsource[contraire:v]{contracter:v,contraction:n,contracture:n}

\coolsource[contraire:v]{contracter:v,contraction:n,contracture:n,contracteur:n}

\coolsource[contraire:v][draw, fill=blue!10, yshift=2pt]{contracter:v,contraction:n,contracture:n,contracteur:n}

\end{document}

在此处输入图片描述


使用不同的分隔符(这种变化允许您更轻松地更改分隔符,因为您只需在代码中更改它们即可):

\documentclass[tikz, border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing, fit}

\ExplSyntaxOn

% if the code does not compile try to uncomment the following line
% \cs_generate_variant:Nn \tl_set:Nn { Ne }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nee }
\seq_new:N \l_vincentkrebs_coolsource_deriv_parts_seq
\cs_new:Npn \vincentkrebs_coolsource_format #1 {
    \seq_set_split:Nee \l_vincentkrebs_coolsource_deriv_parts_seq { , } { #1 }
    \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 1 } }
    \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 2 } } 
    \textit{\tl_use:N \l_tmpa_tl} \tl_if_empty:NF \l_tmpb_tl {\textup{\textsubscript{\textsc{\tl_use:N \l_tmpb_tl}}}}
}

\seq_new:N \l_vincentkrebs_coolsource_derivs_seq
\clist_new:N \l_vincentkrebs_coolsource_fitspec_clist
\NewDocumentCommand{\coolsource}{ o O{} m }{
    \seq_set_split:Nnn \l_vincentkrebs_coolsource_derivs_seq { ; } { #3 }
    \clist_clear:N \l_vincentkrebs_coolsource_fitspec_clist
    \begin{tikzpicture}[baseline=(a), >=stealth]
        \coordinate (a) at (0,0);
        \IfValueT{#1}{
            \node[anchor=south, #2] (A) at (a) { \vincentkrebs_coolsource_format { #1 } };
            \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (A) }
        }
        \coordinate (b) at (-1em,-0.6em);
        \coordinate (c) at (1em,-0.6em);
        \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 1 } }
        \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 2 } }
        \node[anchor=east] (B) at (b) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
        \node[anchor=west] (C) at (c) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } };
        \draw[<->] (b.west) -- (a.south) -- (c.east);
        \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (B), (C) }

        \int_compare:nNnT { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 2 } {
            \int_compare:nNnTF { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 3 } {
                \coordinate (d) at (0em,-1.2em);
                \coordinate (e) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 4 } }
                \node[anchor=north ~ east] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
                \node[anchor=north ~ west] (E) at (e) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } }; 
                \draw[->] (a.south) -- ([xshift=-0.5em]d.north);
                \draw[->] (a.south) -- ([xshift=0.5em]e.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D), (E) }
            } {
                \coordinate (d) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \node[anchor=north] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };  
                \draw[->] (a.south) -- (d.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D) }
            }
        } 
        
        \node[fit={ \clist_use:Nn \l_vincentkrebs_coolsource_fitspec_clist { } }] (frame) {};
        \draw[decorate, decoration={brace, mirror}] (frame.north ~ west) -- (frame.south ~ west);
        \draw[decorate, decoration={brace}] (frame.north ~ east) -- (frame.south ~ east);
    \end{tikzpicture}
}

\ExplSyntaxOff

\begin{document}

\coolsource{contracter,v;contraction,n}

\coolsource{contracter,v;contraction,n;contracture,n}

\coolsource[contraire,v]{contracter,v;contraction,n;contracture,n}

\coolsource[contraire,v]{contracter,v;contraction,n;contracture,n;contracteur,n}

\coolsource[contraire,v][draw, fill=blue!10, yshift=2pt]{contracter,v;contraction,n;contracture,n;contracteur,n}

\end{document}

stealth输出与上面相同(除了我根据您的评论更改为不同的箭头)。


看来您已经有一些格式化命令了。\coolsource如果这能让您更轻松一些,您可以直接将其插入命令中:

\documentclass[tikz, border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing, fit}

\ExplSyntaxOn

% if the code does not compile try to uncomment the following line
% \cs_generate_variant:Nn \tl_set:Nn { Ne }
\clist_new:N \l_vincentkrebs_coolsource_derivs_clist
\clist_new:N \l_vincentkrebs_coolsource_fitspec_clist
\NewDocumentCommand{\coolsource}{ o O{} m }{
    \clist_set:Nn \l_vincentkrebs_coolsource_derivs_clist { #3 }
    \clist_clear:N \l_vincentkrebs_coolsource_fitspec_clist
    \begin{tikzpicture}[baseline=(a), >=stealth]
        \coordinate (a) at (0,0);
        \IfValueT{#1}{
            \node[anchor=south, #2] (A) at (a) { #1 };
            \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (A) }
        }
        \coordinate (b) at (-1em,-0.6em);
        \coordinate (c) at (1em,-0.6em);
        \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 1 } }
        \tl_set:Ne \l_tmpb_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 2 } }
        \node[anchor=east] (B) at (b) { \tl_use:N \l_tmpa_tl };
        \node[anchor=west] (C) at (c) { \tl_use:N \l_tmpb_tl };
        \draw[<->] (b.west) -- (a.south) -- (c.east);
        \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (B), (C) }

        \int_compare:nNnT { \clist_count:N \l_vincentkrebs_coolsource_derivs_clist } > { 2 } {
            \int_compare:nNnTF { \clist_count:N \l_vincentkrebs_coolsource_derivs_clist } > { 3 } {
                \coordinate (d) at (0em,-1.2em);
                \coordinate (e) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 3 } }
                \tl_set:Ne \l_tmpb_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 4 } }
                \node[anchor=north ~ east] (D) at (d) { \tl_use:N \l_tmpa_tl };
                \node[anchor=north ~ west] (E) at (e) { \tl_use:N \l_tmpb_tl }; 
                \draw[->] (a.south) -- ([xshift=-0.5em]d.north);
                \draw[->] (a.south) -- ([xshift=0.5em]e.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D), (E) }
            } {
                \coordinate (d) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \clist_item:Nn \l_vincentkrebs_coolsource_derivs_clist { 3 } }
                \node[anchor=north] (D) at (d) { \tl_use:N \l_tmpa_tl };  
                \draw[->] (a.south) -- (d.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D) }
            }
        } 

        \node[fit={ \clist_use:Nn \l_vincentkrebs_coolsource_fitspec_clist { } }] (frame) {};
        \draw[decorate, decoration={brace, mirror}] (frame.north ~ west) -- (frame.south ~ west);
        \draw[decorate, decoration={brace}] (frame.north ~ east) -- (frame.south ~ east);
    \end{tikzpicture}
}

\ExplSyntaxOff

\NewDocumentCommand{\lexAUX}{mm}{%
    \textit{#1}%
    \IfValueT{#2}{\textup{\textsubscript{\textsc{#2}}}}%
}

\begin{document}

\coolsource[\lexAUX{contraire}{v}]{\lexAUX{contracter}{v},\lexAUX{contraction}{n},\lexAUX{contracture}{n}}

\end{document}

但您也可以修改格式化命令,以便它采用一些语法,例如(prefix:word,category,translation,addendum其中prefix,,和是可选的)。我在这里使用了 Expl 和传统语法的组合,因为换行符在 Ti 中有特殊的定义categorytranslationaddeddum\\Z 似乎需要特别小心对待:

\documentclass[tikz, border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing, fit}

\newcommand{\tslt}[1]{`#1'}

\ExplSyntaxOn
\NewDocumentCommand{\IfEmptyF}{ m m }{
    \tl_if_empty:nF { #1 } { #2 }
}
\ExplSyntaxOff

\NewDocumentCommand{\formatnode}{ m m m m m }{%
    \IfEmptyF{#1}{#1 {}}%
    \IfEmptyF{#2}{\textit{#2}\nocorr}%
    \IfEmptyF{#3}{\textsubscript{\textup{\textsc{#3}}}}%
    \IfEmptyF{#4}{\\\tslt{#4}}%
    \IfEmptyF{#5}{ #5}%
}

\ExplSyntaxOn

% if the code does not compile try to uncomment the following line
% \cs_generate_variant:Nn \tl_set:Nn { Ne }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nee }
\exp_args_generate:n { eeeee }
\cs_new:Npn \vincentkrebs_coolsource_format #1 {
    \seq_set_split:Nee \l_tmpa_seq { , } { #1 }
    \seq_set_split:Nee \l_tmpb_seq { \c_colon_str } { \seq_item:Nn \l_tmpa_seq { 1 } }
    \int_compare:nNnTF { \seq_count:N \l_tmpb_seq } > { 1 } {
        \tl_set:Nn \l_tmpa_tl { \seq_item:Nn \l_tmpb_seq { 1 } }
        \tl_set:Nn \l_tmpb_tl { \seq_item:Nn \l_tmpb_seq { 2 } }
    } {
        \tl_set:Nn \l_tmpa_tl {  }
        \tl_set:Nn \l_tmpb_tl { \seq_item:Nn \l_tmpb_seq { 1 } }
    }
    \exp_args:Neeeee \formatnode{ \l_tmpa_tl }{ \l_tmpb_tl }{
        \seq_item:Nn \l_tmpa_seq { 2 } 
    }{
        \seq_item:Nn \l_tmpa_seq { 3 } 
    }{
        \seq_item:Nn \l_tmpa_seq { 4 } 
    }
}

\seq_new:N \l_vincentkrebs_coolsource_derivs_seq
\clist_new:N \l_vincentkrebs_coolsource_fitspec_clist
\seq_new:N \l_vincentkrebs_coolsource_deriv_parts_seq
\NewDocumentCommand{\coolsource}{ o O{} m }{
    \seq_set_split:Nnn \l_vincentkrebs_coolsource_derivs_seq { ; } { #3 }
    \clist_clear:N \l_vincentkrebs_coolsource_fitspec_clist
    \begin{tikzpicture}[baseline=(a), >=stealth, every ~ node/.append ~ style={align=center}]
        \coordinate (a) at (0,0);
        \IfValueT{#1}{
            \node[anchor=south, #2] (A) at (a) { \vincentkrebs_coolsource_format { #1 } };
            \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (A) }
        }
        \coordinate (b) at (-1em,-0.6em);
        \coordinate (c) at (1em,-0.6em);
        \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 1 } }
        \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 2 } }
        \node[anchor=north ~ east, yshift=0.8em] (B) at (b) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
        \node[anchor=north ~ west, yshift=0.8em] (C) at (c) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } };
        \draw[<->] (b.west) -- (a.south) -- (c.east);
        \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (B), (C) }

        \int_compare:nNnT { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 2 } {
            \int_compare:nNnTF { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 3 } {
                \coordinate (d) at (0em,-1.2em);
                \coordinate (e) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 4 } }
                \node[anchor=north ~ east] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };
                \node[anchor=north ~ west] (E) at (e) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpb_tl } }; 
                \draw[->] (a.south) -- ([xshift=-0.5em]d.north);
                \draw[->] (a.south) -- ([xshift=0.5em]e.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D), (E) }
            } {
                \coordinate (d) at (0em,-1.2em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \node[anchor=north] (D) at (d) { \vincentkrebs_coolsource_format { \tl_use:N \l_tmpa_tl } };  
                \draw[->] (a.south) -- (d.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D) }
            }
        } 
        
        \node[fit={ \clist_use:Nn \l_vincentkrebs_coolsource_fitspec_clist { } }] (frame) {};
        \draw[decorate, decoration={brace, mirror}] (frame.north ~ west) -- (frame.south ~ west);
        \draw[decorate, decoration={brace}] (frame.north ~ east) -- (frame.south ~ east);
    \end{tikzpicture}
}

\ExplSyntaxOff

\begin{document}

\coolsource[pre:contraire,v,foo,bar]{pre:contracter,v;contraction,n,foo;contracture,n,foo,bar}

\end{document}

在此处输入图片描述

如果您想在节点的第二行放置更多文本,可能需要以不同的方式对齐内容。

答案2

Jasper的代码运行得很好,并允许进行所有理想的调整:这里有一个例子,其风格接近 OP 中使用的风格。

\documentclass[tikz, border=0pt]{standalone}
\usepackage{fontspec}
\setmainfont{Times New Roman}
\usepackage{tikz}
\usetikzlibrary{decorations.pathreplacing, fit}

\ExplSyntaxOn

% if the code does not compile try to uncomment the following line
% \cs_generate_variant:Nn \tl_set:Nn { Ne }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nee }
\seq_new:N \l_vincentkrebs_coolsource_deriv_parts_seq
\cs_new:Npn \vincentkrebs_coolsource_format #1 {
    \seq_set_split:Nee \l_vincentkrebs_coolsource_deriv_parts_seq { , } { #1 }
    \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 1 } }
    \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 2 } } 
    \textit{\l_tmpa_tl} \tl_if_empty:NF \l_tmpb_tl {\textup{\textsubscript{\textsc{\l_tmpb_tl}}}}
}

\seq_new:N \l_vincentkrebs_coolsource_derivs_seq
\clist_new:N \l_vincentkrebs_coolsource_fitspec_clist
\NewDocumentCommand{\coolsource}{ o O{} m }{
    \seq_set_split:Nnn \l_vincentkrebs_coolsource_derivs_seq { ; } { #3 }
    \clist_clear:N \l_vincentkrebs_coolsource_fitspec_clist
    \begin{tikzpicture}[baseline=(a), >=stealth,line~width=0.5pt]
        \coordinate (a) at (0,0.25em);
        \IfValueT{#1}{
            \node[anchor=south, #2] (A) at (a) { \vincentkrebs_coolsource_format { #1 } };
            \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (A) }
        }
        \coordinate (b) at (-1em,-0.6em);
        \coordinate (c) at (1em,-0.6em);
        \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 1 } }
        \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 2 } }
        \node[anchor=east] (B) at (b) { \vincentkrebs_coolsource_format { \l_tmpa_tl } };
        \node[anchor=west] (C) at (c) { \vincentkrebs_coolsource_format { \l_tmpb_tl } };
        \draw[<->] (b.west) -- (a.south) -- (c.east);
        \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (B), (C) }
        
        \int_compare:nNnT { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 2 } {
            \int_compare:nNnTF { \seq_count:N \l_vincentkrebs_coolsource_derivs_seq } > { 3 } {
                \coordinate (d) at (0em,-0.9em);
                \coordinate (e) at (0em,-0.9em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 4 } }
                \node[anchor=north ~ east] (D) at (d) { \vincentkrebs_coolsource_format { \l_tmpa_tl } };
                \node[anchor=north ~ west] (E) at (e) { \vincentkrebs_coolsource_format { \l_tmpb_tl } }; 
                \draw[->] (a.south) -- ([xshift=-0.5em]d.north);
                \draw[->] (a.south) -- ([xshift=0.5em]e.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D), (E) }
            } {
                \coordinate (d) at (0em,-0.9em);
                \tl_set:Ne \l_tmpa_tl { \seq_item:Nn \l_vincentkrebs_coolsource_derivs_seq { 3 } }
                \node[anchor=north] (D) at (d) { \vincentkrebs_coolsource_format { \l_tmpa_tl } };  
                \draw[->] (a.south) -- (d.north);
                \clist_push:Nn \l_vincentkrebs_coolsource_fitspec_clist { (D) }
            }
        } 

        \node[fit={ \clist_use:Nn \l_vincentkrebs_coolsource_fitspec_clist { } }] (frame) {};
        \draw[decorate, semithick, decoration={brace, amplitude=2pt, mirror}] ([xshift=0.5em,yshift=-0.3em]frame.north ~ west) -- ([xshift=0.5em,yshift=0.3em]frame.south ~ west);
        \draw[decorate, semithick, decoration={brace, amplitude=2pt}] ([xshift=-0.5em,yshift=-0.3em]frame.north ~ east) -- ([xshift=-0.5em,yshift=0.3em]frame.south ~ east);
    \end{tikzpicture}
}

\ExplSyntaxOff


\begin{document}
\coolsource{contracter,v;contraction,n}

\coolsource{contracter,v;contraction,n;contracture,n}

\coolsource[contraire,v]{contracter,v;contraction,n;contracture,n}

\coolsource[contraire,v]{contracter,v;contraction,n;contracture,n;contracteur,n}

\coolsource[contraire,v][draw, fill=blue!10, yshift=0.4em]{contracter,v;contraction,n;contracture,n;contracteur,n}
    
\end{document}

在此处输入图片描述

相关内容