
Sé que TeX no puede escribir el contenido de hbox en un archivo auxiliar (Volver a analizar el contenido de un registro de caja).
Eso significa que
\newwrite\foo
\immediate\openout\foo=\jobname.txt
\setbox0=\hbox{bar}
\immediate\write\foo{\box0}
no puedo escribir Sin embargo, ¿puede LuaTeX hacerlo? he encontrado
\directlua{
n = tex.getbox(0)
}
Pero no entiendo qué n
representa y si podría usarlo para escribir el contenido del cuadro en un archivo.
Respuesta1
Editar: aquí hay un nuevo código que funciona para ligaduras:
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\setbox0=\hbox{Příliš žluťoučký \textit{kůň} úpěl \hbox{ďábelské} ódy, diffierence, difference}
\directlua{
% local fontstyles = require "l4fontstyles"
local char = unicode.utf8.char
local glyph_id = node.id("glyph")
local glue_id = node.id("glue")
local hlist_id = node.id("hlist")
local vlist_id = node.id("vlist")
local disc_id = node.id("disc")
local minglue = tex.sp("0.2em")
local usedcharacters = {}
local identifiers = fonts.hashes.identifiers
local function get_unicode(xchar,font_id)
local current = {}
local uchar = identifiers[font_id].characters[xchar].tounicode
for i= 1, string.len(uchar), 4 do
local cchar = string.sub(uchar, i, i + 3)
print(xchar,uchar,cchar, font_id, i)
table.insert(current,char(tonumber(cchar,16)))
end
return current
end
local function nodeText(n)
local t = {}
for x in node.traverse(n) do
% glyph node
if x.id == glyph_id then
% local currentchar = fonts.hashes.identifiers[x.font].characters[x.char].tounicode
local chars = get_unicode(x.char,x.font)
for _, current_char in ipairs(chars) do
table.insert(t,current_char)
end
% glue node
elseif x.id == glue_id and node.getglue(x) > minglue then
table.insert(t," ")
% discretionaries
elseif x.id == disc_id then
table.insert(t, nodeText(x.replace))
% recursivelly process hlist and vlist nodes
elseif x.id == hlist_id or x.id == vlist_id then
table.insert(t,nodeText(x.head))
end
end
return table.concat(t)
end
local n = tex.getbox(0)
print(nodeText(n.head))
local f = io.open("hello.txt","w")
f:write(nodeText(n.head))
f:close()
}
\box0
\end{document}
Resulta en hello.txt
:
Příliš žluťoučký kůň úpěl ďábelské ódy, diffierence, difference
Respuesta original:
La variable n
en su ejemplo es una lista de nodos. Existen varios tipos de nodos, como glyphs
para caracteres, glue
para espaciado o hlist
cuál es el tipo que obtienes para tu archivo \hbox
. hlist
contiene nodos secundarios, a los que se puede acceder en n.head
atributo. Luego puede repetir esta lista secundaria en busca de glifos y pegamentos.
Cada tipo de nodo se distingue por el valor del n.id
atributo. Los tipos de nodos concretos y sus posibles atributos se describen en el capítulo "8 Nodos". En este ejemplo particular, necesitamos procesar solo nodos glyph
y glue
, pero debe tener en cuenta que las listas de nodos son recursivas y varios nodos pueden contener listas secundarias, como hlist
, vlist
etc. Puede admitirlas con una llamada recursiva al atributo nodeText
del nodo actual head
.
Con respecto a los nodos de glifo, char
el atributo contiene un valor Unicode solo en el caso de que use fuentes opentype o truetype, si usa fuentes antiguas de 8 bits, contiene solo un valor de 8 bits cuya codificación real depende de la codificación de fuente utilizada y no es fácil. para convertirlo a Unicode.
\documentclass{article}
\usepackage{fontspec}
\begin{document}
\setbox0=\hbox{Příliš žluťoučký \textit{kůň} úpěl \hbox{ďábelské} ódy}
\directlua{
local fontstyles = require "l4fontstyles"
local char = unicode.utf8.char
local glyph_id = node.id("glyph")
local glue_id = node.id("glue")
local hlist_id = node.id("hlist")
local vlist_id = node.id("vlist")
local minglue = tex.sp("0.2em")
local usedcharacters = {}
local identifiers = fonts.hashes.identifiers
local function get_unicode(xchar,font_id)
return char(tonumber(identifiers[font_id].characters[xchar].tounicode,16))
end
local function nodeText(n)
local t = {}
for x in node.traverse(n) do
% glyph node
if x.id == glyph_id then
% local currentchar = fonts.hashes.identifiers[x.font].characters[x.char].tounicode
table.insert(t,get_unicode(x.char,x.font))
local y = fontstyles.get_fontinfo(x.font)
print(x.char,y.name,y.weight,y.style)
% glue node
elseif x.id == glue_id and node.getglue(x) > minglue then
table.insert(t," ")
elseif x.id == hlist_id or x.id == vlist_id then
table.insert(t,nodeText(x.head))
end
end
return table.concat(t)
end
local n = tex.getbox(0)
print(nodeText(n.head))
local f = io.open("hello.txt","w")
f:write(nodeText(n.head))
f:close()
}
\box0
\end{document}
nodeText
La función devuelve el texto contenido en la lista de nodos. Se utiliza para imprimir \hbox
contenidos en la terminal y escribir en un archivo hello.txt
en este ejemplo.
Para obtener información básica sobre el estilo de fuente, puedes intentar usarestilos de fuente l4módulo, así:
local fontstyles = require "l4fontstyles"
...
if x.id == glyph_id then
table.insert(t,char(x.char))
local y = fontstyles.get_fontinfo(x.font)
print(y.name,y.weight,y.style)