3

I have a custom symbol called \trident, which I programmed somehow awkwardly.

I'd like to use a more elegant method such as the one suggested to me by @egreg for my \commonroot symbol in this post:

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

As illustrated in the MWE, the smart \coolsource command must be able to automatically choose which of the two symbols it should use, depending on which arguments are passed.

MWE

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


enter image description here

Also, I would have the use for a \tetradent, thus allowing to have two derivatives at the bottom instead of 1 (instead of the vertical southwards arrow, we would get two arrows, i.e. a SSW arrow and a SSE arrow; the #4/#5 optional argument would be split in two by a comma, and \IfValueT{#5} would trigger the tetradent). Again I could rotate a rightwards arrow with 67.5 and 112.5 angles, but maybe we could use STIX Two in this case too.

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

enter image description here

If I try to include the \tetradent case(s), and also a boolean to somehow distinguish the source lexeme by enclosing it inside a frame, I obtain a command that is unelegantly complex to handle in terms of the rightwards shifts in the possibility tree, and the compensating kerns to calculate and add.

MWE

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

enter image description here

9
  • To understand you correctly. You need an xparse command that can accept either 3 or four arguments, with the fourth being a g-type and then produce two different ouputs? Also your MWE needs a \documentclass etc...
    – yannisl
    Commented Feb 27 at 4:05
  • Yes, just like I show. My command works fine as it is so I would just like a simplification in the spirit of what egreg suggested for \commonroot. Simplifying \trident is mostly what I want, but any idea to simplify \coolsource as well is welcome. Commented Feb 27 at 4:09
  • 1
    The g-type sometimes can be problematic. Consider a simpler interface, where you always pass the same number of arguments (easier to remember), but if the last one is empty, you choose a different symbol and text output. Or a \cmd and \cmd*.
    – yannisl
    Commented Feb 27 at 4:10
  • I know the g argument is deprecated but I like it, it's more confusing for me to leave an argument empty or use square brackets. I guess we all have different ways of thinking. Anyway, the question is mostly about \trident. Also I didn't find the exact kern value to make the \commonroot symbol perfect using egreg's def, the apex is still not perfect, I tried every possible refined value with even 4 digits but I can't obtain the perfect result as with my old definition, no idea why. Commented Feb 27 at 4:11
  • 1
    Agree you shouldn't use [] but in your code you have` {ommg}`. I had difficulties to understand exactly what you wanted, and thanks for the clarification.
    – yannisl
    Commented Feb 27 at 4:17

2 Answers 2

4

Not exactly an answer, but I would probaby opt for an Expl-flavored TikZ solution which makes it much easier to draw the arrows and position the different parts. I would also make use of a comma-separated list (I changed the inner separator to a colon):

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

enter image description here


With different delimiters (this variation would allow you to change the delimiters more easily as you can just change them in the code):

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

The output is the same as above (except for the different arrow heads that I changed to stealth according to your comment).


It seems that you alredy have some formatting command. You can totally just plug this into the \coolsource command if it makes things easier for you:

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

But you can also modify the formatting commmand, so that it takes some syntax like prefix:word,category,translation,addendum (where prefix, category, translation and addeddum would be optional). I used a combination of Expl and traditional syntax here, because the newline character \\ has a special defintion in TikZ that seems to have to be treated with special care:

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

enter image description here

Maybe you need to align things differently if you want to put more text in the second line of the nodes.

14
  • 1
    @VincentKrebs WIth a recent installation of TeX Live, it should work. What is the error exactly? You only need to load tikz for it to work. Commented Feb 27 at 9:32
  • 1
    @VincentKrebs The code compiles on texlive.net/run .
    – projetmbc
    Commented Feb 27 at 9:34
  • 1
    @VincentKrebs This looks very strange. It seems that spaces are ignored somewhere, but I did use ~ in the code to prevent this. Tell me the first error the log shows Commented Feb 27 at 9:42
  • 1
    @VincentKrebs Most likely, the error could have been solved by putting \cs_generate_variant:Nn \tl_set:Nn { Ne } in the code. Commented Feb 27 at 9:46
  • 1
    @VincentKrebs Sorry, you are right. You need to replace \tl_set:Ne \l_tmpb_tl { \exp_args:Ne \str_uppercase:n { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 2 } } } with \tl_set:Ne \l_tmpb_tl { \seq_item:Nn \l_vincentkrebs_coolsource_deriv_parts_seq { 2 } }. I updated the code above. Commented Feb 27 at 9:51
1

Jasper's code works very nicely and allows for all desirable tweaks: here is an example, with a style close to that used in the 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}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .