escribir el contenido de un hbox en un archivo auxiliar

escribir el contenido de un hbox en un archivo auxiliar

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é nrepresenta 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 nen su ejemplo es una lista de nodos. Existen varios tipos de nodos, como glyphspara caracteres, gluepara espaciado o hlistcuál es el tipo que obtienes para tu archivo \hbox. hlistcontiene nodos secundarios, a los que se puede acceder en n.headatributo. Luego puede repetir esta lista secundaria en busca de glifos y pegamentos.

Cada tipo de nodo se distingue por el valor del n.idatributo. 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 glyphy glue, pero debe tener en cuenta que las listas de nodos son recursivas y varios nodos pueden contener listas secundarias, como hlist, vlistetc. Puede admitirlas con una llamada recursiva al atributo nodeTextdel nodo actual head.

Con respecto a los nodos de glifo, charel 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}

nodeTextLa función devuelve el texto contenido en la lista de nodos. Se utiliza para imprimir \hboxcontenidos en la terminal y escribir en un archivo hello.txten 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)

información relacionada