1if not modules then modules = { } end modules ['file-mod'] = {
2 version = 1.001,
3 comment = "companion to file-mod.mkvi",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12
13
14
15local format, find, concat, tonumber = string.format, string.find, table.concat, tonumber
16local sortedhash = table.sortedhash
17local basename = file.basename
18
19local trace_modules = false trackers .register("modules.loading", function(v) trace_modules = v end)
20local permit_unprefixed = false directives.register("modules.permitunprefixed", function(v) permit_unprefixed = v end)
21
22local report = logs.reporter("modules")
23
24local commands = commands
25local context = context
26local implement = interfaces.implement
27
28local findbyscheme = resolvers.finders.byscheme
29local iterator = utilities.parsers.iterator
30
31
32
33local prefixes = {
34 "m",
35 "p",
36 "s",
37 "x",
38
39 "t",
40}
41
42
43
44local suffixes = CONTEXTLMTXMODE > 0 and
45{
46 "mklx",
47 "mkxl",
48 "mkvi",
49 "mkiv",
50 "tex",
51 "cld",
52 "lua",
53}
54 or
55{
56 "mkvi",
57 "mkiv",
58 "tex",
59 "cld",
60 "lua",
61}
62
63
64
65
66
67
68
69
70
71
72
73
74
75local pushrunstate, poprunstate do
76
77 local runstatecodes = tex.runstatecodes
78 local runstate = tex.getrunstate()
79 local setrunstate = tex.setrunstate
80
81 local initializing <const> = runstatecodes.initializing
82 local updating <const> = runstatecodes.updating
83
84
85 if runstate == initializing then
86
87 pushrunstate = function() end
88 poprunstate = function() end
89
90 else
91
92 local level = 0
93
94 pushrunstate = function()
95 level = level + 1
96 if level == 1 then
97 setrunstate(updating)
98 end
99 end
100
101 poprunstate = function()
102 if level == 1 then
103 setrunstate(runstate)
104 end
105 if level > 0 then
106 level = level - 1
107 end
108 end
109
110 end
111
112 luatex.pushrunstate = pushrunstate
113 luatex.poprunstate = poprunstate
114
115 tex.setrunstate = function() end
116
117 implement { name = "pushrunstate", public = true, protected = true, actions = pushrunstate }
118 implement { name = "poprunstate", public = true, protected = true, actions = poprunstate }
119
120end
121
122
123
124local modstatus = { }
125local missing = false
126
127local function usemodule(name,hasscheme)
128 local foundname
129 if hasscheme then
130
131
132 local fullname = file.addsuffix(name,"tex")
133 if trace_modules then
134 report("checking url %a",fullname)
135 end
136 foundname = resolvers.findtexfile(fullname) or ""
137 elseif file.suffix(name) ~= "" then
138 if trace_modules then
139 report("checking file %a",name)
140 end
141 foundname = findbyscheme("any",name) or ""
142 else
143 for i=1,#suffixes do
144 local fullname = file.addsuffix(name,suffixes[i])
145 if trace_modules then
146 report("checking file %a",fullname)
147 end
148 foundname = findbyscheme("any",fullname) or ""
149 if foundname ~= "" then
150 break
151 end
152 end
153 end
154 if foundname ~= "" then
155 if trace_modules then
156 report("loading file %a",foundname)
157 end
158 context.pushrunstate()
159 context.startreadingfile()
160 resolvers.jobs.usefile(foundname,true)
161
162 context.stopreadingfile()
163 context.poprunstate()
164 return true
165 else
166 return false
167 end
168end
169
170function environment.usemodules(prefix,askedname,truename)
171 local truename = truename or environment.truefilename(askedname) or askedname
172 if truename and truename ~= "" then
173 local hasprefix = prefix and prefix ~= ""
174 local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
175 local status = modstatus[hashname] or false
176 if status == 0 then
177
178 elseif status == 1 then
179 status = status + 1
180 else
181 if trace_modules then
182 report("locating, prefix %a, askedname %a, truename %a",prefix,askedname,truename)
183 end
184 local hasscheme = url.hasscheme(truename)
185 if hasscheme then
186
187 if usemodule(truename,true) then
188 status = 1
189 else
190 status = 0
191 end
192 elseif hasprefix then
193 if usemodule(prefix .. "-" .. truename) then
194 status = 1
195 else
196 status = 0
197 end
198 else
199 for i=1,#prefixes do
200
201 local thename = prefixes[i] .. "-" .. truename
202 if thename == tex.jobname then
203
204 status = 1
205 break
206 elseif usemodule(thename) then
207 status = 1
208 break
209 end
210 end
211 if status then
212
213 elseif find(truename,"-",1,true) and usemodule(truename) then
214
215 report("using user prefixed file %a",truename)
216 status = 1
217 elseif permit_unprefixed and usemodule(truename) then
218 report("using unprefixed file %a",truename)
219 status = 1
220 else
221 status = 0
222 end
223 end
224 end
225 if status == 0 then
226 missing = true
227 report("%a is not found",askedname)
228 elseif status == 1 then
229 report("%a is loaded",trace_modules and truename or askedname)
230 else
231 report("%a is already loaded",trace_modules and truename or askedname)
232 end
233 modstatus[hashname] = status
234 end
235end
236
237statistics.register("loaded tex modules", function()
238 if next(modstatus) then
239 local t, f, nt, nf = { }, { }, 0, 0
240 for k, v in sortedhash(modstatus) do
241 local b = basename(k)
242 if v == 0 then
243 nf = nf + 1
244 f[nf] = b
245 else
246 nt = nt + 1
247 t[nt] = b
248 end
249 end
250 if nf == 0 then
251 return format("%s requested, all found (%s)",nt,concat(t," "))
252 elseif nt == 0 then
253 return format("%s requested, all missing (%s)",nf,concat(f," "))
254 else
255 return format("%s requested, %s found (%s), %s missing (%s)",nt+nf,nt,concat(t," "),nf,concat(f," "))
256 end
257 else
258 return nil
259 end
260end)
261
262logs.registerfinalactions(function()
263 logs.startfilelogging(report,"used modules")
264 for k, v in sortedhash(modstatus) do
265 report(v == 0 and " missing: %s" or " loaded : %s",basename(k))
266 end
267 logs.stopfilelogging()
268 if missing and logs.loggingerrors() then
269 logs.starterrorlogging(report,"missing modules")
270 for k, v in sortedhash(modstatus) do
271 if v == 0 then
272 report("%w%s",6,basename(k))
273 end
274 end
275 logs.stoperrorlogging()
276 end
277end)
278
279
280
281local lpegmatch = lpeg.match
282local splitter = lpeg.tsplitter(lpeg.S(". "),tonumber)
283
284function environment.comparedversion(one,two)
285 if not two or two == "" then
286 one, two = environment.version, one
287 elseif one == "" then
288 one = environment.version
289 end
290 one = lpegmatch(splitter,one)
291 two = lpegmatch(splitter,two)
292 one = (one[1] or 0) * 10000 + (one[2] or 0) * 100 + (one[3] or 0)
293 two = (two[1] or 0) * 10000 + (two[2] or 0) * 100 + (two[3] or 0)
294 if one < two then
295 return -1
296 elseif one > two then
297 return 1
298 else
299 return 0
300 end
301end
302
303environment.comparedversion = comparedversion
304
305
306function environment.useluamodule(list)
307 for filename in iterator(list) do
308 environment.loadluafile(filename)
309 end
310end
311
312implement {
313 name = "usemodules",
314 actions = environment.usemodules,
315 arguments = "2 strings",
316}
317
318implement {
319 name = "doifelseolderversion",
320 actions = function(one,two) commands.doifelse(comparedversion(one,two) >= 0) end,
321 arguments = "2 strings"
322}
323
324implement {
325 name = "useluamodule",
326 actions = environment.useluamodule,
327 arguments = "string"
328}
329
330implement {
331 name = "loadluamodule",
332 actions = function(name) dofile(resolvers.findctxfile(name)) end,
333 arguments = "string"
334}
335
336 |