我想编写一个\TransTM
扩展命令,例如,扩展\TransTM{a, x, R | b, y, L}
到\shortstack{a;~x,~R \\ b;~y,~L}
。
数学家协会
\documentclass{article}
\usepackage{lmodern}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \TransTM { m }
{ \edge_label:cn {edge_item_tm:nnn} {#1} }
\cs_new_protected:Npn \edge_label:cn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { | } { #2 }
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \edge_item:cn {#1} {##1} }
\shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}
\cs_new_protected:Npn \edge_item:cn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { , } { #2 }
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { {##1} }
\use:c { #1 } x x x % \seq_use:Nn \l_tmpb_seq { }
}
\cs_new_protected:Npn \edge_item_tm:nnn #1 #2 #3
{
#1;~#2,~#3
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L | b, y, R}
\end{document}
|
仅部分起作用,因为我已设法在第一级上拆分参数,但没有在,
第二级上拆分参数。\seq_use:Nn
被\edge_item:cn
注释掉并由硬编码替换,x x x
因为它会产生错误。
试图在第二个层次上分裂论点有什么错误?
注意:将来会有不同的变体。这就是我将函数名称edge_item_tm:nnn
作为参数传递的原因。\TransFA{a | b | c}
例如,另一个文档级命令应该扩展为\shortstack{a \\ b \\ c}
。区别仅在于标记之间部分的结构|
。
附录
似乎我过于简化了上述 MWE。以下代码
\documentclass{article}
\usepackage{lmodern}
\usepackage{xparse}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{relsize}
\ExplSyntaxOn
\NewDocumentCommand \Char { O{\width} m }
{
\makebox[#1]
{
\str_case_x:nnF { \tl_to_str:n {#2} }
{
{ } { $\varepsilon$ }
{ ## } { \texttt{\#} }
{ \c_tilde_str } { \textscale{.87}{$\Box$} }
}
{ \texttt{#2} }
}
}
\NewDocumentCommand \TransTM { m }
{ \__edge_label_tm:n {#1} }
\cs_new_protected:Npn \__edge_label_tm:n #1
{
\seq_set_split:Nnn \l_tmpa_seq { | } { #1 }
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \SplitItemTM \exp_not:n { {##1} } }
\shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}
\NewDocumentCommand \SplitItemTM { >{\SplitArgument{2}{,}} m }
{ \__edge_item_tm:nnn #1 }
\cs_new_protected:Npn \__edge_item_tm:nnn #1 #2 #3
{
\Char[.63em]{#1};\;\Char[.63em]{#2},\,\Char{#3}
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L} \qquad
\TransTM{a, x, L | b, y, L} \qquad
\TransTM{a, x, L | b, y, L | ~, ~, R}
\end{document}
产生期望的结果。
但是,它滥用了它,\NewDocumentCommand
因为\SplitItemTM
它属于实现,而不是用户界面。\SplitItemTM
用内部函数替换的正确方法是什么?
答案1
首先:您不应该使用\cs_new_protected:Npn
具有签名的函数进行定义:cn
。
我认为您的输入是这种形式\TransTM{a, x, R | b, y, L | c, m, n, p}
,并且您想要隔离每个|
分隔部分中的第一个项目,以便在其后使用分号。
首先将参数拆分为|
,并执行映射,在每个项周围添加辅助函数。此辅助宏将在\shortstack
打印 中的行时起作用:隔离第一个项,打印后跟分号和空格,然后传递其余的序列项,并用逗号和空格分隔。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\TransTM}{m}
{
\matthias_edge_label:n { #1 }
}
\seq_new:N \l__matthias_edge_labels_in_seq
\seq_new:N \l__matthias_edge_labels_out_seq
\seq_new:N \l__matthias_edge_label_seq
\tl_new:N \l__matthias_edge_label_head_tl
\cs_new_protected:Nn \matthias_edge_label:n
{
% first let's split at |
\seq_set_split:Nnn \l__matthias_edge_labels_in_seq { | } { #1 }
% populate the sequence for output
\seq_set_map:NNn
\l__matthias_edge_labels_out_seq
\l__matthias_edge_labels_in_seq
{ \__matthias_edge_label:n { \exp_not:n { ##1 } } }
% deliver it
\shortstack{ \seq_use:Nn \l__matthias_edge_labels_out_seq { \\ } }
}
\cs_new_protected:Nn \__matthias_edge_label:n
{
% split the argument at commas
\seq_set_split:Nnn \l__matthias_edge_label_seq { , } { #1 }
% remove the first item
\seq_pop_left:NN \l__matthias_edge_label_seq \l__matthias_edge_label_head_tl
\tl_use:N \l__matthias_edge_label_head_tl
;~
\seq_use:Nn \l__matthias_edge_label_seq { ,~ }
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L | b, y, R}
\qquad
\TransTM{a, x, R | b, y, L | c, m, n, p}
\end{document}
现在,让我们看看你的方法出了什么问题。当你这样做时
\TransTM{a, x, L | b, y, R}
序列\l_tmpb_seq
将包含以下项目
{\edge_item:cn {edge_item_tm:nnn} {a, x, L}}
{\edge_item:cn {edge_item_tm:nnn} {b, y, R}}
(为了清晰起见,用了外括号,但实际上没有)。当序列传递时,你会得到
\shortstack{%
\edge_item:cn {edge_item_tm:nnn} {a, x, L}\\%
\edge_item:cn {edge_item_tm:nnn} {b, y, R}%
}
(为了便于阅读,我们分行了)。现在,您的想法是将第二个参数中的项目用逗号分开,然后应用一个三参数函数。但是如果您这样做
\use:c{edge_item_tm:nnn} \seq_use:Nn \l_tmpb_seq { }
的第一个参数\edge_item_tm:nnn
将是\seq_use:Nn
,因为它尚未扩展。
虽然可以这样做,但我不推荐这种方法。无论如何,这些c
论点都不合适。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \TransTM { m }
{ \edge_label:Nn \edge_item_tm:nnn {#1} }
\cs_new_protected:Npn \edge_label:Nn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { | } { #2 }
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { \edge_item:Nn #1 {##1} }
\shortstack{ \seq_use:Nn \l_tmpb_seq { \\ } }
}
\cs_new_protected:Npn \edge_item:Nn #1 #2
{
\seq_set_split:Nnn \l_tmpa_seq { , } { #2 }
\seq_set_map:NNn \l_tmpb_seq \l_tmpa_seq { {##1} }
\exp_last_unbraced:Nf #1 \seq_use:Nn \l_tmpb_seq { }
}
\cs_new_protected:Npn \edge_item_tm:nnn #1 #2 #3
{
#1;~#2,~#3
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L | b, y, R}
\end{document}
附录
您认为那\SplitItemTM
不属于那里,这是对的。
\documentclass{article}
\usepackage{xparse}
\usepackage{graphicx,amssymb}
\ExplSyntaxOn
\NewDocumentCommand \Char { O{\width} m }
{
\makebox[#1]{ \edge_char:n { #2 } }
}
\NewDocumentCommand \TransTM { m }
{
\edge_label:n {#1}
}
\seq_new:N \l__edge_labels_in_seq
\seq_new:N \l__edge_labels_out_seq
\cs_new_protected:Nn \edge_char:n
{
\str_case_x:nnF { \tl_to_str:n {#1} }
{
{ } { $\varepsilon$ }
{ ## } { \texttt{\#} }
{ \c_tilde_str } { \scalebox{.87}{$\Box$} }
}
{ \texttt{#1} }
}
\cs_generate_variant:Nn \edge_char:n { f }
\cs_new_protected:Nn \edge_label:n
{
\group_begin:
% this because otherwise boxes would not print
\char_set_active_eq:nN { `\~ } \c_tilde_str
\seq_set_split:Nnn \l__edge_labels_in_seq { | } { #1 }
\seq_set_map:NNn
\l__edge_labels_out_seq
\l__edge_labels_in_seq
{ \edge_item:n { \exp_not:n { ##1 } } }
\shortstack
{
\seq_use:Nn \l__edge_labels_out_seq { \\ }
}
\group_end:
}
\cs_new_protected:Nn \edge_item:n
{
\edge_char:f { \clist_item:nn { #1 } {1} } ; ~
\edge_char:f { \clist_item:nn { #1 } {2} } , ~
\edge_char:f { \clist_item:nn { #1 } {3} }
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L} \qquad
\TransTM{a, , L | b, #, L} \qquad
\TransTM{a, x, L | b, y, L | ~, ~, R}
\end{document}
答案2
L3 版本的替代版本listofitems
。已编辑以消除对参数可扩展性的需要,这通过\ddag
在参数中使用不可扩展性来证明。
\documentclass{article}
\usepackage{listofitems}
\newcommand{\addtotoks}[2]{#1\expandafter{\the#1#2}}
\newcommand{\xxaddtotoks}[2]{\expandafter\expandafter\expandafter\addtotoks%
\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{#2}}
\newtoks\zztoks
\newcommand\TransTM[1]{%
\setsepchar{{|}/,}%
\readlist*\zz{#1}%
\zztoks{}%
\foreachitem\x\in\zz[]{%
\if\xcnt=1\else\addtotoks\zztoks{\\}\fi
\xxaddtotoks\zztoks{\zz[\xcnt,1];~}%
\xxaddtotoks\zztoks{\zz[\xcnt,2],~}%
\xxaddtotoks\zztoks{\zz[\xcnt,3]}%
}%
\expandafter\shortstack\expandafter{\the\zztoks}%
}
\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | c, y, \ddag}
\end{document}
或者如果不喜欢标记列表,则使用\def
s (通过\g@addto@macro
):
\documentclass{article}
\usepackage{listofitems}
\makeatletter
\newcommand\TransTM[1]{%
\setsepchar{{|}/,}%
\readlist*\zz{#1}%
\def\zzz{}%
\foreachitem\x\in\zz[]{%
\if\xcnt=1\else\g@addto@macro\zzz{\\}\fi
\addzzz{\zz[\xcnt,1];~}%
\addzzz{\zz[\xcnt,2],~}%
\addzzz{\zz[\xcnt,3]}%
}%
\expandafter\shortstack\expandafter{\zzz}%
}
\newcommand\addzzz[1]{\expandafter\expandafter\expandafter\g@addto@macro%
\expandafter\expandafter\expandafter\zzz\expandafter\expandafter\expandafter{#1}}
\makeatother
\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | c, y, \ddag}
\end{document}
\Char
显示可以与此方法一起使用的版本:
\documentclass{article}
\usepackage{listofitems,xparse,relsize,amssymb}
\newcommand{\addtotoks}[2]{#1\expandafter{\the#1#2}}
\newcommand{\xxaddtotoks}[2]{\expandafter\expandafter\expandafter\addtotoks%
\expandafter\expandafter\expandafter#1\expandafter\expandafter\expandafter{#2}}
\def\ZZ{\Char[.5em]{~}}%
\newtoks\zztoks
\newcommand\TransTM[1]{%
\setsepchar{{|}/,}%
\readlist*\zz{#1}%
\zztoks{}%
\foreachitem\x\in\zz[]{%
\if\xcnt=1\else\addtotoks\zztoks{\\}\fi
\xxaddtotoks\zztoks{\zz[\xcnt,1];~}%
\xxaddtotoks\zztoks{\zz[\xcnt,2],~}%
\xxaddtotoks\zztoks{\zz[\xcnt,3]}%
}%
\texttt{\expandafter\shortstack\expandafter{\the\zztoks}}%
}
\ExplSyntaxOn
\NewDocumentCommand \Char { O{\width} m }
{
\makebox[#1]
{
\str_case_x:nnF { \tl_to_str:n {#2} }
{
{ } { $\varepsilon$ }
{ ## } { \texttt{\#} }
{ \c_tilde_str } { \textscale{.87}{$\Box$} }
}
{ \texttt{#2} }
}
}
\ExplSyntaxOff
\begin{document}
\TransTM{a, x, L | b, y, R}\quad%
\TransTM{a, x, L | b, y, R | \ZZ, y, \ddag}
\end{document}