diff options
Diffstat (limited to 'Master/texmf-dist/scripts/context/lua/mtx-context.lua')
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-context.lua | 272 |
1 files changed, 167 insertions, 105 deletions
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.lua b/Master/texmf-dist/scripts/context/lua/mtx-context.lua index 87ed3475d0f..b53110bb1a4 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-context.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-context.lua @@ -17,8 +17,17 @@ local settings_to_array = utilities.parsers.settings_to_array local appendtable = table.append local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P -local getargument = environment.getargument or environment.argument -local setargument = environment.setargument +local getargument = environment.getargument or environment.argument +local setargument = environment.setargument + +local filejoinname = file.join +local filebasename = file.basename +local filepathpart = file.pathpart +local filesuffix = file.suffix +local fileaddsuffix = file.addsuffix +local filenewsuffix = file.replacesuffix +local removesuffix = file.removesuffix +local validfile = lfs.isfile local application = logs.application { name = "mtx-context", @@ -78,14 +87,17 @@ scripts.context = scripts.context or { } -- for the moment here -if getargument("jit") or getargument("jiton") then +if jit then -- already luajittex + setargument("engine","luajittex") + setargument("jit",nil) +elseif getargument("jit") or getargument("jiton") then -- relaunch luajittex -- bonus shortcut, we assume than --jit also indicates the engine -- although --jit and --engine=luajittex are independent setargument("engine","luajittex") end -local engine_new = getargument("engine") or directives.value("system.engine") -local engine_old = environment.ownbin +local engine_new = file.nameonly(getargument("engine") or directives.value("system.engine")) +local engine_old = file.nameonly(environment.ownbin) local function restart(engine_old,engine_new) local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline()) @@ -162,14 +174,14 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname) return end - ctxdata.ctxname = ctxname or file.removesuffix(ctxdata.jobname) or "" + ctxdata.ctxname = ctxname or removesuffix(ctxdata.jobname) or "" if ctxdata.ctxname == "" then return end - ctxdata.jobname = file.addsuffix(ctxdata.jobname,'tex') - ctxdata.ctxname = file.addsuffix(ctxdata.ctxname,'ctx') + ctxdata.jobname = fileaddsuffix(ctxdata.jobname,'tex') + ctxdata.ctxname = fileaddsuffix(ctxdata.ctxname,'ctx') report("jobname: %s",ctxdata.jobname) report("ctxname: %s",ctxdata.ctxname) @@ -177,14 +189,14 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname) -- mtxrun should resolve kpse: and file: local usedname = ctxdata.ctxname - local found = lfs.isfile(usedname) + local found = validfile(usedname) -- no further test if qualified path if not found then for _, path in next, ctx_locations do - local fullname = file.join(path,ctxdata.ctxname) - if lfs.isfile(fullname) then + local fullname = filejoinname(path,ctxdata.ctxname) + if validfile(fullname) then usedname = fullname found = true break @@ -197,7 +209,7 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname) found = usedname ~= "" end - if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then + if not found and defaultname and defaultname ~= "" and validfile(defaultname) then usedname = defaultname found = true end @@ -214,7 +226,7 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname) -- test for valid, can be text file end - local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations) + local ctxpaths = table.append({'.', filepathpart(ctxdata.ctxname)}, ctx_locations) xml.include(xmldata,'ctx:include','name', ctxpaths) @@ -244,8 +256,9 @@ end -- multipass control -local multipass_suffixes = { ".tuc" } -local multipass_nofruns = 8 -- or 7 to test oscillation +local multipass_suffixes = { ".tuc" } +local multipass_nofruns = 8 -- or 7 to test oscillation +local multipass_forcedruns = false local function multipass_hashfiles(jobname) local hash = { } @@ -268,7 +281,7 @@ end local function multipass_copyluafile(jobname) local tuaname, tucname = jobname..".tua", jobname..".tuc" - if lfs.isfile(tuaname) then + if validfile(tuaname) then os.remove(tucname) os.rename(tuaname,tucname) end @@ -278,32 +291,38 @@ end local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1) +local prefile = nil +local predata = nil + local function preamble_analyze(filename) -- only files on current path - local t = { } - local line = io.loadlines(file.addsuffix(filename,"tex")) + filename = fileaddsuffix(filename,"tex") -- to be sure + if predata and prefile == filename then + return predata + end + prefile = filename + predata = { } + local line = io.loadlines(prefile) if line then local preamble = lpegmatch(pattern,line) if preamble then - for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do - t[key] = value - end - t.type = "tex" + utilities.parsers.options_to_hash(preamble,predata) + predata.type = "tex" elseif find(line,"^<?xml ") then - t.type = "xml" + predata.type = "xml" end - if t.nofruns then - multipass_nofruns = t.nofruns + if predata.nofruns then + multipass_nofruns = predata.nofruns end - if not t.engine then - t.engine = environment.basicengines[engine_old] --'luatex' + if not predata.engine then + predata.engine = environment.basicengines[engine_old] --'luatex' end - if t.engine ~= engine_old then -- hack - if environment.validengines[t.engine] and t.engine ~= environment.basicengines[engine_old] then - restart(engine_old,t.engine) + if predata.engine ~= engine_old then -- hack + if environment.validengines[predata.engine] and predata.engine ~= environment.basicengines[engine_old] then + restart(engine_old,predata.engine) end end end - return t + return predata end -- automatically opening and closing pdf files @@ -314,21 +333,21 @@ local function pdf_open(name,method) pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex")) pdfview.setmethod(method) report(pdfview.status()) - pdfview.open(file.replacesuffix(name,"pdf")) + pdfview.open(filenewsuffix(name,"pdf")) end local function pdf_close(name,method) pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex")) pdfview.setmethod(method) - pdfview.close(file.replacesuffix(name,"pdf")) + pdfview.close(filenewsuffix(name,"pdf")) end -- result file handling local function result_push_purge(oldbase,newbase) for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) + local oldname = fileaddsuffix(oldbase,suffix) + local newname = fileaddsuffix(newbase,suffix) os.remove(newname) os.remove(oldname) end @@ -336,8 +355,8 @@ end local function result_push_keep(oldbase,newbase) for _, suffix in next, usedsuffixes.before do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) + local oldname = fileaddsuffix(oldbase,suffix) + local newname = fileaddsuffix(newbase,suffix) local tmpname = "keep-"..oldname os.remove(tmpname) os.rename(oldname,tmpname) @@ -348,8 +367,8 @@ end local function result_save_error(oldbase,newbase) for _, suffix in next, usedsuffixes.keep do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) + local oldname = fileaddsuffix(oldbase,suffix) + local newname = fileaddsuffix(newbase,suffix) os.remove(newname) -- to be sure os.rename(oldname,newname) end @@ -357,8 +376,8 @@ end local function result_save_purge(oldbase,newbase) for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) + local oldname = fileaddsuffix(oldbase,suffix) + local newname = fileaddsuffix(newbase,suffix) os.remove(newname) -- to be sure os.rename(oldname,newname) end @@ -366,8 +385,8 @@ end local function result_save_keep(oldbase,newbase) for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) + local oldname = fileaddsuffix(oldbase,suffix) + local newname = fileaddsuffix(newbase,suffix) local tmpname = "keep-"..oldname os.remove(newname) os.rename(oldname,newname) @@ -420,7 +439,7 @@ local function run_plain(plainformat,filename) local command = format("mtxrun --script --texformat=%s plain %s",plainformat,filename) report("running command: %s\n\n",command) -- todo: load and run - local resultname = file.replacesuffix(filename,"pdf") + local resultname = filenewsuffix(filename,"pdf") local pdfview = getargument("autopdf") or getargument("closepdf") if pdfview then pdf_close(resultname,pdfview) @@ -462,6 +481,10 @@ end -- +local function check_synctex(a_synctex) + return a_synctex and (tonumber(a_synctex) or (toboolean(a_synctex,true) and 1) or (a_synctex == "zipped" and 1) or (a_synctex == "unzipped" and -1)) or nil +end + function scripts.context.run(ctxdata,filename) -- local a_nofile = getargument("nofile") @@ -523,30 +546,33 @@ function scripts.context.run(ctxdata,filename) local a_arrange = getargument("arrange") local a_noarrange = getargument("noarrange") local a_jiton = getargument("jiton") + local a_jithash = getargument("jithash") local a_texformat = getargument("texformat") -- a_batchmode = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil - a_synctex = tonumber(a_synctex) or (toboolean(a_synctex,true) and 1) or (a_synctex == "zipped" and 1) or (a_synctex == "unzipped" and -1) or nil + a_synctex = check_synctex(a_synctex) -- for i=1,#filelist do -- local filename = filelist[i] - local basename = file.basename(filename) -- use splitter - local pathname = file.dirname(filename) + local basename = filebasename(filename) -- use splitter + local pathname = filepathpart(filename) -- if pathname == "" and not a_global and filename ~= usedfiles.nop then filename = "./" .. filename - if not lfs.isfile(filename) then + if not validfile(filename) then report("warning: no (local) file %a, proceeding",filename) end end -- - local jobname = file.removesuffix(basename) - -- local jobname = file.removesuffix(filename) + local jobname = removesuffix(basename) + -- local jobname = removesuffix(filename) local ctxname = ctxdata and ctxdata.ctxname -- local analysis = preamble_analyze(filename) -- + a_synctex = a_synctex or check_synctex(analysis.synctex) + -- if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then run_texexec(filename,a_purge,a_purgeall) elseif plain_format(a_texformat or analysis.texformat) then @@ -557,7 +583,8 @@ function scripts.context.run(ctxdata,filename) formatfile, scriptfile = resolvers.locateformat(formatname) end -- - a_jiton = (a_jiton or toboolean(analysis.jiton,true)) and true or nil + a_jiton = (a_jiton or toboolean(analysis.jiton,true)) and true or nil + a_jithash = validstring(a_jithash or analysis.jithash) or nil -- if not formatfile or not scriptfile then report("warning: no format found, forcing remake (source driven)") @@ -568,13 +595,13 @@ function scripts.context.run(ctxdata,filename) local suffix = validstring(getargument("suffix")) local resultname = validstring(getargument("result")) if suffix then - resultname = file.removesuffix(jobname) .. suffix + resultname = removesuffix(jobname) .. suffix end local oldbase = "" local newbase = "" if resultname then - oldbase = file.removesuffix(jobname) - newbase = file.removesuffix(resultname) + oldbase = removesuffix(jobname) + newbase = removesuffix(resultname) if oldbase ~= newbase then if a_purgeresult then result_push_purge(oldbase,newbase) @@ -640,6 +667,7 @@ function scripts.context.run(ctxdata,filename) ["lua"] = scriptfile, ["jobname"] = jobname, ["jiton"] = a_jiton, + ["jithash"] = a_jithash, } -- if a_synctex then @@ -669,6 +697,7 @@ function scripts.context.run(ctxdata,filename) c_flags.final = false c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2 c_flags.maxnofruns = maxnofruns + c_flags.forcedruns = multipass_forcedruns and multipass_forcedruns > 0 and multipass_forcedruns or nil c_flags.currentrun = currentrun c_flags.noarrange = a_noarrange or a_arrange or nil -- @@ -686,10 +715,15 @@ function scripts.context.run(ctxdata,filename) break elseif returncode == 0 then multipass_copyluafile(jobname) - newhash = multipass_hashfiles(jobname) - if multipass_changed(oldhash,newhash) then - oldhash = newhash - else + if not multipass_forcedruns then + newhash = multipass_hashfiles(jobname) + if multipass_changed(oldhash,newhash) then + oldhash = newhash + else + break + end + elseif currentrun == multipass_forcedruns then + report("quitting after force %i runs",multipass_forcedruns) break end else @@ -807,7 +841,7 @@ function scripts.context.pipe() -- still used? filename = "\\relax" report("entering scrollmode, end job with \\end") else - filename = file.addsuffix(filename,"tmp") + filename = fileaddsuffix(filename,"tmp") io.savedata(filename,"\\relax") report("entering scrollmode using '%s' with optionfile, end job with \\end",filename) end @@ -833,7 +867,7 @@ local function make_mkiv_format(name,engine) end local function make_mkii_format(name,engine) - local command = format("mtxrun texexec.rb --make --%s %s",name,engine) + local command = format("mtxrun texexec.rb --make %s --%s",name,engine) report("running command: %s",command) os.spawn(command) end @@ -875,24 +909,26 @@ function scripts.context.ctx() end function scripts.context.autoctx() - local ctxdata = nil - local files = environment.files + local ctxdata = nil + local files = environment.files local firstfile = #files > 0 and files[1] if firstfile then - local suffix = file.suffix(firstfile) + local suffix = filesuffix(firstfile) + local ctxname = nil if suffix == "xml" then local chunk = io.loadchunk(firstfile) -- 1024 if chunk then - local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>") - if ctxname then - ctxdata = ctxrunner.new() - ctxdata.jobname = firstfile - ctxrunner.checkfile(ctxdata,ctxname) - ctxrunner.checkflags(ctxdata) - end + ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>") end - elseif suffix == "tex" then - -- maybe but we scan the preamble later too + elseif suffix == "tex" or suffix == "mkiv" then + local analysis = preamble_analyze(firstfile) + ctxname = analysis.ctxfile or analysis.ctx + end + if ctxname then + ctxdata = ctxrunner.new() + ctxdata.jobname = firstfile + ctxrunner.checkfile(ctxdata,ctxname) + ctxrunner.checkflags(ctxdata) end end scripts.context.run(ctxdata) @@ -921,10 +957,10 @@ end -- formatname = "metafun" -- end -- if getargument("pdf") then --- local basename = file.removesuffix(filename) +-- local basename = removesuffix(filename) -- local resultname = getargument("result") or basename -- local jobname = "mtx-context-metapost" --- local tempname = file.addsuffix(jobname,"tex") +-- local tempname = fileaddsuffix(jobname,"tex") -- io.savedata(tempname,format(template,"metafun",filename)) -- environment.files[1] = tempname -- setargument("result",resultname) @@ -961,7 +997,7 @@ function scripts.context.version() end end --- purging files +-- purging files (we should have an mkii and mkiv variants) local generic_files = { "texexec.tex", "texexec.tui", "texexec.tuo", @@ -975,15 +1011,32 @@ local obsolete_results = { } local temporary_runfiles = { - "tui", "tua", "tup", "ted", "tes", "top", - "log", "tmp", "run", "bck", "rlg", - "mpt", "mpx", "mpd", "mpo", "mpb", "ctl", - "synctex", "synctex.gz", "pgf", - "prep", + "tui", -- mkii two pass file + "tua", -- mkiv obsolete + "tup", "ted", "tes", -- texexec + "top", -- mkii options file + "log", -- tex log file + "tmp", -- mkii buffer file + "run", -- mkii stub + "bck", -- backup (obsolete) + "rlg", -- resource log + "ctl", -- + "mpt", "mpx", "mpd", "mpo", "mpb", -- metafun + "prep", -- context preprocessed + "pgf", -- tikz + "aux", "blg", -- bibtex +} + +local synctex_runfiles = { + "synctex", "synctex.gz", -- synctex } local persistent_runfiles = { - "tuo", "tub", "top", "tuc" + "tuo", -- mkii two pass file + "tub", -- mkii buffer file + "top", -- mkii options file + "tuc", -- mkiv two pass file + "bbl", -- bibtex } local special_runfiles = { @@ -991,34 +1044,40 @@ local special_runfiles = { } local function purge_file(dfile,cfile) - if cfile and lfs.isfile(cfile) then + if cfile and validfile(cfile) then if os.remove(dfile) then - return file.basename(dfile) + return filebasename(dfile) end elseif dfile then if os.remove(dfile) then - return file.basename(dfile) + return filebasename(dfile) end end end function scripts.context.purge_job(jobname,all,mkiitoo) if jobname and jobname ~= "" then - jobname = file.basename(jobname) - local filebase = file.removesuffix(jobname) + jobname = filebasename(jobname) + local filebase = removesuffix(jobname) if mkiitoo then scripts.context.purge(all,filebase,true) -- leading "./" else local deleted = { } for i=1,#obsolete_results do - deleted[#deleted+1] = purge_file(filebase.."."..obsolete_results[i],filebase..".pdf") + deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,obsolete_results[i]),fileaddsuffix(filebase,"pdf")) end for i=1,#temporary_runfiles do - deleted[#deleted+1] = purge_file(filebase.."."..temporary_runfiles[i]) + deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,temporary_runfiles[i])) + end + if not environment.argument("synctex") then + -- special case: not deleted when --synctex is given, but what if given in preamble + for i=1,#synctex_runfiles do + deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,synctex_runfiles[i])) + end end if all then for i=1,#persistent_runfiles do - deleted[#deleted+1] = purge_file(filebase.."."..persistent_runfiles[i]) + deleted[#deleted+1] = purge_file(fileaddsuffix(filebase,persistent_runfiles[i])) end end if #deleted > 0 then @@ -1034,14 +1093,15 @@ function scripts.context.purge(all,pattern,mkiitoo) local files = dir.glob(pattern) local obsolete = table.tohash(obsolete_results) local temporary = table.tohash(temporary_runfiles) + local synctex = table.tohash(synctex_runfiles) local persistent = table.tohash(persistent_runfiles) local generic = table.tohash(generic_files) local deleted = { } for i=1,#files do local name = files[i] - local suffix = file.suffix(name) - local basename = file.basename(name) - if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then + local suffix = filesuffix(name) + local basename = filebasename(name) + if obsolete[suffix] or temporary[suffix] or synctex[suffix] or persistent[suffix] or generic[basename] then deleted[#deleted+1] = purge_file(name) elseif mkiitoo then for i=1,#special_runfiles do @@ -1060,8 +1120,7 @@ end local function touch(path,name,versionpattern,kind,kindpattern) if path and path ~= "" then - name = file.join(path,name) -print(name) + name = filejoinname(path,name) else name = resolvers.findfile(name) end @@ -1083,7 +1142,7 @@ print(name) end) or newdata end if newdata ~= "" and (oldversion ~= newversion or oldkind ~= newkind or newdata ~= olddata) then - local backup = file.replacesuffix(name,"tmp") + local backup = filenewsuffix(name,"tmp") os.remove(backup) os.rename(name,backup) io.savedata(name,newdata) @@ -1097,12 +1156,12 @@ local p_contextversion = "(\\edef\\contextversion%s*{)(.-)(})" local p_newcontextversion = "(\\newcontextversion%s*{)(.-)(})" local function touchfiles(suffix,kind,path) - local foundname, oldversion, newversion, oldkind, newkind = touch(path,file.addsuffix("context",suffix),p_contextversion,kind,p_contextkind) + local foundname, oldversion, newversion, oldkind, newkind = touch(path,fileaddsuffix("context",suffix),p_contextversion,kind,p_contextkind) if foundname then report("old version : %s (%s)",oldversion,oldkind) report("new version : %s (%s)",newversion,newkind) report("touched file : %s",foundname) - local foundname = touch(path,file.addsuffix("cont-new",suffix),p_newcontextversion) + local foundname = touch(path,fileaddsuffix("cont-new",suffix),p_newcontextversion) if foundname then report("touched file : %s", foundname) end @@ -1143,19 +1202,19 @@ function scripts.context.modules(pattern) end -- my dev path for i=1,#cards do - dir.glob(file.join(file.dirname(found),cards[i]),list) + dir.glob(filejoinname(filepathpart(found),cards[i]),list) end else resolvers.findwildcardfiles(pattern,list) - dir.glob(file.join(file.dirname(found,pattern)),list) + dir.glob(filejoinname(filepathpart(found,pattern)),list) end local done = { } -- todo : sort for i=1,#list do local v = list[i] - local base = file.basename(v) + local base = filebasename(v) if not done[base] then done[base] = true - local suffix = file.suffix(base) + local suffix = filesuffix(base) if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then local prefix = match(base,"^([xmst])%-") if prefix then @@ -1193,7 +1252,7 @@ function scripts.context.extras(pattern) end local found = resolvers.findfile("context.mkiv") if found ~= "" then - pattern = file.join(dir.expandname(file.dirname(found)),format("mtx-context-%s.tex",pattern or "*")) + pattern = filejoinname(dir.expandname(filepathpart(found)),format("mtx-context-%s.tex",pattern or "*")) local list = dir.glob(pattern) for i=1,#list do local v = list[i] @@ -1432,9 +1491,12 @@ do end if getargument("once") then - multipass_nofruns = 1 -elseif getargument("runs") then - multipass_nofruns = tonumber(getargument("runs")) or nil + multipass_nofruns = 1 +else + if getargument("runs") then + multipass_nofruns = tonumber(getargument("runs")) or nil + end + multipass_forcedruns = tonumber(getargument("forcedruns")) or nil end if getargument("run") then |