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
|
if not modules then modules = { } end modules ['data-tex'] = {
version = 1.001,
comment = "companion to luat-lib.mkiv",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE / ConTeXt Development Team",
license = "see context related readme files"
}
local char = string.char
local insert, remove = table.insert, table.remove
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local report_tex = logs.reporter("resolvers","tex")
local resolvers = resolvers
local sequencers = utilities.sequencers
local methodhandler = resolvers.methodhandler
local splitlines = string.splitlines
local utffiletype = utf.filetype
-- local fileprocessor = nil
-- local lineprocessor = nil
local textfileactions = sequencers.new {
arguments = "str,filename,coding",
returnvalues = "str",
results = "str",
}
local textlineactions = sequencers.new {
arguments = "str,filename,linenumber,noflines,coding",
returnvalues = "str",
results = "str",
}
local helpers = resolvers.openers.helpers
local appendgroup = sequencers.appendgroup
helpers.textfileactions = textfileactions
helpers.textlineactions = textlineactions
appendgroup(textfileactions,"before") -- user
appendgroup(textfileactions,"system") -- private
appendgroup(textfileactions,"after" ) -- user
appendgroup(textlineactions,"before") -- user
appendgroup(textlineactions,"system") -- private
appendgroup(textlineactions,"after" ) -- user
local ctrl_d = char( 4) -- unix
local ctrl_z = char(26) -- windows
resolvers.inputstack = resolvers.inputstack or { }
local inputstack = resolvers.inputstack
function helpers.textopener(tag,filename,filehandle,coding)
local lines
local t_filehandle = type(filehandle)
if not filehandle then
lines = io.loaddata(filename)
elseif t_filehandle == "string" then
lines = filehandle
elseif t_filehandle == "table" then
lines = filehandle
else
lines = filehandle:read("*a") -- io.readall(filehandle) ... but never that large files anyway
-- lines = io.readall(filehandle)
filehandle:close()
end
if type(lines) == "string" then
local coding = coding or utffiletype(lines) -- so we can signal no regime
if trace_locating then
report_tex("%a opener: %a opened using method %a",tag,filename,coding)
end
if coding == "utf-16-be" then
lines = utf.utf16_to_utf8_be(lines)
elseif coding == "utf-16-le" then
lines = utf.utf16_to_utf8_le(lines)
elseif coding == "utf-32-be" then
lines = utf.utf32_to_utf8_be(lines)
elseif coding == "utf-32-le" then
lines = utf.utf32_to_utf8_le(lines)
else -- utf8 or unknown (could be a mkvi file)
local runner = textfileactions.runner
if runner then
lines = runner(lines,filename,coding) or lines
end
lines = splitlines(lines)
end
elseif trace_locating then
report_tex("%a opener: %a opened",tag,filename)
end
local noflines = #lines
if lines[noflines] == "" then -- maybe some special check is needed
lines[noflines] = nil
end
logs.show_open(filename)
insert(inputstack,filename)
return {
filename = filename,
noflines = noflines,
currentline = 0,
close = function()
if trace_locating then
report_tex("%a closer: %a closed",tag,filename)
end
logs.show_close(filename)
remove(inputstack)
t = nil
end,
reader = function(self)
self = self or t
local currentline, noflines = self.currentline, self.noflines
if currentline >= noflines then
return nil
else
currentline = currentline + 1
self.currentline = currentline
local content = lines[currentline]
if not content then
return nil
elseif content == "" then
return ""
-- elseif content == ctrl_d or ctrl_z then
-- return nil -- we need this as \endinput does not work in prints
else
local runner = textlineactions.runner
if runner then
return runner(content,filename,currentline,noflines,coding) or content
else
return content
end
end
end
end
}
end
function resolvers.findtexfile(filename,filetype)
return methodhandler('finders',filename,filetype)
end
function resolvers.opentexfile(filename)
return methodhandler('openers',filename)
end
function resolvers.openfile(filename)
local fullname = methodhandler('finders',filename)
return fullname and fullname ~= "" and methodhandler('openers',fullname) or nil
end
function resolvers.loadtexfile(filename,filetype)
-- todo: optionally apply filters
local ok, data, size = resolvers.loadbinfile(filename, filetype)
return data or ""
end
resolvers.texdatablob = resolvers.loadtexfile
local function installhandler(namespace,what,where,func)
if not func then
where, func = "after", where
end
if where == "before" or where == "after" then
sequencers.appendaction(namespace,where,func)
else
report_tex("installing input %a handlers in %a is not possible",what,tostring(where))
end
end
function resolvers.installinputlinehandler(...) installhandler(helpers.textlineactions,"line",...) end
function resolvers.installinputfilehandler(...) installhandler(helpers.textfileactions,"file",...) end
-- local basename = file.basename
-- resolvers.installinputlinehandler(function(str,filename,linenumber,noflines)
-- report_tex("[lc] file %a, line %a of %a, length %a",basename(filename),linenumber,noflines,#str)
-- end)
-- resolvers.installinputfilehandler(function(str,filename)
-- report_tex("[fc] file %a, length %a",basename(filename),#str)
-- end)
|