答案1
首先:
\newcommand*\smashoperator[2][lr]{
\def\MT_smop_use:NNNNN {\@nameuse{MT_smop_smash_#1:NNNNN}}
\toks@{#2}
\expandafter\MT_smop_get_args:wwwNnNn
\the\toks@\@nil\@nil\@nil\@nil\@nil\@nil\@@nil
}
调用时\smashoperator{\sum_{a}^{b}}
,宏\MT_smop_use:NNNNN
被定义为扩展为\MT_smop_smash_lr:NNNNN
,参数被加载到令牌寄存器中\toks@
。目前还不清楚为什么要做这个中间步骤,因为令牌寄存器的内容会立即被传递,我们得到
\MT_smop_get_args:wwwNnNn \sum_{a}^{b}\@nil\@nil\@nil\@nil\@nil\@nil\@@nil
的目的\MT_smop_get_args:wwwNnNn
是用很长的代码来标识操作符、下标和上标。然后将上标和下标设置在具有适当狭窄样式的框中,并放置在上方和下方,但占用零宽度。
更简单的实现如下xparse
:
\documentclass{article}
\usepackage{mathtools,xparse}
\NewDocumentCommand{\xsmashoperator}{me{_^}}{%
\doxsmashoperator{#1}{#2}{#3}%
}
\ExplSyntaxOn
\NewDocumentCommand{\doxsmashoperator}{mmm}
{
#1
\IfValueT{#2}{\sb{\mathclap{\cramped{#2}}}}
\IfValueT{#3}{\sp{\mathclap{\cramped{#3}}}}
}
\ExplSyntaxOff
\begin{document}
\begin{gather*}
XXXX\smashoperator{\sum_{k=12345^2}^{123456789}}YYYYYY \\
XXXX\xsmashoperator\sum_{k=12345^2}^{123456789}YYYYYY
\end{gather*}
\end{document}
l
实现和选项会更加复杂r
,但主要要素已经存在,即如何吸收可选的下标和上标,甚至不需要额外的括号(版本中不允许xparse
)。
请注意,\ExplSyntaxOn
和不是必需的;它们是根据和\ExplSyntaxOff
的实现来使用的。l
r
基本上,需要进行测量,并添加必要的前后间距。让斯普,某人和操作分别为上标、下标和运算符的宽度。然后,将运算符设置为其正常宽度,上标/下标的宽度为零。如果r
设置了,则宽度为 max(0pt, max(斯普,某人) -操作)/2 添加在运算符之前;如果l
设置了,则添加在运算符之后。
这是一个完整的实现:
\documentclass{article}
\usepackage{mathtools,xparse}
\NewDocumentCommand{\xsmashoperator}{ome{_^}}{%
\IfNoValueTF{#1}
{%
\doxsmashoperator{#2}{#3}{#4}%
}
{%
\doxsmashoperatoropt{#1}{#2}{#3}{#4}%
}
}
\ExplSyntaxOn
\NewDocumentCommand{\doxsmashoperator}{mmm}
{
#1
\IfValueT{#2}{\sb{\mathclap{\cramped{#2}}}}
\IfValueT{#3}{\sp{\mathclap{\cramped{#3}}}}
}
\NewDocumentCommand{\doxsmashoperatoropt}{mmmm}
{
\group_begin:
\__siracusa_xsmashoperator:nnnn { #1 } { #2 } { #3 } { #4 }
\group_end:
}
\box_new:N \l__siracusa_xsmashoperator_op_box
\box_new:N \l__siracusa_xsmashoperator_sb_box
\box_new:N \l__siracusa_xsmashoperator_sp_box
\dim_new:N \l__siracusa_xsmashoperator_dim
\cs_new_protected:Nn \__siracusa_xsmashoperator_math:n
{
$ \use:c { m@th } #1 $
}
\cs_new_protected:Nn \__siracusa_xsmashoperator:nnnn
{
\hbox_set:Nn \l__siracusa_xsmashoperator_op_box
{
\__siracusa_xsmashoperator_math:n { \displaystyle{#2} }
}
\hbox_set:Nn \l__siracusa_xsmashoperator_sb_box
{
\tl_if_novalue:nF { #3 }{ \__siracusa_xsmashoperator_math:n {\scriptstyle\cramped{#3}} }
}
\hbox_set:Nn \l__siracusa_xsmashoperator_sp_box
{
\tl_if_novalue:nF { #4 }{ \__siracusa_xsmashoperator_math:n {\scriptstyle\cramped{#4}} }
}
\dim_set:Nn \l__siracusa_xsmashoperator_dim
{
\dim_max:nn
{ \box_wd:N \l__siracusa_xsmashoperator_sp_box }
{ \box_wd:N \l__siracusa_xsmashoperator_sb_box }
- \box_wd:N \l__siracusa_xsmashoperator_op_box
}
\dim_set:Nn \l__siracusa_xsmashoperator_dim
{
\dim_max:nn { \l__siracusa_xsmashoperator_dim } { 0pt } / 2
}
% now do the typesetting
\str_if_eq:nnT { #1 } { r } { \hspace{\l__siracusa_xsmashoperator_dim} }
#2
\tl_if_novalue:nF { #3 } { \sb{\mathclap{\cramped{#3}}} }
\tl_if_novalue:nF { #4 } { \sp{\mathclap{\cramped{#4}}} }
\str_if_eq:nnT { #1 } { l } { \hspace{\l__siracusa_xsmashoperator_dim} }
}
\ExplSyntaxOff
\begin{document}
\begin{gather*}
XXXX\smashoperator{\sum_{k=12345^2}^{123456789}}YYYYYY \\
XXXX\xsmashoperator\sum_{k=12345^2}^{123456789}YYYYYY \\
XXXX\smashoperator[l]{\sum_{k=12345^2}^{123456789}}YYYYYY \\
XXXX\xsmashoperator[l]\sum_{k=12345^2}^{123456789}YYYYYY \\
XXXX\smashoperator[r]{\sum_{k=12345^2}^{123456789}}YYYYYY \\
XXXX\xsmashoperator[r]\sum_{k=12345^2}^{123456789}YYYYYY
\end{gather*}
\end{document}