注意力我已经有一个可能的答案,很快就会添加它。我认为在网站上有一个解决方案会很有用。(当然也欢迎其他答案)。
问题\href
如何在局部(针对某一特定)和全局的文本参数中激活或抑制某些标点符号(如冒号)前的法语空格\href
?切换语言不是答案!
用于测试的最少示例(的参数\href
通常应该是有效的 url,因此在链接中添加没有冒号的示例有点不公平):
pdflatex
\href
对于 pdflatex 来说,参数的打印方式取决于链接:
\documentclass{article}
\usepackage[french]{babel}
\usepackage{hyperref}
\begin{document}
With pdflatex no french spacing in links with colons:
\href{link}{a:b}
\href{link:colon}{a:b}
\end{document}
路拉泰克斯
使用 lualatex 时,空格始终存在:
\documentclass{article}
\usepackage[french]{babel}
\usepackage{hyperref}
\begin{document}
With lualatex always spaces:
\href{link}{a:b}
\href{link:colon}{a:b}
\end{document}
答案1
Ulrike Fisher 提到的 lualatex 问题可以轻松修复。babel-french 的新版本 (3.3d) 已经修复,该版本正在向 CTAN 迈进。
该修复与 \href 无关;babel-french 现在的工作方式如下:为了决定是否应在冒号前添加不间断空格,luatex 代码会检查“:”周围的两个节点。
1) 如果在冒号前发现粘连(实际上宽度>1sp),则将其删除并用不间断空格替换(惩罚+适当的粘连)。
2) 如果冒号前没有空格,则在默认模式下(AutoSpacePunctuation=true),冒号前会添加一个不间断空格除非下一个节点是不是字形(这是 v.3.3d 中的新功能)。
这样,URL、MS-DOS 路径 (C:\Program Files) 和时间表 (10:55) 就不再需要 {\NoAutoSpacing ...} 才能正确打印。这仅适用于 luatex,我尝试使用 \futurelet 执行相同操作,但在 xetex 上失败,并在 pdftex 上导致不可靠的结果。
@jfbu:“\hskip1sp 技巧”(\href{link:colon}{a\hskip1sp:b})在 babel-french 中既不是“表示某种可能的错误”,也不是记录\NoAutoSpacing 命令。
正如 babel-french 的文档代码中所解释的,这个技巧适用于表格“l”列:以下示例的输出对于 lualatex(左图)是正确的,但对于 xelatex(右图)和 pdflatex 来说是错误的。
\documentclass[french]{article}
\usepackage{babel}
\begin{document}
\begin{tabular}{|l|l|}
\hline
Char&Code\\ \hline
.&U+002E\\
:&U+003A\\
\hline
\end{tabular}
\end{document}
不幸的是,XeTeXinterchar 机制为所有非字符标记(粘连、字距、惩罚、\hbox、数学边界等)提供了一个单一类(4095);这不足以区分小粘连(<=1sp,不应触发额外空间)和在法语高标点符号前需要额外空间的其他标记。
答案2
对于带有冒号的链接,的行为\href
有所不同,因为 hyperref 会进行某种“链接类型”识别。如果在链接中发现冒号,则将通过\hyper@linkurl
调用来传递文本参数hyper@chars
,从而停用活动字符。
以下代码展示了多种可能性。它也适用于 xelatex。它包含许多zzz
仅用于演示的补丁!它们显示了哪些\href
受补丁影响。
\documentclass{scrartcl}
\usepackage[ngerman,french]{babel}
\usepackage{hyperref,etoolbox,ifluatex}
\begin{document}
\minisec{Default behaviour \ifluatex lualatex \else pdflatex \fi}
\href{link}{a:b}
\href{link:colon}{a:bcolon}
\selectlanguage{ngerman}
\href{link}{a"=b}
\href{link:colon}{a"=bcolon}
\selectlanguage{french}
\minisec{Suppress the space locally}
\href{link}{\csname NoAutoSpacing\endcsname a:b}
\href{link:colon}{\csname NoAutoSpacing\endcsname a:bcolon} %not needed with pdflatex
\minisec{Activate the space locally}
(will activate other active characters too)
\href{link}{\csname @safe@activesfalse\endcsname a:b} %not needed, default
\href{link:colon}{\csname @safe@activesfalse\endcsname a:bcolon}%not needed with lualatex
\selectlanguage{ngerman}
\href{link}{\csname @safe@activesfalse\endcsname a"=b} %not needed, default
\href{link:colon}{\csname @safe@activesfalse\endcsname a"=bcolon}
\selectlanguage{french}
\minisec{Suppress the space globally/for a group}
The \texttt{zzz} is only for demo!
\begin{enumerate}
\item With \verb+\NoAutoSpacing+
\begingroup
\makeatletter
\patchcmd{\hyper@link@}
{\expandafter{\Hy@tempb}{#4}}
{\expandafter{\Hy@tempb}{zzz\csname NoAutoSpacing\endcsname #4}}
{}{\fail}
\makeatother
\href{link}{a:b}
\href{link:colon}{a:bcolon}
\selectlanguage{ngerman}
\href{link}{a"=b}
\href{link:colon}{a"=bcolon}
\selectlanguage{french}
\endgroup
\item With \verb+\@safe@activestrue+. This will affect other active chars too.
\begingroup
\makeatletter
\patchcmd{\hyper@link@}
{\expandafter{\Hy@tempb}{#4}}
{\expandafter{\Hy@tempb}{zzz\csname @safe@activestrue\endcsname #4}}
{}{\fail}
\makeatother
\href{link}{a:b}
\href{link:colon}{a:bcolon}
\selectlanguage{ngerman}
\href{link}{a"=b}
\href{link:colon}{a"=bcolon}
\selectlanguage{french}
\endgroup
\end{enumerate}
\minisec{Activate the space globally/for a group}
\begin{enumerate}
\item Activate the space by deactivating \verb+\Hy@safe@activestrue+ in
\verb+\hyper@chars+. This affects only links with colons as can seen by the \texttt{zzz}. It
affects also other active chars.
\begingroup
\makeatletter
\renewcommand*\hyper@chars{%
\let\#\hyper@hash
\let\%\@percentchar
%\Hy@safe@activestrue
zzz %for demo only!
}
\href{link:colon}{a:bcolon}
\href{link}{a:b}
\selectlanguage{ngerman}
\href{link}{a"=b}
\href{link:colon}{a"=bcolon}
\selectlanguage{french}
\endgroup
\item Activate the space by patching \verb+\hyper@link@+ and adding \verb+\@safe@activesfalse+.
This affects both types as seen by the \texttt{zzz}. It also affects other active chars.
\begingroup
\makeatletter
\patchcmd{\hyper@link@}
{\expandafter{\Hy@tempb}{#4}}
{\expandafter{\Hy@tempb}{zzz\csname @safe@activesfalse\endcsname #4}}
{}{\fail}
\makeatother
\href{link}{a:b}
\href{link:colon}{a:bcolon}
\selectlanguage{ngerman}
\href{link}{a"=b}
\href{link:colon}{a"=bcolon}
\selectlanguage{french}
\endgroup
\end{enumerate}
\end{document}
pdflatex 的输出
lualatex 的输出
答案3
对于一个特定的,与(但不与和)\href
一起工作的解决方案是lualatex
xelatex
pdflatex
\href{link:colon}{a\hskip1sp:b}
\href{linknocolon}{a\hskip1sp:b}
它的工作原理表明可能存在某种错误frenchb
。
对于pdflatex
一个人来说,可以使用\string:
而,但在链接本身带有冒号的默认情况下,是\string:
不需要的。
对于xelatex
该机制,\XeTeXinterchartokenstate
我不知道简单的标记来停用它(除了关闭它),但无论如何,对于这里的本地问题,总是可以(这是文档frenchb
推荐的方法)使用
{\NoAutoSpacing\href{link:colon}{a:b}}
这当然适用于所有引擎。
全局关闭多余的法语空格\href
(适用于所有引擎):
\makeatletter
\let\originalhyper@normalise\hyper@normalise
\def\hyper@normalise{\NoAutoSpacing\originalhyper@normalise}
\makeatother
默认\hyper@normalise
以 开头\begingroup
,但在执行添加时已经输入了两个半简单组\NoAutoSpacing
,因此无需担心,其效果将是本地执行\href
。
@Ulrike 询问激活法国空间\href
文本。如上所示,LuaLaTeX、XeLaTeX 默认就是这种情况,因此我在此讨论 PDFLaTeX 的情况。为此,请使用
\href{http://www.foo.com}{\@safe@activesfalse a:b}
当然这样就有点不方便了,需要\makeatletter
等。
再次,由于不使用活动字符,因此使用 lualatex/xelatexhyperref
停用 Babel 简写的机制失败frenchb
frenchb
并没有告诉 Babel 找到一种方法将其停用机制扩展到非 Babel 速记......这有点可以理解,但在这里导致了这个问题,即 lualatex/xelatex 的行为与 pdflatex 不同 \href
。(也许frenchb
应该在 lualatex/xelatex 案例中实际声明假的 Babel 速记并将其\FB@spacingfalse
本地插入到表单中inert
,但必须是本地的;没有想太多。)
如果想在全球范围内做到这一点:
\begingroup
\catcode`$ 6
\catcode`# 12
\gdef\href@split $1#$2#$3\\$4{\hyper@@link {$1}{$2}{\@safe@activesfalse$4}\endgroup }
\endgroup
有一种方法可以将黑客攻击注入到第二个参数中\href
并强制改变第一个参数的 catcode 机制:
\protected\def\myhref#1#2{{%
% \mymacrochangingcatcodes % for example
\endlinechar\m@ne\everyeof{{\@safe@activesfalse#2}}%
\scantokens{\href{#1}}%
}}
这样,就不需要破解一些内部宏了。
如果空格处于活动状态,请不要执行此操作(即在 之前使空格字符处于非活动状态
\scantokens
),当然,需要重新存储
href
第一个参数所需的所有 catcode 更改,例如的 catcode#
或的 catcode 之一%
,而对于后者,这是不可能的,因为已经太晚了,因为在第一个参数中\myhref
授权了%
,这里的想法是,以防万一需要更改比默认处理的更多的 catcode
hyperref
(并且%
必须\%
在链接中开始编码)。在这个例子中,
\@safe@activesfalse
第二个参数中有一个额外的内容,对于空的第二个参数的 hyperref 测试将始终采用 False 分支,但这看起来并不重要(也适用于\href@split
上面的黑客攻击)
这种方法在尝试使用\href
已修改的 catcode 时非常有用,超出了hyperref
规定范围。不过,这可能与此处的问题关系不大。