![LuaLaTeX:为每行的第一个单词着色](https://linux22.com/image/411984/LuaLaTeX%EF%BC%9A%E4%B8%BA%E6%AF%8F%E8%A1%8C%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8D%95%E8%AF%8D%E7%9D%80%E8%89%B2.png)
假设我有一篇文档,我想给每行的第一个单词上色。也就是说,当一个单词是某一行的第一个单词时,应该用 \textcolor{red}{[单词]} 替换它。
这个问题已经使用自由连字符部分回答了这个问题,但是当你用一个单词开始一个段落时,这种方法就不管用了,而且还有间距问题。
我认为 Lua(La)TeX 解决方案是可行的。有没有办法遍历每一行(排版),获取每一行(排版)的第一个单词,然后使用 LuaTeX 将该单词替换为彩色版本?这样,无论单词是否出现在自由连字符的位置,都不必手动为单词着色。
答案1
在很多情况下,这个问题并没有提供足够的细节来确定正确的行为,所以这是一种相当简单的方法:
只考虑经过换行例程的行(因此水平框被忽略),然后为所有字形着色,直到找到粘合节点。在大多数情况下,这似乎做了“正确的事情”:
\documentclass{article}
\usepackage{blindtext,luacolor}
\newattribute\ColFirstAttr
\directlua{
local ourattr = \number\allocationnumber;
local glyph_id = node.id'glyph'
local glue_id = node.id'glue'
require'pre_append_to_vlist_filter'
local luacolorattr = oberdiek.luacolor.getattribute()
luatexbase.add_to_callback('pre_append_to_vlist_filter', function(head, kind)
if not kind == 'post_linebreak' then return true end
local attr = node.has_attribute(head, ourattr)
if not attr then return true end
local wordfound
for n, id in node.traverse(head.head) do
if id == glyph_id then
node.set_attribute(n, luacolorattr, attr)
wordfound = true
elseif id == glue_id and wordfound then
break
end
end
return true
end, 'color first word')
}
\makeatletter
\newcommand\SetFirstColor{}
\protected\def\SetFirstColor#1#{%
\@SetFirstColor{#1}%
}
\def\@SetFirstColor#1#2{%
\begingroup
\color#1{#2}%
\expandafter\endgroup
\expandafter\ColFirstAttr\the\LuaCol@Attribute\space
}
\makeatother
\begin{document}
\SetFirstColor{red}
\blinddocument
\end{document}