我想定义一个新的 mathmode 命令,例如:
- 输入是一个字符串s;
- 输出是相同的字符串,其中每个字符的字体根据字符是小写还是大写而改变。
用伪代码来说,它看起来像这样:
\newcommand{\cat}{
forEach (character char in #1) {
if (isLowerCase(char)) -> print \mathit{char}
else -> print \mathcal{char}
}
}
似乎我可以使用if/elseifthenelse
包中的代码ifthen
。我找不到如何操作:
- 从字符串中提取字符;
- 对每个字符进行循环;
- 检查字符是否是小写。
顺便说一句,如果有人知道关于定义命令的可读但又详尽的参考,我将不胜感激(我只能找到太基础或“超出我理解范围”的参考)。
感谢您的帮助!
PS:如果有人需要一些背景信息,我正在研究范畴论,其中范畴的典型字体是 \mathcal。由于 mathcal 中的小写字母没有定义,所以我需要找到一种解决方法。
编辑:我在这里描述我对 Ulrike Fischer 解决方案的理解,因为它可能对其他人有用。
\ExplSyntaxOn
\NewDocumentCommand\cat{m}
{
\tl_set:Nn\l_tmpa_tl {#1}
\regex_replace_all:nnN {[a-z]}{\c{mathit}\cB\{\0\cE\}}\l_tmpa_tl
\regex_replace_all:nnN {[A-Z]}{\c{mathcal}\cB\{\0\cE\}}\l_tmpa_tl
\l_tmpa_tl
}
\ExplSyntaxOff
ExplSyntaxOn...ExplSyntaxOff
:更改代码机制,其中空格被忽略,“:”和“_”被视为字母。访问函数和变量时需要。请参阅 interface3.pdf,第 7 页。\NewDocumentCommand \cat {m} {...}
:创建一个新的文档级函数。首先应描述函数名称(\cat
)、参数集( ,一个在函数代码中{m}
引用的参数)和函数代码本身( )。请参阅 xparse.pdf,第 7 页。#1
{...}
\tl_set:Nn \l_tmpa_tl {#1}
:\tl_set:Nn
设置某个变量(或“标记列表”,因此)的值tl
。N
并n
定义此函数的通常参数类型,N
代表单个标记和n
括号之间的标记列表。\l_tmpa_tl
是本地临时分配标记列表的标准名称。- 的第一个参数
\regex_replace_all:nnN
是要替换的标记列表,例如{[a-z]}
。第二个参数是如何处理这些标记,例如{\c{mathit}\cB\{\0\cE\}}
。\c{mathit}
相当于\mathit
(出于某种原因,您不能只写\mathit
)。\0
代表通过第一个参数选择的所有内容。出于某种原因,它应该被 包围\cB\{...\cE\}
。最后,第三个参数是应用该函数的标记列表。 - 最后
\l_tpma_tl
只是显示结果标记。
答案1
Ulrike 的回答很好,但我们可以通过删除不需要的字距来改进它。
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\AtBeginDocument{$\mathcal{\global\chardef\calfam=\fam}$}
\ExplSyntaxOn
\cs_new_protected:Nn \__trynopsis_cat_neg:n
{
\mathchoice
{ \__trynopsis_cat_neg_aux:Nn \textfont { #1 } }
{ \__trynopsis_cat_neg_aux:Nn \textfont { #1 } }
{ \__trynopsis_cat_neg_aux:Nn \scriptfont { #1 } }
{ \__trynopsis_cat_neg_aux:Nn \scriptscriptfont { #1 } }
}
\cs_new_protected:Nn \__trynopsis_cat_neg_aux:Nn
{
\kern -\fontcharic#1\calfam`#2
}
\NewDocumentCommand{\cat}{m}
{
\trynopsis_cat:n { #1 }
}
\tl_new:N \l__trynopsis_cat_tl
\cs_new_protected:Nn \trynopsis_cat:n
{
\tl_set:Nn \l__trynopsis_cat_tl { #1 }
\regex_replace_all:nnN
{ ([A-Z]) ([a-z]) } % search uppercase letter followed by a lowercase letter
{ \1 \c{__trynopsis_cat_neg:n} \1 \2 } % add a negative space in between
\l__trynopsis_cat_tl
\regex_replace_all:nnN
{ [A-Z]+ } % search any run of uppercase letters
{ \c{mathcal}\cB\{\0\cE\} } % enclose it in \mathcal
\l__trynopsis_cat_tl
\regex_replace_all:nnN
{ [a-z]+ } % search any run of lowercase letters
{ \c{mathit}\cB\{\0\cE\} } % enclose it in \mathit
\l__trynopsis_cat_tl
\regex_replace_all:nnN
{ \c{__trynopsis_cat_neg:n} \c{mathcal} }
{ \c{__trynopsis_cat_neg:n} }
\l__trynopsis_cat_tl
% deliver the new token list
\tl_use:N \l__trynopsis_cat_tl
}
\cs_new_protected:Nn \__trynopsis_cat_neg:
{
\mspace{-2mu}
}
\ExplSyntaxOff
\begin{document}
$\cat{Set}\quad\cat{Grp}\quad\cat{Abc\_def}$
$\scriptstyle\cat{Set}\quad\cat{Grp}\quad\cat{Abc\_def}$
\end{document}
第四次替换将不需要的转换\__trynopsis_cat_neg:n \mathcal {<letter>}
为\__trynopsis_cat_neg:n {<letter>}
。
的目的\__trynopsis_cat_neg:n
是删除大写(书法)字母后面跟着小写(斜体)字母时的多余空格。
答案2
假设参数中只有 aZ:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand\mycal{m}
{
\tl_set:Nn\l_tmpa_tl {#1}
\regex_replace_all:nnN {[a-z]}{\c{mathit}\cB\{\0\cE\}}\l_tmpa_tl
\regex_replace_all:nnN {[A-Z]}{\c{mathcal}\cB\{\0\cE\}}\l_tmpa_tl
\l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
$\mycal{abcABC}$
\end{document}