summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtx-context.lua
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2012-10-19 01:20:13 +0300
committerMarius <mariausol@gmail.com>2012-10-19 01:20:13 +0300
commit69d2352af4b60929b37fc49f3bdb263977016244 (patch)
treedb5eb11398e345dfa23b4c4500fb93575d2afb7c /scripts/context/lua/mtx-context.lua
parentc18f7cbe51449a611ea1819fedd9a4ff18529b7d (diff)
downloadcontext-69d2352af4b60929b37fc49f3bdb263977016244.tar.gz
stable 2012.05.30 11:26
Diffstat (limited to 'scripts/context/lua/mtx-context.lua')
-rw-r--r--scripts/context/lua/mtx-context.lua1518
1 files changed, 910 insertions, 608 deletions
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua
index f33363a0d..e07ecdfc7 100644
--- a/scripts/context/lua/mtx-context.lua
+++ b/scripts/context/lua/mtx-context.lua
@@ -6,18 +6,11 @@ if not modules then modules = { } end modules ['mtx-context'] = {
license = "see context related readme files"
}
--- todo: more local functions
--- todo: pass jobticket/ctxdata table around
-
local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find
-local quote, validstring = string.quote, string.valid
+local quote = string.quote
local concat = table.concat
-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.argument
local basicinfo = [[
--run process (one or more) files (default action)
@@ -42,10 +35,8 @@ local basicinfo = [[
--noconsole disable logging to the console (logfile only)
--purgeresult purge result file before run
---forcexml force xml stub
+--forcexml force xml stub (optional flag: --mkii)
--forcecld force cld (context lua document) stub
---forcelua force lua stub (like texlua)
---forcemp force mp stub
--arrange run extra imposition pass, given that the style sets up imposition
--noarrange ignore imposition specifications in the style
@@ -59,16 +50,23 @@ local basicinfo = [[
--version report installed context version
--global assume given file present elsewhere
---nofile use dummy file as jobname
--expert expert options
]]
+-- filter=list is kind of obsolete
+-- color is obsolete for mkiv, always on
+-- separation is obsolete for mkiv, no longer available
+-- output is currently obsolete for mkiv
+-- setuppath=list must check
+-- modefile=name must check
+-- input=name load the given inputfile (must check)
+
local expertinfo = [[
expert options:
--touch update context version number (remake needed afterwards, also provide --expert)
---nostatistics omit runtime statistics at the end of the run
+--nostats omit runtime statistics at the end of the run
--update update context from website (not to be confused with contextgarden)
--profile profile job (use: mtxrun --script profile --analyze)
--timing generate timing and statistics overview
@@ -82,14 +80,13 @@ special options:
--pdftex process file with texexec using pdftex
--xetex process file with texexec using xetex
---mkii process file with texexec
--pipe don't check for file and enter scroll mode (--dummyfile=whatever.tmp)
]]
local application = logs.application {
name = "mtx-context",
- banner = "ConTeXt Process Management 0.60",
+ banner = "ConTeXt Process Management 0.52",
helpinfo = {
basic = basicinfo,
extra = extrainfo,
@@ -97,105 +94,159 @@ local application = logs.application {
}
}
--- local luatexflags = {
--- ["8bit"] = true, -- ignored, input is assumed to be in UTF-8 encoding
--- ["default-translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
--- ["translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
--- ["etex"] = true, -- ignored, the etex extensions are always active
---
--- ["credits"] = true, -- display credits and exit
--- ["debug-format"] = true, -- enable format debugging
--- ["disable-write18"] = true, -- disable \write18{SHELL COMMAND}
--- ["draftmode"] = true, -- switch on draft mode (generates no output PDF)
--- ["enable-write18"] = true, -- enable \write18{SHELL COMMAND}
--- ["file-line-error"] = true, -- enable file:line:error style messages
--- ["file-line-error-style"] = true, -- aliases of --file-line-error
--- ["no-file-line-error"] = true, -- disable file:line:error style messages
--- ["no-file-line-error-style"] = true, -- aliases of --no-file-line-error
--- ["fmt"] = true, -- load the format file FORMAT
--- ["halt-on-error"] = true, -- stop processing at the first error
--- ["help"] = true, -- display help and exit
--- ["ini"] = true, -- be iniluatex, for dumping formats
--- ["interaction"] = true, -- set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)
--- ["jobname"] = true, -- set the job name to STRING
--- ["kpathsea-debug"] = true, -- set path searching debugging flags according to the bits of NUMBER
--- ["lua"] = true, -- load and execute a lua initialization script
--- ["mktex"] = true, -- enable mktexFMT generation (FMT=tex/tfm)
--- ["no-mktex"] = true, -- disable mktexFMT generation (FMT=tex/tfm)
--- ["nosocket"] = true, -- disable the lua socket library
--- ["output-comment"] = true, -- use STRING for DVI file comment instead of date (no effect for PDF)
--- ["output-directory"] = true, -- use existing DIR as the directory to write files in
--- ["output-format"] = true, -- use FORMAT for job output; FORMAT is 'dvi' or 'pdf'
--- ["parse-first-line"] = true, -- enable parsing of the first line of the input file
--- ["no-parse-first-line"] = true, -- disable parsing of the first line of the input file
--- ["progname"] = true, -- set the program name to STRING
--- ["recorder"] = true, -- enable filename recorder
--- ["safer"] = true, -- disable easily exploitable lua commands
--- ["shell-escape"] = true, -- enable \write18{SHELL COMMAND}
--- ["no-shell-escape"] = true, -- disable \write18{SHELL COMMAND}
--- ["shell-restricted"] = true, -- restrict \write18 to a list of commands given in texmf.cnf
--- ["synctex"] = true, -- enable synctex
--- ["version"] = true, -- display version and exit
--- ["luaonly"] = true, -- run a lua file, then exit
--- ["luaconly"] = true, -- byte-compile a lua file, then exit
--- }
-
local report = application.report
scripts = scripts or { }
scripts.context = scripts.context or { }
--- constants
+-- a demo cld file:
+--
+-- context.starttext()
+-- context.chapter("Hello There")
+-- context.readfile("tufte","","not found")
+-- context.stoptext()
-local usedfiles = {
- nop = "cont-nop.mkiv",
- yes = "cont-yes.mkiv",
-}
+-- l-file / todo
-local usedsuffixes = {
- before = {
- "tuc"
- },
- after = {
- "pdf", "tuc", "log"
- },
- keep = {
- "log"
- },
-}
+function file.needsupdate(oldfile,newfile)
+ return true
+end
+function file.syncmtimes(oldfile,newfile)
+end
-local formatofinterface = {
- en = "cont-en",
- uk = "cont-uk",
- de = "cont-de",
- fr = "cont-fr",
- nl = "cont-nl",
- cs = "cont-cs",
- it = "cont-it",
- ro = "cont-ro",
- pe = "cont-pe",
-}
+-- l-io
-local defaultformats = {
- "cont-en",
- "cont-nl",
-}
+function io.copydata(fromfile,tofile)
+ io.savedata(tofile,io.loaddata(fromfile) or "")
+end
--- process information
+-- ctx (will become util-ctx)
+
+local ctxrunner = { }
+
+function ctxrunner.filtered(str,method)
+ str = tostring(str)
+ if method == 'name' then str = file.removesuffix(file.basename(str))
+ elseif method == 'path' then str = file.dirname(str)
+ elseif method == 'suffix' then str = file.extname(str)
+ elseif method == 'nosuffix' then str = file.removesuffix(str)
+ elseif method == 'nopath' then str = file.basename(str)
+ elseif method == 'base' then str = file.basename(str)
+-- elseif method == 'full' then
+-- elseif method == 'complete' then
+-- elseif method == 'expand' then -- str = file.expandpath(str)
+ end
+ return str:gsub("\\","/")
+end
-local ctxrunner = { } -- namespace will go
+function ctxrunner.substitute(e,str)
+ local attributes = e.at
+ if str and attributes then
+ if attributes['method'] then
+ str = ctxrunner.filtered(str,attributes['method'])
+ end
+ if str == "" and attributes['default'] then
+ str = attributes['default']
+ end
+ end
+ return str
+end
-local ctx_locations = { '..', '../..' }
+function ctxrunner.reflag(flags)
+ local t = { }
+ for _, flag in next, flags do
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ t[key] = value
+ else
+ t[flag] = true
+ end
+ end
+ return t
+end
+
+function ctxrunner.substitute(str)
+ return str
+end
+
+function ctxrunner.justtext(str)
+ str = xml.unescaped(tostring(str))
+ str = xml.cleansed(str)
+ str = str:gsub("\\+",'/')
+ str = str:gsub("%s+",' ')
+ return str
+end
function ctxrunner.new()
return {
- ctxname = "",
- jobname = "",
- flags = { },
+ ctxname = "",
+ jobname = "",
+ xmldata = nil,
+ suffix = "prep",
+ locations = { '..', '../..' },
+ variables = { },
+ messages = { },
+ environments = { },
+ modules = { },
+ filters = { },
+ flags = { },
+ modes = { },
+ prepfiles = { },
+ paths = { },
}
end
-function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
+function ctxrunner.savelog(ctxdata,ctlname)
+ local function yn(b)
+ if b then return 'yes' else return 'no' end
+ end
+ if not ctlname or ctlname == "" or ctlname == ctxdata.jobname then
+ if ctxdata.jobname then
+ ctlname = file.replacesuffix(ctxdata.jobname,'ctl')
+ elseif ctxdata.ctxname then
+ ctlname = file.replacesuffix(ctxdata.ctxname,'ctl')
+ else
+ report("invalid ctl name: %s",ctlname or "?")
+ return
+ end
+ end
+ local prepfiles = ctxdata.prepfiles
+ if prepfiles and next(prepfiles) then
+ report("saving logdata in: %s",ctlname)
+ f = io.open(ctlname,'w')
+ if f then
+ f:write("<?xml version='1.0' standalone='yes'?>\n\n")
+ f:write(format("<ctx:preplist local='%s'>\n",yn(ctxdata.runlocal)))
+ local sorted = table.sortedkeys(prepfiles)
+ for i=1,#sorted do
+ local name = sorted[i]
+ f:write(format("\t<ctx:prepfile done='%s'>%s</ctx:prepfile>\n",yn(prepfiles[name]),name))
+ end
+ f:write("</ctx:preplist>\n")
+ f:close()
+ end
+ else
+ report("nothing prepared, no ctl file saved")
+ os.remove(ctlname)
+ end
+end
+
+function ctxrunner.register_path(ctxdata,path)
+ -- test if exists
+ ctxdata.paths[ctxdata.paths+1] = path
+end
+
+function ctxrunner.trace(ctxdata)
+ print(table.serialize(ctxdata.messages))
+ print(table.serialize(ctxdata.flags))
+ print(table.serialize(ctxdata.environments))
+ print(table.serialize(ctxdata.modules))
+ print(table.serialize(ctxdata.filters))
+ print(table.serialize(ctxdata.modes))
+ print(xml.tostring(ctxdata.xmldata))
+end
+
+function ctxrunner.manipulate(ctxdata,ctxname,defaultname)
if not ctxdata.jobname or ctxdata.jobname == "" then
return
@@ -218,14 +269,13 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
local usedname = ctxdata.ctxname
local found = lfs.isfile(usedname)
- -- no further test if qualified path
+ -- no futher test if qualified path
if not found then
- for _, path in next, ctx_locations do
+ for _, path in next, ctxdata.locations do
local fullname = file.join(path,ctxdata.ctxname)
if lfs.isfile(fullname) then
- usedname = fullname
- found = true
+ usedname, found = fullname, true
break
end
end
@@ -233,70 +283,194 @@ function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
if not found then
usedname = resolvers.findfile(ctxdata.ctxname,"tex")
- found = usedname ~= ""
+ found = usedname ~= ""
end
if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then
- usedname = defaultname
- found = true
+ usedname, found = defaultname, true
end
if not found then
return
end
- local xmldata = xml.load(usedname)
+ ctxdata.xmldata = xml.load(usedname)
- if not xmldata then
+ if not ctxdata.xmldata then
return
else
-- test for valid, can be text file
end
- local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations)
+ xml.include(ctxdata.xmldata,'ctx:include','name', table.append({'.', file.dirname(ctxdata.ctxname)},ctxdata.locations))
- xml.include(xmldata,'ctx:include','name', ctxpaths)
+ ctxdata.variables['job'] = ctxdata.jobname
- local flags = ctxdata.flags
+ ctxdata.flags = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:flags/ctx:flag",true)
+ ctxdata.environments = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment",true)
+ ctxdata.modules = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module",true)
+ ctxdata.filters = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:filter",true)
+ ctxdata.modes = xml.collect_texts(ctxdata.xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode",true)
+ ctxdata.messages = xml.collect_texts(ctxdata.xmldata,"ctx:message",true)
- for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
- local flag = xml.text(e) or ""
- local key, value = match(flag,"^(.-)=(.+)$")
- if key and value then
- flags[key] = value
- else
- flags[flag] = true
- end
+ ctxdata.flags = ctxrunner.reflag(ctxdata.flags)
+
+ local messages = ctxdata.messages
+ for i=1,#messages do
+ report("ctx comment: %s", xml.tostring(messages[i]))
end
-end
+ for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value[@name='job']") do
+ d[k] = ctxdata.variables['job'] or ""
+ end
-function ctxrunner.checkflags(ctxdata)
- if ctxdata then
- for k,v in next, ctxdata.flags do
- if getargument(k) == nil then
- setargument(k,v)
+ local commands = { }
+ for e in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
+ commands[e.at and e.at['name'] or "unknown"] = e
+ end
+
+ local suffix = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/attribute('suffix')") or ctxdata.suffix
+ local runlocal = xml.filter(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
+
+ runlocal = toboolean(runlocal)
+
+ for files in xml.collected(ctxdata.xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
+ for pattern in xml.collected(files,"ctx:file") do
+
+ preprocessor = pattern.at['processor'] or ""
+
+ if preprocessor ~= "" then
+
+ ctxdata.variables['old'] = ctxdata.jobname
+ for r, d, k in xml.elements(ctxdata.xmldata,"ctx:value") do
+ local ek = d[k]
+ local ekat = ek.at['name']
+ if ekat == 'old' then
+ d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
+ end
+ end
+
+ pattern = ctxrunner.justtext(xml.tostring(pattern))
+
+ local oldfiles = dir.glob(pattern)
+
+ local pluspath = false
+ if #oldfiles == 0 then
+ -- message: no files match pattern
+ local paths = ctxdata.paths
+ for i=1,#paths do
+ local p = paths[i]
+ local oldfiles = dir.glob(path.join(p,pattern))
+ if #oldfiles > 0 then
+ pluspath = true
+ break
+ end
+ end
+ end
+ if #oldfiles == 0 then
+ -- message: no old files
+ else
+ for i=1,#oldfiles do
+ local oldfile = oldfiles[i]
+ local newfile = oldfile .. "." .. suffix -- addsuffix will add one only
+ if ctxdata.runlocal then
+ newfile = file.basename(newfile)
+ end
+ if oldfile ~= newfile and file.needsupdate(oldfile,newfile) then
+ -- message: oldfile needs preprocessing
+ -- os.remove(newfile)
+ local splitted = preprocessor:split(',')
+ for i=1,#splitted do
+ local pp = splitted[i]
+ local command = commands[pp]
+ if command then
+ command = xml.copy(command)
+ local suf = (command.at and command.at['suffix']) or ctxdata.suffix
+ if suf then
+ newfile = oldfile .. "." .. suf
+ end
+ if ctxdata.runlocal then
+ newfile = file.basename(newfile)
+ end
+ for r, d, k in xml.elements(command,"ctx:old") do
+ d[k] = ctxrunner.substitute(oldfile)
+ end
+ for r, d, k in xml.elements(command,"ctx:new") do
+ d[k] = ctxrunner.substitute(newfile)
+ end
+ ctxdata.variables['old'] = oldfile
+ ctxdata.variables['new'] = newfile
+ for r, d, k in xml.elements(command,"ctx:value") do
+ local ek = d[k]
+ local ekat = ek.at and ek.at['name']
+ if ekat then
+ d[k] = ctxrunner.substitute(ctxdata.variables[ekat] or "")
+ end
+ end
+ -- potential optimization: when mtxrun run internal
+ command = xml.content(command)
+ command = ctxrunner.justtext(command)
+ report("command: %s",command)
+ local result = os.spawn(command) or 0
+ -- somehow we get the wrong return value
+ if result > 0 then
+ report("error, return code: %s",result)
+ end
+ if ctxdata.runlocal then
+ oldfile = file.basename(oldfile)
+ end
+ end
+ end
+ if lfs.isfile(newfile) then
+ file.syncmtimes(oldfile,newfile)
+ ctxdata.prepfiles[oldfile] = true
+ else
+ report("error, check target location of new file: %s", newfile)
+ ctxdata.prepfiles[oldfile] = false
+ end
+ else
+ report("old file needs no preprocessing")
+ ctxdata.prepfiles[oldfile] = lfs.isfile(newfile)
+ end
+ end
+ end
end
end
end
+
+ ctxrunner.savelog(ctxdata)
+
end
--- multipass control
+function ctxrunner.preppedfile(ctxdata,filename)
+ if ctxdata.prepfiles[file.basename(filename)] then
+ return filename .. ".prep"
+ else
+ return filename
+ end
+end
-local multipass_suffixes = { ".tuc" }
-local multipass_nofruns = 8 -- or 7 to test oscillation
+-- rest
+
+scripts.context.multipass = {
+-- suffixes = { ".tuo", ".tuc" },
+ suffixes = { ".tuc" },
+ nofruns = 8,
+-- nofruns = 7, -- test oscillation
+}
-local function multipass_hashfiles(jobname)
+function scripts.context.multipass.hashfiles(jobname)
local hash = { }
- for i=1,#multipass_suffixes do
- local suffix = multipass_suffixes[i]
+ local suffixes = scripts.context.multipass.suffixes
+ for i=1,#suffixes do
+ local suffix = suffixes[i]
local full = jobname .. suffix
hash[full] = md5.hex(io.loaddata(full) or "unknown")
end
return hash
end
-local function multipass_changed(oldhash, newhash)
+function scripts.context.multipass.changed(oldhash, newhash)
for k,v in next, oldhash do
if v ~= newhash[k] then
return true
@@ -305,7 +479,126 @@ local function multipass_changed(oldhash, newhash)
return false
end
-local function multipass_copyluafile(jobname)
+function scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,currentrun,finalrun,once)
+ -- take jobname from ctx
+ jobname = file.removesuffix(jobname)
+ local f = io.open(jobname..".top","w")
+ if f then
+ local function someflag(flag)
+ return (ctxdata and ctxdata.flags[flag]) or getargument(flag)
+ end
+ local function setvalue(flag,template,hash,default)
+ local a = someflag(flag) or default
+ if a and a ~= "" then
+ if hash then
+ if hash[a] then
+ f:write(format(template,a),"\n")
+ end
+ else
+ f:write(format(template,a),"\n")
+ end
+ end
+ end
+ local function setvalues(flag,template,plural)
+ if type(flag) == "table" then
+ for k, v in next, flag do
+ f:write(format(template,v),"\n")
+ end
+ else
+ local a = someflag(flag) or (plural and someflag(flag.."s"))
+ if a and a ~= "" then
+ for v in gmatch(a,"%s*([^,]+)") do
+ f:write(format(template,v),"\n")
+ end
+ end
+ end
+ end
+ local function setfixed(flag,template,...)
+ if someflag(flag) then
+ f:write(format(template,...),"\n")
+ end
+ end
+ local function setalways(template,...)
+ f:write(format(template,...),"\n")
+ end
+ --
+ -- This might change ... we can just pass the relevant flags directly.
+ --
+ setalways("%% runtime options files (command line driven)")
+ --
+ setalways("\\unprotect")
+ --
+ setalways("%% feedback and basic job control")
+ --
+ -- Option file, we can pass more on the commandline some day soon. Actually we
+ -- should use directives and trackers.
+ --
+ setfixed ("timing" , "\\usemodule[timing]")
+ setfixed ("batchmode" , "\\batchmode")
+ setfixed ("batch" , "\\batchmode")
+ setfixed ("nonstopmode" , "\\nonstopmode")
+ setfixed ("nonstop" , "\\nonstopmode")
+ -- setfixed ("tracefiles" , "\\tracefilestrue")
+ setfixed ("nostats" , "\\nomkivstatistics")
+ setfixed ("paranoid" , "\\def\\maxreadlevel{1}")
+ --
+ setalways("%% handy for special styles")
+ --
+ setalways("\\startluacode")
+ setalways("document = document or { }")
+ setalways(table.serialize(environment.arguments, "document.arguments"))
+ setalways(table.serialize(environment.files, "document.files"))
+ setalways("\\stopluacode")
+ --
+ setalways("%% process info")
+ --
+ setalways( "\\setupsystem[inputfile=%s]",getargument("input") or environment.files[1] or "\\jobname")
+ setvalue ("result" , "\\setupsystem[file=%s]")
+ setalways( "\\setupsystem[\\c!n=%s,\\c!m=%s]", kindofrun or 0, currentrun or 0)
+ setvalues("path" , "\\usepath[%s]")
+ setvalue ("setuppath" , "\\setupsystem[\\c!directory={%s}]")
+ setvalue ("randomseed" , "\\setupsystem[\\c!random=%s]")
+ setvalue ("arguments" , "\\setupenv[%s]")
+ if once then
+ setalways("\\enabledirectives[system.runonce]")
+ end
+ setalways("%% modes")
+ setvalues("modefile" , "\\readlocfile{%s}{}{}")
+ setvalues("mode" , "\\enablemode[%s]", true)
+ if ctxdata then
+ setvalues(ctxdata.modes, "\\enablemode[%s]")
+ end
+ --
+ setalways("%% options (not that important)")
+ --
+ setalways("\\startsetups *runtime:options")
+ setfixed ("color" , "\\setupcolors[\\c!state=\\v!start]")
+ setvalue ("separation" , "\\setupcolors[\\c!split=%s]")
+ setfixed ("noarrange" , "\\setuparranging[\\v!disable]")
+ if getargument('arrange') and not finalrun then
+ setalways( "\\setuparranging[\\v!disable]")
+ end
+ setalways("\\stopsetups")
+ --
+ setalways("%% styles and modules")
+ --
+ setalways("\\startsetups *runtime:modules")
+ setvalues("usemodule" , "\\usemodule[%s]", true)
+ setvalues("environment" , "\\environment %s ", true)
+ if ctxdata then
+ setvalues(ctxdata.modules, "\\usemodule[%s]")
+ setvalues(ctxdata.environments, "\\environment %s ")
+ end
+ setalways("\\stopsetups")
+ --
+ setalways("%% done")
+ --
+ setalways("\\protect \\endinput")
+ f:close()
+ end
+end
+
+function scripts.context.multipass.copyluafile(jobname) -- obsolete
local tuaname, tucname = jobname..".tua", jobname..".tuc"
if lfs.isfile(tuaname) then
os.remove(tucname)
@@ -313,54 +606,120 @@ local function multipass_copyluafile(jobname)
end
end
---
+scripts.context.cldsuffixes = table.tohash {
+ "cld",
+}
+
+scripts.context.xmlsuffixes = table.tohash {
+ "xml",
+}
+
+scripts.context.luasuffixes = table.tohash {
+ "lua",
+}
+
+scripts.context.beforesuffixes = {
+ "tuo", "tuc"
+}
+scripts.context.aftersuffixes = {
+ "pdf", "tuo", "tuc", "log"
+}
+
+scripts.context.errorsuffixes = {
+ "log"
+}
+
+scripts.context.interfaces = {
+ en = "cont-en",
+ uk = "cont-uk",
+ de = "cont-de",
+ fr = "cont-fr",
+ nl = "cont-nl",
+ cs = "cont-cs",
+ it = "cont-it",
+ ro = "cont-ro",
+ pe = "cont-pe",
+}
+
+scripts.context.defaultformats = {
+ "cont-en",
+ "cont-nl",
+-- "mptopdf", -- todo: mak emkiv variant
+-- "metatex", -- will show up soon
+-- "metafun", -- todo: mp formats
+-- "plain"
+}
+
+local lpegpatterns, Cs, P = lpeg.patterns, lpeg.Cs, lpeg.P
local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1)
-local function preamble_analyze(filename) -- only files on current path
- local t = { }
- local line = io.loadlines(file.addsuffix(filename,"tex"))
- if line then
- local preamble = lpegmatch(pattern,line)
+local function analyze(filename) -- only files on current path
+ local f = io.open(file.addsuffix(filename,"tex"))
+ if f then
+ local t = { }
+ local line = f:read("*line") or ""
+ local preamble = lpeg.match(pattern,line)
if preamble then
for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do
t[key] = value
end
t.type = "tex"
- elseif find(line,"^<?xml ") then
+ elseif line:find("^<?xml ") then
t.type = "xml"
end
if t.nofruns then
- multipass_nofruns = t.nofruns
+ scripts.context.multipass.nofruns = t.nofruns
end
if not t.engine then
t.engine = 'luatex'
end
+ f:close()
+ return t
end
- return t
end
--- automatically opening and closing pdf files
+local function makestub(wrap,template,filename,prepname)
+ local stubname = file.replacesuffix(file.basename(filename),'run')
+ local f = io.open(stubname,'w')
+ if f then
+ if wrap then
+ f:write("\\starttext\n")
+ end
+ f:write(format(template,prepname or filename),"\n")
+ if wrap then
+ f:write("\\stoptext\n")
+ end
+ f:close()
+ filename = stubname
+ end
+ return filename
+end
-local pdfview -- delayed
+--~ function scripts.context.openpdf(name)
+--~ os.spawn(format('pdfopen --file "%s" 2>&1', file.replacesuffix(name,"pdf")))
+--~ end
+--~ function scripts.context.closepdf(name)
+--~ os.spawn(format('pdfclose --file "%s" 2>&1', file.replacesuffix(name,"pdf")))
+--~ end
-local function pdf_open(name,method)
+local pdfview -- delayed loading
+
+function scripts.context.openpdf(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
report(pdfview.status())
pdfview.open(file.replacesuffix(name,"pdf"))
end
-local function pdf_close(name,method)
+function scripts.context.closepdf(name,method)
pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
pdfview.setmethod(method)
pdfview.close(file.replacesuffix(name,"pdf"))
end
--- result file handling
-
-local function result_push_purge(oldbase,newbase)
- for _, suffix in next, usedsuffixes.after do
+local function push_result_purge(oldbase,newbase)
+ for _, suffix in next, scripts.context.aftersuffixes do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname)
@@ -368,8 +727,8 @@ local function result_push_purge(oldbase,newbase)
end
end
-local function result_push_keep(oldbase,newbase)
- for _, suffix in next, usedsuffixes.before do
+local function push_result_keep(oldbase,newbase)
+ for _, suffix in next, scripts.context.beforesuffixes do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -380,8 +739,8 @@ local function result_push_keep(oldbase,newbase)
end
end
-local function result_save_error(oldbase,newbase)
- for _, suffix in next, usedsuffixes.keep do
+local function save_result_error(oldbase,newbase)
+ for _, suffix in next, scripts.context.errorsuffixes do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -389,8 +748,8 @@ local function result_save_error(oldbase,newbase)
end
end
-local function result_save_purge(oldbase,newbase)
- for _, suffix in next, usedsuffixes.after do
+local function save_result_purge(oldbase,newbase)
+ for _, suffix in next, scripts.context.aftersuffixes do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
os.remove(newname) -- to be sure
@@ -398,8 +757,8 @@ local function result_save_purge(oldbase,newbase)
end
end
-local function result_save_keep(oldbase,newbase)
- for _, suffix in next, usedsuffixes.after do
+local function save_result_keep(oldbase,newbase)
+ for _, suffix in next, scripts.context.aftersuffixes do
local oldname = file.addsuffix(oldbase,suffix)
local newname = file.addsuffix(newbase,suffix)
local tmpname = "keep-"..oldname
@@ -409,339 +768,313 @@ local function result_save_keep(oldbase,newbase)
end
end
--- executing luatex
-
-local function flags_to_string(flags,prefix) -- context flags get prepended by c:
- local t = { }
- for k, v in table.sortedhash(flags) do
- if prefix then
- k = format("c:%s",k)
- end
- if not v or v == "" or v == '""' then
- -- no need to flag false
- elseif v == true then
- t[#t+1] = format('--%s',k)
- elseif type(v) == "string" then
- t[#t+1] = format('--%s=%s',k,quote(v))
- else
- t[#t+1] = format('--%s=%s',k,tostring(v))
- end
- end
- return concat(t," ")
-end
-
-local function luatex_command(l_flags,c_flags,filename)
- return format('luatex %s %s "%s"',
- flags_to_string(l_flags),
- flags_to_string(c_flags,true),
- filename
- )
-end
-
-local function run_texexec(filename,a_purge,a_purgeall)
- if false then
- -- we need to write a top etc too and run mp etc so it's not worth the
- -- trouble, so it will take a while before the next is finished
- --
- -- context --extra=texutil --convert myfile
- else
- local texexec = resolvers.findfile("texexec.rb") or ""
- if texexec ~= "" then
- os.setenv("RUBYOPT","")
- local options = environment.reconstructcommandline(environment.arguments_after)
- options = gsub(options,"--purge","")
- options = gsub(options,"--purgeall","")
- local command = format("ruby %s %s",texexec,options)
- if a_purge then
- os.execute(command)
- scripts.context.purge_job(filename,false,true)
- elseif a_purgeall then
- os.execute(command)
- scripts.context.purge_job(filename,true,true)
- else
- os.exec(command)
- end
- end
- end
-end
-
---
-
function scripts.context.run(ctxdata,filename)
- --
- local a_nofile = getargument("nofile")
- --
- local files = environment.files or { }
- --
- local filelist, mainfile
- --
- if filename then
- -- the given forced name is processed, the filelist is passed to context
- mainfile = filename
- filelist = { filename }
- -- files = files
- elseif a_nofile then
- -- the list of given files is processed using the dummy file
- mainfile = usedfiles.nop
- filelist = { usedfiles.nop }
- -- files = { }
- elseif #files > 0 then
- -- the list of given files is processed using the stub file
- mainfile = usedfiles.yes
- filelist = files
- files = { }
- else
- return
- end
- --
- local interface = validstring(getargument("interface")) or "en"
- local formatname = formatofinterface[interface] or "cont-en"
- local formatfile, scriptfile = resolvers.locateformat(formatname)
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (commandline driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
- end
- if formatfile and scriptfile then
- -- okay
- elseif formatname then
- report("error, no format found with name: %s, aborting",formatname)
- return
- else
- report("error, no format found (provide formatname or interface)")
- return
+ -- filename overloads environment.files
+ local files = (filename and { filename }) or environment.files
+ if ctxdata then
+ -- todo: interface
+ for k,v in next, ctxdata.flags do
+ environment.setargument(k,v)
+ end
end
- --
- local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex")
- local a_purge = getargument("purge")
- local a_purgeall = getargument("purgeall")
- local a_purgeresult = getargument("purgeresult")
- local a_global = getargument("global")
- local a_timing = getargument("timing")
- local a_batchmode = getargument("batchmode")
- local a_nonstopmode = getargument("nonstopmode")
- local a_once = getargument("once")
- local a_synctex = getargument("synctex")
- local a_backend = getargument("backend")
- local a_arrange = getargument("arrange")
- local a_noarrange = getargument("noarrange")
- --
- for i=1,#filelist do
+ if #files > 0 then
--
- local filename = filelist[i]
- local basename = file.basename(filename)
- local pathname = file.dirname(filename)
- local jobname = file.removesuffix(basename)
- local ctxname = ctxdata and ctxdata.ctxname
+ local interface = getargument("interface")
+ -- todo: getargument("interface","en")
+ interface = (type(interface) == "string" and interface) or "en"
--
- if pathname == "" and not a_global and filename ~= usedfiles.nop then
- filename = "./" .. filename
+ local formatname = scripts.context.interfaces[interface] or "cont-en"
+ local formatfile, scriptfile = resolvers.locateformat(formatname)
+ -- this catches the command line
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (commandline driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
end
--
- local analysis = preamble_analyze(filename)
- --
- if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then
- run_texexec(filename,a_purge,a_purgeall)
- else
- if analysis.interface and analysis.interface ~= interface then
- formatname = formatofinterface[analysis.interface] or formatname
- formatfile, scriptfile = resolvers.locateformat(formatname)
- end
- if not formatfile or not scriptfile then
- report("warning: no format found, forcing remake (source driven)")
- scripts.context.make(formatname)
- formatfile, scriptfile = resolvers.locateformat(formatname)
- end
- if formatfile and scriptfile then
- --
- local suffix = validstring(getargument("suffix"))
- local resultname = validstring(getargument("result"))
- if suffix then
- resultname = file.removesuffix(jobname) .. suffix
+ if formatfile and scriptfile then
+ for i=1,#files do
+ local filename = files[i]
+ local basename, pathname = file.basename(filename), file.dirname(filename)
+ local jobname = file.removesuffix(basename)
+ if pathname == "" and not getargument("global") then
+ filename = "./" .. filename
end
- local oldbase = ""
- local newbase = ""
- if resultname then
- oldbase = file.removesuffix(jobname)
- newbase = file.removesuffix(resultname)
- if oldbase ~= newbase then
- if a_purgeresult then
- result_push_purge(oldbase,newbase)
- else
- result_push_keep(oldbase,newbase)
- end
+ -- look at the first line
+ local a = analyze(filename)
+ if a and (a.engine == 'pdftex' or a.engine == 'xetex' or getargument("pdftex") or getargument("xetex")) then
+ if false then
+ -- we need to write a top etc too and run mp etc so it's not worth the
+ -- trouble, so it will take a while before the next is finished
+ --
+ -- context --extra=texutil --convert myfile
else
- resultname = nil
+ local texexec = resolvers.findfile("texexec.rb") or ""
+ if texexec ~= "" then
+ os.setenv("RUBYOPT","")
+ local options = environment.reconstructcommandline(environment.arguments_after)
+ options = gsub(options,"--purge","")
+ options = gsub(options,"--purgeall","")
+ local command = format("ruby %s %s",texexec,options)
+ if getargument("purge") then
+ os.execute(command)
+ scripts.context.purge_job(filename,false,true)
+ elseif getargument("purgeall") then
+ os.execute(command)
+ scripts.context.purge_job(filename,true,true)
+ else
+ os.exec(command)
+ end
+ end
end
- end
- --
- local pdfview = getargument("autopdf") or getargument("closepdf")
- if pdfview then
- pdf_close(filename,pdfview)
- if resultname then
- pdf_close(resultname,pdfview)
+ else
+ if a and a.interface and a.interface ~= interface then
+ formatname = scripts.context.interfaces[a.interface] or formatname
+ formatfile, scriptfile = resolvers.locateformat(formatname)
end
- end
- --
- local okay = statistics.checkfmtstatus(formatfile)
- if okay ~= true then
- report("warning: %s, forcing remake",tostring(okay))
- scripts.context.make(formatname)
- end
- --
- local oldhash = multipass_hashfiles(jobname)
- local newhash = { }
- local maxnofruns = once and 1 or multipass_nofruns
- --
- local c_flags = {
- directives = validstring(environment.directives), -- gets passed via mtxrun
- trackers = validstring(environment.trackers), -- gets passed via mtxrun
- experiments = validstring(environment.experiments), -- gets passed via mtxrun
- --
- result = validstring(resultname),
- input = validstring(getargument("input") or filename), -- alternative input
- fulljobname = validstring(filename),
- files = concat(files,","),
- ctx = validstring(ctxname),
- }
- --
- for k, v in next, environment.arguments do
- if c_flags[k] == nil then
- c_flags[k] = v
+ -- this catches the command line
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (source driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
end
- end
- --
- local l_flags = {
- ["interaction"] = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil,
- ["synctex"] = a_synctex and 1 or nil,
- ["no-parse-first-line"] = true,
- -- ["no-mktex"] = true,
- -- ["file-line-error-style"] = true,
- ["fmt"] = formatfile,
- ["lua"] = scriptfile,
- ["jobname"] = jobname,
- }
- --
- if a_synctex then
- report("warning: synctex is enabled") -- can add upto 5% runtime
- end
- --
- -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns
- --
- for currentrun=1,maxnofruns do
- --
- 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.currentrun = currentrun
- c_flags.noarrange = a_noarrange or a_arrange or nil
- --
- local command = luatex_command(l_flags,c_flags,mainfile)
- --
- report("run %s: %s",i,command)
- print("") -- cleaner, else continuation on same line
- local returncode, errorstring = os.spawn(command)
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- if resultname then
- result_save_error(oldbase,newbase)
+ if formatfile and scriptfile then
+ -- we default to mkiv xml !
+ -- the --prep argument might become automatic (and noprep)
+ local suffix = file.extname(filename) or "?"
+ if scripts.context.xmlsuffixes[suffix] or getargument("forcexml") then
+ if getargument("mkii") then
+ filename = makestub(true,"\\processXMLfilegrouped{%s}",filename)
+ else
+ filename = makestub(true,"\\xmlprocess{\\xmldocument}{%s}{}",filename)
+ end
+ elseif scripts.context.cldsuffixes[suffix] or getargument("forcecld") then
+ -- self contained cld files need to have a starttext/stoptext (less fontloading)
+ filename = makestub(false,"\\ctxlua{context.runfile('%s')}",filename)
+ elseif scripts.context.luasuffixes[suffix] or getargument("forcelua") then
+ filename = makestub(true,"\\ctxlua{dofile('%s')}",filename)
+ elseif getargument("prep") then
+ -- we need to keep the original jobname
+ filename = makestub(true,"\\readfile{%s}{}{}",filename,ctxrunner.preppedfile(ctxdata,filename))
end
- os.exit(1)
- break
- elseif returncode == 0 then
- multipass_copyluafile(jobname)
- newhash = multipass_hashfiles(jobname)
- if multipass_changed(oldhash,newhash) then
- oldhash = newhash
+ --
+ -- todo: also other stubs
+ --
+ local suffix, resultname = getargument("suffix"), getargument("result")
+ if type(suffix) == "string" then
+ resultname = file.removesuffix(jobname) .. suffix
+ end
+ local oldbase, newbase = "", ""
+ if type(resultname) == "string" then
+ oldbase = file.removesuffix(jobname)
+ newbase = file.removesuffix(resultname)
+ if oldbase ~= newbase then
+ if getargument("purgeresult") then
+ push_result_purge(oldbase,newbase)
+ else
+ push_result_keep(oldbase,newbase)
+ end
+ else
+ resultname = nil
+ end
else
- break
+ resultname = nil
end
- else
- report("fatal error: return code: %s",returncode or "?")
+ --
+ local pdfview = getargument("autopdf") or getargument("closepdf")
+ if pdfview then
+ scripts.context.closepdf(filename,pdfview)
+ if resultname then
+ scripts.context.closepdf(resultname,pdfview)
+ end
+ end
+ --
+ local okay = statistics.checkfmtstatus(formatfile)
+ if okay ~= true then
+ report("warning: %s, forcing remake",tostring(okay))
+ scripts.context.make(formatname)
+ end
+ --
+ local flags = { }
+ if getargument("batchmode") or getargument("batch") then
+ flags[#flags+1] = "--interaction=batchmode"
+ end
+ if getargument("synctex") then
+ -- this should become a directive
+ report("warning: synctex is enabled") -- can add upto 5% runtime
+ flags[#flags+1] = "--synctex=1"
+ end
+ flags[#flags+1] = "--fmt=" .. quote(formatfile)
+ flags[#flags+1] = "--lua=" .. quote(scriptfile)
+ --
+ -- We pass these directly.
+ --
+
+--~ local silent = getargument("silent")
+--~ local noconsole = getargument("noconsole")
+--~ local directives = getargument("directives")
+--~ local trackers = getargument("trackers")
+--~ if silent == true then
+--~ silent = "*"
+--~ end
+--~ if type(silent) == "string" then
+--~ if type(directives) == "string" then
+--~ directives = format("%s,logs.blocked={%s}",directives,silent)
+--~ else
+--~ directives = format("logs.blocked={%s}",silent)
+--~ end
+--~ end
+--~ if noconsole then
+--~ if type(directives) == "string" then
+--~ directives = format("%s,logs.target=file",directives)
+--~ else
+--~ directives = format("logs.target=file")
+--~ end
+--~ end
+
+ local directives = environment.directives
+ local trackers = environment.trackers
+ local experiments = environment.experiments
+
+ --
+ if type(directives) == "string" then
+ flags[#flags+1] = format('--directives="%s"',directives)
+ end
+ if type(trackers) == "string" then
+ flags[#flags+1] = format('--trackers="%s"',trackers)
+ end
+ --
+ local backend = getargument("backend")
+ if type(backend) ~= "string" then
+ backend = "pdf"
+ end
+ flags[#flags+1] = format('--backend="%s"',backend)
+ --
+ local command = format("luatex %s %s \\stoptext", concat(flags," "), quote(filename))
+ local oldhash, newhash = scripts.context.multipass.hashfiles(jobname), { }
+ local once = getargument("once")
+ local maxnofruns = (once and 1) or scripts.context.multipass.nofruns
+ local arrange = getargument("arrange")
+ for i=1,maxnofruns do
+ -- 1:first run, 2:successive run, 3:once, 4:last of maxruns
+ local kindofrun = (once and 3) or (i==1 and 1) or (i==maxnofruns and 4) or 2
+ scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,false,once) -- kindofrun, currentrun, final
+ report("run %s: %s",i,command)
+--~ print("\n") -- cleaner, else continuation on same line
+ print("") -- cleaner, else continuation on same line
+ local returncode, errorstring = os.spawn(command)
+ --~ if returncode == 3 then
+ --~ scripts.context.make(formatname)
+ --~ returncode, errorstring = os.spawn(command)
+ --~ if returncode == 3 then
+ --~ report("ks: return code 3, message: %s",errorstring or "?")
+ --~ os.exit(1)
+ --~ end
+ --~ end
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ if resultname then
+ save_result_error(oldbase,newbase)
+ end
+ os.exit(1)
+ break
+ elseif returncode > 0 then
+ report("fatal error: return code: %s",returncode or "?")
+ if resultname then
+ save_result_error(oldbase,newbase)
+ end
+ os.exit(returncode)
+ break
+ else
+ scripts.context.multipass.copyluafile(jobname)
+ -- scripts.context.multipass.copytuifile(jobname)
+ newhash = scripts.context.multipass.hashfiles(jobname)
+ if scripts.context.multipass.changed(oldhash,newhash) then
+ oldhash = newhash
+ else
+ break
+ end
+ end
+ end
+ --
+ if arrange then
+ local kindofrun = 3
+ scripts.context.multipass.makeoptionfile(jobname,ctxdata,kindofrun,i,true) -- kindofrun, currentrun, final
+ report("arrange run: %s",command)
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ os.exit(1)
+ elseif returncode > 0 then
+ report("fatal error: return code: %s",returncode or "?")
+ os.exit(returncode)
+ end
+ end
+ --
+ if getargument("purge") then
+ scripts.context.purge_job(jobname)
+ elseif getargument("purgeall") then
+ scripts.context.purge_job(jobname,true)
+ end
+ --
+ os.remove(jobname..".top")
+ --
if resultname then
- result_save_error(oldbase,newbase)
+ if getargument("purgeresult") then
+ -- so, if there is no result then we don't get the old one, but
+ -- related files (log etc) are still there for tracing purposes
+ save_result_purge(oldbase,newbase)
+ else
+ save_result_keep(oldbase,newbase)
+ end
+ report("result renamed to: %s",newbase)
+ end
+ --
+ if getargument("purge") then
+ scripts.context.purge_job(resultname)
+ elseif getargument("purgeall") then
+ scripts.context.purge_job(resultname,true)
+ end
+ --
+ local pdfview = getargument("autopdf")
+ if pdfview then
+ scripts.context.openpdf(resultname or filename,pdfview)
+ end
+ --
+ if getargument("timing") then
+ report()
+ report("you can process (timing) statistics with:",jobname)
+ report()
+ report("context --extra=timing '%s'",jobname)
+ report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
+ report()
end
- os.exit(1) -- (returncode)
- break
- end
- --
- end
- --
- if a_arrange then
- --
- c_flags.final = true
- c_flags.kindofrun = 3
- c_flags.currentrun = c_flags.currentrun + 1
- c_flags.noarrange = nil
- --
- local command = luatex_command(l_flags,c_flags,mainfile)
- --
- report("arrange run: %s",command)
- local returncode, errorstring = os.spawn(command)
- if not returncode then
- report("fatal error: no return code, message: %s",errorstring or "?")
- os.exit(1)
- elseif returncode > 0 then
- report("fatal error: return code: %s",returncode or "?")
- os.exit(returncode)
- end
- --
- end
- --
- if a_purge then
- scripts.context.purge_job(jobname)
- elseif a_purgeall then
- scripts.context.purge_job(jobname,true)
- end
- --
- if resultname then
- if a_purgeresult then
- -- so, if there is no result then we don't get the old one, but
- -- related files (log etc) are still there for tracing purposes
- result_save_purge(oldbase,newbase)
else
- result_save_keep(oldbase,newbase)
+ if formatname then
+ report("error, no format found with name: %s, skipping",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ break
end
- report("result renamed to: %s",newbase)
- end
- --
- if purge then
- scripts.context.purge_job(resultname)
- elseif purgeall then
- scripts.context.purge_job(resultname,true)
- end
- --
- local pdfview = getargument("autopdf")
- if pdfview then
- pdf_open(resultname or jobname,pdfview)
- end
- --
- if a_timing then
- report()
- report("you can process (timing) statistics with:",jobname)
- report()
- report("context --extra=timing '%s'",jobname)
- report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
- report()
end
+ end
+ else
+ if formatname then
+ report("error, no format found with name: %s, aborting",formatname)
else
- if formatname then
- report("error, no format found with name: %s, skipping",formatname)
- else
- report("error, no format found (provide formatname or interface)")
- end
- break
+ report("error, no format found (provide formatname or interface)")
end
end
end
- --
end
-function scripts.context.pipe() -- still used?
+function scripts.context.pipe()
-- context --pipe
-- context --pipe --purge --dummyfile=whatever.tmp
local interface = getargument("interface")
interface = (type(interface) == "string" and interface) or "en"
- local formatname = formatofinterface[interface] or "cont-en"
+ local formatname = scripts.context.interfaces[interface] or "cont-en"
local formatfile, scriptfile = resolvers.locateformat(formatname)
if not formatfile or not scriptfile then
report("warning: no format found, forcing remake (commandline driven)")
@@ -754,16 +1087,11 @@ function scripts.context.pipe() -- still used?
report("warning: %s, forcing remake",tostring(okay))
scripts.context.make(formatname)
end
- local l_flags = {
- interaction = "scrollmode",
- fmt = formatfile,
- lua = scriptfile,
- }
- local c_flags = {
- backend = "pdf",
- final = false,
- kindofrun = 3,
- currentrun = 1,
+ local flags = {
+ "--interaction=scrollmode",
+ "--fmt=" .. quote(formatfile),
+ "--lua=" .. quote(scriptfile),
+ "--backend=pdf",
}
local filename = getargument("dummyfile") or ""
if filename == "" then
@@ -772,9 +1100,10 @@ function scripts.context.pipe() -- still used?
else
filename = file.addsuffix(filename,"tmp")
io.savedata(filename,"\\relax")
+ scripts.context.multipass.makeoptionfile(filename,{ flags = flags },3,1,false) -- kindofrun, currentrun, final
report("entering scrollmode using '%s' with optionfile, end job with \\end",filename)
end
- local command = luatex_command(l_flags,c_flags,filename)
+ local command = format("luatex %s %s", concat(flags," "), quote(filename))
os.spawn(command)
if getargument("purge") then
scripts.context.purge_job(filename)
@@ -794,9 +1123,11 @@ end
local make_mkiv_format = environment.make_format
local function make_mkii_format(name,engine)
- local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
- report("running command: %s",command)
- os.spawn(command)
+ if getargument(engine) then
+ local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
+ report("running command: %s",command)
+ os.spawn(command)
+ end
end
function scripts.context.generate()
@@ -809,17 +1140,14 @@ function scripts.context.make(name)
if not getargument("fast") then -- as in texexec
scripts.context.generate()
end
- local list = (name and { name }) or (environment.files[1] and environment.files) or defaultformats
- local engine = getargument("engine") or "luatex"
+ local list = (name and { name }) or (environment.files[1] and environment.files) or scripts.context.defaultformats
for i=1,#list do
local name = list[i]
- name = formatofinterface[name] or name or ""
- if name == "" then
- -- nothing
- elseif engine == "luatex" then
+ name = scripts.context.interfaces[name] or name or ""
+ if name ~= "" then
make_mkiv_format(name)
- elseif engine == "pdftex" or engine == "xetex" then
- make_mkii_format(name,engine)
+ make_mkii_format(name,"pdftex")
+ make_mkii_format(name,"xetex")
end
end
end
@@ -827,77 +1155,68 @@ end
function scripts.context.ctx()
local ctxdata = ctxrunner.new()
ctxdata.jobname = environment.files[1]
- ctxrunner.checkfile(ctxdata,getargument("ctx"))
- ctxrunner.checkflags(ctxdata)
+ ctxrunner.manipulate(ctxdata,getargument("ctx"))
scripts.context.run(ctxdata)
end
function scripts.context.autoctx()
local ctxdata = nil
- local files = environment.files
+ local files = (filename and { filename }) or environment.files
local firstfile = #files > 0 and files[1]
- if firstfile then
- local suffix = file.suffix(firstfile)
- 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
+ if firstfile and file.extname(firstfile) == "xml" then
+ local f = io.open(firstfile)
+ if f then
+ local chunk = f:read(512) or ""
+ f:close()
+ local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
+ if ctxname then
+ ctxdata = ctxrunner.new()
+ ctxdata.jobname = firstfile
+ ctxrunner.manipulate(ctxdata,ctxname)
end
- elseif suffix == "tex" then
- -- maybe but we scan the preamble later too
end
end
scripts.context.run(ctxdata)
end
--- no longer ok as mlib-run misses something:
+local template = [[
+\starttext
+ \directMPgraphic{%s}{input "%s"}
+\stoptext
+]]
--- local template = [[
--- \starttext
--- \directMPgraphic{%s}{input "%s"}
--- \stoptext
--- ]]
---
--- local loaded = false
---
--- function scripts.context.metapost()
--- local filename = environment.files[1] or ""
--- if not loaded then
--- dofile(resolvers.findfile("mlib-run.lua"))
--- loaded = true
--- commands = commands or { }
--- commands.writestatus = report -- no longer needed
--- end
--- local formatname = getargument("format") or "metafun"
--- if formatname == "" or type(formatname) == "boolean" then
--- formatname = "metafun"
--- end
--- if getargument("pdf") then
--- local basename = file.removesuffix(filename)
--- local resultname = getargument("result") or basename
--- local jobname = "mtx-context-metapost"
--- local tempname = file.addsuffix(jobname,"tex")
--- io.savedata(tempname,format(template,"metafun",filename))
--- environment.files[1] = tempname
--- setargument("result",resultname)
--- setargument("once",true)
--- scripts.context.run()
--- scripts.context.purge_job(jobname,true)
--- scripts.context.purge_job(resultname,true)
--- elseif getargument("svg") then
--- metapost.directrun(formatname,filename,"svg")
--- else
--- metapost.directrun(formatname,filename,"mps")
--- end
--- end
-
--- --
+local loaded = false
+
+function scripts.context.metapost()
+ local filename = environment.files[1] or ""
+ if not loaded then
+ dofile(resolvers.findfile("mlib-run.lua"))
+ loaded = true
+ commands = commands or { }
+ commands.writestatus = report -- no longer needed
+ end
+ local formatname = getargument("format") or "metafun"
+ if formatname == "" or type(formatname) == "boolean" then
+ formatname = "metafun"
+ end
+ if getargument("pdf") then
+ local basename = file.removesuffix(filename)
+ local resultname = getargument("result") or basename
+ local jobname = "mtx-context-metapost"
+ local tempname = file.addsuffix(jobname,"tex")
+ io.savedata(tempname,format(template,"metafun",filename))
+ environment.files[1] = tempname
+ environment.setargument("result",resultname)
+ environment.setargument("once",true)
+ scripts.context.run()
+ scripts.context.purge_job(jobname,true)
+ scripts.context.purge_job(resultname,true)
+ elseif getargument("svg") then
+ metapost.directrun(formatname,filename,"svg")
+ else
+ metapost.directrun(formatname,filename,"mps")
+ end
+end
function scripts.context.version()
local name = resolvers.findfile("context.mkiv")
@@ -919,8 +1238,6 @@ function scripts.context.version()
end
end
--- purging files
-
local generic_files = {
"texexec.tex", "texexec.tui", "texexec.tuo",
"texexec.tuc", "texexec.tua",
@@ -945,6 +1262,7 @@ local persistent_runfiles = {
}
local special_runfiles = {
+--~ "-mpgraph*", "-mprun*", "-temp-*" -- hm, wasn't this escaped?
"-mpgraph", "-mprun", "-temp-"
}
@@ -960,6 +1278,9 @@ local function purge_file(dfile,cfile)
end
end
+local function remove_special_files(pattern)
+end
+
function scripts.context.purge_job(jobname,all,mkiitoo)
if jobname and jobname ~= "" then
jobname = file.basename(jobname)
@@ -997,7 +1318,7 @@ function scripts.context.purge(all,pattern,mkiitoo)
local deleted = { }
for i=1,#files do
local name = files[i]
- local suffix = file.suffix(name)
+ local suffix = file.extname(name)
local basename = file.basename(name)
if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then
deleted[#deleted+1] = purge_file(name)
@@ -1014,14 +1335,12 @@ function scripts.context.purge(all,pattern,mkiitoo)
end
end
--- touching files (signals regeneration of formats)
-
local function touch(name,pattern)
local name = resolvers.findfile(name)
local olddata = io.loaddata(name)
if olddata then
local oldversion, newversion = "", os.date("%Y.%m.%d %H:%M")
- local newdata, ok = gsub(olddata,pattern,function(pre,mid,post)
+ local newdata, ok = olddata:gsub(pattern,function(pre,mid,post)
oldversion = mid
return pre .. newversion .. post
end)
@@ -1055,29 +1374,25 @@ function scripts.context.touch()
touchfiles("mkii")
touchfiles("mkiv")
touchfiles("mkvi")
- touchfiles("mkix")
- touchfiles("mkxi")
- else
- report("touching needs --expert")
end
end
-- modules
local labels = { "title", "comment", "status" }
-local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" }
+local cards = { "*.mkvi", "*.mkiv", "*.tex" }
function scripts.context.modules(pattern)
local list = { }
local found = resolvers.findfile("context.mkiv")
if not pattern or pattern == "" then
-- official files in the tree
- for i=1,#cards do
- resolvers.findwildcardfiles(cards[i],list)
+ for _, card in ipairs(cards) do
+ resolvers.findwildcardfiles(card,list)
end
-- my dev path
- for i=1,#cards do
- dir.glob(file.join(file.dirname(found),cards[i]),list)
+ for _, card in ipairs(cards) do
+ dir.glob(file.join(file.dirname(found),card),list)
end
else
resolvers.findwildcardfiles(pattern,list)
@@ -1090,7 +1405,7 @@ function scripts.context.modules(pattern)
if not done[base] then
done[base] = true
local suffix = file.suffix(base)
- if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then
+ if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" then
local prefix = match(base,"^([xmst])%-")
if prefix then
v = resolvers.findfile(base) -- so that files on my dev path are seen
@@ -1147,28 +1462,30 @@ end
function scripts.context.extra()
local extra = getargument("extra")
- if type(extra) ~= "string" then
- scripts.context.extras()
- elseif getargument("help") then
- scripts.context.extras(extra)
- else
- local fullextra = extra
- if not find(fullextra,"mtx%-context%-") then
- fullextra = "mtx-context-" .. extra
- end
- local foundextra = resolvers.findfile(fullextra)
- if foundextra == "" then
- scripts.context.extras()
- return
+ if type(extra) == "string" then
+ if getargument("help") then
+ scripts.context.extras(extra)
else
- report("processing extra: %s", foundextra)
- end
- setargument("purgeall",true)
- local result = getargument("result") or ""
- if result == "" then
- setargument("result","context-extra")
+ local fullextra = extra
+ if not find(fullextra,"mtx%-context%-") then
+ fullextra = "mtx-context-" .. extra
+ end
+ local foundextra = resolvers.findfile(fullextra)
+ if foundextra == "" then
+ scripts.context.extras()
+ return
+ else
+ report("processing extra: %s", foundextra)
+ end
+ environment.setargument("purgeall",true)
+ local result = environment.setargument("result") or ""
+ if result == "" then
+ environment.setargument("result","context-extra")
+ end
+ scripts.context.run(nil,foundextra)
end
- scripts.context.run(nil,foundextra)
+ else
+ scripts.context.extras()
end
end
@@ -1176,27 +1493,25 @@ end
function scripts.context.trackers()
environment.files = { resolvers.findfile("m-trackers.mkiv") }
- multipass_nofruns = 1
- setargument("purgeall",true)
+ scripts.context.multipass.nofruns = 1
+ environment.setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.directives()
environment.files = { resolvers.findfile("m-directives.mkiv") }
- multipass_nofruns = 1
- setargument("purgeall",true)
+ scripts.context.multipass.nofruns = 1
+ environment.setargument("purgeall",true)
scripts.context.run()
end
function scripts.context.logcategories()
environment.files = { resolvers.findfile("m-logcategories.mkiv") }
- multipass_nofruns = 1
- setargument("purgeall",true)
+ scripts.context.multipass.nofruns = 1
+ environment.setargument("purgeall",true)
scripts.context.run()
end
--- updating (often one will use mtx-update instead)
-
function scripts.context.timed(action)
statistics.timed(action)
end
@@ -1233,7 +1548,7 @@ function scripts.context.update()
local function is_okay(basetree)
for _, tree in next, validtrees do
local pattern = gsub(tree,"%-","%%-")
- if find(basetree,pattern) then
+ if basetree:find(pattern) then
return tree
end
end
@@ -1299,7 +1614,7 @@ function scripts.context.update()
end
for k in zipfile:files() do
local filename = k.filename
- if find(filename,"/$") then
+ if filename:find("/$") then
lfs.mkdir(filename)
else
local data = zip.loaddata(zipfile,filename)
@@ -1337,23 +1652,6 @@ function scripts.context.update()
end
end
--- getting it done
-
-if getargument("nostats") then
- setargument("nostatistics",true)
- setargument("nostat",nil)
-end
-
-if getargument("batch") then
- setargument("batchmode",true)
- setargument("batch",nil)
-end
-
-if getargument("nonstop") then
- setargument("nonstopmode",true)
- setargument("nonstop",nil)
-end
-
do
local silent = getargument("silent")
@@ -1366,9 +1664,9 @@ do
end
if getargument("once") then
- multipass_nofruns = 1
+ scripts.context.multipass.nofruns = 1
elseif getargument("runs") then
- multipass_nofruns = tonumber(getargument("runs")) or nil
+ scripts.context.multipass.nofruns = tonumber(getargument("runs")) or nil
end
if getargument("profile") then
@@ -1376,6 +1674,7 @@ if getargument("profile") then
end
if getargument("run") then
+-- scripts.context.timed(scripts.context.run)
scripts.context.timed(scripts.context.autoctx)
elseif getargument("make") then
scripts.context.timed(function() scripts.context.make() end)
@@ -1383,8 +1682,8 @@ elseif getargument("generate") then
scripts.context.timed(function() scripts.context.generate() end)
elseif getargument("ctx") then
scripts.context.timed(scripts.context.ctx)
--- elseif getargument("mp") or getargument("metapost") then
--- scripts.context.timed(scripts.context.metapost)
+elseif getargument("mp") or getargument("metapost") then
+ scripts.context.timed(scripts.context.metapost)
elseif getargument("version") then
application.identify()
scripts.context.version()
@@ -1412,7 +1711,10 @@ elseif getargument("showdirectives") or getargument("directives") == true then
scripts.context.directives()
elseif getargument("showlogcategories") then
scripts.context.logcategories()
-elseif environment.files[1] or getargument("nofile") then
+elseif getargument("track") and type(getargument("track")) == "boolean" then -- for old times sake, will go
+ scripts.context.trackers()
+elseif environment.files[1] then
+-- scripts.context.timed(scripts.context.run)
scripts.context.timed(scripts.context.autoctx)
elseif getargument("pipe") then
scripts.context.timed(scripts.context.pipe)