答案1
传统的印刷惯例是避免使用连字符连接这样的单词,因此这样的规则被 Knuth 编入了 TeX 程序中。
但是,仍然可以插入允许中断的连字符,方法是欺骗 TeX 认为我们有两个单独的单词(通过插入空的粘连符)。如果我们愿意输入特殊序列(如\Hyphdash
或 )而\-/
不是连字符,这可以很容易地做到,这正是 等软件包所提供的extdash
。但如果我们坚持在 TeX 文件中输入常规连字符,那么“经典”TeX 引擎(即除 LuaTeX 之外的引擎)只提供一种将常规连字符视为其他东西的方法,那就是将 的 catcode 更改-
为 active,以便它成为一个扩展为更长内容的宏。但是,只要在-
常规文本以外的任何地方使用 ,这都会导致问题,这种情况很常见(请参阅 Steven 的回答中的问题示例)。我想,如果在经典 TeX 世界中存在一个很好的解决方案,那么像 这样的一些软件包extdash
就会解决它。
(实际上,有一种非常合理的方法,但由于某种原因,在 TeX 世界中并不十分流行:那就是使用一些“智能”的外部脚本预处理输入文件,仅用\Hyphdash
(或其扩展)或其他内容替换常规文本中出现的连字符。但出于某种原因,人们希望在 TeX 内部完成所有操作。)
LuaTeX 允许更广泛地访问 TeX 内部结构,因此很多事情都成为可能,许多 catcode 和宏相关的麻烦也消失了。例如,LuaTeX 有一个hyphenate
回调,可用于修改其执行的常规连字操作。此回调获取一个节点列表,我们可以在其中任意插入任意节点(连字符)。这比使用宏执行所有操作要容易得多(很难设置适当的输入,稍后将其扩展为我们需要的输入,而不会受到其他干扰)。甚至还有一个lang.hyphenate
函数,我们可以使用它简单地执行常规连字操作。
以下似乎有效:将以下内容放入文件中,例如hyphenateall.lua
:
function hyphenate_always(head, tail)
local n = head
while n do
if node.type(n.id) == 'glyph' and n.char == string.byte('-') then
-- Insert an infinite penalty before, and a zero-width glue node after, the hyphen.
-- Like writing "\nobreak-\hspace{0pt}" or equivalently "\penalty10000-\hskip0pt"
local p = node.new(node.id('penalty'))
p.penalty = 10000
head, p = node.insert_before(head, n, p)
local g = node.new(node.id('glue'))
head, g = node.insert_after(head, n, g)
n = g
end
n = n.next
end
lang.hyphenate(head, tail)
end
luatexbase.add_to_callback('hyphenate', hyphenate_always, 'Hyphenate even words containing hyphens')
并将其放入\directlua{require('hyphenateall')}
您的.tex
文件中。
例如(借用 Steven 的回答中的例子):
\documentclass{article}
% Not needed -- used in this example just to show it's not needed :-)
\newcommand\?{\nobreak-\hspace{0pt}}
\begin{document}
\begin{minipage}[t]{0in}
\hbox{Before:} often hungry Works: often\?hungry What about: often-hungry
\end{minipage}\hspace{1in}%
\directlua{require('hyphenateall')}%
\begin{minipage}[t]{0in}
\hbox{After:} often hungry Works: often\?hungry What about: often-hungry
\end{minipage}
\end{document}
请注意,调用之后\directlua
,我们不需要特殊的语法来获取额外的连字符。
答案2
您可以通过更改 的 catcode 来实现此目的-
,但这会破坏所有类型的东西,因为-
在数学中不仅是破折号,而且还是负号(以及尺寸符号,如\kern-1pt
,\vspace{-\baselineskip}
,\rule[-1pt]{1pt}{3pt}
)。
因此,下面的 MWE 仅仅是一个演示,而不是实际的建议。在 MWE 中显示了两个零宽度minipage
,没有然后是 active -
。
\documentclass{article}
\let\svdash-
{\catcode`-=\active %
\gdef-{\nobreak\svdash\nobreak\hspace{0pt}}
}
\begin{document}
\begin{minipage}[t]{0in}
\catcode`-=12 %
First,
asteroid
Then,
shower
Last,
asteroid-shower
\end{minipage}\hspace{1in}%
\begin{minipage}[t]{0in}
\catcode`-=\active %
First,
asteroid
Then,
shower
Last,
asteroid-shower
\end{minipage}
\end{document}
因此,更好的方法是(如extdash
包中所述)指定一个特殊宏作为这种特殊类型的连字符。在这里我选择\?
,结果与之前的 MWE 输出相同:
\documentclass{article}
\newcommand\?{\nobreak-\nobreak\hspace{0pt}}
\begin{document}
\begin{minipage}[t]{0in}
First,
asteroid
Then,
shower
Last,
asteroid-shower
\end{minipage}\hspace{1in}%
\begin{minipage}[t]{0in}
First,
asteroid
Then,
shower
Last,
asteroid\?shower
\end{minipage}
\end{document}