1if not modules then modules = { } end modules [ ' core-ctx ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to core-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
9
30
31
32
33
34local trace_prepfiles = false trackers . register ( " system.prepfiles " , function ( v ) trace_prepfiles = v end )
35
36local tostring = tostring
37local gsub , find , match , validstring = string . gsub , string . find , string . match , string . valid
38local concat = table . concat
39local xmltext = xml . text
40
41local report_jobfile = logs . reporter ( " system " , " jobfile " )
42local report_prepfiles = logs . reporter ( " system " , " prepfiles " )
43
44local commands = commands
45local implement = interfaces . implement
46
47ctxrunner = ctxrunner or { }
48
49ctxrunner . prepfiles = utilities . storage . allocate ( )
50
51local function dontpreparefile ( t , k )
52 return k
53end
54
55table . setmetatableindex ( ctxrunner . prepfiles , dontpreparefile )
56
57local function filtered ( str , method )
58 str = tostring ( str )
59 if method = = ' name ' then str = file . nameonly ( str )
60 elseif method = = ' path ' then str = file . dirname ( str )
61 elseif method = = ' suffix ' then str = file . suffix ( str )
62 elseif method = = ' nosuffix ' then str = file . removesuffix ( str )
63 elseif method = = ' nopath ' then str = file . basename ( str )
64 elseif method = = ' base ' then str = file . basename ( str )
65
66
67
68 end
69 return ( gsub ( str , " \\ " , " / " ) )
70end
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85local function substitute ( str )
86 return str
87end
88
89local function justtext ( str )
90 str = xml . unescaped ( tostring ( str ) )
91 str = xml . cleansed ( str )
92 str = gsub ( str , " \\+ " , ' / ' )
93 str = gsub ( str , " %s+ " , ' ' )
94 return str
95end
96
97function ctxrunner . load ( ctxname )
98
99 report_jobfile ( " processing %a " , ctxname )
100
101 local xmldata = xml . load ( ctxname )
102
103 local jobname = tex . jobname
104
105 local variables = { job = jobname }
106 local commands = { }
107 local flags = { }
108 local paths = { }
109 local treatments = { }
110 local suffix = " prep "
111
112 xml . include ( xmldata , ' ctx:include ' , ' name ' , { ' . ' , file . dirname ( ctxname ) , " .. " , " ../.. " } )
113
114 for e in xml . collected ( xmldata , " /ctx:job/ctx:flags/ctx:flag " ) do
115 local flag = xmltext ( e )
116 local key , value = match ( flag , " ^(.-)=(.+)$ " )
117 if key and value then
118 environment . setargument ( key , value )
119 else
120 environment . setargument ( flag , true )
121 end
122 end
123
124
125
126 local ctxfile = document . options . ctxfile
127
128 local modes = ctxfile . modes
129 local modules = ctxfile . modules
130 local environments = ctxfile . environments
131
132 for e in xml . collected ( xmldata , " /ctx:job/ctx:process/ctx:resources/ctx:mode " ) do
133 modes [ # modes + 1 ] = xmltext ( e )
134 end
135
136 for e in xml . collected ( xmldata , " /ctx:job/ctx:process/ctx:resources/ctx:module " ) do
137 modules [ # modules + 1 ] = xmltext ( e )
138 end
139
140 for e in xml . collected ( xmldata , " /ctx:job/ctx:process/ctx:resources/ctx:environment " ) do
141 environments [ # environments + 1 ] = xmltext ( e )
142 end
143
144 for e in xml . collected ( xmldata , " ctx:message " ) do
145 report_jobfile ( " ctx comment: %s " , xmltext ( e ) )
146 end
147
148 for r , d , k in xml . elements ( xmldata , " ctx:value[@name='job'] " ) do
149 d [ k ] = variables [ ' job ' ] or " "
150 end
151
152 for e in xml . collected ( xmldata , " /ctx:job/ctx:preprocess/ctx:processors/ctx:processor " ) do
153 local name = e . at and e . at [ ' name ' ] or " unknown "
154 local suffix = e . at and e . at [ ' suffix ' ] or " prep "
155 for r , d , k in xml . elements ( command , " ctx:old " ) do
156 d [ k ] = " %old% "
157 end
158 for r , d , k in xml . elements ( e , " ctx:new " ) do
159 d [ k ] = " %new% "
160 end
161 for r , d , k in xml . elements ( e , " ctx:value " ) do
162 local tag = d [ k ] . at [ ' name ' ]
163 if tag then
164 d [ k ] = " % " . . tag . . " % "
165 end
166 end
167 local runner = xml . textonly ( e )
168 if runner and runner ~ = " " then
169 commands [ name ] = {
170 suffix = suffix ,
171 runner = runner ,
172 }
173 end
174 end
175
176 local suffix = xml . filter ( xmldata , " xml:///ctx:job/ctx:preprocess/attribute('suffix') " ) or suffix
177 local runlocal = xml . filter ( xmldata , " xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local') " )
178
179 runlocal = toboolean ( runlocal )
180
181
182
183 local inputfile = validstring ( environment . arguments . input ) or jobname
184
185 variables . old = inputfile
186
187 for files in xml . collected ( xmldata , " /ctx:job/ctx:preprocess/ctx:files " ) do
188 for pattern in xml . collected ( files , " ctx:file " ) do
189 local preprocessor = pattern . at [ ' processor ' ] or " "
190 for r , d , k in xml . elements ( pattern , " /ctx:old " ) do
191 d [ k ] = jobname
192 end
193 for r , d , k in xml . elements ( pattern , " /ctx:value[@name='old' " ) do
194 d [ k ] = jobname
195 end
196 pattern = justtext ( xml . tostring ( pattern ) )
197 if preprocessor and preprocessor ~ = " " and pattern and pattern ~ = " " then
198 local noftreatments = # treatments + 1
199 local findpattern = string . topattern ( pattern )
200 local preprocessors = utilities . parsers . settings_to_array ( preprocessor )
201 treatments [ noftreatments ] = {
202 pattern = findpattern ,
203 preprocessors = preprocessors ,
204 }
205 report_jobfile ( " step %s, pattern %a, preprocessor: %a " , noftreatments , findpattern , preprocessors )
206 end
207 end
208 end
209
210 if # treatments = = 0 then
211 report_jobfile ( " no treatments needed " )
212 end
213
214 local function needstreatment ( oldfile )
215 for i = 1 , # treatments do
216 local treatment = treatments [ i ]
217 local pattern = treatment . pattern
218 if find ( oldfile , pattern ) then
219 return treatment
220 end
221 end
222 end
223
224 local preparefile = # treatments > 0 and function ( prepfiles , filename )
225
226 filename = file . collapsepath ( filename )
227
228 local treatment = needstreatment ( filename )
229 local oldfile = filename
230 local newfile = false
231 if treatment then
232 local preprocessors = treatment . preprocessors
233 local runners = { }
234 for i = 1 , # preprocessors do
235 local preprocessor = preprocessors [ i ]
236 local command = commands [ preprocessor ]
237 if command then
238 local runner = command . runner
239 local suffix = command . suffix
240 local result = filename . . " . " . . suffix
241 if runlocal then
242 result = file . basename ( result )
243 end
244 variables . old = oldfile
245 variables . new = result
246 runner = utilities . templates . replace ( runner , variables )
247 if runner and runner ~ = " " then
248 runners [ # runners + 1 ] = runner
249 oldfile = result
250 if runlocal then
251 oldfile = file . basename ( oldfile )
252 end
253 newfile = oldfile
254 end
255 end
256 end
257 oldname = file . collapsepath ( oldname )
258 newname = file . collapsepath ( newname )
259 if not newfile then
260 newfile = filename
261 report_prepfiles ( " %a is not converted to %a " , filename , newfile )
262 elseif not lfs . isfile ( newfile ) or file . needsupdating ( filename , newfile ) then
263 for i = 1 , # runners do
264 report_prepfiles ( " step %i: %s " , i , runners [ i ] )
265 end
266
267 for i = 1 , # runners do
268 local command = runners [ i ]
269 report_prepfiles ( " command: %s " , command )
270
271
272
273
274 local result = os . execute ( command ) or 0
275
276
277
278
279 logs . newline ( )
280 logs . newline ( )
281 end
282 if lfs . isfile ( newfile ) then
283 file . syncmtimes ( filename , newfile )
284 report_prepfiles ( " %a is converted to %a " , filename , newfile )
285 else
286 report_prepfiles ( " %a is not converted to %a " , filename , newfile )
287 newfile = filename
288 end
289 elseif lfs . isfile ( newfile ) then
290 report_prepfiles ( " %a is already converted to %a " , filename , newfile )
291 else
292 report_prepfiles ( " unknown error when converting %a to %a " , filename , newfile )
293 end
294 else
295 newfile = filename
296 end
297 prepfiles [ filename ] = newfile
298
299 prepfiles [ newfile ] = newfile
300 return newfile
301 end
302
303 table . setmetatableindex ( ctxrunner . prepfiles , preparefile or dontpreparefile )
304
305
306
307end
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322local function resolve ( name )
323 return ctxrunner . prepfiles [ file . collapsepath ( name ) ] or false
324end
325
326function ctxrunner . preparedfile ( name )
327 return resolve ( name ) or name
328end
329
330local processfile = commands . processfile
331local doifelseinputfile = commands . doifelseinputfile
332
333implement {
334 name = " processfile " ,
335 overload = true ,
336 arguments = { " string " , " integer " } ,
337 actions = function ( name , maxreadlevel )
338 local prepname = resolve ( name )
339 if prepname then
340 return processfile ( prepname , 0 )
341 end
342 return processfile ( name , maxreadlevel )
343 end
344}
345
346implement {
347 name = " doifelseinputfile " ,
348 overload = true ,
349 arguments = { " string " , " integer " } ,
350 actions = function ( name , depth )
351 local prepname = resolve ( name )
352 if prepname then
353 return doifelseinputfile ( prepname , 0 )
354 end
355 return doifelseinputfile ( name , depth )
356 end
357}
358
359
360
361
362
363
364
365implement {
366 name = " setdocumentctxfile " ,
367 onlyonce = true ,
368 actions = function ( )
369 local ctxfile = document . arguments . ctx or " "
370 if ctxfile ~ = " " then
371 ctxrunner . load ( ctxfile )
372 end
373 end
374}
375
376function ctxrunner . resolve ( name )
377 local collapsedname = file . collapsepath ( name , " . " )
378 return ctxrunner . prepfiles [ collapsedname ] or collapsedname
379end
380
381
382
383
384
385
386
387
388
389
390 |