summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/lualatex/lua-check-hyphen/lua-check-hyphen.lua
blob: 9730b4d5eac98db0f738e401ad8e5fba95298f24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
-- Copyright 2012 Patrick Gundlach, patrick@gundla.ch
-- Public repository: https://github.com/pgundlach/lua-check-hyphen (issues/pull requests,...)
-- Version: 0.1


-- for debugging purpuse:
-- function w( ... )
--   texio.write_nl(string.format(...))
-- end

local explode = function(s,p)
   local t = { }
   for s in unicode.utf8.gmatch(s,p) do
       if s ~= "" then
           t[#t+1] = s
       end
   end
   return t
end

luachekchyphen = {}


luachekchyphen.hyphenattr = luatexbase.new_attribute("hyphenattr")
luachekchyphen.hyphenwords = {}
luachekchyphen.all_hyphenatedwords = {}
luachekchyphen.word_whitelist = {}
luachekchyphen.rectangle = node.new("whatsit","pdf_literal")
luachekchyphen.rectangle.data = string.format("q 0 0 10 10 re f S Q")

luachekchyphen.deligature = function ( glyph_node )
  local sln = unicode.utf8
  local head = glyph_node.components
  local str = ""
  while head do
    if head.id == 37 then
      if head.components then
        str = str .. luachekchyphen.deligature(head)
      else
        str = str .. sln.char(head.char)
      end
    end
    head = head.next
  end
  return str
end


luachekchyphen.collect_discs = function(head)
  local word_start
  local word
  -- this is where we store all the breakpoints
  local thisbreakpoint
  local word_with_hyphen
  local c
  local hyphencounter = #luachekchyphen.hyphenwords + 1
  local sln = unicode.utf8
  while head do
    if head.id == 0 then
    elseif head.id == 7 then --disc
      word_start = head
      word_end   = head
      while word_start.prev and word_start.prev.id ~= 10 do
        word_start = word_start.prev
      end
      word = ""
      c = 0
      while word_start and word_start.id ~= 10 do
        if word_start == head then -- disc
          -- there is a breakpoint after letter c
          node.set_attribute(head,luachekchyphen.hyphenattr,hyphencounter)
          thisbreakpoint = c
        elseif word_start.id == 37 then
          c = c + 1
          if word_start.components then
            word = word .. luachekchyphen.deligature(word_start)
          elseif sln.match(sln.char(word_start.char),"%a") then
            word = word .. sln.char(word_start.char)
          end
        end
        word_start = word_start.next
      end
      if thisbreakpoint then
        word_with_hyphen = sln.sub(word,1,thisbreakpoint) .. "-" .. sln.sub(word,thisbreakpoint+1,-1)
        luachekchyphen.hyphenwords[hyphencounter] = word_with_hyphen
        hyphencounter = #luachekchyphen.hyphenwords + 1
      end
    end
    head = head.next
  end
  return true
end

luachekchyphen.check_discs = function (head,parent)
  local c
  local word
  local tmp
  while head do
    if head.id < 2 then
      luachekchyphen.check_discs(head.list,head)
    elseif head.id == 7 and head.next and head.next.id == 10 then -- disc
      c = node.has_attribute(head,luachekchyphen.hyphenattr)
      word = luachekchyphen.hyphenwords[c]
      if luachekchyphen.word_whitelist[word] then
      	  -- word found, but OK (whitelisted)
      else
	      luachekchyphen.all_hyphenatedwords[word] = true
     	  if luachekchyphen.drawmarks then
     	  	tmp = node.copy(luachekchyphen.rectangle)
     	  	node.insert_after(parent,head,tmp)
     	  end
	  end
    end
    head = head.next
  end
  return true
end

luachekchyphen.listhyphenatedwords = function()
	if luachekchyphen.final == "true" then
		return
	end
    local unknown_hyphenation_filename = tex.jobname .. ".uhy"
    local unknown_hyphenation_file = io.open(unknown_hyphenation_filename,"w")
  
    texio.write_nl("All words with unknown hyphenation below")
    for k,v in pairs(luachekchyphen.all_hyphenatedwords) do
  	    texio.write_nl(k)
    	unknown_hyphenation_file:write(k .. "\n")
    end
    unknown_hyphenation_file:close()
    texio.write_nl("All words with unknown hyphenation above\n")
end

luachekchyphen.enable = function()
	if luachekchyphen.final == "true" then
		return
	end
  	local whitelistfile,err
  	local filecontents
  	if luachekchyphen.whitelist then
  		for i,v in ipairs(string.explode(luachekchyphen.whitelist,",")) do
  			whitelistfile,err = io.open(v)
  			if not whitelistfile then
  				texio.write_nl(err)
	  		else
  				filecontents = whitelistfile:read("*a")
  				for _,entry in ipairs(explode(filecontents,"[^%s]+")) do
  					luachekchyphen.word_whitelist[entry] = true
	  			end
  			end
  		end
 	end
  	if luachekchyphen.mark == "true" then
  		luachekchyphen.drawmarks = true
  	end
    luatexbase.add_to_callback("pre_linebreak_filter", luachekchyphen.collect_discs,"collect_discs")
    luatexbase.add_to_callback("post_linebreak_filter",luachekchyphen.check_discs,"check_discs")
end

return luachekchyphen

-- end of file