答案1
使用 Luatex,您可以从排版框节点重新创建字符标记,这是经典 tex 中不可能实现的方向。
\documentclass{article}
\usepackage{color}
\begin{document}
\def\dohyphens#1#2{%
\directlua{
res='\string\\gdef\string\\#1\iftrue\string{\else}\fi'
local G = node.id("glyph")
local D = node.id("disc")
local K = node.id("kern")
gethyph = function (head)
local l = -1
for n in node.traverse(head) do
if n.id==G then
if l\string~=G then
res = res ..'\string\\HYchars\iftrue\string{\else}\fi'
end
res = res .. string.char(n.char)
else
if l\string==G then
res = res .. '\iffalse{\else\string}\fi'
end
if n.id==D then
res = res .. '\string\\HYhyphen'
else if (n.id ==K) then
else if l==G or l==D then
res = res .. '\string\\HYspace'
end
end
end
end
l=n.id
end
res = res ..'\iffalse{\else\string}\fi'
return true
end
luatexbase.add_to_callback('pre_linebreak_filter',gethyph,'get hyphens')
}%
\setbox0\vbox{\hsize\maxdimen\ttfamily\hyphenchar\font=`\-#2}%
\directlua{
luatexbase.remove_from_callback('pre_linebreak_filter','get hyphens')
tex.sprint(res)
}%
}
\protected\def\HYchars#1{\color{red}{#1}}
\protected\def\HYhyphen{\colorbox{yellow}{\color{blue}{---}}}
\protected\def\HYspace{ }
\dohyphens{tmp}{supercalifragilisticexpialidocious}
\typeout{tmp is}
\typeout{\meaning\tmp}
\tmp
\end{document}
上面的操作将supercalifragilisticexpialidocious
结果\tmp
显示在终端上
tmp is
macro:->\HYchars {su}\HYhyphen \HYchars {p}\HYchars {er}\HYhyphen \HYchars {cal
}\HYhyphen \HYchars {ifrag}\HYhyphen \HYchars {ilis}\HYhyphen \HYchars {tic}\HY
hyphen \HYchars {ex}\HYhyphen \HYchars {pi}\HYhyphen \HYchars {ali}\HYhyphen \H
Ychars {do}\HYhyphen \HYchars {cious}\HYspace
因此,基本上,字母串最终会变成\HYchars
自由连字符,因为\HYhyphen
字母间的字距被删除了(虽然不应该有字距,因为使用 ttfamily 也可以避免连字),其他的都是\HYspace
你可以\HY...
在这里定义命令来做任何你想做的事情,它只是添加了一些颜色和夸张的、非随意的破折号
在评论中评论后,你似乎想要更多类似的东西,使用来post_linebreak_filter
收集行后换行。
\documentclass{article}
\usepackage{color}
\begin{document}
\def\foo{a supercalifragilisticexpialidocious one two three four
supercalifragilisticexpialidocious one two three four
apples oranges carrots bananas
difficult find finger floor Vouch}
\def\showlines{\directlua{tex.print(res)}}
\def\getlines#1#2{%
\directlua{
local N = node.id("hlist")
local G = node.id("glyph")
local D = node.id("disc")
local K = node.id("kern")
local GLUE = node.id("glue")
%
getlines = function (head)
res=''
for vnode in node.traverse(head) do
if vnode.id==N then
res=res .. getlinetext(vnode.head)
end
end
return true
end
%
getlinetext = function (head)
local linetext=''
for n in node.traverse(head) do
if n.id==G then
if n.subtype==2 then
for nn in node.traverse(n.components) do
linetext = linetext .. string.char(nn.char)
end
else
linetext = linetext .. string.char(n.char)
end
else if n.id==GLUE then
linetext = linetext .. ' '
else if n.id==D then
if n.replace \string~= nil then
for nn in node.traverse(n.replace) do
if nn.char \string~= nil then
if nn.char==14 then
linetext = linetext .. 'ffi' % OT1 encoding specific
else
linetext = linetext .. string.char(nn.char)
end
end
end
end
end
end
end
end
texio.write_nl('\string\\textline{' .. linetext .. '}')
return '\string\\textline{' .. linetext .. '}'
end
luatexbase.add_to_callback('post_linebreak_filter',getlines,'get lines')
}%
\vbox{\hsize#1\relax#2}% show typeset result to check: add \setbox0= to hide
\directlua{
luatexbase.remove_from_callback('post_linebreak_filter','get lines')
}%
}
\getlines{5cm}{\foo}
produces the following linebreaks
\bigskip
\def\textline#1{\texttt{#1}\par}
\showlines
\end{document}
答案2
在完成连字操作后,可以访问单词部分,但只能以已排版框的形式访问,这几乎就是\showhyphens
包xltxtra
中的宏testhyphens
所做的。但是,这些单词部分无法在标记处理阶段检索,因为连字操作发生在段落被拆分成行时,并且用户无法控制(除了设置参数)。
我们可能会想象一个两阶段的过程,其中单词部分通过类似的宏写入日志文件中\showhyphens
;Perl 或类似语言中的过滤器可能会在 LaTeX 运行之间从日志文件中检索单词部分。
也许使用 LuaTeX 可以实现这一点,这将是一个有趣的研究项目。