正如这个网站上的许多问题(分别是答案)所指出的那样,可以耗尽(分别是扩展)分配给数学字母表的插槽列表。以下 MWE 实现了我的目标,但很麻烦。由于数学版本“normal”中的所有数学字母表插槽都被使用,我决定将数学版本切换为“normal2”,但只弄清楚了如何做到这一点按每项,如表格最后一行中的 ABC 条目所示。
\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}
\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}
\begin{document}
\begin{tabular}{r|*{3}{c@{~~}}}
rm & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
pzc &\mathversion{normal2} \(\mathpzc A\) & \mathversion{normal2}\(\mathpzc B\) & \mathversion{normal2}\(\mathpzc C\)\\
\end{tabular}
\end{document}
当\mathversion{normal2}
从最后一行删除任何字母时,编译后的代码会发出“数学字母太多”警告。另一方面,将其包含在每条条目中非常麻烦(实际表格是完整的 26 个宽字母表)。这让我想到了手头的问题。
问题: 有没有办法改变表格和/或数组环境中的数学版本以跨越给定行中的所有条目,或者(甚至更好)跨越多行?
附言 1:当然,繁琐的代码可以降级为宏,这也是我目前实际上正在做的事情,但在我看来,让编译器在数学版本之间来回切换并不是一个好主意,所以如果可能的话,最好有一个替代方案。
附言 2:由于以上内容是 MWE,因此它确实是解决核心问题的最低要求。我想要构建的实际表格大约有 70 行长,并且是整个字母表的宽度。它的目的是成为字体的一站式商店;我的同事可以访问它,快速确定他们想要使用哪种字体,然后重定向到即将包含的参考资料,在那里他们可以将相关信息复制/粘贴到他们的 LaTeX 代码中,目标是尽快开始实际工作。特别是,在文档的其他部分,我需要 lmodern 和 pxfonts 包,即使它们在这个 MWE 中的实际用途并不那么明显(除了占用数学字母表)。我提到这一点是因为“你为什么要浪费数学字母表\mathrm
而不是仅仅使用文本模式”之类的评论/答案没有帮助;我只想在 MWE 中尽可能高效地使用数学字母表。
答案1
如果您要生成许多类似的表格,最好让 LaTeX 完成大部分工作,您只需提供字母表(比如说A, B, C, D
)和要使用的“字体”列表,例如:
\MathCharacterTable{
mathrm, mathbf, mathtt, mathit, mathsf, mathfrak, b!mathfrak,
mathcal, eucal, b!mathcal, b!eucal, 2!mathpzc
}
这里的重点是,每个命令都是命令的名称:\mathbf{A}
等都\mathsf{A}
可以。唯一需要解释的部分可能是b!
表示应用\bm
和2!
表示\mathversion{normal2}
需要。有了这些,下面的代码就会生成表格:
左侧由\MathCharacterTable
命令生成,而用于比较的右侧来自 OP。
代码是使用 latex3 编写的,只需处理两个逗号分隔的列表:字母表列表和“字体”列表。将“特殊”字体描述(如b!eucal
)转换为正确的命令需要一些技巧,但除此之外,这基本上很简单。代码的结构方式应该很容易添加新的“字体”并更改字母表。
以下是代码:
\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}
\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}
\usepackage{xparse}
\ExplSyntaxOn
% define the alphabet for the table as a comma separated list
\clist_const:Nn \c_alphabet_clist {A,B,C,D}
\str_new:N \l_mathopt_str
\str_new:N \l_mathstyle_str
\cs_new_protected_nopar:Nn \process_row:n {
\str_if_in:nnTF {#1} {!}
{% we have a ! : b=\bm or 2=\mathversion{2}
\seq_set_split:Nnn \l_tmpa_seq {!} {#1}
\str_set:Nx \l_mathopt_str {\seq_item:Nn \l_tmpa_seq {1}}
\str_gset:Nx \l_mathstyle_str {\seq_item:Nn \l_tmpa_seq {2}}
\cs_set_mathstyle:VV \l_mathopt_str \l_mathstyle_str
}
{% no ! => normal processing
#1 % the row label
\cs_gset_nopar:Npn \math_style:n ##1 { $\use:c{#1}{##1}$ }
}
% now apply the math style to the alphabet for the row
\clist_map_inline:Nn \c_alphabet_clist { &\math_style:n ##1 }
\\ % end the tabular row
}
% define the \math_style:n command for \bm and math version w
\cs_new_protected_nopar:Nn \cs_set_mathstyle:nn {
\str_case:nn { #1 } {
{b} { #2+bm % the row label
\cs_gset_nopar:Npn \math_style:n ##1 { $\bm{\use:c{#2}{##1}}$ }
}
{2} { #2 % the row label
\cs_gset_nopar:Npn \math_style:n ##1 {
\mathversion{normal2}$\use:c{#2}##1$
}
}
}
% add new modifers <?!font> here
}
% force the strings to expand when we use \cs_set_mathstyle:nn
\cs_generate_variant:Nn \cs_set_mathstyle:nn {VV}
\NewDocumentCommand\MathCharacterTable{m}{
\clist_set:Nn \l_mathstyles_clist {#1}
\begin{tabular}{r|*{\clist_count:N \c_alphabet_clist}{c@{~~}}}
\clist_map_function:nN {#1} \process_row:n
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{l@{\qquad}l}
Generated by MathCharacterTable & Explicitly entered\\[1mm]\hline
\MathCharacterTable{
mathrm, mathbf, mathtt, mathit, mathsf, mathfrak, b!mathfrak,
mathcal, eucal, b!mathcal, b!eucal, 2!mathpzc
}
&
\begin{tabular}{r|*{3}{c@{~~}}}
rm & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
pzc &\mathversion{normal2} \(\mathpzc A\) & \mathversion{normal2}\(\mathpzc B\) & \mathversion{normal2}\(\mathpzc C\)\\
\end{tabular}
\end{tabular}
\end{document}
答案2
经过进一步研究,我发现需要在原始帖子的每个条目中重新发布的原因\mathversion{<name>}
是,该调用仅影响其所在环境的范围:该范围仅持续到本地环境(即条目)的结束。使用“本地”一词让我想起有方法可以使命令成为全局命令。
考虑到这一点,令我有点惊讶的是,原始问题的答案是是的\global
,并且可以通过在转换之前添加来实现\mathversion
。(在下面的代码中,此调用是在最后一行的第一个条目中给出的,但也可以在第二个条目的开头给出,甚至可以在上一行的任何位置给出。)
\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}
\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}
\begin{document}
\begin{tabular}{r|*{3}{c@{~~}}}
rm & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
\global\mathversion{normal2}
pzc & \(\mathpzc A\) & \(\mathpzc B\) & \(\mathpzc C\)\\
\end{tabular}
\end{document}
此外,答案是是的即使在数组环境中:只需将\global\mathversion{normal2}
调用包裹在 中即可\mbox
。
\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}
\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}
\begin{document}
\[
\begin{array}{r|*{3}{c@{~~}}}
\text{rm } & \mathrm A & \mathrm B & \mathrm C\\
\text{bf} & \mathbf A & \mathbf B & \mathbf C\\
\text{tt} & \mathtt A & \mathtt B & \mathtt C\\
\text{it} & \mathit A & \mathit B & \mathit C\\
\text{sf} & \mathsf A & \mathsf B & \mathsf C\\
\text{frak} &\mathfrak A & \mathfrak B & \mathfrak C\\
\text{frak+bm} & \bm{\mathfrak A} & \bm{\mathfrak B} & \bm{\mathfrak C}\\
\text{cal} & \mathcal A & \mathcal B & \mathcal C\\
\text{euc} & \eucal A & \eucal B & \eucal C\\
\text{cal+bm} & \bm{\mathcal A} & \bm{\mathcal B} & \bm{\mathcal C}\\
\text{euc+bm} & \bm{\eucal A} & \bm{\eucal B} & \bm{\eucal C}\\
\mbox{\global\mathversion{normal2}}
\text{pzc} & \mathpzc A & \mathpzc B & \mathpzc C\\
\end{array}
\]
\end{document}
顺便说一句,我必须推荐一下 David Carlisle 的 longtable 包。我实际创建的内容比这些示例中展示的要长得多,而且该包完美地在表格中提供了分页符(前提是,与我不同,您记得重新编译文件适当的次数)。