1if not modules then modules = { } end modules ['mlib-fio'] = {
2 version = 1.001,
3 comment = "companion to mlib-ctx.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files",
7}
8
9local type = type
10local find = string.find
11local concat = table.concat
12local suffix, addsuffix, is_writable = file.suffix, file.addsuffix, file.is_writable
13local urlhashed = url.hashed
14
15local findfile = resolvers.findfile
16local mplibnew = mplib.new
17
18
19local trace_terminal = false trackers.register("metapost.terminal", function(v) trace_terminal = v end)
20
21local report_metapost = logs.reporter("metapost")
22local report_terminal = logs.reporter("metapost","terminal")
23local report_logger = logs.reporter("metapost","log")
24local report_error = logs.reporter("metapost","error")
25
26mplib.realtimelogging = false
27
28local handlelog do
29
30 local l, nl, dl = { }, 0, false
31
32 handlelog = function(instance,target,str)
33 if target == 1 then
34
35 elseif target == 2 or target == 3 then
36
37 if str == "\n" then
38 mplib.realtimelogging = true
39 if nl > 0 then
40 report_logger(concat(l,"",1,nl))
41 nl, dl = 0, false
42 elseif not dl then
43 report_logger("")
44 dl = true
45 end
46 else
47 nl = nl + 1
48 l[nl] = str
49 end
50 elseif target == 4 then
51 report_error(str)
52 end
53 end
54
55end
56
57local finders = { }
58mplib.finders = finders
59
60local function validftype(ftype)
61 return ftype == "mp" and "mp" or nil
62end
63
64
65
66local findtexfile = resolvers.findtexfile
67local opentexfile = resolvers.opentexfile
68local splitlines = string.splitlines
69
70local suffixlist = { "mpxl", "mpiv", "mp" }
71
72local remapped = {
73
74
75 ["hatching.mp"] = "mp-remapped-hatching.mp",
76 ["boxes.mp"] = "mp-remapped-boxes.mp",
77 ["hatching"] = "mp-remapped-hatching.mp",
78 ["boxes"] = "mp-remapped-boxes.mp",
79}
80
81local function findmpfile(name,ftype)
82 local usedname = remapped[name] or name
83 local validtyp = validftype(ftype)
84 local fullname = findtexfile(usedname,validtyp)
85 if fullname and fullname ~= "" then
86 return fullname
87 elseif suffix(usedname) == "" then
88 for i=1,#suffixlist do
89 fullname = findfile(addsuffix(usedname,suffixlist[i]),validtyp)
90 if fullname and fullname ~= "" then
91 return fullname
92 end
93 end
94 end
95 return nil
96end
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
124finders.file = function(specification,name,mode,kind)
125 if mode == "w" then
126 return is_writable(name) and name or nil
127 else
128 return findmpfile(name,kind) or nil
129 end
130end
131
132local function finder(name,mode,kind)
133 local specification = urlhashed(name)
134 local finder = finders[specification.scheme] or finders.file
135 local found = finder(specification,name,mode,validftype(ftype))
136 return found
137end
138
139local function writetoterminal(terminaldata,maxterm,d)
140 local t = type(d)
141 local n = 0
142 if t == "string" then
143 d = splitlines(d)
144 n = #d
145 for i=1,#d do
146 maxterm = maxterm + 1
147 terminaldata[maxterm] = d[i]
148 end
149 elseif t == "table" then
150 for i=1,#d do
151 local l = d[i]
152 if not l then
153
154 elseif find(l,"[\n\r]") then
155 local s = splitlines(l)
156 local m = #s
157 for i=1,m do
158 maxterm = maxterm + 1
159 terminaldata[maxterm] = s[i]
160 end
161 n = n + m
162 else
163 maxterm = maxterm + 1
164 terminaldata[maxterm] = d[i]
165 n = 1
166 end
167 end
168 end
169 if trace_terminal then
170 report_metapost("writing %i lines, in cache %s",n,maxterm)
171 end
172 return maxterm
173end
174
175local function readfromterminal(terminaldata,maxterm,nowterm)
176 if nowterm >= maxterm then
177 terminaldata[nowterm] = false
178 maxterm = 0
179 nowterm = 0
180 if trace_terminal then
181 report_metapost("resetting, maxcache %i",#terminaldata)
182 end
183 return maxterm, nowterm, nil
184 else
185 if nowterm > 0 then
186 terminaldata[nowterm] = false
187 end
188 nowterm = nowterm + 1
189 local s = terminaldata[nowterm]
190 if trace_terminal then
191 report_metapost("reading line %i: %s",nowterm,s)
192 end
193 return maxterm, nowterm, s
194 end
195end
196
197local function fileopener()
198
199
200
201 local terminaldata = { }
202 local maxterm = 0
203 local nowterm = 0
204
205 local terminal = {
206 name = "terminal",
207 close = function()
208
209
210
211 end,
212 reader = function()
213 local line
214 maxterm, nowterm, line = readfromterminal(terminaldata,maxterm,nowterm)
215 return line
216 end,
217 writer = function(d)
218 maxterm = writetoterminal(terminaldata,maxterm,d)
219 end,
220 }
221
222 return function(name,mode,kind)
223 if name == "terminal" then
224
225 return terminal
226 elseif mode == "w" then
227
228 local f = io.open(name,"wb")
229 if f then
230
231 return {
232 name = full,
233 writer = function(s) return f:write(s) end,
234 close = function() f:close() end,
235 }
236 end
237 else
238 local full = findtexfile(name,validftype(ftype))
239 if full then
240
241 return opentexfile(full)
242 end
243 end
244 end
245
246end
247
248local overloadmode = "warning"
249
250directives.register("metapost.overloadmode",function(v)
251 if v == "warning" or v == "error" then
252 overloadmode = v
253 else
254 overloadmode= false
255 end
256end)
257
258local propertycodes = {
259 [-3] = "mutable",
260 [ 1] = "primitive",
261 [ 2] = "permanent",
262 [ 3] = "immutable",
263}
264
265mplib.propertycodes = propertycodes
266
267local report = logs.reporter("metafun", "log")
268
269local function overload(property,name)
270 if overloadmode and property >= 0 then
271
272 local code = propertycodes[property] or "unknown"
273 report("overloading %s %a",code, name)
274
275 if overloadmode == "error" then
276 luatex.abort()
277 end
278 return false
279 else
280
281 return true
282 end
283end
284
285local showcontext = mplib.showcontext
286
287local function handleerror(instance, message, helpinfo, interaction)
288 report()
289 report("error: %s", message)
290 report()
291 showcontext(instance)
292 report()
293 report(helpinfo)
294 report()
295 if interaction == 5 then
296
297 end
298end
299
300local function handlewarning(instance, message)
301 report()
302 report("warning: %s", message)
303 report()
304end
305
306function mplib.new(specification)
307 local openfile = fileopener()
308 local handlers = specification.handlers
309 local instance
310 instance = mplibnew {
311
312 bend_tolerance = specification.bendtolerance,
313 move_tolerance = specification.movetolerance,
314 math_mode = specification.mathmode,
315 run_script = specification.runscript,
316 run_internal = specification.runinternal,
317 script_error = specification.scripterror,
318 make_text = specification.maketext,
319
320 extensions = 1,
321
322 utf8_mode = true,
323 text_mode = true,
324 show_mode = true,
325
326
327
328
329 find_file = finder,
330 run_overload = overload,
331 open_file = openfile,
332 interaction = "silent",
333 job_name = tex.jobname,
334 halt_on_error = true,
335 run_logger = handlers.log or function(...) handlelog (instance,...) end,
336 run_error = handlers.error or function(...) handleerror (instance,...) end,
337 run_warning = handlers.warning or function(...) handlewarning(instance,...) end,
338 }
339 return instance, openfile("terminal")
340end
341
342mplib.finder = finder
343
344 |