1if not modules then modules = { } end modules['mtx-context'] = {
2 version = 1.001,
3 comment = "companion to mtxrun.lua",
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
12local type, next, tostring, tonumber = type, next, tostring, tonumber
13local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find
14local quote, validstring, splitstring = string.quote, string.valid, string.split
15local sort, concat, insert, sortedhash, tohash = table.sort, table.concat, table.insert, table.sortedhash, table.tohash
16local settings_to_array = utilities.parsers.settings_to_array
17local appendtable = table.append
18local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P
19
20local getargument = environment.getargument or environment.argument
21local setargument = environment.setargument
22
23local filejoinname = file.join
24local filebasename = file.basename
25local filenameonly = file.nameonly
26local filepathpart = file.pathpart
27local filesuffix = file.suffix
28local fileaddsuffix = file.addsuffix
29local filenewsuffix = file.replacesuffix
30local removesuffix = file.removesuffix
31local validfile = lfs.isfile
32local removefile = os.remove
33local renamefile = os.rename
34local formatters = string.formatters
35
36local application = logs.application {
37 name = "mtx-context",
38 banner = "ConTeXt Process Management 1.04",
39
40 helpinfo = "mtx-context.xml",
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
89local report = application.report
90
91scripts = scripts or { }
92scripts.context = scripts.context or { }
93
94
95
96if jit then
97 setargument("engine","luajittex")
98 setargument("jit",nil)
99elseif getargument("luatex") then
100 setargument("engine","luatex")
101elseif getargument("jit") or getargument("luajittex") then
102
103
104 setargument("engine","luajittex")
105end
106
107
108
109
110local engine_new = filenameonly(getargument("engine") or directives.value("system.engine"))
111local engine_old = filenameonly(environment.ownmain) or filenameonly(environment.ownbin)
112
113local function restart(engine_old,engine_new)
114 local generate = environment.arguments.generate and (engine_new == "luatex" or engine_new == "luajittex")
115 local arguments = generate and "--generate" or environment.reconstructcommandline()
116 local ownname = filejoinname(filepathpart(environment.ownname),"mtxrun.lua")
117 local command = format("%s --luaonly %q %s --redirected",engine_new,ownname,arguments)
118 report(format("redirect %s -> %s: %s",engine_old,engine_new,command))
119 local result = os.execute(command)
120 os.exit(result == 0 and 0 or 1)
121end
122
123
124
125
126
127
128
129
130
131
132
133if environment.validengines[engine_new] and engine_new ~= environment.basicengines[engine_old] then
134 restart(engine_old,engine_new)
135end
136
137
138
139
140
141local usedfiles = {
142 nop = "cont-nop.mkiv",
143 yes = "cont-yes.mkiv",
144}
145
146local usedsuffixes = {
147 before = {
148 "tuc"
149 },
150 after = {
151 "pdf", "tuc", "log"
152 },
153 keep = {
154 "log"
155 },
156}
157
158local formatofinterface = {
159 en = "cont-en",
160 uk = "cont-uk",
161 de = "cont-de",
162 fr = "cont-fr",
163 nl = "cont-nl",
164 cs = "cont-cs",
165 it = "cont-it",
166 ro = "cont-ro",
167 pe = "cont-pe",
168}
169
170local defaultformats = {
171 "cont-en",
172
173}
174
175
176
177local generic_files = {
178 "texexec.tex", "texexec.tui", "texexec.tuo",
179 "texexec.tuc", "texexec.tua",
180 "texexec.ps", "texexec.pdf", "texexec.dvi",
181 "cont-opt.tex", "cont-opt.bak"
182}
183
184local obsolete_results = {
185 "dvi",
186}
187
188local temporary_runfiles = {
189 "tui",
190 "tua",
191 "tup", "ted", "tes",
192 "top",
193 "log",
194 "tmp",
195 "run",
196 "bck",
197 "rlg",
198 "ctl",
199 "mpt", "mpx", "mpd", "mpo", "mpb",
200 "prep",
201 "pgf",
202 "aux", "blg",
203}
204
205local temporary_suffixes = {
206 "prep",
207}
208
209local synctex_runfiles = {
210 "synctex", "synctex.gz", "syncctx"
211}
212
213local persistent_runfiles = {
214 "tuo",
215 "tub",
216 "top",
217 "tuc",
218 "bbl",
219}
220
221local special_runfiles = {
222 "%-mpgraph", "%-mprun", "%-temp%-",
223}
224
225local extra_runfiles = {
226 "^m_k_i_v_.-%.pdf$",
227 "^l_m_t_x_.-%.pdf$",
228}
229
230local function purge_file(dfile,cfile)
231 if cfile and validfile(cfile) then
232 if removefile(dfile) then
233 return filebasename(dfile)
234 end
235 elseif dfile then
236 if removefile(dfile) then
237 return filebasename(dfile)
238 end
239 end
240end
241
242
243
244local ctxrunner = { }
245
246local ctx_locations = { '..', '../..' }
247
248function ctxrunner.new()
249 return {
250 ctxname = "",
251 jobname = "",
252 flags = { },
253 }
254end
255
256function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
257
258 if not ctxdata.jobname or ctxdata.jobname == "" or getargument("noctx") then
259 return
260 end
261
262 ctxdata.ctxname = ctxname or removesuffix(ctxdata.jobname) or ""
263
264 if ctxdata.ctxname == "" then
265 return
266 end
267
268 ctxdata.jobname = fileaddsuffix(ctxdata.jobname,'tex')
269 ctxdata.ctxname = fileaddsuffix(ctxdata.ctxname,'ctx')
270
271 report("jobname: %s",ctxdata.jobname)
272 report("ctxname: %s",ctxdata.ctxname)
273
274
275
276 local usedname = ctxdata.ctxname
277 local found = validfile(usedname)
278
279
280
281 if not found then
282 for _, path in next, ctx_locations do
283 local fullname = filejoinname(path,ctxdata.ctxname)
284 if validfile(fullname) then
285 usedname = fullname
286 found = true
287 break
288 end
289 end
290 end
291
292 if not found then
293 usedname = resolvers.findfile(ctxdata.ctxname,"tex")
294 found = usedname ~= ""
295 end
296
297 if not found and defaultname and defaultname ~= "" and validfile(defaultname) then
298 usedname = defaultname
299 found = true
300 end
301
302 if not found then
303 return
304 end
305
306 local xmldata = xml.load(usedname)
307
308 if not xmldata then
309 return
310 else
311
312 end
313
314 local ctxpaths = table.append({'.', filepathpart(ctxdata.ctxname)}, ctx_locations)
315
316 xml.include(xmldata,'ctx:include','name', ctxpaths)
317
318 local flags = ctxdata.flags
319
320 for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
321 local flag = xml.text(e) or ""
322 local key, value = match(flag,"^(.-)=(.+)$")
323 if key and value then
324 flags[key] = value
325 else
326 flags[flag] = true
327 end
328 end
329
330end
331
332function ctxrunner.checkflags(ctxdata)
333 if ctxdata then
334 for k,v in next, ctxdata.flags do
335 if getargument(k) == nil then
336 setargument(k,v)
337 end
338 end
339 end
340end
341
342
343
344local multipass_suffixes = { ".tuc" }
345local multipass_nofruns = 9
346local multipass_forcedruns = false
347
348local function multipass_hashfiles(jobname)
349 local hash = { }
350 for i=1,#multipass_suffixes do
351 local suffix = multipass_suffixes[i]
352 local full = jobname .. suffix
353 hash[full] = md5.hex(io.loaddata(full) or "unknown")
354 end
355 return hash
356end
357
358local function multipass_changed(oldhash, newhash)
359 for k,v in next, oldhash do
360 if v ~= newhash[k] then
361 return true
362 end
363 end
364 return false
365end
366
367local f_tempfile_i = formatters["%s-%s-%02d.tmp"]
368local f_tempfile_s = formatters["%s-%s-keep.%s"]
369
370local function backup(jobname,run,kind,filename)
371 if run then
372 if run == 1 then
373 for i=1,10 do
374 local tmpname = f_tempfile_i(jobname,kind,i)
375 if validfile(tmpname) then
376 removefile(tmpname)
377 report("removing %a",tmpname)
378 end
379 end
380 end
381 if validfile(filename) then
382 local tmpname = f_tempfile(jobname,kind,run or 1)
383 report("copying %a into %a",filename,tmpname)
384 file.copy(filename,tmpname)
385 else
386 report("no file %a, nothing kept",filename)
387 end
388 elseif validfile(filename) then
389 local tmpname = f_tempfile_s(jobname,kind,kind)
390 report("copying %a into %a",filename,tmpname)
391 file.copy(filename,tmpname)
392 else
393 report("no file %a, nothing kept",filename)
394 end
395end
396
397local function multipass_copyluafile(jobname,run)
398 local tuaname, tucname = jobname..".tua", jobname..".tuc"
399 if validfile(tuaname) then
400 if run then
401 backup(jobname,run,"tuc",tucname)
402 report("copying %a into %a",tuaname,tucname)
403 report()
404 end
405 removefile(tucname)
406 renamefile(tuaname,tucname)
407 end
408end
409
410local function multipass_copypdffile(jobname,run)
411 if run then
412 local pdfname = jobname..".pdf"
413 if validfile(pdfname) then
414 backup(jobname,false,"pdf",pdfname)
415 report()
416 end
417 end
418end
419
420local function multipass_copylogfile(jobname,run)
421 if run then
422 local logname = jobname..".log"
423 if validfile(logname) then
424 backup(jobname,run,"log",logname)
425 report()
426 end
427 end
428end
429
430
431
432local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1)
433
434local prefile = nil
435local predata = nil
436
437local function preamble_analyze(filename)
438 filename = fileaddsuffix(filename,"tex")
439 if predata and prefile == filename then
440 return predata
441 end
442 prefile = filename
443 predata = { }
444 local line = io.loadlines(prefile)
445 if line then
446 local preamble = lpegmatch(pattern,line)
447 if preamble then
448 utilities.parsers.options_to_hash(preamble,predata)
449 predata.type = "tex"
450 elseif find(line,"^<?xml ") then
451 predata.type = "xml"
452 end
453 if predata.nofruns then
454 multipass_nofruns = predata.nofruns
455 end
456 if not predata.engine then
457 predata.engine = environment.basicengines[engine_old]
458 end
459 if predata.engine ~= engine_old then
460 if environment.validengines[predata.engine] and predata.engine ~= environment.basicengines[engine_old] then
461 restart(engine_old,predata.engine)
462 end
463 end
464 end
465 return predata
466end
467
468
469
470local pdfview
471
472local function pdf_open(name,method)
473 statistics.starttiming("pdfview")
474 pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
475 pdfview.setmethod(method)
476 report(pdfview.status())
477 local pdfname = filenewsuffix(name,"pdf")
478 if not lfs.isfile(pdfname) then
479 pdfname = name .. ".pdf"
480 end
481 pdfview.open(pdfname)
482 statistics.stoptiming("pdfview")
483 report("pdfview overhead: %s seconds",statistics.elapsedtime("pdfview"))
484end
485
486local function pdf_close(name,method)
487 statistics.starttiming("pdfview")
488 pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
489 pdfview.setmethod(method)
490 local pdfname = filenewsuffix(name,"pdf")
491 if lfs.isfile(pdfname) then
492 pdfview.close(pdfname)
493 end
494 pdfname = name .. ".pdf"
495 pdfview.close(pdfname)
496 statistics.stoptiming("pdfview")
497end
498
499
500
501local function result_push_purge(oldbase,newbase)
502 for _, suffix in next, usedsuffixes.after do
503 local oldname = fileaddsuffix(oldbase,suffix)
504 local newname = fileaddsuffix(newbase,suffix)
505 removefile(newname)
506 removefile(oldname)
507 end
508end
509
510local function result_push_keep(oldbase,newbase)
511 for _, suffix in next, usedsuffixes.before do
512 local oldname = fileaddsuffix(oldbase,suffix)
513 local newname = fileaddsuffix(newbase,suffix)
514 local tmpname = "keep-"..oldname
515 removefile(tmpname)
516 renamefile(oldname,tmpname)
517 removefile(oldname)
518 renamefile(newname,oldname)
519 end
520end
521
522local function result_save_error(oldbase,newbase)
523 for _, suffix in next, usedsuffixes.keep do
524 local oldname = fileaddsuffix(oldbase,suffix)
525 local newname = fileaddsuffix(newbase,suffix)
526 removefile(newname)
527 renamefile(oldname,newname)
528 end
529end
530
531local function result_save_purge(oldbase,newbase)
532 for _, suffix in next, usedsuffixes.after do
533 local oldname = fileaddsuffix(oldbase,suffix)
534 local newname = fileaddsuffix(newbase,suffix)
535 removefile(newname)
536 renamefile(oldname,newname)
537 end
538end
539
540local function result_save_keep(oldbase,newbase)
541 for _, suffix in next, usedsuffixes.after do
542 local oldname = fileaddsuffix(oldbase,suffix)
543 local newname = fileaddsuffix(newbase,suffix)
544 local tmpname = "keep-"..oldname
545 removefile(newname)
546 renamefile(oldname,newname)
547 renamefile(tmpname,oldname)
548 end
549end
550
551
552
553local plain_formats = {
554 ["plain"] = "plain",
555 ["luatex-plain"] = "luatex-plain",
556}
557
558local function plain_format(plainformat)
559 return plainformat and plain_formats[plainformat]
560end
561
562local function run_plain(plainformat,filename)
563 local plainformat = plain_formats[plainformat]
564 if plainformat then
565 local command = format("mtxrun --script --texformat=%s plain %s",plainformat,filename)
566 report("running command: %s\n\n",command)
567
568 local resultname = filenewsuffix(filename,"pdf")
569 local pdfview = getargument("autopdf") or getargument("closepdf")
570 if pdfview then
571 pdf_close(resultname,pdfview)
572 os.execute(command)
573 pdf_open(resultname,pdfview)
574 else
575 os.execute(command)
576 end
577 end
578end
579
580local function run_texexec(filename,a_purge,a_purgeall)
581 if false then
582
583
584
585
586 else
587 local texexec = resolvers.findfile("texexec.rb") or ""
588 if texexec ~= "" then
589 os.setenv("RUBYOPT","")
590 local options = environment.reconstructcommandline(environment.arguments_after)
591 options = gsub(options,"--purge","")
592 options = gsub(options,"--purgeall","")
593 local command = format("ruby %s %s",texexec,options)
594 report("running command: %s\n\n",command)
595 if a_purge then
596 os.execute(command)
597 scripts.context.purge_job(filename,false,true)
598 elseif a_purgeall then
599 os.execute(command)
600 scripts.context.purge_job(filename,true,true)
601 else
602 os.execute(command)
603 end
604 end
605 end
606end
607
608
609
610local function flags_to_string(flags,prefix)
611
612 local t = { }
613 for k, v in table.sortedhash(flags) do
614 if prefix then
615 k = format("c:%s",k)
616 end
617 if not v or v == "" or v == '""' then
618
619 elseif v == true then
620 t[#t+1] = format('--%s',k)
621 elseif type(v) == "string" then
622 t[#t+1] = format('--%s=%s',k,quote(v))
623 else
624 t[#t+1] = format('--%s=%s',k,tostring(v))
625 end
626 end
627 return concat(t," ")
628end
629
630function scripts.context.run(ctxdata,filename)
631
632 local verbose = false
633
634 local a_nofile = getargument("nofile")
635 local a_engine = getargument("engine")
636
637 local files = environment.filenames or { }
638
639 local filelist, mainfile
640
641 if filename then
642
643 mainfile = filename
644 filelist = { filename }
645
646 elseif a_nofile then
647
648 mainfile = usedfiles.nop
649 filelist = { usedfiles.nop }
650
651 elseif #files > 0 then
652
653 mainfile = usedfiles.yes
654 filelist = files
655 files = { }
656 else
657 return
658 end
659
660 local interface = validstring(getargument("interface")) or "en"
661 local formatname = formatofinterface[interface] or "cont-en"
662 local formatfile,
663 scriptfile = resolvers.locateformat(formatname)
664 if not formatfile or not scriptfile then
665 report("warning: no format found, forcing remake (commandline driven)")
666 scripts.context.make(formatname)
667 formatfile, scriptfile = resolvers.locateformat(formatname)
668 end
669 if formatfile and scriptfile then
670
671 elseif formatname then
672 report("error, no format found with name: %s, aborting",formatname)
673 return
674 else
675 report("error, no format found (provide formatname or interface)")
676 return
677 end
678
679 local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex")
680 local a_purge = getargument("purge")
681 local a_purgeall = getargument("purgeall")
682 local a_purgeresult = getargument("purgeresult")
683 local a_global = getargument("global")
684 local a_runpath = getargument("runpath")
685 local a_timing = getargument("timing")
686 local a_profile = getargument("profile")
687 local a_batchmode = getargument("batchmode")
688 local a_nonstopmode = getargument("nonstopmode")
689 local a_scollmode = getargument("scrollmode")
690 local a_once = getargument("once")
691 local a_backend = getargument("backend")
692 local a_arrange = getargument("arrange")
693 local a_noarrange = getargument("noarrange")
694 local a_jithash = getargument("jithash")
695 local a_permitloadlib = getargument("permitloadlib")
696 local a_texformat = getargument("texformat")
697 local a_keeptuc = getargument("keeptuc")
698 local a_keeplog = getargument("keeplog")
699 local a_keeppdf = getargument("keeppdf")
700 local a_export = getargument("export")
701 local a_nodates = getargument("nodates")
702 local a_trailerid = getargument("trailerid")
703 local a_nocompression = getargument("nocompression")
704
705 a_batchmode = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or (a_scrollmode and "scrollmode") or nil
706
707 for i=1,#filelist do
708
709 local filename = filelist[i]
710
711 if filename == "" then
712 report("warning: bad filename")
713 break
714 end
715
716 local basename = filebasename(filename)
717 local pathname = filepathpart(filename)
718
719 if filesuffix(filename) == "" then
720 filename = fileaddsuffix(filename,"tex")
721 end
722
723 if pathname == "" and not a_global and filename ~= usedfiles.nop then
724 filename = "./" .. filename
725 if not validfile(filename) then
726 report("warning: no (local) file %a, proceeding",filename)
727 end
728 end
729
730 local jobname = removesuffix(basename)
731
732 local ctxname = ctxdata and ctxdata.ctxname
733
734 local analysis = preamble_analyze(filename)
735
736 if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then
737 run_texexec(filename,a_purge,a_purgeall)
738 elseif plain_format(a_texformat or analysis.texformat) then
739 run_plain(a_texformat or analysis.texformat,filename)
740 else
741 if analysis.interface and analysis.interface ~= interface then
742 formatname = formatofinterface[analysis.interface] or formatname
743 formatfile, scriptfile = resolvers.locateformat(formatname)
744 end
745
746 local runpath = a_runpath or analysis.runpath
747 if type(runpath) == "string" and runpath ~= "" then
748 runpath = resolvers.resolve(runpath)
749 local currentdir = dir.current()
750 if not lfs.isdir(runpath) then
751 if dir.makedirs(runpath) then
752 report("runpath %a has been created",runpath)
753 else
754 report("error: runpath %a cannot be created",runpath)
755 os.exit()
756 end
757 end
758 if lfs.chdir(runpath) then
759 report("changing to runpath %a",runpath)
760 else
761 report("error: changing to runpath %a is impossible",runpath)
762 os.exit()
763 end
764 environment.arguments.path = currentdir
765 environment.arguments.runpath = runpath
766 if filepathpart(filename) == "." then
767 filename = filebasename(filename)
768 end
769 end
770
771 a_jithash = validstring(a_jithash or analysis.jithash) or nil
772 a_permitloadlib = a_permitloadlib or analysis.permitloadlib or nil
773
774 if not formatfile or not scriptfile then
775 report("warning: no format found, forcing remake (source driven)")
776 scripts.context.make(formatname,a_engine)
777 formatfile, scriptfile = resolvers.locateformat(formatname)
778 end
779
780 local function combine(key)
781 local flag = validstring(environment[key])
782 local plus = analysis[key]
783 if flag and plus then
784 return plus .. "," .. flag
785 else
786 return flag or plus
787 end
788 end
789
790
791 local directives = combine("directives")
792 local trackers = combine("trackers")
793 local experiments = combine("experiments")
794
795 if formatfile and scriptfile then
796 local suffix = validstring(getargument("suffix"))
797 local resultname = validstring(getargument("result"))
798 if not resultname or resultname == "" then
799 resultname = validstring(analysis.result)
800 end
801 local resultpath = filepathpart(resultname)
802 if resultpath ~= "" then
803 resultname = nil
804 elseif suffix then
805 resultname = removesuffix(jobname) .. suffix
806 end
807 local oldbase = ""
808 local newbase = ""
809 if resultname then
810 oldbase = removesuffix(jobname)
811 newbase = removesuffix(resultname)
812 if oldbase ~= newbase then
813 if a_purgeresult then
814 result_push_purge(oldbase,newbase)
815 else
816 result_push_keep(oldbase,newbase)
817 end
818 else
819 resultname = nil
820 end
821 end
822
823 local pdfview = getargument("autopdf") or getargument("closepdf")
824 if pdfview then
825 pdf_close(filename,pdfview)
826 if resultname then
827 pdf_close(resultname,pdfview)
828 end
829 end
830
831
832
833
834
835
836
837 local okay = statistics.checkfmtstatus(formatfile,a_engine)
838 if okay ~= true then
839 report("warning: %s, forcing remake",tostring(okay))
840 scripts.context.make(formatname)
841 end
842
843 local oldhash = multipass_hashfiles(jobname)
844 local newhash = { }
845 local maxnofruns = once and 1 or multipass_nofruns
846 local fulljobname = validstring(filename)
847
848 local c_flags = {
849 directives = directives,
850 trackers = trackers,
851 experiments = experiments,
852
853 result = validstring(resultname),
854 input = validstring(getargument("input") or filename),
855 fulljobname = fulljobname,
856 files = concat(files,","),
857 ctx = validstring(ctxname),
858 export = a_export and true or nil,
859 nocompression = a_nocompression and true or nil,
860 texmfbinpath = os.selfdir,
861 }
862
863 for k, v in next, environment.arguments do
864
865 if c_flags[k] == nil then
866 c_flags[k] = v
867 end
868 end
869
870
871
872 local usedname = jobname
873 local engine = analysis.engine or "luametatex"
874 if engine == "luametatex" and (mainfile == usedfiles.yes or mainfile == usedfiles.nop) and not getargument("redirected") then
875 mainfile = ""
876 usedname = fulljobname
877 end
878
879
880 local l_flags = {
881 ["interaction"] = a_batchmode,
882
883
884
885
886
887
888
889
890 ["jobname"] = usedname,
891 ["jithash"] = a_jithash,
892 ["permitloadlib"] = a_permitloadlib,
893 }
894
895 local directives = { }
896
897 if a_nodates then
898 directives[#directives+1] = format("backend.date=%s",type(a_nodates) == "string" and a_nodates or "no")
899 end
900
901 if type(a_trailerid) == "string" then
902 directives[#directives+1] = format("backend.trailerid=%s",a_trailerid)
903 end
904
905 if a_profile then
906 directives[#directives+1] = format("system.profile=%s",tonumber(a_profile) or 0)
907 end
908
909 for i=1,#synctex_runfiles do
910 removefile(fileaddsuffix(jobname,synctex_runfiles[i]))
911 end
912
913 if #directives > 0 then
914 c_flags.directives = concat(directives,",")
915 end
916
917
918
919
920
921 multipass_copypdffile(jobname,a_keeppdf or analysis.keeppdf)
922
923 for currentrun=1,maxnofruns do
924
925 c_flags.final = false
926 c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2
927 c_flags.maxnofruns = maxnofruns
928 c_flags.forcedruns = multipass_forcedruns and multipass_forcedruns > 0 and multipass_forcedruns or nil
929 c_flags.currentrun = currentrun
930 c_flags.noarrange = a_noarrange or a_arrange or nil
931 c_flags.profile = a_profile and (tonumber(a_profile) or 0) or nil
932
933 print("")
934
935 local returncode = environment.run_format(
936 formatfile,
937 scriptfile,
938 mainfile,
939 flags_to_string(l_flags),
940 flags_to_string(c_flags,true),
941 verbose
942 )
943
944 if not returncode then
945 report("fatal error: no return code")
946 if resultname then
947 result_save_error(oldbase,newbase)
948 end
949 os.exit(1)
950 break
951 elseif returncode == 0 then
952 multipass_copyluafile(jobname,a_keeptuc and currentrun)
953 multipass_copylogfile(jobname,a_keeplog and currentrun)
954 if not multipass_forcedruns then
955 newhash = multipass_hashfiles(jobname)
956 if multipass_changed(oldhash,newhash) then
957 oldhash = newhash
958 else
959 break
960 end
961 elseif currentrun == multipass_forcedruns then
962 report("quitting after force %i runs",multipass_forcedruns)
963 break
964 end
965 else
966 report("fatal error: return code: %s",returncode or "?")
967 if resultname then
968 result_save_error(oldbase,newbase)
969 end
970 os.exit(1)
971 break
972 end
973
974 end
975
976 if environment.arguments["ansilog"] then
977 local logfile = filenewsuffix(jobname,"log")
978 local logdata = io.loaddata(logfile) or ""
979 if logdata ~= "" then
980 io.savedata(logfile,(gsub(logdata,"%[.-m","")))
981 end
982 end
983
984
985
986
987 local syncctx = fileaddsuffix(jobname,"syncctx")
988 if validfile(syncctx) then
989 renamefile(syncctx,fileaddsuffix(jobname,"synctex"))
990 end
991
992 if a_arrange then
993
994 c_flags.final = true
995 c_flags.kindofrun = 3
996 c_flags.currentrun = c_flags.currentrun + 1
997 c_flags.noarrange = nil
998
999 report("arrange run: %s",command)
1000
1001 local returncode = environment.run_format(
1002 formatfile,
1003 scriptfile,
1004 mainfile,
1005 flags_to_string(l_flags),
1006 flags_to_string(c_flags,true),
1007 verbose
1008 )
1009
1010 if not returncode then
1011 report("fatal error: no return code, message: %s",errorstring or "?")
1012 os.exit(1)
1013 elseif returncode > 0 then
1014 report("fatal error: return code: %s",returncode or "?")
1015 os.exit(returncode)
1016 end
1017
1018 end
1019
1020 if a_purge then
1021 scripts.context.purge_job(jobname,false,false,fulljobname)
1022 elseif a_purgeall then
1023 scripts.context.purge_job(jobname,true,false,fulljobname)
1024 end
1025
1026 if resultname then
1027 if a_purgeresult then
1028
1029
1030 result_save_purge(oldbase,newbase)
1031 else
1032 result_save_keep(oldbase,newbase)
1033 end
1034 report("result renamed to: %s",newbase)
1035 elseif resultpath ~= "" then
1036 report()
1037 report("results are to be on the running path, not on %a, ignoring --result",resultpath)
1038 report()
1039 end
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049 local pdfview = getargument("autopdf")
1050 if pdfview then
1051 pdf_open(resultname or jobname,pdfview)
1052 end
1053
1054 local epub = analysis.epub
1055 if epub then
1056 if type(epub) == "string" then
1057 local t = settings_to_array(epub)
1058 for i=1,#t do
1059 t[i] = "--" .. gsub(t[i],"^%-*","")
1060 end
1061 epub = concat(t," ")
1062 else
1063 epub = "--make"
1064 end
1065 local command = "mtxrun --script epub " .. epub .. " " .. jobname
1066 report()
1067 report("making epub file: ",command)
1068 report()
1069 os.execute(command)
1070 end
1071
1072 if a_timing then
1073 report()
1074 report("you can process (timing) statistics with:",jobname)
1075 report()
1076 report("context --extra=timing '%s'",jobname)
1077
1078 report()
1079 end
1080 else
1081 if formatname then
1082 report("error, no format found with name: %s, skipping",formatname)
1083 else
1084 report("error, no format found (provide formatname or interface)")
1085 end
1086 break
1087 end
1088 end
1089 end
1090
1091end
1092
1093function scripts.context.pipe()
1094
1095
1096 local interface = getargument("interface")
1097 interface = (type(interface) == "string" and interface) or "en"
1098 local formatname = formatofinterface[interface] or "cont-en"
1099 local formatfile, scriptfile = resolvers.locateformat(formatname)
1100 if not formatfile or not scriptfile then
1101 report("warning: no format found, forcing remake (commandline driven)")
1102 scripts.context.make(formatname)
1103 formatfile, scriptfile = resolvers.locateformat(formatname)
1104 end
1105 if formatfile and scriptfile then
1106 local okay = statistics.checkfmtstatus(formatfile)
1107 if okay ~= true then
1108 report("warning: %s, forcing remake",tostring(okay))
1109 scripts.context.make(formatname)
1110 end
1111 local l_flags = {
1112 interaction = "scrollmode",
1113 fmt = formatfile,
1114 lua = scriptfile,
1115 }
1116 local c_flags = {
1117 backend = "pdf",
1118 final = false,
1119 kindofrun = 3,
1120 currentrun = 1,
1121 }
1122 local filename = getargument("dummyfile") or ""
1123 if filename == "" then
1124 filename = "\\relax"
1125 report("entering scrollmode, end job with \\end")
1126 else
1127 filename = fileaddsuffix(filename,"tmp")
1128 io.savedata(filename,"\\relax")
1129 report("entering scrollmode using '%s' with optionfile, end job with \\end",filename)
1130 end
1131 local returncode = environment.run_format(
1132 formatfile,
1133 scriptfile,
1134 filename,
1135 flags_to_string(l_flags),
1136 flags_to_string(c_flags,true),
1137 verbose
1138 )
1139 if getargument("purge") then
1140 scripts.context.purge_job(filename)
1141 elseif getargument("purgeall") then
1142 scripts.context.purge_job(filename,true)
1143 removefile(filename)
1144 end
1145 elseif formatname then
1146 report("error, no format found with name: %s, aborting",formatname)
1147 else
1148 report("error, no format found (provide formatname or interface)")
1149 end
1150end
1151
1152local function make_mkiv_format(name,engine)
1153 environment.make_format(name)
1154end
1155
1156local make_mkii_format
1157
1158do
1159
1160 local function mktexlsr()
1161 if environment.arguments.silent then
1162 local result = os.execute("mktexlsr --quiet > temp.log")
1163 if result ~= 0 then
1164 print("mktexlsr silent run > fatal error")
1165 else
1166 print("mktexlsr silent run")
1167 end
1168 removefile("temp.log")
1169 else
1170 report("running mktexlsr")
1171 os.execute("mktexlsr")
1172 end
1173 end
1174
1175 local function engine(texengine,texformat)
1176 local command = string.format('%s --ini --etex --8bit %s \\dump',texengine,fileaddsuffix(texformat,"mkii"))
1177 if environment.arguments.silent then
1178 statistics.starttiming()
1179 local command = format("%s > temp.log",command)
1180 local result = os.execute(command)
1181 local runtime = statistics.stoptiming()
1182 if result ~= 0 then
1183 print(format("%s silent make > fatal error when making format %q",texengine,texformat))
1184 else
1185 print(format("%s silent make > format %q made in %.3f seconds",texengine,texformat,runtime))
1186 end
1187 removefile("temp.log")
1188 else
1189 report("running command: %s",command)
1190 os.execute(command)
1191 end
1192 end
1193
1194 local function resultof(...)
1195 local command = string.format(...)
1196 report("running command %a",command)
1197 return string.strip(os.resultof(command) or "")
1198 end
1199
1200 local function make(texengine,texformat)
1201 report("generating kpse file database")
1202 mktexlsr()
1203 local fmtpathspec = resultof("kpsewhich --var-value=TEXFORMATS --engine=%s",texengine)
1204 if fmtpathspec ~= "" then
1205 report("using path specification %a",fmtpathspec)
1206 fmtpathspec = resultof('kpsewhich -expand-braces="%s"',fmtpathspec)
1207 end
1208 if fmtpathspec ~= "" then
1209 report("using path expansion %a",fmtpathspec)
1210 else
1211 report("no valid path reported, trying alternative")
1212 fmtpathspec = resultof("kpsewhich --show-path=fmt --engine=%s",texengine)
1213 if fmtpathspec ~= "" then
1214 report("using path expansion %a",fmtpathspec)
1215 else
1216 report("no valid path reported, falling back to current path")
1217 fmtpathspec = "."
1218 end
1219 end
1220 fmtpathspec = string.splitlines(fmtpathspec)[1] or fmtpathspec
1221 fmtpathspec = fmtpathspec and file.splitpath(fmtpathspec)
1222 local fmtpath = nil
1223 if fmtpathspec then
1224 for i=1,#fmtpathspec do
1225 local path = fmtpathspec[i]
1226 if path ~= "." then
1227 dir.makedirs(path)
1228 if lfs.isdir(path) and file.is_writable(path) then
1229 fmtpath = path
1230 break
1231 end
1232 end
1233 end
1234 end
1235 if not fmtpath or fmtpath == "" then
1236 fmtpath = "."
1237 else
1238 lfs.chdir(fmtpath)
1239 end
1240 engine(texengine,texformat)
1241 report("generating kpse file database")
1242 mktexlsr()
1243 report("format %a saved on path %a",texformat,fmtpath)
1244 end
1245
1246 local function run(texengine,texformat,filename)
1247 local t = { }
1248 for k, v in next, environment.arguments do
1249 t[#t+1] = string.format("--mtx:%s=%s",k,v)
1250 end
1251 execute('%s --fmt=%s %s "%s"',texengine,removesuffix(texformat),table.concat(t," "),filename)
1252 end
1253
1254 make_mkii_format = function(name,engine)
1255
1256
1257
1258 os.setenv('SELFAUTOPARENT', "")
1259 os.setenv('SELFAUTODIR', "")
1260 os.setenv('SELFAUTOLOC', "")
1261 os.setenv('TEXROOT', "")
1262 os.setenv('TEXOS', "")
1263 os.setenv('TEXMFOS', "")
1264 os.setenv('TEXMFCNF', "")
1265
1266 make(engine,name)
1267 end
1268
1269end
1270
1271function scripts.context.generate()
1272 resolvers.renewcache()
1273 trackers.enable("resolvers.locating")
1274 resolvers.load()
1275end
1276
1277function scripts.context.make(name)
1278 if not getargument("fast") then
1279 scripts.context.generate()
1280 end
1281 local list = (name and { name }) or (environment.filenames[1] and environment.filenames) or defaultformats
1282 local engine = getargument("engine") or (status and status.luatex_engine) or "luatex"
1283 if getargument("jit") then
1284 engine = "luajittex"
1285 end
1286 for i=1,#list do
1287 local name = list[i]
1288 name = formatofinterface[name] or name or ""
1289 if name == "" then
1290
1291 elseif engine == "luametatex" or engine == "luatex" or engine == "luajittex" then
1292 make_mkiv_format(name,engine)
1293 elseif engine == "pdftex" or engine == "xetex" then
1294 make_mkii_format(name,engine)
1295 end
1296 end
1297end
1298
1299function scripts.context.ctx()
1300 local ctxdata = ctxrunner.new()
1301 ctxdata.jobname = environment.filenames[1]
1302 ctxrunner.checkfile(ctxdata,getargument("ctx"))
1303 ctxrunner.checkflags(ctxdata)
1304 scripts.context.run(ctxdata)
1305end
1306
1307function scripts.context.autoctx()
1308 local ctxdata = nil
1309 local files = environment.filenames
1310 local firstfile = #files > 0 and files[1]
1311 if firstfile then
1312 local suffix = filesuffix(firstfile)
1313 local ctxname = nil
1314 if suffix == "xml" then
1315 local chunk = io.loadchunk(firstfile)
1316 if chunk then
1317 ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
1318 end
1319 elseif suffix == "tex" or suffix == "mkiv" or suffix == "mkxl" then
1320 local analysis = preamble_analyze(firstfile)
1321 ctxname = analysis.ctxfile or analysis.ctx
1322 end
1323 if ctxname then
1324 ctxdata = ctxrunner.new()
1325 ctxdata.jobname = firstfile
1326 ctxrunner.checkfile(ctxdata,ctxname)
1327 ctxrunner.checkflags(ctxdata)
1328 end
1329 end
1330 scripts.context.run(ctxdata)
1331end
1332
1333function scripts.context.version()
1334 local list = { "context.mkiv", "context.mkxl" }
1335 for i=1,#list do
1336 local base = list[i]
1337 local name = resolvers.findfile(base)
1338 if name ~= "" then
1339 report("main context file: %s",name)
1340 local data = io.loaddata(name)
1341 if data then
1342 local version = match(data,"\\edef\\contextversion{(.-)}")
1343 if version then
1344 report("current version: %s",version)
1345 else
1346 report("context version: unknown, no timestamp found")
1347 end
1348 else
1349 report("context version: unknown, load error")
1350 end
1351 else
1352 report("main context file: unknown, %a not found",base)
1353 end
1354 end
1355end
1356
1357function scripts.context.purge_job(jobname,all,mkiitoo,fulljobname)
1358 if jobname and jobname ~= "" then
1359 jobname = filebasename(jobname)
1360 local filebase = removesuffix(jobname)
1361 if mkiitoo then
1362 scripts.context.purge(all,filebase,true)
1363 else
1364 local deleted = { }
1365 for i=1,#obsolete_results do
1366 deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,obsolete_results[i]),fileaddsuffix(filebase,"pdf"))
1367 end
1368 for i=1,#temporary_runfiles do
1369 deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,temporary_runfiles[i]))
1370 end
1371 if fulljobname and fulljobname ~= jobname then
1372 for i=1,#temporary_suffixes do
1373 deleted[#deleted+1] = purge_file(fileaddsuffix(fulljobname,temporary_suffixes[i],true))
1374 end
1375 end
1376 if all then
1377 for i=1,#persistent_runfiles do
1378 deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,persistent_runfiles[i]))
1379 end
1380 end
1381 if #deleted > 0 then
1382 report("purged files: %s", concat(deleted,", "))
1383 end
1384 end
1385 end
1386end
1387
1388function scripts.context.purge(all,pattern,mkiitoo)
1389 local all = all or getargument("all")
1390 local pattern = getargument("pattern") or (pattern and (pattern.."*")) or "*.*"
1391 local files = dir.glob(pattern)
1392 local obsolete = tohash(obsolete_results)
1393 local temporary = tohash(temporary_runfiles)
1394 local synctex = tohash(synctex_runfiles)
1395 local persistent = tohash(persistent_runfiles)
1396 local generic = tohash(generic_files)
1397 local deleted = { }
1398 for i=1,#files do
1399 local name = files[i]
1400 local suffix = filesuffix(name)
1401 local basename = filebasename(name)
1402 if obsolete[suffix] or temporary[suffix] or synctex[suffix] or persistent[suffix] or generic[basename] then
1403 deleted[#deleted+1] = purge_file(name)
1404 elseif mkiitoo then
1405 for i=1,#special_runfiles do
1406 if find(name,special_runfiles[i]) then
1407 deleted[#deleted+1] = purge_file(name)
1408 end
1409 end
1410 end
1411 for i=1,#extra_runfiles do
1412 if find(basename,extra_runfiles[i]) then
1413 deleted[#deleted+1] = purge_file(name)
1414 end
1415 end
1416 end
1417 if #deleted > 0 then
1418 report("purged files: %s", concat(deleted,", "))
1419 end
1420end
1421
1422
1423
1424local newversion = false
1425
1426local function touch(path,name,versionpattern,kind,kindpattern)
1427 if path and path ~= "" then
1428 name = filejoinname(path,name)
1429 else
1430 name = resolvers.findfile(name)
1431 end
1432 local olddata = io.loaddata(name)
1433 if olddata then
1434 local oldkind = ""
1435 local newkind = kind or ""
1436 local oldversion = ""
1437 local newdata
1438 newversion = newversion or os.date("%Y.%m.%d %H:%M")
1439 if versionpattern then
1440 newdata = gsub(olddata,versionpattern,function(pre,mid,post)
1441 oldversion = mid
1442 return pre .. newversion .. post
1443 end) or olddata
1444 end
1445 if kind and kindpattern then
1446 newdata = gsub(newdata,kindpattern,function(pre,mid,post)
1447 oldkind = mid
1448 return pre .. newkind .. post
1449 end) or newdata
1450 end
1451 if newdata ~= "" and (oldversion ~= newversion or oldkind ~= newkind or newdata ~= olddata) then
1452 local backup = filenewsuffix(name,"tmp")
1453 removefile(backup)
1454 renamefile(name,backup)
1455 io.savedata(name,newdata)
1456 return name, oldversion, newversion, oldkind, newkind
1457 end
1458 end
1459end
1460
1461local p_contextkind = "(\\edef\\contextkind%s*{)(.-)(})"
1462local p_contextversion = "(\\edef\\contextversion%s*{)(.-)(})"
1463local p_newcontextversion = "(\\newcontextversion%s*{)(.-)(})"
1464
1465local function touchfiles(suffix,kind,path)
1466 local foundname, oldversion, newversion, oldkind, newkind = touch(path,fileaddsuffix("context",suffix),p_contextversion,kind,p_contextkind)
1467 if foundname then
1468 report("old version : %s (%s)",oldversion,oldkind)
1469 report("new version : %s (%s)",newversion,newkind)
1470 report("touched file : %s",foundname)
1471 local foundname = touch(path,fileaddsuffix("cont-new",suffix),p_newcontextversion)
1472 if foundname then
1473 report("touched file : %s", foundname)
1474 end
1475 else
1476 report("nothing touched")
1477 end
1478end
1479
1480local tobetouched = tohash { "mkii", "mkiv", "mkvi", "mkxl", "mklx" }
1481
1482function scripts.context.touch()
1483 if getargument("expert") then
1484 local touch = getargument("touch")
1485 local kind = getargument("kind")
1486 local path = getargument("basepath")
1487 if tobetouched[touch] then
1488 touchfiles(touch,kind,path)
1489 else
1490 for touch in sortedhash(tobetouched) do
1491 touchfiles(touch,kind,path)
1492 end
1493 end
1494 else
1495 report("touching needs --expert")
1496 end
1497end
1498
1499function scripts.context.pages()
1500 local filename = environment.files[1]
1501 if filename then
1502 local u = table.load(fileaddsuffix(filename,"tuc"))
1503 if u then
1504 local p = u.structures.pages.collected
1505 local l = u.structures.lists.collected
1506 local page = environment.arguments.page
1507 local list = environment.arguments.list
1508 if type(page) == "string" then
1509 page = settings_to_array(page)
1510 end
1511 if type(list) == "string" then
1512 list = settings_to_array(list)
1513 end
1514 if page or list then
1515 if page then
1516 for i=1,#page do
1517 page[i] = string.topattern(page[i])
1518 end
1519 for i=1,#p do
1520 local pi = p[i]
1521 local m = pi.marked
1522 if m then
1523 local ml = #m
1524 for j=1,#page do
1525 local n = page[j]
1526 for k=1,ml do
1527 if find(m[k],n) then
1528 report("page : %04i %s",i,m[k])
1529 end
1530 end
1531 end
1532 end
1533 end
1534 end
1535 if list then
1536 for i=1,#list do
1537 list[i] = string.topattern(list[i])
1538 end
1539 for i=1,#l do
1540 local li = l[i]
1541 local r = li.references
1542 if r then
1543 local rr = r.reference
1544 if rr then
1545 rr = splitstring(rr,",")
1546 local rrl = #rr
1547 for j=1,#list do
1548 local n = list[j]
1549 for k=1,rrl do
1550 if find(rr[k],n) then
1551 report("list : %04i %s",r.realpage,rr[k])
1552 end
1553 end
1554 end
1555 end
1556 end
1557 end
1558 end
1559 else
1560 for i=1,#p do
1561 local pi = p[i]
1562 local m = pi.marked
1563 if m then
1564 report("page : %04i % t",i,m)
1565 end
1566 end
1567 end
1568 end
1569 end
1570end
1571
1572
1573
1574local labels = { "title", "comment", "status" }
1575local cards = { "*.mkiv", "*.mkvi", "*.mkix", "*.mkxi", "*.mkxl", "*.mklx", "*.tex" }
1576local valid = tohash { "mkiv", "mkvi", "mkix", "mkxi", "mkxl", "mklx", "tex" }
1577
1578function scripts.context.modules(pattern)
1579 local list = { }
1580 local found = resolvers.findfile("context.mkiv")
1581 if not pattern or pattern == "" then
1582
1583 for i=1,#cards do
1584 resolvers.findwildcardfiles(cards[i],list)
1585 end
1586
1587 for i=1,#cards do
1588 dir.glob(filejoinname(filepathpart(found),cards[i]),list)
1589 end
1590 else
1591 resolvers.findwildcardfiles(pattern,list)
1592 dir.glob(filejoinname(filepathpart(found,pattern)),list)
1593 end
1594 local done = { }
1595 local none = { x = { }, m = { }, s = { }, t = { } }
1596 for i=1,#list do
1597 local v = list[i]
1598 local base = filebasename(v)
1599 if not done[base] then
1600 done[base] = true
1601 local suffix = filesuffix(base)
1602 if valid[suffix] then
1603 local prefix, rest = match(base,"^([xmst])%-(.*)")
1604 if prefix then
1605 v = resolvers.findfile(base)
1606 local data = io.loaddata(v) or ""
1607 data = match(data,"%% begin info(.-)%% end info")
1608 if data then
1609 local info = { }
1610 for label, text in gmatch(data,"%% +([^ ]+) *: *(.-)[\n\r]") do
1611 info[label] = text
1612 end
1613 report()
1614 report("%-7s : %s","module",base)
1615 report()
1616 for i=1,#labels do
1617 local l = labels[i]
1618 if info[l] then
1619 report("%-7s : %s",l,info[l])
1620 end
1621 end
1622 report()
1623 else
1624 insert(none[prefix],rest)
1625 end
1626 end
1627 end
1628 end
1629 end
1630
1631 local function show(k,v)
1632 sort(v)
1633 if #v > 0 then
1634 report()
1635 for i=1,#v do
1636 report("%s : %s",k,v[i])
1637 end
1638 end
1639 end
1640 for k, v in sortedhash(none) do
1641 show(k,v)
1642 end
1643end
1644
1645
1646
1647function scripts.context.extras(pattern)
1648
1649 if type(pattern) ~= "string" then
1650 pattern = "*"
1651 end
1652 local found = resolvers.findfile("context.mkiv")
1653 if found ~= "" then
1654 pattern = filejoinname(dir.expandname(filepathpart(found)),format("mtx-context-%s.tex",pattern or "*"))
1655 local list = dir.glob(pattern)
1656 for i=1,#list do
1657 local v = list[i]
1658 local data = io.loaddata(v) or ""
1659 data = match(data,"%% begin help(.-)%% end help")
1660 if data then
1661 report()
1662 report("extra: %s (%s)",(gsub(v,"^.*mtx%-context%-(.-)%.tex$","%1")),v)
1663 for s in gmatch(data,"%% *(.-)[\n\r]") do
1664 report(s)
1665 end
1666 report()
1667 end
1668 end
1669 end
1670end
1671
1672function scripts.context.extra()
1673 local extra = getargument("extra")
1674 if type(extra) ~= "string" then
1675 scripts.context.extras()
1676 elseif getargument("help") then
1677 scripts.context.extras(extra)
1678 else
1679 local fullextra = extra
1680 if not find(fullextra,"mtx%-context%-") then
1681 fullextra = "mtx-context-" .. extra
1682 end
1683 local foundextra = resolvers.findfile(fullextra)
1684 if foundextra == "" then
1685 scripts.context.extras()
1686 return
1687 else
1688 report("processing extra: %s", foundextra)
1689 end
1690 setargument("purgeall",true)
1691 local result = getargument("result") or ""
1692 if result == "" then
1693 setargument("result","context-extra")
1694 end
1695 scripts.context.run(nil,foundextra)
1696 end
1697end
1698
1699
1700
1701local function showsetter()
1702 environment.files = { resolvers.findfile("mtx-context-setters.tex") }
1703 multipass_nofruns = 1
1704 setargument("purgeall",true)
1705 scripts.context.run()
1706end
1707
1708scripts.context.trackers = showsetter
1709scripts.context.directives = showsetter
1710scripts.context.experiments = showsetter
1711
1712function scripts.context.logcategories()
1713 environment.files = { resolvers.findfile("m-logcategories.mkiv") }
1714 multipass_nofruns = 1
1715 setargument("purgeall",true)
1716 scripts.context.run()
1717end
1718
1719function scripts.context.timed(action)
1720 statistics.timed(action,true)
1721end
1722
1723
1724
1725if getargument("pdftex") then
1726 setargument("engine","pdftex")
1727elseif getargument("xetex") then
1728 setargument("engine","xetex")
1729end
1730
1731if getargument("timedlog") then
1732 logs.settimedlog()
1733end
1734
1735if getargument("nostats") then
1736 setargument("nostatistics",true)
1737 setargument("nostat",nil)
1738end
1739
1740if getargument("batch") then
1741 setargument("batchmode",true)
1742 setargument("batch",nil)
1743end
1744
1745if getargument("nonstop") then
1746 setargument("nonstopmode",true)
1747 setargument("nonstop",nil)
1748end
1749
1750do
1751
1752 local htmlerrorpage = getargument("htmlerrorpage")
1753 if htmlerrorpage == "scite" then
1754 directives.enable("system.showerror=scite")
1755 elseif htmlerrorpage then
1756 directives.enable("system.showerror")
1757 end
1758
1759end
1760
1761do
1762
1763 local silent = getargument("silent")
1764 if type(silent) == "string" then
1765 directives.enable(format("logs.blocked={%s}",silent))
1766 elseif silent then
1767 directives.enable("logs.blocked")
1768 end
1769
1770 local errors = getargument("errors")
1771 if type(errors) == "errors" then
1772 directives.enable(format("logs.errors={%s}",silent))
1773 elseif errors then
1774 directives.enable("logs.errors")
1775 end
1776
1777end
1778
1779if getargument("once") then
1780 multipass_nofruns = 1
1781else
1782 if getargument("runs") then
1783 multipass_nofruns = tonumber(getargument("runs")) or nil
1784 end
1785 multipass_forcedruns = tonumber(getargument("forcedruns")) or nil
1786end
1787
1788if getargument("run") then
1789 scripts.context.timed(scripts.context.autoctx)
1790elseif getargument("make") then
1791 scripts.context.timed(function() scripts.context.make() end)
1792elseif getargument("generate") then
1793 scripts.context.timed(function() scripts.context.generate() end)
1794elseif getargument("ctx") and not getargument("noctx") then
1795 scripts.context.timed(scripts.context.ctx)
1796elseif getargument("version") then
1797 application.identify()
1798 scripts.context.version()
1799elseif getargument("touch") then
1800 scripts.context.touch()
1801elseif getargument("pages") then
1802 scripts.context.pages()
1803elseif getargument("expert") then
1804 application.help("expert", "special")
1805elseif getargument("showmodules") or getargument("modules") then
1806 scripts.context.modules()
1807elseif getargument("showextras") or getargument("extras") then
1808 scripts.context.extras(environment.filenames[1] or getargument("extras"))
1809elseif getargument("extra") then
1810 scripts.context.extra()
1811elseif getargument("exporthelp") then
1812
1813 application.export()
1814elseif getargument("help") then
1815 if environment.filenames[1] == "extras" then
1816 scripts.context.extras()
1817 else
1818 application.help("basic")
1819 end
1820elseif getargument("showtrackers") or getargument("trackers") == true then
1821 scripts.context.trackers()
1822elseif getargument("showdirectives") or getargument("directives") == true then
1823 scripts.context.directives()
1824elseif getargument("showlogcategories") then
1825 scripts.context.logcategories()
1826elseif environment.filenames[1] or getargument("nofile") then
1827 scripts.context.timed(scripts.context.autoctx)
1828elseif getargument("pipe") then
1829 scripts.context.timed(scripts.context.pipe)
1830elseif getargument("purge") then
1831
1832 scripts.context.purge()
1833elseif getargument("purgeall") then
1834
1835 scripts.context.purge(true,nil,true)
1836elseif getargument("pattern") then
1837 environment.filenames = dir.glob(getargument("pattern"))
1838 scripts.context.timed(scripts.context.autoctx)
1839else
1840 application.help("basic")
1841end
1842
1843
1844
1845do
1846
1847 if getargument("wipebusy") then
1848 removefile("context-is-busy.tmp")
1849 end
1850
1851end
1852 |