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
67local setrunstate = tex.setrunstate
68local level = 0
69
70local function pushrunstate()
71 level = level + 1
72 if level == 1 then
73 setrunstate(1)
74 end
75end
76
77local function poprunstate()
78 if level == 1 then
79 setrunstate(3)
80 end
81 if level > 0 then
82 level = level - 1
83 end
84end
85
86luatex.pushrunstate = pushrunstate
87luatex.poprunstate = poprunstate
88
89tex.setrunstate = function() end
90
91implement { name = "pushrunstate", public = true, protected = true, actions = pushrunstate }
92implement { name = "poprunstate", public = true, protected = true, actions = poprunstate }
93
94
95
96local modstatus = { }
97local missing = false
98
99local function usemodule(name,hasscheme)
100 local foundname
101 if hasscheme then
102
103
104 local fullname = file.addsuffix(name,"tex")
105 if trace_modules then
106 report("checking url %a",fullname)
107 end
108 foundname = resolvers.findtexfile(fullname) or ""
109 elseif file.suffix(name) ~= "" then
110 if trace_modules then
111 report("checking file %a",name)
112 end
113 foundname = findbyscheme("any",name) or ""
114 else
115 for i=1,#suffixes do
116 local fullname = file.addsuffix(name,suffixes[i])
117 if trace_modules then
118 report("checking file %a",fullname)
119 end
120 foundname = findbyscheme("any",fullname) or ""
121 if foundname ~= "" then
122 break
123 end
124 end
125 end
126 if foundname ~= "" then
127 if trace_modules then
128 report("loading file %a",foundname)
129 end
130 context.pushrunstate()
131 context.startreadingfile()
132 resolvers.jobs.usefile(foundname,true)
133
134 context.stopreadingfile()
135 context.poprunstate()
136 return true
137 else
138 return false
139 end
140end
141
142function environment.usemodules(prefix,askedname,truename)
143 local truename = truename or environment.truefilename(askedname) or askedname
144 if truename and truename ~= "" then
145 local hasprefix = prefix and prefix ~= ""
146 local hashname = ((hasprefix and prefix) or "*") .. "-" .. truename
147 local status = modstatus[hashname] or false
148 if status == 0 then
149
150 elseif status == 1 then
151 status = status + 1
152 else
153 if trace_modules then
154 report("locating, prefix %a, askedname %a, truename %a",prefix,askedname,truename)
155 end
156 local hasscheme = url.hasscheme(truename)
157 if hasscheme then
158
159 if usemodule(truename,true) then
160 status = 1
161 else
162 status = 0
163 end
164 elseif hasprefix then
165 if usemodule(prefix .. "-" .. truename) then
166 status = 1
167 else
168 status = 0
169 end
170 else
171 for i=1,#prefixes do
172
173 local thename = prefixes[i] .. "-" .. truename
174 if thename == tex.jobname then
175
176 status = 1
177 break
178 elseif usemodule(thename) then
179 status = 1
180 break
181 end
182 end
183 if status then
184
185 elseif find(truename,"-",1,true) and usemodule(truename) then
186
187 report("using user prefixed file %a",truename)
188 status = 1
189 elseif permit_unprefixed and usemodule(truename) then
190 report("using unprefixed file %a",truename)
191 status = 1
192 else
193 status = 0
194 end
195 end
196 end
197 if status == 0 then
198 missing = true
199 report("%a is not found",askedname)
200 elseif status == 1 then
201 report("%a is loaded",trace_modules and truename or askedname)
202 else
203 report("%a is already loaded",trace_modules and truename or askedname)
204 end
205 modstatus[hashname] = status
206 end
207end
208
209statistics.register("loaded tex modules", function()
210 if next(modstatus) then
211 local t, f, nt, nf = { }, { }, 0, 0
212 for k, v in sortedhash(modstatus) do
213 local b = basename(k)
214 if v == 0 then
215 nf = nf + 1
216 f[nf] = b
217 else
218 nt = nt + 1
219 t[nt] = b
220 end
221 end
222 if nf == 0 then
223 return format("%s requested, all found (%s)",nt,concat(t," "))
224 elseif nt == 0 then
225 return format("%s requested, all missing (%s)",nf,concat(f," "))
226 else
227 return format("%s requested, %s found (%s), %s missing (%s)",nt+nf,nt,concat(t," "),nf,concat(f," "))
228 end
229 else
230 return nil
231 end
232end)
233
234logs.registerfinalactions(function()
235 logs.startfilelogging(report,"used modules")
236 for k, v in sortedhash(modstatus) do
237 report(v == 0 and "missing: %s" or "loaded : %s",basename(k))
238 end
239 logs.stopfilelogging()
240 if missing and logs.loggingerrors() then
241 logs.starterrorlogging(report,"missing modules")
242 for k, v in sortedhash(modstatus) do
243 if v == 0 then
244 report("%w%s",6,basename(k))
245 end
246 end
247 logs.stoperrorlogging()
248 end
249end)
250
251
252
253local lpegmatch = lpeg.match
254local splitter = lpeg.tsplitter(lpeg.S(". "),tonumber)
255
256function environment.comparedversion(one,two)
257 if not two or two == "" then
258 one, two = environment.version, one
259 elseif one == "" then
260 one = environment.version
261 end
262 one = lpegmatch(splitter,one)
263 two = lpegmatch(splitter,two)
264 one = (one[1] or 0) * 10000 + (one[2] or 0) * 100 + (one[3] or 0)
265 two = (two[1] or 0) * 10000 + (two[2] or 0) * 100 + (two[3] or 0)
266 if one < two then
267 return -1
268 elseif one > two then
269 return 1
270 else
271 return 0
272 end
273end
274
275environment.comparedversion = comparedversion
276
277
278function environment.useluamodule(list)
279 for filename in iterator(list) do
280 environment.loadluafile(filename)
281 end
282end
283
284implement {
285 name = "usemodules",
286 actions = environment.usemodules,
287 arguments = "2 strings",
288}
289
290implement {
291 name = "doifelseolderversion",
292 actions = function(one,two) commands.doifelse(comparedversion(one,two) >= 0) end,
293 arguments = "2 strings"
294}
295
296implement {
297 name = "useluamodule",
298 actions = environment.useluamodule,
299 arguments = "string"
300}
301
302implement {
303 name = "loadluamodule",
304 actions = function(name) dofile(resolvers.findctxfile(name)) end,
305 arguments = "string"
306}
307
308 |