帮助我理解重新定义 \textbullet 时的行为

帮助我理解重新定义 \textbullet 时的行为

我已重新定义\textbullet它以使其稍微大一些(因为 Libertinus 字体使用的字符与 Computer Modern 等效字符相比非常小),如下所示:

\documentclass[11pt]{report}
\usepackage{libertinus}

% Resize \textbullet to make it a bit larger (closer to Computer Modern)
\let\oldbullet\textbullet
\renewcommand*\textbullet{{\large\oldbullet}}

\begin{document}
\oldbullet\textbullet$\mathord\bullet$
\end{document}

就实现我的主要目标而言,这很好(\textbullet现在生成一个稍大一点的版本)。我不明白的是为什么\oldbullet也显示更大?我期望\oldbullet生成一个小项目符号并\textbullet生成一个稍大一点的项目符号,因为我认为使用\let定义\oldbullet为与原来的的定义\textbullet。显然,这里的情况并非如此。

我试图查看 LaTeX 源文件 ( \DeclareUnicodeCharacter{2022}{\textbullet}) 和\show定义 ( ->\?-cmd \textbullet \?\textbullet .),但我不太明白它们的含义......

关于我下一步应该看哪里,有什么指示吗?

答案1

这里发生的情况是,的定义\textbullet在使用时查找了几件事,因此尝试用保存符号会\let失败。

修复

如果您在现代引擎(例如 LuaLaTeX 或 XeLaTeX)中进行编译,该libertinus包将加载fontspecunicode-math以及文本和数学字体的 Unicode 版本。

这些字体支持 Unicode 符号 ⚫、•、∙ 等。它甚至为它们unicode-math定义了宏\vysmblkcircle\smblkcircle\mdblkcircle等。Libertinus 字体有一些但不是全部,因此如果您想重新定义\textbullet为更大的字体,您需要首先选择包含它的字体。我选择了 DejaVu Sans。

如果您在传统的 TeX 引擎(例如 PDFLaTeX)中进行编译,则需要定义TS1 编码的\oldbullet插槽(本质上是复制中的旧定义,而不是在现代 LaTeX 内核中保存更复杂的命令)。如果您要使用不附带 TS1 扩展的字体,则需要定义以选择字体系列和编码以及字体大小。由于您使用的是其他字体包,所以这不是问题。"88\textbullettextcomp\textbulletlibertinus

但是,您并不想总是选择\large大小,即使在脚注中也是如此。您更可能希望符号比当前字体大一号。您可以使用 来实现这一点relsize

一个样品:

\tracinglostchars=2 % Print a warning to the console if a character is missing.
\documentclass[11pt]{report}
\usepackage{iftex}
\usepackage{libertinus}

\ifTUTeX
% The libertinus package loaded fontspec and unicode-math, with Libertinus
% Math as the math font.
  \newfontfamily\symbolfont{DejaVu Sans}[Scale=MatchLowercase]
  \DeclareTextSymbol{\oldbullet}{\UnicodeEncodingName}{"2022}
  \DeclareTextSymbolDefault{\oldbullet}{\UnicodeEncodingName}
  \renewcommand\textbullet{{\symbolfont\symbol{"26AB}}}
\else
% The libertinus package loaded the legacy Type 1 font.
  \usepackage[T1]{fontenc}
  \usepackage[libertine]{newtxmath}
  \usepackage{relsize}
  \DeclareTextSymbol{\oldbullet}{TS1}{"88}
  \DeclareTextSymbolDefault{\oldbullet}{TS1}
  \renewcommand\textbullet{{\larger\oldbullet}}
\fi

\begin{document}
\oldbullet\textbullet$\mathord\bullet$
\end{document}

\textbullet如果您还希望 U+2022在文本模式和数学模式下等效\bullet,您可以添加类似内容:

\usepackage{newunicodechar}
\newunicodechar{^^^^2022}{\ifmmode\bullet\else\textbullet\fi}

这是怎么回事?

LaTeX 内核\textbullet使用三种不同的编码之一进行声明:来自 TS1 8 位编码的旧符号、来自 OMS 7 位编码的更古老的旧符号以及 Unicode 符号。这意味着命令\textbullet无法提前知道将使用哪种字体或编码,并且尝试使用 保存定义然后\let重新定义\textbullet将无法按预期工作。

历史原因在于,子弹运算符在 80 年代首次被定义为数学符号。1996 年,Jörg Knappen 定义了一种文本符号编码 TS1,作为新 T1 Cork 编码的配套。然而,当时大多数可用的字体仅支持不到一半的 TS1。作为一种错误解决方法,在接下来的二十年里,LaTeX 作者会加载该textcomp包,它会尝试检测当前字体支持的符号,并在必要时回退到 poor-man 版本。

不再需要加载单独的包:此代码现在位于 LaTeX 内核中。

该定义记录在 LaTeX2e 源代码的 §20.4.1 中。相关部分是\DeclareTextCommand扩展为代码,该代码检查当前编码以及我们是否处于数学模式。这指的是\?\textbullet由 定义的\DeclareTextCommandDefault,它最终以递归方式展开。

答案2

发生这种情况是因为您刚刚定义了顶层\oldbullet,然后它扩展为\?-cmd \textbullet \?\textbullet,最终扩展为您重新定义\textbullet\large\oldbullet

正如评论中提到的那样,这基本上与强命令的问题相同:它们不是一个宏,而是一组与顶级宏同名的宏,当您重新定义一个宏时,您必须重新定义它们全部,否则您会看到不必要的行为(但是,这并未包括在内letltxmacro)。

要做您想做的事情,您可以不用将定义复制\textbullet到新名称,而是可以采用与 LaTeX\oldbullet相同的方式进行声明:\textbullet

\DeclareTextSymbol{\oldbullet}{TS1}{136}
\DeclareTextSymbolDefault{\oldbullet}{TS1}

第一行表示该命令将从当前字体的编码中\oldbullet获取字符编号,第二行表示的默认编码是,因此 LaTeX 会在必要时更改编码以使用该符号(否则符号将始终使用当前编码,无论它是哪种编码)。136TS1\oldbulletTS1

然后就可以\textbullet正常重新定义:

\documentclass[11pt]{report}
\usepackage{libertinus}

% Resize \textbullet to make it a bit larger (closer to Computer Modern)
\DeclareTextSymbol{\oldbullet}{TS1}{136}
\DeclareTextSymbolDefault{\oldbullet}{TS1}
\renewcommand*\textbullet{{\LARGE\oldbullet}}

\begin{document}
\oldbullet\textbullet$\mathord\bullet$

\indent\kern1pt\raise5pt\hbox{$\smile$}
\end{document}

在此处输入图片描述

相关内容