我想编写一个命令\foo
,它接受一个数学模式表达式,并使用 中打印的一些选定符号(比如用 表示#
)来呈现它\mathcal
。例如,\foo{#X^A_B}
应该扩展为\mathcal{X}^A_B
。
顺便问一句,如果命令具有以下行为,那会很方便。如果输入由多个符号组成,则按上述方式解析。但是,如果输入仅由一个符号组成,则\mathcal
即使该符号前面没有 ,也应该将其转换为#
。例如\foo{X}
和\foo{#X}
都应扩展为 ,\mathcal{X}
而\foo{X^A}
应扩展为X^A
。
实现此目的的最简单方法是什么?我不坚持这种特定的语法。任何合理紧凑的语法都可以。
答案1
这个想法是打开\foo
一个组,并将组内选定的字符设置为数学活动,其操作只是\mathcal
。如果参数是单个标记,则只需应用于\mathcal
它。
这很容易expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{m}
{
\szumilo_foo:n { #1 }
}
\cs_new_protected:Nn \szumilo_foo:n
{
\tl_if_single:nTF { #1 }
{ \mathcal{#1} }
{ \szumilo_foo_multiple:n { #1 } }
}
\cs_new_protected:Nn \szumilo_foo_multiple:n
{
\group_begin:
\char_set_mathcode:nn { `* } { "8000 }
#1
\group_end:
}
\char_set_active_eq:NN * \mathcal
\ExplSyntaxOff
\begin{document}
$\foo{*X}+\foo{X}+\foo{X^A}+\foo{*X^A_B}$
\end{document}
如果坚持使用的话#
就会比较困难。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{m}
{
\szumilo_foo:n { #1 }
}
\cs_new_protected:Nn \szumilo_foo:n
{
\tl_if_single:nTF { #1 }
{ \mathcal{#1} }
{ \szumilo_foo_multiple:n { #1 } }
}
\cs_new_protected:Nn \szumilo_foo_multiple:n
{
\group_begin:
\tl_set_rescan:Nnn \l_szumilo_foo_arg_tl { \char_set_catcode:nn { `\# } { 12 } } { #1 }
\char_set_mathcode:nn { `\# } { "8000 }
\tl_use:N \l_szumilo_foo_arg_tl
\group_end:
}
\cs_new:Nn \szumilo_foo_mathcal:NN { \mathcal{#2} }
\char_set_active_eq:nN { `\# } \szumilo_foo_mathcal:NN
\ExplSyntaxOff
\begin{document}
$\foo{#X}+\foo{X}+\foo{X^A}+\foo{#X^A_B}$
\end{document}
除了需要重新扫描#
第 12 类的论据之外,我们还需要吞下一个#
(因为当这些标记具有第 6 类时,它们会加倍)。
答案2
这是一种简单的方法,使用listofitems
解析:
\documentclass{article}
\usepackage{listofitems}
\newcommand\foo[1]{\fooaux#1\fooend}
\def\fooaux#1#2\fooend{
\ifx\relax#2\relax\mathcal{#1}\else
\setsepchar{"}
\readlist\mylist{#1#2}
\foreachitem\i\in\mylist{
\ifnum\icnt=1\else\expandafter\expandafter\expandafter\mathcal\expandafter\fi
\i
}
\fi
}
\begin{document}
$\foo{X}\quad\foo{"X}\quad\foo{X^A}$
$\foo{"X}+\foo{X}+\foo{X^A}+\foo{"X^A_B}$
\end{document}
还有一种更简单的方法\catcode
,使用 s 可以产生相同的结果。
\documentclass{article}
\catcode`"=\active %
\def"{\mathcal}
\newcommand\foo{\catcode`"=\active\fooz}
\newcommand\fooz[1]{\foozz#1\fooend}
\def\foozz#1#2\fooend{\ifx\relax#2\relax\mathcal{#1}\else#1#2\fi}
\catcode`"=12 %
\begin{document}
$\foo{X}\quad\foo{"X}\quad\foo{X^A}$
$\foo{"X}+\foo{X}+\foo{X^A}+\foo{"X^A_B}$
\end{document}
由于 OP 没有与特定语法绑定,我将特殊字符从 更改#
为"
。