diff options
Diffstat (limited to 'tex/context/base/core-ctx.lua')
-rw-r--r-- | tex/context/base/core-ctx.lua | 694 |
1 files changed, 347 insertions, 347 deletions
diff --git a/tex/context/base/core-ctx.lua b/tex/context/base/core-ctx.lua index d5cdc3143..18978a530 100644 --- a/tex/context/base/core-ctx.lua +++ b/tex/context/base/core-ctx.lua @@ -1,347 +1,347 @@ -if not modules then modules = { } end modules ['core-ctx'] = {
- version = 1.001,
- comment = "companion to core-ctx.mkiv",
- author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright = "PRAGMA ADE / ConTeXt Development Team",
- license = "see context related readme files"
-}
-
---[[
-Job control files aka ctx files are rather old and date from the mkii times.
-They were handled in texexec and mtx-context and deals with modes, modules,
-environments and preprocessing in projects where one such file drives the
-processing of lots of files without the need to provide command line
-arguments.
-
-In mkiv this concept was of course supported as well. The first implementation
-of mtx-context took much of the approach of texexec, but by now we have gotten
-rid of the option file (for passing modes, modules and environments), the stubs
-(for directly processing cld and xml) as well as the preprocessing component
-of the ctx files. Special helper features, like typesetting listings, were
-already moved to the extras (a direct side effect of the ability to pass along
-command line arguments.) All this made mtx-context more simple than its ancestor
-texexec.
-
-Because some of the modes might affect the mtx-context end, the ctx file is
-still loaded there but only for getting the modes. The file is loaded again
-during the run but as loading and basic processing takes less than a
-millisecond it's not that much of a burden.
---]]
-
--- the ctxrunner tabel might either become private or move to the job namespace
--- which also affects the loading order
-
-local trace_prepfiles = false trackers.register("system.prepfiles", function(v) trace_prepfiles = v end)
-
-local gsub, find, match, validstring = string.gsub, string.find, string.match, string.valid
-local concat = table.concat
-local xmltext = xml.text
-
-local report_prepfiles = logs.reporter("system","prepfiles")
-
-commands = commands or { }
-local commands = commands
-
-ctxrunner = ctxrunner or { }
-
-ctxrunner.prepfiles = utilities.storage.allocate()
-
-local function dontpreparefile(t,k)
- return k -- we only store when we have a prepper
-end
-
-table.setmetatableindex(ctxrunner.prepfiles,dontpreparefile)
-
-local function filtered(str,method) -- in resolvers?
- str = tostring(str)
- if method == 'name' then str = file.nameonly(str)
- elseif method == 'path' then str = file.dirname(str)
- elseif method == 'suffix' then str = file.suffix(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 (gsub(str,"\\","/"))
-end
-
--- local function substitute(e,str)
--- local attributes = e.at
--- if str and attributes then
--- if attributes['method'] then
--- str = filtered(str,attributes['method'])
--- end
--- if str == "" and attributes['default'] then
--- str = attributes['default']
--- end
--- end
--- return str
--- end
-
-local function substitute(str)
- return str
-end
-
-local function justtext(str)
- str = xml.unescaped(tostring(str))
- str = xml.cleansed(str)
- str = gsub(str,"\\+",'/')
- str = gsub(str,"%s+",' ')
- return str
-end
-
-function ctxrunner.load(ctxname)
-
- local xmldata = xml.load(ctxname)
-
- local jobname = tex.jobname -- todo
-
- local variables = { job = jobname }
- local commands = { }
- local flags = { }
- local paths = { } -- todo
- local treatments = { }
- local suffix = "prep"
-
- xml.include(xmldata,'ctx:include','name', {'.', file.dirname(ctxname), "..", "../.." })
-
- for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
- local flag = xmltext(e)
- local key, value = match(flag,"^(.-)=(.+)$")
- if key and value then
- environment.setargument(key,value)
- else
- environment.setargument(flag,true)
- end
- end
-
- -- add to document.options.ctxfile[...]
-
- local ctxfile = document.options.ctxfile
-
- local modes = ctxfile.modes
- local modules = ctxfile.modules
- local environments = ctxfile.environments
-
- for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode") do
- modes[#modes+1] = xmltext(e)
- end
-
- for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module") do
- modules[#modules+1] = xmltext(e)
- end
-
- for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do
- environments[#environments+1] = xmltext(e)
- end
-
- for e in xml.collected(xmldata,"ctx:message") do
- report_prepfiles("ctx comment: %s", xmltext(e))
- end
-
- for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do
- d[k] = variables['job'] or ""
- end
-
- for e in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do
- local name = e.at and e.at['name'] or "unknown"
- local suffix = e.at and e.at['suffix'] or "prep"
- for r, d, k in xml.elements(command,"ctx:old") do
- d[k] = "%old%"
- end
- for r, d, k in xml.elements(e,"ctx:new") do
- d[k] = "%new%"
- end
- for r, d, k in xml.elements(e,"ctx:value") do
- local tag = d[k].at['name']
- if tag then
- d[k] = "%" .. tag .. "%"
- end
- end
- local runner = xml.textonly(e)
- if runner and runner ~= "" then
- commands[name] = {
- suffix = suffix,
- runner = runner,
- }
- end
- end
-
- local suffix = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/attribute('suffix')") or suffix
- local runlocal = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local')")
-
- runlocal = toboolean(runlocal)
-
- -- todo: only collect, then plug into file handler
-
- local inputfile = validstring(environment.arguments.input) or jobname
-
- variables.old = inputfile
-
- for files in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:files") do
- for pattern in xml.collected(files,"ctx:file") do
- local preprocessor = pattern.at['processor'] or ""
- for r, d, k in xml.elements(pattern,"/ctx:old") do
- d[k] = jobname
- end
- for r, d, k in xml.elements(pattern,"/ctx:value[@name='old'") do
- d[k] = jobname
- end
- pattern =justtext(xml.tostring(pattern))
- if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then
- local noftreatments = #treatments + 1
- local findpattern = string.topattern(pattern)
- local preprocessors = utilities.parsers.settings_to_array(preprocessor)
- treatments[noftreatments] = {
- pattern = findpattern,
- preprocessors = preprocessors,
- }
- report_prepfiles("step %s, pattern %a, preprocessor: %a",noftreatments,findpattern,preprocessors)
- end
- end
- end
-
- local function needstreatment(oldfile)
- for i=1,#treatments do
- local treatment = treatments[i]
- local pattern = treatment.pattern
- if find(oldfile,pattern) then
- return treatment
- end
- end
- end
-
- local preparefile = #treatments > 0 and function(prepfiles,filename)
-
- local treatment = needstreatment(filename)
- local oldfile = filename
- local newfile = false
- if treatment then
- local preprocessors = treatment.preprocessors
- local runners = { }
- for i=1,#preprocessors do
- local preprocessor = preprocessors[i]
- local command = commands[preprocessor]
- if command then
- local runner = command.runner
- local suffix = command.suffix
- local result = filename .. "." .. suffix
- if runlocal then
- result = file.basename(result)
- end
- variables.old = oldfile
- variables.new = result
- runner = utilities.templates.replace(runner,variables)
- if runner and runner ~= "" then
- runners[#runners+1] = runner
- oldfile = result
- if runlocal then
- oldfile = file.basename(oldfile)
- end
- newfile = oldfile
- end
- end
- end
- if not newfile then
- newfile = filename
- elseif file.needsupdating(filename,newfile) then
- for i=1,#runners do
- report_prepfiles("step %i: %s",i,runners[i])
- end
- --
- for i=1,#runners do
- local command = runners[i]
- report_prepfiles("command: %s",command)
- local result = os.spawn(command) or 0
- -- if result > 0 then
- -- report_prepfiles("error, return code: %s",result)
- -- end
- end
- if lfs.isfile(newfile) then
- file.syncmtimes(filename,newfile)
- report_prepfiles("%a is converted to %a",filename,newfile)
- else
- report_prepfiles("%a is not converted to %a",filename,newfile)
- newfile = filename
- end
- elseif lfs.isfile(newfile) then
- report_prepfiles("%a is already converted to %a",filename,newfile)
- end
- else
- newfile = filename
- end
- prepfiles[filename] = newfile
- -- in case we ask twice (with the prepped name) ... todo: avoid this mess
- prepfiles[newfile] = newfile
- return newfile
- end
-
- table.setmetatableindex(ctxrunner.prepfiles,preparefile or dontpreparefile)
-
- -- we need to deal with the input filename as it has already be resolved
-
-end
-
--- print("\n")
--- document = {
--- options = {
--- ctxfile = {
--- modes = { },
--- modules = { },
--- environments = { },
--- }
--- }
--- }
--- environment.arguments.input = "test.tex"
--- ctxrunner.load("x-ldx.ctx")
-
-local function resolve(name) -- used a few times later on
- return ctxrunner.prepfiles[file.collapsepath(name)] or false
-end
-
-local processfile = commands.processfile
-local doifinputfileelse = commands.doifinputfileelse
-
-function commands.processfile(name,maxreadlevel) -- overloaded
- local prepname = resolve(name)
- if prepname then
- return processfile(prepname,0)
- end
- return processfile(name,maxreadlevel)
-end
-
-function commands.doifinputfileelse(name,depth)
- local prepname = resolve(name)
- if prepname then
- return doifinputfileelse(prepname,0)
- end
- return doifinputfileelse(name,depth)
-end
-
-function commands.preparedfile(name)
- return resolve(name) or name
-end
-
-function commands.getctxfile()
- local ctxfile = document.arguments.ctx or ""
- if ctxfile ~= "" then
- ctxrunner.load(ctxfile) -- do we need to locate it?
- end
-end
-
-function ctxrunner.resolve(name) -- used a few times later on
- local collapsedname = file.collapsepath(name,".")
- return ctxrunner.prepfiles[collapsedname] or collapsedname
-end
-
--- ctxrunner.load("t:/sources/core-ctx.ctx")
-
--- context(ctxrunner.prepfiles["one-a.xml"]) context.par()
--- context(ctxrunner.prepfiles["one-b.xml"]) context.par()
--- context(ctxrunner.prepfiles["two-c.xml"]) context.par()
--- context(ctxrunner.prepfiles["two-d.xml"]) context.par()
--- context(ctxrunner.prepfiles["all-x.xml"]) context.par()
-
--- inspect(ctxrunner.prepfiles)
+if not modules then modules = { } end modules ['core-ctx'] = { + version = 1.001, + comment = "companion to core-ctx.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +--[[ +Job control files aka ctx files are rather old and date from the mkii times. +They were handled in texexec and mtx-context and deals with modes, modules, +environments and preprocessing in projects where one such file drives the +processing of lots of files without the need to provide command line +arguments. + +In mkiv this concept was of course supported as well. The first implementation +of mtx-context took much of the approach of texexec, but by now we have gotten +rid of the option file (for passing modes, modules and environments), the stubs +(for directly processing cld and xml) as well as the preprocessing component +of the ctx files. Special helper features, like typesetting listings, were +already moved to the extras (a direct side effect of the ability to pass along +command line arguments.) All this made mtx-context more simple than its ancestor +texexec. + +Because some of the modes might affect the mtx-context end, the ctx file is +still loaded there but only for getting the modes. The file is loaded again +during the run but as loading and basic processing takes less than a +millisecond it's not that much of a burden. +--]] + +-- the ctxrunner tabel might either become private or move to the job namespace +-- which also affects the loading order + +local trace_prepfiles = false trackers.register("system.prepfiles", function(v) trace_prepfiles = v end) + +local gsub, find, match, validstring = string.gsub, string.find, string.match, string.valid +local concat = table.concat +local xmltext = xml.text + +local report_prepfiles = logs.reporter("system","prepfiles") + +commands = commands or { } +local commands = commands + +ctxrunner = ctxrunner or { } + +ctxrunner.prepfiles = utilities.storage.allocate() + +local function dontpreparefile(t,k) + return k -- we only store when we have a prepper +end + +table.setmetatableindex(ctxrunner.prepfiles,dontpreparefile) + +local function filtered(str,method) -- in resolvers? + str = tostring(str) + if method == 'name' then str = file.nameonly(str) + elseif method == 'path' then str = file.dirname(str) + elseif method == 'suffix' then str = file.suffix(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 (gsub(str,"\\","/")) +end + +-- local function substitute(e,str) +-- local attributes = e.at +-- if str and attributes then +-- if attributes['method'] then +-- str = filtered(str,attributes['method']) +-- end +-- if str == "" and attributes['default'] then +-- str = attributes['default'] +-- end +-- end +-- return str +-- end + +local function substitute(str) + return str +end + +local function justtext(str) + str = xml.unescaped(tostring(str)) + str = xml.cleansed(str) + str = gsub(str,"\\+",'/') + str = gsub(str,"%s+",' ') + return str +end + +function ctxrunner.load(ctxname) + + local xmldata = xml.load(ctxname) + + local jobname = tex.jobname -- todo + + local variables = { job = jobname } + local commands = { } + local flags = { } + local paths = { } -- todo + local treatments = { } + local suffix = "prep" + + xml.include(xmldata,'ctx:include','name', {'.', file.dirname(ctxname), "..", "../.." }) + + for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do + local flag = xmltext(e) + local key, value = match(flag,"^(.-)=(.+)$") + if key and value then + environment.setargument(key,value) + else + environment.setargument(flag,true) + end + end + + -- add to document.options.ctxfile[...] + + local ctxfile = document.options.ctxfile + + local modes = ctxfile.modes + local modules = ctxfile.modules + local environments = ctxfile.environments + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:mode") do + modes[#modes+1] = xmltext(e) + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:module") do + modules[#modules+1] = xmltext(e) + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do + environments[#environments+1] = xmltext(e) + end + + for e in xml.collected(xmldata,"ctx:message") do + report_prepfiles("ctx comment: %s", xmltext(e)) + end + + for r, d, k in xml.elements(xmldata,"ctx:value[@name='job']") do + d[k] = variables['job'] or "" + end + + for e in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do + local name = e.at and e.at['name'] or "unknown" + local suffix = e.at and e.at['suffix'] or "prep" + for r, d, k in xml.elements(command,"ctx:old") do + d[k] = "%old%" + end + for r, d, k in xml.elements(e,"ctx:new") do + d[k] = "%new%" + end + for r, d, k in xml.elements(e,"ctx:value") do + local tag = d[k].at['name'] + if tag then + d[k] = "%" .. tag .. "%" + end + end + local runner = xml.textonly(e) + if runner and runner ~= "" then + commands[name] = { + suffix = suffix, + runner = runner, + } + end + end + + local suffix = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/attribute('suffix')") or suffix + local runlocal = xml.filter(xmldata,"xml:///ctx:job/ctx:preprocess/ctx:processors/attribute('local')") + + runlocal = toboolean(runlocal) + + -- todo: only collect, then plug into file handler + + local inputfile = validstring(environment.arguments.input) or jobname + + variables.old = inputfile + + for files in xml.collected(xmldata,"/ctx:job/ctx:preprocess/ctx:files") do + for pattern in xml.collected(files,"ctx:file") do + local preprocessor = pattern.at['processor'] or "" + for r, d, k in xml.elements(pattern,"/ctx:old") do + d[k] = jobname + end + for r, d, k in xml.elements(pattern,"/ctx:value[@name='old'") do + d[k] = jobname + end + pattern =justtext(xml.tostring(pattern)) + if preprocessor and preprocessor ~= "" and pattern and pattern ~= "" then + local noftreatments = #treatments + 1 + local findpattern = string.topattern(pattern) + local preprocessors = utilities.parsers.settings_to_array(preprocessor) + treatments[noftreatments] = { + pattern = findpattern, + preprocessors = preprocessors, + } + report_prepfiles("step %s, pattern %a, preprocessor: %a",noftreatments,findpattern,preprocessors) + end + end + end + + local function needstreatment(oldfile) + for i=1,#treatments do + local treatment = treatments[i] + local pattern = treatment.pattern + if find(oldfile,pattern) then + return treatment + end + end + end + + local preparefile = #treatments > 0 and function(prepfiles,filename) + + local treatment = needstreatment(filename) + local oldfile = filename + local newfile = false + if treatment then + local preprocessors = treatment.preprocessors + local runners = { } + for i=1,#preprocessors do + local preprocessor = preprocessors[i] + local command = commands[preprocessor] + if command then + local runner = command.runner + local suffix = command.suffix + local result = filename .. "." .. suffix + if runlocal then + result = file.basename(result) + end + variables.old = oldfile + variables.new = result + runner = utilities.templates.replace(runner,variables) + if runner and runner ~= "" then + runners[#runners+1] = runner + oldfile = result + if runlocal then + oldfile = file.basename(oldfile) + end + newfile = oldfile + end + end + end + if not newfile then + newfile = filename + elseif file.needsupdating(filename,newfile) then + for i=1,#runners do + report_prepfiles("step %i: %s",i,runners[i]) + end + -- + for i=1,#runners do + local command = runners[i] + report_prepfiles("command: %s",command) + local result = os.spawn(command) or 0 + -- if result > 0 then + -- report_prepfiles("error, return code: %s",result) + -- end + end + if lfs.isfile(newfile) then + file.syncmtimes(filename,newfile) + report_prepfiles("%a is converted to %a",filename,newfile) + else + report_prepfiles("%a is not converted to %a",filename,newfile) + newfile = filename + end + elseif lfs.isfile(newfile) then + report_prepfiles("%a is already converted to %a",filename,newfile) + end + else + newfile = filename + end + prepfiles[filename] = newfile + -- in case we ask twice (with the prepped name) ... todo: avoid this mess + prepfiles[newfile] = newfile + return newfile + end + + table.setmetatableindex(ctxrunner.prepfiles,preparefile or dontpreparefile) + + -- we need to deal with the input filename as it has already be resolved + +end + +-- print("\n") +-- document = { +-- options = { +-- ctxfile = { +-- modes = { }, +-- modules = { }, +-- environments = { }, +-- } +-- } +-- } +-- environment.arguments.input = "test.tex" +-- ctxrunner.load("x-ldx.ctx") + +local function resolve(name) -- used a few times later on + return ctxrunner.prepfiles[file.collapsepath(name)] or false +end + +local processfile = commands.processfile +local doifinputfileelse = commands.doifinputfileelse + +function commands.processfile(name,maxreadlevel) -- overloaded + local prepname = resolve(name) + if prepname then + return processfile(prepname,0) + end + return processfile(name,maxreadlevel) +end + +function commands.doifinputfileelse(name,depth) + local prepname = resolve(name) + if prepname then + return doifinputfileelse(prepname,0) + end + return doifinputfileelse(name,depth) +end + +function commands.preparedfile(name) + return resolve(name) or name +end + +function commands.getctxfile() + local ctxfile = document.arguments.ctx or "" + if ctxfile ~= "" then + ctxrunner.load(ctxfile) -- do we need to locate it? + end +end + +function ctxrunner.resolve(name) -- used a few times later on + local collapsedname = file.collapsepath(name,".") + return ctxrunner.prepfiles[collapsedname] or collapsedname +end + +-- ctxrunner.load("t:/sources/core-ctx.ctx") + +-- context(ctxrunner.prepfiles["one-a.xml"]) context.par() +-- context(ctxrunner.prepfiles["one-b.xml"]) context.par() +-- context(ctxrunner.prepfiles["two-c.xml"]) context.par() +-- context(ctxrunner.prepfiles["two-d.xml"]) context.par() +-- context(ctxrunner.prepfiles["all-x.xml"]) context.par() + +-- inspect(ctxrunner.prepfiles) |