为什么 hyperref 包会改变字体命令的编码?

为什么 hyperref 包会改变字体命令的编码?

如果您使用 hyperref 编译以下文档,XeLaTeX您将看到文本命令的编码被包更改hyperref为“PU”编码。为什么这是必要的?

\documentclass{article}
\usepackage{fontspec}
\setmainfont{Linux Libertine O}
\usepackage{hyperref}

\begin{document}
\ttfamily
\meaning\textasciitilde\\
\meaning\textcelsius\\
\meaning\"\\
\meaning\NG\\
\meaning\k\\

\end{document}

有没有什么“陷阱”值得注意?

答案1

如果你不加载hyperref,那么你会得到

macro:->\T1-cmd \textasciitilde \T1\textasciitilde

尽管默认编码是EU1(或EU2使用LuaLaTeX)。

hyperref你一起得到

macro:->\PU-cmd \textasciitilde \PU\textasciitilde

因为puenc.def稍后已加载。该宏\PU-cmd查找两个参数并执行

\ifx\protect\@typeset@protect
  \@inmathwarn#1%
  \expandafter\ifx\csname\cf@encoding\string#1\endcsname\relax
    \expandafter\ifx\csname ?\string#1\endcsname\relax
      \expandafter\def\csname ?\string#1\endcsname{\TextSymbolUnavailable#1}
    \fi
    \global\expandafter\let\csname\cf@encoding\string#1\expandafter\endcsname 
      \csname ?\string#1\endcsname
  \fi
  \csname\cf@encoding\string#1\expandafter\endcsname
\else
  \noexpand#1%
\fi

参数是\textasciitilde\PU\textasciitilde(一个标记)。

在正常排版中,\ifx\protect\typeset@protect是真实的,所以\@inmathwarn\textasciitilde是扩展的,但它确实

\ifmmode \@latex@warning {Command \protect #1 invalid in math mode}\fi

所以除非我们处于数学模式,否则什么也不会发生。然后 LaTeX 检查是否

\EU1\textasciitilde

(一个标记)的定义是:\cf@encoding扩展为当前输出编码。如果不是,则通常意义上的\EU1\textasciitilde相当于\relax或未定义,LaTeX 将查找\?\textasciitilde(默认文本命令),如果缺少其定义,则会定义错误消息以供进一步使用,\EU1\textasciitilde全局等效于\?\textasciitilde

最后,\EU1\textasciitilde进行扩展。

如果第一个条件为假(即我们正在写入文件或其他特殊位置),则\noexpand\textasciitilde只会保留在输入流中。

你看,这PU永远不会干预,除非\cf@encoding PU,这是在hyperref执行写书签工作时发生的。

相关内容