pdflatex

pdflatex

注意力我已经有一个可能的答案,很快就会添加它。我认为在网站上有一个解决方案会很有用。(当然也欢迎其他答案)。

问题\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一起工作的解决方案是lualatexxelatexpdflatex

\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 简写的机制失败frenchbfrenchb并没有告诉 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规定范围。不过,这可能与此处的问题关系不大。

相关内容