Uma prova de conceito

Uma prova de conceito

existe algum pacote que possa destacar automaticamente palavras não hifenizáveis ​​no PDF de saída? Ou seja, palavras que não estão na lista de palavras para hifenização. Por exemplo:

insira a descrição da imagem aqui

Estou usando o pacote polyglossia. Muito obrigado!

Responder1

Uma prova de conceito

Verificamos alguns pacotes comuns, comoulemá(Donald Arseneau) ealma(Melchior Franz), depois voltamos nossa atenção para omostrar hífens,lua-verificar-hífenelua-visual-debugpacotes criados por Patrick Gundlach. Infelizmente, o OP precisa do oposto do que esses pacotes oferecem.

Começamos nosso trabalho analisando e aprendendo comeste código do TeX.SX(Veja tambémhttp://wiki.luatex.org/index.php/Show_the_hyphenation_points) por Patrick Gundlach. Somos sempre apoiados pelomanual de referência do LuaTeX,onde notamos tipos definidos de nós (veja Capítulo 8 Nós, primeira página; página 169+ no manual). Podemos ler sobre seus campos nas páginas seguintes.

Precisávamos especialmente destes tipos:

  • hlist (0), listas horizontais,
  • vlist (1), listas verticais,
  • disco (7), um local onde uma palavra pode ser hifenizada,
  • whasit (8), tipo adequado para a criação de um novo nó,
  • cola (10), espaços,
  • Kern (11), kernings e,
  • glifo (37), o tipo de nó chave para esse tipo de trabalho.

Nossa tarefa era percorrer todos os nós, coletar e armazenar seus IDs em uma tabela Lua, fazer algumas análises básicas em nível de texto e depois fazer alguns destaques básicos dos resultados (neste exemplo, usamos sublinhado de cada glifo).

Estamos passando um número mínimo de letras que devem conter aquela palavra para ser destacada. Uma única palavra consiste em letras, dígitos, pontuações, etc. Acreditamos que isso deve ser suficiente para esta prova de conceito.

O código original para mostrar hífens usa algoritmo recursivo para percorrer a árvore de nós. Precisávamos de duas passagens, portanto envolvemos essa função ( show_hyph) em outra ( towork). A análise é feita na showmefunção. Usamos headuserdata, poderíamos imprimir os campos usando a getmetatablefunção. Ele é comentado no código e também imprime informações adicionais sobre os nós.

A análise de texto consiste em diversas condições, principalmente de:

  • ID 0 ou ID 10 seguido de ID 37 (mais a palavra já não pode estar hifenizada), é o início de uma palavra. É uma nova linha ou espaço seguido por um glifo.
  • ID 7 significa que pode haver um disco e essa palavra não nos interessa.
  • ID 11 (kerning) ou ID 37 (glifo) faz parte de uma palavra, incluímos essa parte para análise posterior.
  • ID 37 seguido de ID 10 é o final de uma palavra.

Armazenamos todas as informações em uma tabela Lua. Precisávamos de duas variáveis ​​sobre o comprimento da palavra, para exibir uma palavra que usamos malsizetrue(glifos + nós de kerning), para interação com um usuário que usamos malsize(apenas glifos). A princípio foi estranho pensar nas palavras nesses termos, mas foi necessário.

Usamos head.width( spunidades) para obter o sublinhado adequado. No exemplo abaixo, cada letra é sublinhada separadamente, poderia ser melhorado para desenhar uma única linha por palavra. Estamos deixando essa ideia aberta para novas experiências com o código. Isso exigiria armazenar larguras na primeira execução da função e usá-las na segunda execução no nível Lua.

No exemplo a seguir, usamos algum texto básico e definimos um número mínimo de letras por palavra de 1 a 8. Colocamos o código e uma prévia do resultado (8 páginas). Funciona conforme esperado neste exemplo, mas acho que esse trecho requer mais testes.

Nós corremos lualatex mal-hyph.tex.

% lualatex mal-hyph.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{luacode} % the core package in LuaLaTeX, recommended is luatextra
\usepackage[english]{babel} % loading some hyphenation rules
\usepackage{kantlipsum} % loading some text
\usepackage{fontspec} % loading some font

\begin{luacode*}
-- This is the core function for callback...
function towork(head)

-- This inner function is recursive...
function show_hyph(head)
while head do

  -- If we want to see userdata of >head<...
  -- for i,j in pairs(getmetatable(head)) do
  --    print(i,j)
  -- end

  -- If we need to get nodes ID..., this is the way.
  --[=[  io.write(head.id.." ")
    if head.id ==10 then io.write(" ") end
    if head.id == 37 then 
       io.write(unicode.utf8.char(head.char).."; ")
       end    
    --]=] -- be silent

    if head.id == 0 or head.id == 1 then
       show_hyph(head.head) -- the core of recursion
    end -- if, head.id, 0 (hlist) or 1 (vlist)

    counter=counter+1 -- number of nodes
    malglyphs[counter]=head.id -- saving IDs for later analysis

if run then -- We can add nodes after analysis...
  if maldraw[counter]==1 then -- These letters belong to unhyphenateable words.
      local n = node.new("whatsit","pdf_literal") -- Underline them, please,
      n.mode = 0
      if head.width then dista=head.width/65535 else dista=0 end -- with proper  width,
      distb=0
      n.data = "q 1 w 0 0 1 RG "..-dista.." -2 m "..distb.." -2 l S Q" -- with some common line.
      n.next = head.next -- Add line to the node tree.
      n.prev = head
      head.next = n
      head = n
  end -- if we are done with lines.

    if head.id == 7 and run then -- a divis, this is an original example, addition of disc
      local n = node.new("whatsit","pdf_literal")
      n.mode = 0
      n.data = "q 0.9 w 1 .1 .1 RG 0 2 m 0 7 l S Q" -- an original setting was: q 0.3 w 0 2 m 0 7 l S Q
      n.next = head.next
      n.prev = head
      head.next = n
      head = n
    end -- if, head.id==7
end -- if, run

head = head.next -- go to the next node
end -- while, node three

end -- function, show_hyph


-- This function analyses ID of nodes.
function showme()
-- Initialize some variables.
malwrite=0 -- Can I store a unhyphenateable word?
maldraw={} -- Table with 1s for storing information.
malsize=0 -- A size of the last word (only letters, ID 37).
malsizetrue=0 -- A size of the last word (letters+kerning, IDs 11+37).
broken=0 -- Is a word already hyphenated?

for malcounter=1,#malglyphs do -- Let's analyse all nodes.

-- Print some letters from actual position backward.
-- print(malglyphs[malcounter-2], malglyphs[malcounter-1], malglyphs[malcounter]) 

-- Are we at the beginning of the word?
if  (malglyphs[malcounter-1]==0 or malglyphs[malcounter-1]==10) and malglyphs[malcounter]==37 and broken~=1 then malwrite=1; malsize=0; malsizetrue=0 end

-- Are we at the end of the word? Can we modify data in our Lua table?
if malglyphs[malcounter-1]==37 and (malglyphs[malcounter]==10 or malglyphs[malcounter]==12) then 
   if malwrite==1 and malsize>=malmax then -- used to be: malsize>0
   for malback=1,malsizetrue do -- set letters of unhyphenated word for underlining/highlighting, plus kerning
      maldraw[malcounter-malback]=1 -- mark them letter by letter
   end -- for, malback
   end -- if, malwrite
end -- if, malglyphs...

-- Are we in the middle of the hyphenated word?
if malglyphs[malcounter]==7 then broken=1 end -- Yes, we are!
if malglyphs[malcounter]==37 then broken=0 end -- No, at least not at the beginning of the line!

-- Is this a node with letter or kerning in some word?
if malglyphs[malcounter]==37 or malglyphs[malcounter]==11 then 
   malsizetrue=malsizetrue+1 -- letters+kernings
   if malglyphs[malcounter]==37 then malsize=malsize+1 end -- Only letters.
   else 
   malwrite=0 -- Stop analysing actual word, it has no meaning anymore.
   end -- stop searching

end -- for, malcounter

-- If we need some information from the Lua table...
--[[for allchars=1,#malglyphs do
   if maldraw then print(allchars, maldraw[allchars]) end
   end -- for, malheader
   ]]
end -- function, showme


-- This is the first run, we need data about nodes.
malglyphs={}; run=nil; counter=0
show_hyph(head)
showme()

-- This is the second run, we will highlight letters (and also kerning with an invisible pen :-) ).
malglyphs={}; run=1; counter=0
show_hyph(head)
showme()

return true -- Let's finish our work and send data back to a callback.
end -- major function, towork()
\end{luacode*}


% Some TeX commands for general use...
% A minimum of letters required in an unhyphenateable word to be highlighted.
\def\malactivateset#1{
   \luaexec{
   print("malmax "..#1)
   malmax=tonumber(#1) or 0
   }}

% This command activates a callback.
\def\malactivate{
   \directlua{luatexbase.add_to_callback("post_linebreak_filter",towork,"towork")}
   } % End of \activateme...

% This command deactivates a callback.
\def\maldeactivate{
   \directlua{luatexbase.remove_from_callback("post_linebreak_filter","towork")}
   } % End of \deactivateme...

% This text is an example for TeX.SX.
\def\maltext{\newpage
   Minimum of required letters: \the\malletters.\par
   Hello, the World!\par
   Here is some text without meaning.\par 
   \kant[1]\par
   } % End of \maltext...

% Small changes in paper mirror...
\rightskip=7cm
\parindent=0pt


\begin{document}
% A small example...
\malactivate % This command activates the algorithm...
\newcount\malletters 
\malletters=0 % Start with 0+1 letters, a common minimum.
\loop
   \advance\malletters by 1 % Try more letters.
   \malactivateset{\the\malletters} % Pass No. of letters to Lua.
   \maltext \relax % Text to be tested.
\ifnum\malletters<8 \repeat % Show us 8 pages.
\maldeactivate % This command deactivates the algorithm...
\end{document}

um exemplo de prova de conceito

informação relacionada