如何将字符串变量拆分为具有一定宽度的带连字符的字符串变量数组

如何将字符串变量拆分为具有一定宽度的带连字符的字符串变量数组

我有一个变量(用定义\csdef{id}{value}),它包含一个正常的(虽然很长)文本字符串。

我需要一个宏(?),其大致执行以下操作:

  • 将此字符串压缩到“虚拟”(不可见)小页面中
  • 为此,它使用标准连字符规则将字符串分成单独的行
  • 这个小页面有一定的宽度,我已经指定了
  • 这些行被写入一个字符串数组(可能使用相同的\csdef{id}{value}命令)。

这些 问题与非常相似的内容有关,但我没有需要解析的特殊结构化文本。我只需要利用 LaTeX 的标准连字功能,除了“幕后”,而不需要实际排版任何内容。

答案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

在完成连字操作后,可以访问单词部分,但只能以已排版框的形式访问,这几乎就是\showhyphensxltxtra中的宏testhyphens所做的。但是,这些单词部分无法在标记处理阶段检索,因为连字操作发生在段落被拆分成行时,并且用户无法控制(除了设置参数)。

我们可能会想象一个两阶段的过程,其中单词部分通过类似的宏写入日志文件中\showhyphens;Perl 或类似语言中的过滤器可能会在 LaTeX 运行之间从日志文件中检索单词部分。

也许使用 LuaTeX 可以实现这一点,这将是一个有趣的研究项目。

相关内容