概念実証

概念実証

出力 PDF でハイフン付けできない単語を自動的に強調表示できるパッケージはありますか? つまり、ハイフン付けする単語のリストにない単語です。例:

ここに画像の説明を入力してください

私はpolyglossiaパッケージを使用しています。 ありがとうございます!

答え1

概念実証

次のような一般的なパッケージを確認しました。ウレム(ドナルド・アーセノー)と(メルヒオール・フランツ)その後、私たちはハイフンを表示lua チェックハイフンそしてlua ビジュアルデバッグPatrick Gundlach によって作成されたパッケージ。残念ながら、OP はこれらのパッケージが提供するものとは逆のものを必要としています。

私たちは分析と学習から仕事を開始しましたTeX.SXのこのコード(参照http://wiki.luatex.org/index.php/Show_the_hyphenation_points)パトリック・ガンドラック著。私たちは常にLuaTeXのリファレンスマニュアル、ここで、ノードの定義されたタイプに気づきました (マニュアルの最初のページ、第 8 章「ノード」の 169 ページ以降を参照)。次のページで、それらのフィールドについて読むことができます。

特に以下のタイプが必要でした:

  • hlist (0)、水平リスト、
  • vlist (1)、垂直リスト、
  • ディスク(7)、単語をハイフンでつなぐ場所、
  • whasit (8)、新しいノードの作成に適したタイプ、
  • 接着剤(10)、スペース、
  • カーン(11)、カーニング、そして、
  • グリフ(37)、この種の作業のキーノードタイプ。

私たちのタスクは、すべてのノードを調べ、それらの ID を収集して Lua テーブルに保存し、テキスト レベルで基本的な分析を実行し、その後、結果の基本的な強調表示を実行することです (この例では、すべてのグリフに下線を付けました)。

単語を強調表示するには、その単語に必要な最小文字数を渡します。 1 つの単語は、文字、数字、句読点などで構成されます。 この概念実証にはこれで十分だと考えています。

ハイフンを表示するための元のコードでは、ノード ツリーを通過するために再帰アルゴリズムを使用しています。2 つのパスが必要だったため、その関数 ( show_hyph) を別の関数 ( towork) にラップしました。分析はshowme関数内で行われます。ユーザー データを使用しておりhead、関数を使用してフィールドを印刷できますgetmetatable。コード内ではコメント アウトされており、ノードに関する追加情報も印刷されています。

テキスト分析は、主に以下のいくつかの条件で構成されます。

  • ID 0 または ID 10 の後に ID 37 が続く場合 (さらに、単語がすでにハイフンで区切られていない場合)、これは単語の始まりです。これは、新しい行またはスペースの後にグリフが続くものです。
  • ID 7 はディスクが存在する可能性があることを意味し、その単語は私たちにとっては興味がありません。
  • ID 11 (カーニング) または ID 37 (グリフ) は単語の一部であるため、その部分をさらなる分析に含めます。
  • ID 37 の後に ID 10 が続くと単語の終わりになります。

すべての情報を Lua テーブルに保存します。単語の長さに関する 2 つの変数、使用した単語を表示するための変数malsizetrue(グリフ + カーニング ノード)、使用したユーザーとのやり取りのためのmalsize変数 (グリフのみ) が必要でした。最初は単語をこのような観点から考えるのは奇妙でしたが、必要なことでした。

head.width適切な下線を引くために(単位)を使用しましたsp。以下の例では、すべての文字が個別に下線が引かれていますが、単語ごとに 1 本の線を引くように改善できます。このアイデアは、コードでさらに実験するために残しておきます。そのためには、関数の最初の実行時に幅を保存し、2 回目の実行時に Lua レベルでそれらを使用する必要があります。

次の例では、基本的なテキストを使用し、単語あたりの最小文字数を 1 から 8 に設定しました。コードと結果のプレビュー (8 ページ) を添付します。この例では期待どおりに動作しますが、このスニペットにはさらにテストが必要だと思います。

私たちは走る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}

概念実証の例

関連情報