summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/spelling/spelling-stage-4.lua
blob: ce027c8c50c903f1b9e7c4aa6fa1497c2e1ee61e (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
--- spelling-stage-4.lua
--- Copyright 2012, 2013 Stephan Hennig
--
-- This work may be distributed and/or modified under the conditions of
-- the LaTeX Project Public License, either version 1.3 of this license
-- or (at your option) any later version.  The latest version of this
-- license is in http://www.latex-project.org/lppl.txt
-- and version 1.3 or later is part of all distributions of LaTeX
-- version 2005/12/01 or later.
--
-- See file README for more information.
--


--- At the end of a LuaTeX run, write the text stored in a text document
--- data structure to a file.
-- This module provides means to write the text stored in a text
-- document data structure to a file at the end of a LuaTeX run.
--
-- @author Stephan Hennig
-- @copyright 2012, 2013 Stephan Hennig
-- @release version 0.41
--
-- @trick Prevent LuaDoc from looking past here for module description.
--[[ Trick LuaDoc into entering 'module' mode without using that command.
module(...)
--]]


-- Module table.
local M = {}


-- Import external modules.
local unicode = require('unicode')


-- Function short-cuts.
local tabconcat = table.concat
local tabinsert = table.insert

local Ulen = unicode.utf8.len


-- Declare local variables to store references to resources that are
-- provided by external code.
--
-- Text document data structure.
local __text_document


--- Module options.
-- This table contains all module options.  User functions to set
-- options are provided.
--
-- @class table
-- @name __opts
-- @field output_file_name  Output file name.
-- @field output_line_length  Line length in output.
local __opts = {
  output_file_name,
  output_line_lenght,
}


--- Set output file name.
-- Text output will be written to a file with the given name.
--
-- @param name  New output file name.
local function set_output_file_name(name)
  __opts.output_file_name = name
end
M.set_output_file_name = set_output_file_name


--- Set output line length.
-- Set the number of columns in text output.  Text output will be
-- wrapped at spaces so that lines don't contain more than the specified
-- number of characters per line.  There's one exception: if a word is
-- longer than the specified number of characters, the word is put on
-- its own line and that line will be overfull.
--
-- @param cols  New line length in output.  If the argument is smaller
-- than 1, lines aren't wrapped, i.e., all text of a paragraph is put on
-- a single line.
local function set_output_line_length(cols)
  __opts.output_line_length = cols
end
M.set_output_line_length = set_output_line_length


--- Break a text paragraph into lines.
-- Lines are broken at spaces only.  Lines containing only one word may
-- exceed maximum line length.
--
-- @param par  A text paragraph (an array of words).
-- @param max_line_len Maximum length of lines in wrapped paragraph.  If
-- the argument is less then 1, paragraph isn't wrapped at all.
-- @return Table containing the lines of the paragraph.
local function __wrap_text_paragraph(par, max_line_len)
  local wrapped_par = {}
  -- Index of first word on current line.  Initialize current line with
  -- first word of paragraph.
  local line_start = 1
  -- Track current line length.
  local line_len = Ulen(par[line_start])
  -- Iterate over remaining words in paragraph.
  for i = 2,#par do
    local word_len = Ulen(par[i])
    local new_line_len = line_len + 1 + word_len
    -- Maximum line length exceeded?
    if new_line_len > max_line_len and max_line_len >= 1 then
      -- Insert current line into wrapped paragraph.
      tabinsert(wrapped_par, tabconcat(par, ' ', line_start, i-1))
      -- Initialize new current line.
      line_start = i
      new_line_len = word_len
    end
    -- Append word to current line.
    line_len = new_line_len
  end
  -- Insert last line of paragraph.
  tabinsert(wrapped_par, tabconcat(par, ' ', line_start))
  return wrapped_par
end


--- Write all text stored in the text document to a file.
--
local function __write_text_document()
  -- Open output file.
  local fname = __opts.output_file_name or (tex.jobname .. '.spell.txt')
  local f = assert(io.open(fname, 'w'))
  local max_line_len = __opts.output_line_length
  -- Iterate through document paragraphs.
  for _,par in ipairs(__text_document) do
    -- Write wrapped paragraph to file with a leading empty line.
    f:write('\n', tabconcat(__wrap_text_paragraph(par, max_line_len), '\n'), '\n')
    -- Delete paragraph from memory.
    __text_document[_] = nil
  end
  -- Close output file.
  f:close()
end


--- Callback function that writes all document text into a file.
local function __cb_stopr_pkg_spelling()
  __write_text_document()
end


-- Call-back status.
local __is_active_output


--- Enable text document output.
-- Registers call-back `stop_run` to output the text stored in the text
-- document at the end of the LuaTeX run.
local function enable_text_output()
  if not __is_active_output then
    -- Register call-back: At the end of the LuaTeX run, output all text
    -- stored in the text document.
    luatexbase.add_to_callback('stop_run', __write_text_document, '__cb_stop_run_pkg_spelling')
    __is_active_output = true
  end
end
M.enable_text_output = enable_text_output


--- Disable text document output.
-- De-registers call-back `stop_run`.
local function disable_text_output()
  if __is_active_output then
    -- De-register call-back.
    luatexbase.remove_from_callback('stop_run', '__cb_stop_run_pkg_spelling')
    __is_active_output = false
  end
end
M.disable_text_output = disable_text_output


--- Module initialisation.
--
local function __init()
  -- Get local references to package ressources.
  __text_document = PKG_spelling.res.text_document
  -- Set default output file name.
  set_output_file_name(nil)
  -- Set default output line length.
  set_output_line_length(72)
  -- Remember call-back status.
  __is_active_output = false
end


-- Initialize module.
__init()


-- Return module table.
return M