diff options
author | Siep Kroonenberg <siepo@cybercomm.nl> | 2023-02-26 14:42:54 +0000 |
---|---|---|
committer | Siep Kroonenberg <siepo@cybercomm.nl> | 2023-02-26 14:42:54 +0000 |
commit | c2cbe5554ef9b3243e33d38ed75cfd00542103fd (patch) | |
tree | da3591d9e0b9b690cec136eec56853a130f537e6 /Master/texmf-dist/scripts/context/lua | |
parent | b09967bfe2ae329f19b19973e14acd2b69754357 (diff) |
ConTeXt LMTX: scripts
git-svn-id: svn://tug.org/texlive/trunk@66175 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/context/lua')
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-cache.lua | 3 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-context.lua | 146 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-context.xml | 16 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-ctan.lua | 319 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-fonts.lua | 35 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-install.lua | 64 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-interface.lua | 138 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-patterns.lua | 24 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-pdf.lua | 26 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-spell.lua | 346 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-synctex.lua | 179 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-unicode.lua | 173 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-update.lua | 69 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/context/lua/mtx-vscode.lua | 417 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/context/lua/mtxrun.lua | 1208 |
15 files changed, 2427 insertions, 736 deletions
diff --git a/Master/texmf-dist/scripts/context/lua/mtx-cache.lua b/Master/texmf-dist/scripts/context/lua/mtx-cache.lua index 4f378ff0a69..79b9a118cf1 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-cache.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-cache.lua @@ -78,7 +78,8 @@ local function erase(banner,path,list) local kept = 0 for i=1,#list do local filename = list[i] - if find(filename,"luatex%-cache") then + -- if find(filename,"luatex%-cache") then + if find(filename,LUATEXENGINE .. "%-cache") then remove(filename) if isfile(filename) then kept = kept + 1 diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.lua b/Master/texmf-dist/scripts/context/lua/mtx-context.lua index 7ae350111be..014a7d4efe4 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-context.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-context.lua @@ -22,6 +22,7 @@ local setargument = environment.setargument local filejoinname = file.join local filebasename = file.basename +local filenameonly = file.nameonly local filepathpart = file.pathpart local filesuffix = file.suffix local fileaddsuffix = file.addsuffix @@ -106,12 +107,14 @@ end -- -- The way we use stubs will change in a bit in 2019 (mtxrun and context). We also normalize -- -- the platforms to use a similar approach to this. -local engine_new = file.nameonly(getargument("engine") or directives.value("system.engine")) -local engine_old = file.nameonly(environment.ownmain) or file.nameonly(environment.ownbin) +local engine_new = filenameonly(getargument("engine") or directives.value("system.engine")) +local engine_old = filenameonly(environment.ownmain) or filenameonly(environment.ownbin) local function restart(engine_old,engine_new) - local ownname = file.join(file.dirname(environment.ownname),"mtxrun.lua") - local command = format("%s --luaonly %q %s --redirected",engine_new,ownname,environment.reconstructcommandline()) + local generate = environment.arguments.generate and (engine_new == "luatex" or engine_new == "luajittex") + local arguments = generate and "--generate" or environment.reconstructcommandline() + local ownname = filejoinname(filepathpart(environment.ownname),"mtxrun.lua") + local command = format("%s --luaonly %q %s --redirected",engine_new,ownname,arguments) report(format("redirect %s -> %s: %s",engine_old,engine_new,command)) local result = os.execute(command) os.exit(result == 0 and 0 or 1) @@ -361,20 +364,29 @@ local function multipass_changed(oldhash, newhash) return false end -local f_tempfile = formatters["%s-%s-%02d.tmp"] +local f_tempfile_i = formatters["%s-%s-%02d.tmp"] +local f_tempfile_s = formatters["%s-%s-keep.%s"] local function backup(jobname,run,kind,filename) - if run == 1 then - for i=1,10 do - local tmpname = f_tempfile(jobname,kind,i) - if validfile(tmpname) then - removefile(tmpname) - report("removing %a",tmpname) + if run then + if run == 1 then + for i=1,10 do + local tmpname = f_tempfile_i(jobname,kind,i) + if validfile(tmpname) then + removefile(tmpname) + report("removing %a",tmpname) + end end end - end - if validfile(filename) then - local tmpname = f_tempfile(jobname,kind,run or 1) + if validfile(filename) then + local tmpname = f_tempfile_i(jobname,kind,run or 1) + report("copying %a into %a",filename,tmpname) + file.copy(filename,tmpname) + else + report("no file %a, nothing kept",filename) + end + elseif validfile(filename) then + local tmpname = f_tempfile_s(jobname,kind,kind) report("copying %a into %a",filename,tmpname) file.copy(filename,tmpname) else @@ -395,10 +407,20 @@ local function multipass_copyluafile(jobname,run) end end +local function multipass_copypdffile(jobname,run) + if run then + local pdfname = jobname..".pdf" + if validfile(pdfname) then + backup(jobname,false,"pdf",pdfname) + report() + end + end +end + local function multipass_copylogfile(jobname,run) - local logname = jobname..".log" - if validfile(logname) then - if run then + if run then + local logname = jobname..".log" + if validfile(logname) then backup(jobname,run,"log",logname) report() end @@ -659,6 +681,7 @@ function scripts.context.run(ctxdata,filename) local a_purgeall = getargument("purgeall") local a_purgeresult = getargument("purgeresult") local a_global = getargument("global") + local a_runpath = getargument("runpath") local a_timing = getargument("timing") local a_profile = getargument("profile") local a_batchmode = getargument("batchmode") @@ -673,6 +696,7 @@ function scripts.context.run(ctxdata,filename) local a_texformat = getargument("texformat") local a_keeptuc = getargument("keeptuc") local a_keeplog = getargument("keeplog") + local a_keeppdf = getargument("keeppdf") local a_export = getargument("export") local a_nodates = getargument("nodates") local a_trailerid = getargument("trailerid") @@ -692,9 +716,13 @@ function scripts.context.run(ctxdata,filename) local basename = filebasename(filename) -- use splitter local pathname = filepathpart(filename) -- + if filesuffix(filename) == "" then + filename = fileaddsuffix(filename,"tex") + end + -- if pathname == "" and not a_global and filename ~= usedfiles.nop then filename = "./" .. filename - if not validfile(filename) and not validfile(filename..".tex") then + if not validfile(filename) then report("warning: no (local) file %a, proceeding",filename) end end @@ -715,6 +743,31 @@ function scripts.context.run(ctxdata,filename) formatfile, scriptfile = resolvers.locateformat(formatname) end -- + local runpath = a_runpath or analysis.runpath + if type(runpath) == "string" and runpath ~= "" then + runpath = resolvers.resolve(runpath) + local currentdir = dir.current() + if not lfs.isdir(runpath) then + if dir.makedirs(runpath) then + report("runpath %a has been created",runpath) + else + report("error: runpath %a cannot be created",runpath) + os.exit() + end + end + if lfs.chdir(runpath) then + report("changing to runpath %a",runpath) + else + report("error: changing to runpath %a is impossible",runpath) + os.exit() + end + environment.arguments.path = currentdir + environment.arguments.runpath = runpath + if filepathpart(filename) == "." then + filename = filebasename(filename) + end + end + -- a_jithash = validstring(a_jithash or analysis.jithash) or nil a_permitloadlib = a_permitloadlib or analysis.permitloadlib or nil -- @@ -733,19 +786,23 @@ function scripts.context.run(ctxdata,filename) return flag or plus -- flag wins end end - local a_trackers = analysis.trackers - local a_experiments = analysis.experiments + ----- a_trackers = analysis.trackers + ----- a_experiments = analysis.experiments local directives = combine("directives") local trackers = combine("trackers") local experiments = combine("experiments") -- + local ownerpassword = environment.ownerpassword or analysis.ownerpassword + local userpassword = environment.userpassword or analysis.userpassword + local permissions = environment.permissions or analysis.permissions + -- if formatfile and scriptfile then local suffix = validstring(getargument("suffix")) local resultname = validstring(getargument("result")) if not resultname or resultname == "" then resultname = validstring(analysis.result) end - local resultpath = file.pathpart(resultname) + local resultpath = filepathpart(resultname) if resultpath ~= "" then resultname = nil elseif suffix then @@ -805,6 +862,10 @@ function scripts.context.run(ctxdata,filename) export = a_export and true or nil, nocompression = a_nocompression and true or nil, texmfbinpath = os.selfdir, + -- + ownerpassword = ownerpassword, + userpassword = userpassword, + permissions = permissions, } -- for k, v in next, environment.arguments do @@ -816,6 +877,14 @@ function scripts.context.run(ctxdata,filename) -- -- todo: --output-file=... in luatex -- + local usedname = jobname + local engine = analysis.engine or "luametatex" + if engine == "luametatex" and (mainfile == usedfiles.yes or mainfile == usedfiles.nop) and not getargument("redirected") then + mainfile = "" -- we don't need that + usedname = fulljobname + end + -- + -- local l_flags = { ["interaction"] = a_batchmode, -- ["synctex"] = false, -- context has its own way @@ -825,7 +894,8 @@ function scripts.context.run(ctxdata,filename) -- ["file-line-error-style"] = true, -- ["fmt"] = formatfile, -- ["lua"] = scriptfile, - ["jobname"] = jobname, +-- ["jobname"] = jobname, + ["jobname"] = usedname, ["jithash"] = a_jithash, ["permitloadlib"] = a_permitloadlib, } @@ -854,10 +924,9 @@ function scripts.context.run(ctxdata,filename) -- -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns -- - local engine = analysis.engine or "luametatex" - if engine == "luametatex" and (mainfile == usedfiles.yes or mainfile == usedfiles.nop) then - mainfile = "" -- we don't need that - end + -- can be used to include pages from a previous run, --keeppdf or "% keeppdf" on first-line + -- + multipass_copypdffile(jobname,a_keeppdf or analysis.keeppdf) -- for currentrun=1,maxnofruns do -- @@ -913,7 +982,7 @@ function scripts.context.run(ctxdata,filename) end -- if environment.arguments["ansilog"] then - local logfile = file.replacesuffix(jobname,"log") + local logfile = filenewsuffix(jobname,"log") local logdata = io.loaddata(logfile) or "" if logdata ~= "" then io.savedata(logfile,(gsub(logdata,"%[.-m",""))) @@ -1438,7 +1507,7 @@ end function scripts.context.pages() local filename = environment.files[1] if filename then - local u = table.load(file.addsuffix(filename,"tuc")) + local u = table.load(fileaddsuffix(filename,"tuc")) if u then local p = u.structures.pages.collected local l = u.structures.lists.collected @@ -1637,19 +1706,16 @@ end -- todo: we need to do a dummy run -function scripts.context.trackers() - environment.files = { resolvers.findfile("m-trackers.mkiv") } +local function showsetter() + environment.files = { resolvers.findfile("mtx-context-setters.tex") } multipass_nofruns = 1 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.run() -end +scripts.context.trackers = showsetter +scripts.context.directives = showsetter +scripts.context.experiments = showsetter function scripts.context.logcategories() environment.files = { resolvers.findfile("m-logcategories.mkiv") } @@ -1664,6 +1730,12 @@ end -- getting it done +if getargument("pdftex") then + setargument("engine","pdftex") +elseif getargument("xetex") then + setargument("engine","xetex") +end + if getargument("timedlog") then logs.settimedlog() end @@ -1781,7 +1853,7 @@ end do if getargument("wipebusy") then - os.remove("context-is-busy.tmp") + removefile("context-is-busy.tmp") end end diff --git a/Master/texmf-dist/scripts/context/lua/mtx-context.xml b/Master/texmf-dist/scripts/context/lua/mtx-context.xml index 98a75244b12..bf341c21a9f 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-context.xml +++ b/Master/texmf-dist/scripts/context/lua/mtx-context.xml @@ -148,7 +148,7 @@ <short>never initializes synctex (for production runs)</short> </flag> <flag name="synctex"> - <short>run with synctex enabled (better use \setupsynctex[state=start]</short> + <short>run with synctex enabled (better use \setupsynctex[state=start])</short> </flag> </subcategory> <subcategory> @@ -202,6 +202,9 @@ <flag name="keeptuc"> <short>keep previous tuc files (jobname-tuc-[run].tmp)</short> </flag> + <flag name="keeppdf"> + <short>keep previous pdf files (jobname-pdf-keep.tmp)</short> + </flag> <flag name="keeplog"> <short>keep previous log files (jobname-log-[run].tmp)</short> </flag> @@ -220,6 +223,17 @@ <short>show extras</short> </flag> </subcategory> + <subcategory> + <flag name="ownerpassword"> + <short>encrypt the (pdf) file using this master password</short> + </flag> + <flag name="userpassword"> + <short>use an additional password for opening the document</short> + </flag> + <flag name="permissions"> + <short>list of: print, modify, extract, add, fillin, assemble, quality</short> + </flag> + </subcategory> </category> <category name="special"> <subcategory> diff --git a/Master/texmf-dist/scripts/context/lua/mtx-ctan.lua b/Master/texmf-dist/scripts/context/lua/mtx-ctan.lua new file mode 100644 index 00000000000..798a2da02f4 --- /dev/null +++ b/Master/texmf-dist/scripts/context/lua/mtx-ctan.lua @@ -0,0 +1,319 @@ +if not modules then modules = { } end modules ['mtx-ctan'] = { + version = 1.00, + comment = "companion to mtxrun.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +-- This is just an experiment. Some day I want to be able to install fonts this way +-- but maybe fetching tex live packages is also an option (I need to check if there +-- is an api for that ... in wintertime). Normally fonts come from the web but I had +-- to fetch newcm from ctan, so ... +-- +-- mtxrun --script ctan --packages --pattern=computermodern + +-- http://www.ctan.org/json/2.0/packages +-- http://www.ctan.org/json/2.0/pkg/name +-- http://www.ctan.org/json/2.0/topics : key details +-- http://www.ctan.org/json/2.0/topic/name : key details +-- http://www.ctan.org/json/2.0/topic/name?ref=true : key details packages + +local lower, find, gsub = string.lower, string.find, string.gsub +local write_nl = (logs and logs.writer) or (texio and texio.write_nl) or print +local xmlconvert, xmltext, xmlattr, xmlcollected = xml.convert, xml.text, xml.attribute, xml.collected + +local helpinfo = [[ +<?xml version="1.0"?> +<application> + <metadata> + <entry name="name">mtx-ctan</entry> + <entry name="detail">Dealing with CTAN</entry> + <entry name="version">1.00</entry> + </metadata> + <flags> + <category name="basic"> + <subcategory> + <flag name="packages"><short>list available packages</short></flag> + <flag name="topics"><short>list available topics</short></flag> + <flag name="detail"><short>show details about package</short></flag> + <flag name="pattern" value="string"><short>use this pattern, otherwise first argument</short></flag> + </subcategory> + </category> + </flags> +</application> +]] + +local application = logs.application { + name = "mtx-ctan", + banner = "Dealing with CTAN", + helpinfo = helpinfo, +} + +local report = application.report + +scripts = scripts or { } +scripts.ctan = scripts.ctan or { } + +local okay, json = pcall(require,"util-jsn") +local okay, curl = pcall(require,"libs-imp-curl") + pcall(require,"char-ini") + +local jsontolua = json and json.tolua +local shaped = characters and characters.shaped or lower + +-- local ignore = { +-- "latex", +-- "plain", +-- "xetex", +-- } + +-- what is the url to fetch a zip + +-- We cannot use the socket library because we don't compile that massive amount of +-- ssl code into lua(meta)tex. aybe some day one fo these small embedded libraries +-- makes sense but there are so many changes in all that security stuff that it +-- defeats long term stability of the ecosystem anyway ... just like some of my old +-- devices suddenly are no longer accessible with modern browsers I expect it to +-- happen everywhere. I'm not sure why ctan can't support http because I see no +-- added value in the 's' here. + +local ctanurl = "https://www.ctan.org/" .. (json and "json" or "xml") .. "/2.0/" + +local fetched = curl and + + function(str) + local data, message = curl.fetch { + url = ctanurl .. str, + sslverifyhost = false, + sslverifypeer = false, + } + if not data then + report("some error: %s",message) + end + return data + end + +or + + function(str) + -- So, no redirect to http, which means that we cannot use the built in socket + -- library. What if the client is happy with http? + local data = os.resultof("curl -sS " .. ctanurl .. str) + -- print(data) + return data + end + +-- for j=1,#ignore do +-- if find(str,ignore[j]) then +-- return false +-- end +-- end + +local function strfound(pattern,str) + if not pattern then + return true + else + local str = lower(shaped(str)) + if find(str,pattern) then + return true + else + str = gsub(str,"[^a-zA-Z0-9]","") + if find(str,pattern) then + return true + else + return false + end + end + end +end + +local function showresult(found) + if #found > 2 then + utilities.formatters.formatcolumns(found) + report("") + for k=1,#found do + report(found[k]) + end + report("") + end +end + +local function checkedpattern(pattern) + if pattern then + return lower(shaped(pattern)) + end +end + +local validdata = json and + + function(data) + if data then + data = jsontolua(data) + if type(data) == "table" then + return data + else + report("unable to handle this json data") + end + else + report("unable to fetch packages") + end + end + +or + + function(data) + if data then + data = xmlconvert(data) + if data.error then + report("unable to handle this json data") + else + return data + end + else + report("unable to fetch packages") + end + end + +scripts.ctan.details = json and + + function(name) + if name then + local data = validdata(fetched("pkg/" .. name)) + if data then + report("") + -- report("key : %s",data.key or "-") + report("name : %s",data.name or "-") + report("caption : %s",data.caption or "-") + report("path : %s",data.ctan.path or "-") + report("") + end + end + end + +or + + function (name) + if name then + local data = validdata(fetched("pkg/" .. name)) + report("") + -- report("key : %s",data.key or "-") + report("name : %s",xmltext(data,"/entry/name")) + report("caption : %s",xmltext(data,"/entry/caption")) + report("path : %s",xmlattr(data,"/entry/ctan","path")) + report("") + end + end + +scripts.ctan.packages = json and + + function(pattern) + local data = validdata(fetched("packages")) + if data then + local found = { + { "key", "name", "caption" }, + { "", "", "" }, + } + pattern = checkedpattern(pattern) + for i=1,#data do + local entry = data[i] + if strfound(pattern,entry.caption) then + found[#found+1] = { entry.key, entry.name, entry.caption } + end + end + showresult(found) + end + end + +or + + function(pattern) + local data = validdata(fetched("packages")) + if data then + local found = { + { "key", "name", "caption" }, + { "", "", "" }, + } + pattern = checkedpattern(pattern) + for c in xmlcollected(data,"/packages/package") do + local at = c.at + if strfound(pattern,at.caption) then + found[#found+1] = { at.key, at.name, at.caption } + end + end + showresult(found) + end + end + +scripts.ctan.topics = json and + + function (pattern) + local data = validdata(fetched("topics")) + if data then + local found = { + { "key", "details" }, + { "", "" }, + } + pattern = checkedpattern(pattern) + for i=1,#data do + local entry = data[i] + if strfound(pattern,entry.details) then + found[#found+1] = { entry.key or entry.name, entry.details } -- inconsistency between json and xml + end + end + showresult(found) + end + end + +or + + function(pattern) + local data = validdata(fetched("topics")) + if data then + local found = { + { "name", "details" }, + { "", "" }, + } + pattern = checkedpattern(pattern) + for c in xmlcollected(data,"/topics/topic") do + local at = c.at + if strfound(pattern,at.caption) then + found[#found+1] = { at.key or at.name, at.details } -- inconsistency between json and xml + end + end + showresult(found) + end + end + +local function whatever() + report("") + report("using %s interface", json and "json" or "xml") + report("using curl %s", curl and "library" or "binary") + report("") +end + +if environment.argument("packages") then + whatever() + scripts.ctan.packages(environment.argument("pattern") or environment.files[1]) +elseif environment.argument("topics") then + whatever() + scripts.ctan.topics(environment.argument("pattern") or environment.files[1]) +elseif environment.argument("details") then + whatever() + scripts.ctan.details(environment.files[1]) +elseif environment.argument("exporthelp") then + application.export(environment.argument("exporthelp"),environment.files[1]) +else + application.help() +end + +-- scripts.ctan.packages(environment.argument("pattern") or environment.files[1]) +-- scripts.ctan.packages("font") +-- scripts.ctan.details("tex") +-- scripts.ctan.details("ipaex") + +-- scripts.ctan.packages("Półtawskiego") +-- scripts.ctan.packages("Poltawskiego") + +-- scripts.ctan.topics("font") +-- scripts.ctan.topics() diff --git a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua index 65a661ac40b..37107ea1e3f 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-fonts.lua @@ -12,11 +12,11 @@ local givenfiles = environment.files local suffix, addsuffix, removesuffix, replacesuffix = file.suffix, file.addsuffix, file.removesuffix, file.replacesuffix local nameonly, basename, joinpath, collapsepath = file.nameonly, file.basename, file.join, file.collapsepath -local lower = string.lower +local lower, gsub = string.lower, string.gsub local concat = table.concat local write_nl = (logs and logs.writer) or (texio and texio.write_nl) or print -local otlversion = 3.113 +local otlversion = 3.133 local helpinfo = [[ <?xml version="1.0"?> @@ -60,6 +60,10 @@ local helpinfo = [[ <example><command>mtxrun --script font --list somename (== --pattern=*somename*)</command></example> </subcategory> <subcategory> + <example><command>mtxrun --script font --list --file filename</command></example> + <example><command>mtxrun --script font --list --name --pattern=*somefile*</command></example> + </subcategory> + <subcategory> <example><command>mtxrun --script font --list --name somename</command></example> <example><command>mtxrun --script font --list --name --pattern=*somename*</command></example> </subcategory> @@ -123,7 +127,7 @@ loadmodule("font-otr.lua") loadmodule("font-cff.lua") loadmodule("font-ttf.lua") loadmodule("font-tmp.lua") -loadmodule("font-dsp.lua") +loadmodule("font-dsp.lua") -- autosuffix loadmodule("font-oup.lua") loadmodule("font-otl.lua") @@ -183,6 +187,9 @@ function fonts.names.simple(alsotypeone) local simplelist = { "ttf", "otf", "ttc", alsotypeone and "afm" or nil } local name = "luatex-fonts-names.lua" local path = collapsepath(caches.getwritablepath("..","..","generic","fonts","data")) + + path = gsub(path, "luametatex%-cache", "luatex-cache") -- maybe have an option to force it + fonts.names.filters.list = simplelist fonts.names.version = simpleversion -- this number is the same as in font-dum.lua report("generating font database for 'luatex-fonts' version %s",fonts.names.version) @@ -288,7 +295,7 @@ local function showfeatures(tag,specification) else done = true end - report(" % -8s % -8s % -8s",f,s,concat(table.sortedkeys(ss), " ")) -- todo: padd 4 + report(" %-8s %-8s %-8s",f,s,concat(table.sortedkeys(ss), " ")) -- todo: padd 4 end end end @@ -310,7 +317,7 @@ local function showfeatures(tag,specification) report(" method feature formats") report() for k, v in table.sortedhash(methods) do - report(" % -8s % -14s %s",k,v.feature,v.format) + report(" %-8s %-14s %s",k,v.feature,v.format) end end end @@ -406,46 +413,46 @@ function scripts.fonts.list() if getargument("name") then if pattern then - --~ mtxrun --script font --list --name --pattern=*somename* + -- mtxrun --script font --list --name --pattern=*somename* list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info) elseif filter then report("not supported: --list --name --filter",name) elseif given then - --~ mtxrun --script font --list --name somename + -- mtxrun --script font --list --name somename list_matches(fonts.names.list(given,reload,all),info) else report("not supported: --list --name <no specification>",name) end elseif getargument("spec") then if pattern then - --~ mtxrun --script font --list --spec --pattern=*somename* + -- mtxrun --script font --list --spec --pattern=*somename* report("not supported: --list --spec --pattern",name) elseif filter then - --~ mtxrun --script font --list --spec --filter="fontname=somename" + -- mtxrun --script font --list --spec --filter="fontname=somename" list_specifications(fonts.names.getlookups(filter),info) elseif given then - --~ mtxrun --script font --list --spec somename + -- mtxrun --script font --list --spec somename list_specifications(fonts.names.collectspec(given,reload,all),info) else report("not supported: --list --spec <no specification>",name) end elseif getargument("file") then if pattern then - --~ mtxrun --script font --list --file --pattern=*somename* + -- mtxrun --script font --list --file --pattern=*somename* list_specifications(fonts.names.collectfiles(string.topattern(pattern,true),reload,all),info) elseif filter then report("not supported: --list --spec",name) elseif given then - --~ mtxrun --script font --list --file somename + -- mtxrun --script font --list --file somename list_specifications(fonts.names.collectfiles(given,reload,all),info) else report("not supported: --list --file <no specification>",name) end elseif pattern then - --~ mtxrun --script font --list --pattern=*somename* + -- mtxrun --script font --list --pattern=*somename* list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info) elseif given then - --~ mtxrun --script font --list somename + -- mtxrun --script font --list somename list_matches(fonts.names.list(given,reload,all),info) elseif all then pattern = "*" diff --git a/Master/texmf-dist/scripts/context/lua/mtx-install.lua b/Master/texmf-dist/scripts/context/lua/mtx-install.lua index 614d20e9294..7efd8f5edee 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-install.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-install.lua @@ -14,7 +14,7 @@ local helpinfo = [[ <metadata> <entry name="name">mtx-install</entry> <entry name="detail">ConTeXt Installer</entry> - <entry name="version">2.00</entry> + <entry name="version">2.01</entry> </metadata> <flags> <category name="basic"> @@ -28,27 +28,55 @@ local helpinfo = [[ <flag name="update"><short>update context</short></flag> <flag name="erase"><short>wipe the cache</short></flag> <flag name="identify"><short>create list of files</short></flag> + <flag name="secure"><short>use curl for https</short></flag> </subcategory> </category> </flags> </application> ]] +local type, tonumber = type, tonumber local gsub, find, escapedpattern = string.gsub, string.find, string.escapedpattern local round = math.round local savetable, loadtable, sortedhash = table.save, table.load, table.sortedhash local copyfile, joinfile, filesize, dirname, addsuffix, basename = file.copy, file.join, file.size, file.dirname, file.addsuffix, file.basename local isdir, isfile, walkdir, pushdir, popdir, currentdir = lfs.isdir, lfs.isfile, lfs.dir, lfs.chdir, dir.push, dir.pop, currentdir local mkdirs, globdir = dir.mkdirs, dir.glob -local osremove, osexecute, ostype = os.remove, os.execute, os.type +local osremove, osexecute, ostype, resultof = os.remove, os.execute, os.type, os.resultof local savedata = io.savedata local formatters = string.formatters +local httprequest = socket.http.request -local fetch = socket.http.request +local usecurl = false + +local function checkcurl() + local s = resultof("curl --version") + return type(s) == "string" and find(s,"libcurl") and find(s,"rotocols") +end + +local function fetch(url) + local data = nil + local detail = nil + if usecurl and find(url,"^https") then + data = resultof("curl " .. url) + else + data, detail = httprequest(url) + end + if type(data) ~= "string" then + data = false + elseif #data < 2048 then + local n, t = find(data,"<head>%s*<title>%s*(%d+)%s(.-)</title>") + if tonumber(n) then + data = false + detail = n .. " " .. t + end + end + return data, detail +end local application = logs.application { name = "mtx-install", - banner = "ConTeXt Installer 2.00", + banner = "ConTeXt Installer 2.01", helpinfo = helpinfo, } @@ -75,11 +103,14 @@ local platforms = { ["windows"] = "mswin", ["win32"] = "mswin", ["win"] = "mswin", + ["arm32"] = "windows-arm32", + ["windows-arm32"] = "windows-arm32", -- ["mswin-64"] = "win64", ["windows-64"] = "win64", ["win64"] = "win64", ["arm64"] = "windows-arm64", + ["windows-arm64"] = "windows-arm64", -- ["linux"] = "linux", ["linux-32"] = "linux", @@ -93,9 +124,9 @@ local platforms = { -- ["linux-armhf"] = "linux-armhf", -- - ["openbsd"] = "openbsd6.8", - ["openbsd-i386"] = "openbsd6.8", - ["openbsd-amd64"] = "openbsd6.8-amd64", + ["openbsd"] = "openbsd7.2", + ["openbsd-i386"] = "openbsd7.2", + ["openbsd-amd64"] = "openbsd7.2-amd64", -- ["freebsd"] = "freebsd", ["freebsd-i386"] = "freebsd", @@ -121,10 +152,8 @@ local platforms = { ["macosx"] = "osx-64", ["osx"] = "osx-64", ["osx-64"] = "osx-64", --- ["osx-arm"] = "osx-arm64", --- ["osx-arm64"] = "osx-arm64", - ["osx-arm"] = "osx-64", - ["osx-arm64"] = "osx-64", + ["osx-arm"] = "osx-arm64", + ["osx-arm64"] = "osx-arm64", -- -- ["solaris-intel"] = "solaris-intel", -- @@ -589,6 +618,11 @@ function install.update() end run("%s --make en", contextbin) + -- in case we also install luatex: + + run("%s --luatex --generate",contextbin) + run("%s --luatex --make en", contextbin) + -- in calling script: update mtxrun.exe and mtxrun.lua report("") @@ -602,6 +636,14 @@ function install.update() report("update, done") end +if environment.argument("secure") then + usecurl = checkcurl() + if not usecurl then + report("no curl installed, quitting") + os.exit() + end +end + if environment.argument("identify") then install.identify() elseif environment.argument("install") then diff --git a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua index a335560fa56..ec2da63cce0 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-interface.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-interface.lua @@ -7,9 +7,9 @@ if not modules then modules = { } end modules ['mtx-cache'] = { } local concat, sort, insert = table.concat, table.sort, table.insert -local gsub, format, gmatch, find = string.gsub, string.format, string.gmatch, string.find +local gsub, format, gmatch, find, upper = string.gsub, string.format, string.gmatch, string.find, string.upper local utfchar, utfgsub = utf.char, utf.gsub -local sortedkeys = table.sortedkeys +local sortedkeys, sortedhash, serialize = table.sortedkeys, table.sortedhash, table.serialize local helpinfo = [[ <?xml version="1.0"?> @@ -32,6 +32,7 @@ local helpinfo = [[ <flag name="bbedit"><short>generate bbedit interface files</short></flag> <flag name="jedit"><short>generate jedit interface files</short></flag> <flag name="textpad"><short>generate textpad interface files</short></flag> + <flag name="vim"><short>generate vim interface files</short></flag> <flag name="text"><short>create text files for commands and environments</short></flag> <flag name="raw"><short>report commands to the console</short></flag> <flag name="check"><short>generate check file</short></flag> @@ -71,19 +72,19 @@ local messageinterfaces = { 'en','cs','de','it','nl','ro','fr','pe','no' } local function collect(filename,class,data) if data then - local result = { } - for name, list in table.sortedhash(data) do - result[#result+1] = format("keywordclass.%s.%s=\\\n",class,name) + local result, r = { }, 0 + for name, list in sortedhash(data) do + r = r + 1 ; result[r] = format("keywordclass.%s.%s=\\\n",class,name) for i=1,#list do if i%5 == 0 then - result[#result+1] = "\\\n" + r = r + 1 ; result[r] = "\\\n" end - result[#result+1] = format("%s ",list[i]) + r = r + 1 ; result[r] = format("%s ",list[i]) end - result[#result+1] = "\n\n" + r = r + 1 ; result[r] = "\n\n" end io.savedata(file.addsuffix(filename,"properties"),concat(result)) - io.savedata(file.addsuffix(filename,"lua"), table.serialize(data,true)) + io.savedata(file.addsuffix(filename,"lua"),serialize(data,true)) else os.remove(filename) end @@ -127,18 +128,18 @@ function flushers.jedit(collected) for interface, whatever in next, collected do local commands = whatever.commands local environments = whatever.environments - local result = { } - result[#result+1] = "<?xml version='1.0'?>" - result[#result+1] = "<!DOCTYPE MODE SYSTEM 'xmode.dtd'>\n" - result[#result+1] = "<MODE>" - result[#result+1] = "\t<RULES>" - result[#result+1] = "\t\t<KEYWORDS>" + local result, r = { }, 0 + r = r + 1 ; result[r] = "<?xml version='1.0'?>" + r = r + 1 ; result[r] = "<!DOCTYPE MODE SYSTEM 'xmode.dtd'>\n" + r = r + 1 ; result[r] = "<MODE>" + r = r + 1 ; result[r] = "\t<RULES>" + r = r + 1 ; result[r] = "\t\t<KEYWORDS>" for i=1,#commands do - result[#result+1] = format("\t\t\t<KEYWORD2>%s</KEYWORD2>",commands[i]) + r = r + 1 ; result[r] = format("\t\t\t<KEYWORD2>%s</KEYWORD2>",commands[i]) end - result[#result+1] = "\t\t</KEYWORDS>" - result[#result+1] = "\t</RULES>" - result[#result+1] = "</MODE>" + r = r + 1 ; result[r] = "\t\t</KEYWORDS>" + r = r + 1 ; result[r] = "\t</RULES>" + r = r + 1 ; result[r] = "</MODE>" io.savedata(format("context-jedit-%s.xml",interface), concat(result),"\n") end end @@ -147,18 +148,100 @@ function flushers.bbedit(collected) for interface, whatever in next, collected do local commands = whatever.commands local environments = whatever.environments - local result = {} - result[#result+1] = "<?xml version='1.0'?>" - result[#result+1] = "<key>BBLMKeywordList</key>" - result[#result+1] = "<array>" + local result, r = { }, 0 + r = r + 1 ; result[r] = "<?xml version='1.0'?>" + r = r + 1 ; result[r] = "<key>BBLMKeywordList</key>" + r = r + 1 ; result[r] = "<array>" for i=1,#commands do - result[#result+1] = format("\t<string>\\%s</string>",commands[i]) + r = r + 1 ; result[r] = format("\t<string>\\%s</string>",commands[i]) end - result[#result+1] = "</array>" + r = r + 1 ; result[r] = "</array>" io.savedata(format("context-bbedit-%s.xml",interface), concat(result),"\n") end end +-- The Vim export is maintained by Nicola Vitacolonna: + +local function vimcollect(filename,class,data) + if data then + local result, r = { }, 0 + local endline = " contained\n" + if find(class,"^meta") then + endline = "\n" + end + r = r + 1 ; result[r] = "vim9script\n\n" + r = r + 1 ; result[r] = "# Vim syntax file\n" + r = r + 1 ; result[r] = "# Language: ConTeXt\n" + r = r + 1 ; result[r] = format("# Automatically generated by mtx-interface (%s)\n\n", os.date()) + local n = 5 -- number of keywords per row + for name, list in sortedhash(data) do + local i = 1 + while i <= #list do + r = r + 1 ; result[r] = format("syn keyword %s%s", class, (gsub(name,"^%l",upper))) -- upper is fragile + local j = 0 +-- while i+j <= #list and j < n do +-- if list[i+j] == "transparent" then -- this is a Vim keyword +-- r = r + 1 ; result[r] = format(" %s[]",list[i+j]) +-- else +-- r = r + 1 ; result[r] = format(" %s",list[i+j]) +-- end +-- j = j + 1 +-- end + while j < n do + local lij = list[i + j] + if not lij then + break + elseif lij == "transparent" then -- this is a Vim keyword + r = r + 1 ; result[r] = format(" %s[]",lij) + else + r = r + 1 ; result[r] = format(" %s",lij) + end + j = j + 1 + end + r = r + 1 ; result[r] = endline + i = i + n + end + end + io.savedata(file.addsuffix(filename,"vim"),concat(result)) + else + os.remove(filename) + end +end + +function flushers.vim(collected) + local data = { } + -- for interface, whatever in next, collected do + -- data[interface] = whatever.commands + -- end + local function add(target,origin,field) + if origin then + local list = origin[field] + if list then + for i=1,#list do + target[list[i]] = true + end + end + end + end + -- + for interface, whatever in next, collected do + local combined = { } + add(combined,whatever,"commands") + add(combined,whatever,"environments") + if interface == "common" then + add(combined,whatever,"textnames") + add(combined,whatever,"mathnames") + end + data[interface] = sortedkeys(combined) + end + -- + vimcollect("context-data-interfaces", "context", data) + -- vimcollect("context-data-metapost", "metapost", dofile(resolvers.findfile("mult-mps.lua"))) + vimcollect("context-data-metafun", "metafun", dofile(resolvers.findfile("mult-fun.lua"))) + vimcollect("context-data-context", "context", dofile(resolvers.findfile("mult-low.lua"))) + vimcollect("context-data-tex", "tex", dofile(resolvers.findfile("mult-prm.lua"))) +end + function flushers.raw(collected) for interface, whatever in next, collected do local commands = whatever.commands @@ -749,7 +832,7 @@ elseif ea("bidi") then scripts.interface.bidi() elseif ea("check") then scripts.interface.check() -elseif ea("scite") or ea("bbedit") or ea("jedit") or ea("textpad") or ea("text") or ea("raw") then +elseif ea("scite") or ea("bbedit") or ea("jedit") or ea("textpad") or ea("vim") or ea("text") or ea("raw") then if ea("scite") then scripts.interface.editor("scite") end @@ -762,6 +845,9 @@ elseif ea("scite") or ea("bbedit") or ea("jedit") or ea("textpad") or ea("text") if ea("textpad") then scripts.interface.editor("textpad",true, { "en" }) end + if ea("vim") then + scripts.interface.editor("vim",true, { "en" }) + end if ea("text") then scripts.interface.editor("text") end diff --git a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua index 36b60192d28..7f5c1c55629 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-patterns.lua @@ -93,7 +93,7 @@ scripts.patterns.list = { -- { "ar", "hyph-ar", "arabic" }, -- { "as", "hyph-as", "assamese" }, { "bg", "hyph-bg", "bulgarian" }, - -- { "bn", "hyph-bn", "bengali" }, + { "bn", "hyph-bn", "bengali" }, { "ca", "hyph-ca", "catalan" }, -- { "??", "hyph-cop", "coptic" }, { "cs", "hyph-cs", "czech" }, @@ -102,8 +102,8 @@ scripts.patterns.list = { { "deo", "hyph-de-1901", "german, old spelling" }, { "de", "hyph-de-1996", "german, new spelling" }, -- { "??", "hyph-de-ch-1901", "swiss german" }, - -- { "??", "hyph-el-monoton", "greek" }, - -- { "gr", "hyph-el-polyton", "greek" }, + -- { "??", "hyph-el-polyton", "greek" }, + { "gr", "hyph-el-monoton", "greek" }, { "agr", "hyph-grc", "ancient greek", ignored_ancient_greek }, { "gb", "hyph-en-gb", "british english" }, { "us", "hyph-en-us", "american english" }, @@ -116,8 +116,8 @@ scripts.patterns.list = { { "fr", "hyph-fr", "french", ignored_french }, -- { "??", "hyph-ga", "irish" }, -- { "??", "hyph-gl", "galician" }, - -- { "gu", "hyph-gu", "gujarati" }, - -- { "hi", "hyph-hi", "hindi" }, + { "gu", "hyph-gu", "gujarati" }, + { "hi", "hyph-hi", "hindi" }, { "hr", "hyph-hr", "croatian" }, -- { "??", "hyph-hsb", "upper sorbian" }, { "hu", "hyph-hu", "hungarian" }, @@ -127,7 +127,7 @@ scripts.patterns.list = { { "is", "hyph-is", "icelandic" }, { "it", "hyph-it", "italian" }, -- { "??", "hyph-kmr", "kurmanji" }, - -- { "kn", "hyph-kn", "kannada" }, + { "kn", "hyph-kn", "kannada" }, { "la", "hyph-la", "latin" }, { "ala", "hyph-la-x-classic", "ancient latin" }, -- { "lo", "hyph-lo", "lao" }, @@ -147,15 +147,16 @@ scripts.patterns.list = { { "pt", "hyph-pt", "portuguese" }, { "ro", "hyph-ro", "romanian" }, { "ru", "hyph-ru", "russian" }, - -- { "sa", "hyph-sa", "sanskrit" }, + { "sa", "hyph-sa", "sanskrit" }, { "sk", "hyph-sk", "slovak" }, { "sl", "hyph-sl", "slovenian" }, - { "sr", "hyph-sr", "serbian", false, { "hyph-sr-cyrl", "hyph-sr-latn" }, }, + { "sq", "hyph-sq", "albanian" }, + { "sr", "hyph-sr", "serbian", false, { "hyph-sh-cyrl", "hyph-sh-latn" }, }, -- { "sr", "hyph-sr-cyrl", "serbian", false }, -- { "sr", "hyph-sr-latn", "serbian" }, { "sv", "hyph-sv", "swedish" }, - -- { "ta", "hyph-ta", "tamil" }, - -- { "te", "hyph-te", "telugu" }, + { "ta", "hyph-ta", "tamil" }, + { "te", "hyph-te", "telugu" }, { "th", "hyph-th", "thai" }, { "tk", "hyph-tk", "turkmen" }, { "tr", "hyph-tr", "turkish" }, @@ -186,6 +187,7 @@ function scripts.patterns.load(path,name,mnemonic,ignored, merged) local splitpatternsold, splithyphenationsold = { }, { } local usedpatterncharactersnew, usedhyphenationcharactersnew = { }, { } if merged then + -- no version info report("using merged txt files %s.[hyp|pat|lic].txt",name) for i=1,#merged do local fullname = file.join(path,merged[i]) @@ -194,11 +196,13 @@ function scripts.patterns.load(path,name,mnemonic,ignored, merged) hyphenations = hyphenations .. (io.loaddata(addsuffix(fullname,"hyp.txt")) or "") .. "\n\n" end elseif lfs.isfile(patfile) then + -- no version info report("using txt files %s.[hyp|pat|lic].txt",name) comment = io.loaddata(licfile) or "" patterns = io.loaddata(patfile) or "" hyphenations = io.loaddata(hypfile) or "" elseif lfs.isfile(texfile) then + -- version info in comment blob report("using tex file %s.txt",name) local data = io.loaddata(texfile) or "" if data ~= "" then diff --git a/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua index fbb1a3995e5..0ce17ec5b56 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-pdf.lua @@ -7,7 +7,7 @@ if not modules then modules = { } end modules ['mtx-pdf'] = { } local tonumber = tonumber -local format, gmatch, gsub = string.format, string.gmatch, string.gsub +local format, gmatch, gsub, match, find = string.format, string.gmatch, string.gsub, string.match, string.find local utfchar = utf.char local concat = table.concat local setmetatableindex, sortedhash, sortedkeys = table.setmetatableindex, table.sortedhash, table.sortedkeys @@ -27,11 +27,13 @@ local helpinfo = [[ <flag name="metadata"><short>show metadata xml blob</short></flag> <flag name="pretty"><short>replace newlines in metadata</short></flag> <flag name="fonts"><short>show used fonts (<ref name="detail)"/></short></flag> + <flag name="object"><short>show object"/></short></flag> </subcategory> <subcategory> <example><command>mtxrun --script pdf --info foo.pdf</command></example> <example><command>mtxrun --script pdf --metadata foo.pdf</command></example> <example><command>mtxrun --script pdf --metadata --pretty foo.pdf</command></example> + <example><command>mtxrun --script pdf --stream=4 foo.pdf</command></example> </subcategory> </category> </flags> @@ -46,10 +48,14 @@ local application = logs.application { local report = application.report -if pdfe then - dofile(resolvers.findfile("lpdf-pde.lua","tex")) -else +if not pdfe then dofile(resolvers.findfile("lpdf-epd.lua","tex")) +elseif CONTEXTLMTXMODE then + dofile(resolvers.findfile("util-dim.lua","tex")) + dofile(resolvers.findfile("lpdf-ini.lmt","tex")) + dofile(resolvers.findfile("lpdf-pde.lmt","tex")) +else + dofile(resolvers.findfile("lpdf-pde.lua","tex")) end scripts = scripts or { } @@ -271,6 +277,7 @@ function scripts.pdf.fonts(filename) chars[i] = c freqs[i] = format("U+%05X %s %s",k,counts[k] > 1 and "+" or " ", c) else + chars[i] = k == 32 and "SPACE" or format("U+%03X",k) freqs[i] = format("U+%05X %s --",k,counts[k] > 1 and "+" or " ") end end @@ -349,6 +356,15 @@ function scripts.pdf.fonts(filename) end end +function scripts.pdf.object(filename,n) + if n then + local pdffile = loadpdffile(filename) + if pdffile then + print(lpdf.epdf.verboseobject(pdffile,n) or "no object with number " .. n) + end + end +end + -- scripts.pdf.info("e:/tmp/oeps.pdf") -- scripts.pdf.metadata("e:/tmp/oeps.pdf") -- scripts.pdf.fonts("e:/tmp/oeps.pdf") @@ -364,6 +380,8 @@ elseif environment.argument("metadata") then scripts.pdf.metadata(filename,environment.argument("pretty")) elseif environment.argument("fonts") then scripts.pdf.fonts(filename) +elseif environment.argument("object") then + scripts.pdf.object(filename,tonumber(environment.argument("object"))) elseif environment.argument("exporthelp") then application.export(environment.argument("exporthelp"),filename) else diff --git a/Master/texmf-dist/scripts/context/lua/mtx-spell.lua b/Master/texmf-dist/scripts/context/lua/mtx-spell.lua new file mode 100644 index 00000000000..dcfc9feb100 --- /dev/null +++ b/Master/texmf-dist/scripts/context/lua/mtx-spell.lua @@ -0,0 +1,346 @@ +if not modules then modules = { } end modules ['mtx-patterns'] = { + version = 1.001, + comment = "companion to mtxrun.lua", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local find, gsub, match = string.find, string.gsub, string.match +local concat = table.concat +local P, R, S, C, Ct, Cmt, Cc, Cs = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cc, lpeg.Cs +local patterns = lpeg.patterns +local lpegmatch = lpeg.match + +local helpinfo = [[ +<?xml version="1.0"?> +<application> + <metadata> + <entry name="name">mtx-spell</entry> + <entry name="detail">ConTeXt Word Filtering</entry> + <entry name="version">0.10</entry> + </metadata> + <flags> + <category name="basic"> + <subcategory> + <flag name="expand"><short>expand hunspell dics and aff files</short></flag> + <flag name="dictionary"><short>word file (.dics)</short></flag> + <flag name="specification"><short>affix specification file (.aff)</short></flag> + <flag name="result"><short>destination file</short></flag> + </subcategory> + </category> + </flags> + <examples> + <category> + <title>Examples</title> + <subcategory> + <example><command>mtxrun --script spell --expand --dictionary="en_US.dic" --specification="en_US.txt" --result="data-us.txt"</command></example> + </subcategory> + </category> + </examples> +</application> +]] + + +local application = logs.application { + name = "mtx-spell", + banner = "ConTeXt Word Filtering 0.10", + helpinfo = helpinfo, +} + +local report = application.report +local trace = false + +scripts = scripts or { } +scripts.spell = scripts.spell or { } + +--------------- + +require("char-def") +require("char-utf") + +-- nl: ij => ij + +do + + local prefixes, suffixes, affixes, continue, collected + + local function resetall() + prefixes = table.setmetatableindex("table") + suffixes = table.setmetatableindex("table") + affixes = table.setmetatableindex("table") + continue = { } + collected = { } + end + + local uppers = { } + local chardata = characters.data + for k, v in next, chardata do + if v.category == "lu" then + uppers[utf.char(k)] = true + end + end + + local newline = patterns.newline + local digit = patterns.digit + local skipped = digit + lpeg.utfchartabletopattern(uppers) + local ignored = 1 - newline + local garbage = S("'-") + + local function fixeddata(data) + data = gsub(data,"ij","ij") + return data + end + + local function registersuffix(tag,f) + table.insert(suffixes[tag],f) + table.insert(affixes [tag],f) + end + + local function registerprefix(tag,f) + table.insert(prefixes[tag],f) + table.insert(affixes [tag],f) + end + + local function getfixes(specification) + + local data = fixeddata(io.loaddata(specification) or "") + local lines = string.splitlines(data) + + -- /* in two + -- Y/N continuation + + -- [^...] [...] ... + + local p0 = nil + + local p1 = P("[^") * Cs((1-P("]"))^1) * P("]") / function(s) + local t = utf.split(s) + local p = 1 - lpeg.utfchartabletopattern(t) + p0 = p0 and (p0 * p) or p + end + local p2 = P("[") * Cs((1-P("]"))^1) * P("]") / function(s) + local t = utf.split(s) + local p = lpeg.utfchartabletopattern(t) + p0 = p0 and (p0 * p) or p + end + local p3 = (patterns.utf8char - S("[]"))^1 / function(s) + local p = P(s) + p0 = p0 and (p0 * p) or p + end + + local p = (p1 + p2 + p3)^1 + + local function makepattern(s) + p0 = nil + lpegmatch(p,s) + return p0 + end + + local i = 1 + while i <= #lines do + local line = lines[i] + local tag, continuation, n = match(line,"PFX%s+(%S+)%s+(%S+)%s+(%d+)") + if tag then + n = tonumber(n) or 0 + continue[tag] = continuation == "Y" + for j=1,n do + i = i + 1 + line = lines[i] + if not find(line,"[-']") then + local tag, one, two, three = match(line,"PFX%s+(%S+)%s+(%S+)%s+([^%s/]+)%S*%s+(%S+)") + if tag then + if one == "0" and two and three == "." then + -- simple case: PFX A 0 re . + registerprefix(tag,function(str) + local new = two .. str + if trace then + print("p 1",str,new) + end + return new + end) + elseif one == "0" and two and three then + -- strip begin + if trace then + print('2',line) + end + elseif one and two and three then + if trace then + print('3',line) + end + else + if trace then + print('4',line) + end + end + end + end + end + end + local tag, continuation, n = match(line,"SFX%s+(%S+)%s+(%S+)%s+(%S+)") + if tag then + n = tonumber(n) or 0 + continue[tag] = continuation == "Y" + for j=1,n do + i = i + 1 + line = lines[i] + if not find(line,"[-']") then + local tag, one, two, three = match(line,"SFX%s+(%S+)%s+(%S+)%s+([^%s/]+)%S*%s+(%S+)") + if tag then + if one == "0" and two and three == "." then + -- SFX Y 0 ly . + registersuffix(tag,function(str) + local new = str .. two + if trace then + print("s 1",str,new) + end + return new + end) + elseif one == "0" and two and three then + -- SFX G 0 ing [^e] + local final = makepattern(three) * P(-1) + local check = (1 - final)^0 * final + registersuffix(tag,function(str) + if lpegmatch(check,str) then + local new = str .. two + if trace then + print("s 2",str,new) + end + return new + end + end) + elseif one and two and three then + -- SFX G match$ suffix old$ (dutch has sloppy matches, use english as reference) + local final = makepattern(three) * P(-1) + local check = (1 - final)^1 * final + local final = makepattern(one) * P(-1) + local replace = Cs((1 - final)^1 * (final/two)) + registersuffix(tag,function(str) + if lpegmatch(check,str) then + local new = lpegmatch(replace,str) + if new then + if trace then + print("s 3",str,new) + end + return new + end + end + end) + else + if trace then + print('4',line) + end + end + end + end + end + end + i = i + 1 + end + end + + local function expand(_,_,word,spec) + if spec then + local w = { word } + local n = 1 + for i=1,#spec do + local s = spec[i] + local affix = affixes[s] + if affix then + for i=1,#affix do + local ai = affix[i] + local wi = ai(word) + if wi then + n = n + 1 + w[n] = wi + if not continue[s] then + break + end + end + end + end + end + for i=1,n do + collected[w[i]] = true + end + elseif not find(word,"/") then + collected[word] = true + end + return true + end + + local function getwords(dictionary) + local data = fixeddata(io.loaddata(dictionary) or "") + local keys = { } + for k, v in next, prefixes do + keys[k] = true + end + for k, v in next, suffixes do + keys[k] = true + end + local validkeys = lpeg.utfchartabletopattern(keys) + local specifier = P("/") * Ct(C(validkeys)^1)^0 * newline + local pattern = ( + newline^1 + + skipped * (1-newline)^0 + + Cmt(C((1-specifier-newline-garbage)^1) * specifier^0, expand) + + ignored^1 * newline^1 + )^0 + lpegmatch(pattern,data) + collected = table.keys(collected) + table.sort(collected) + return collected + end + + local function saveall(result) + if result then + io.savedata(result,concat(collected,"\n")) + end + end + + function scripts.spell.expand(arguments) + if arguments then + local dictionary = environment.arguments.dictionary + local specification = environment.arguments.specification + local result = environment.arguments.result + if type(dictionary) ~= "string" or dictionary == "" then + report("missing --dictionary=name") + elseif type(specification) ~= "string" or specification == "" then + report("missing --specification=name") + elseif type(result) ~= "string" or result == "" then + resetall() + getfixes(specification) + getwords(dictionary) + saveall(result) + return collected + end + end + end + +end + +-- spell.dicaff { +-- dictionary = "e:/context/spell/lo/en_US.dic.txt", +-- specification = "e:/context/spell/lo/en_US.aff.txt", +-- result = "e:/context/spell/lo/data-en.txt", +-- } + +-- spell.dicaff { +-- dictionary = "e:/context/spell/lo/en_GB.dic.txt", +-- specification = "e:/context/spell/lo/en_GB.aff.txt", +-- result = "e:/context/spell/lo/data-uk.txt", +-- } + +-- spell.dicaff { +-- dictionary = "e:/context/spell/lo/nl_NL.dic.txt", +-- specification = "e:/context/spell/lo/nl_NL.aff.txt", +-- result = "e:/context/spell/lo/data-nl.txt", +-- } + +if environment.argument("expand") then + scripts.spell.expand(environment.arguments) +elseif environment.argument("exporthelp") then + application.export(environment.argument("exporthelp"),environment.files[1]) +else + application.help() +end diff --git a/Master/texmf-dist/scripts/context/lua/mtx-synctex.lua b/Master/texmf-dist/scripts/context/lua/mtx-synctex.lua index 3c4f6ee7184..f94a9605f3b 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-synctex.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-synctex.lua @@ -10,8 +10,9 @@ if not modules then modules = { } end modules ['mtx-synctex'] = { -- InverseSearchCmdLine = mtxrun.exe --script synctex --edit --name="%f" --line="%l" $ local tonumber = tonumber -local find, match, gsub = string.find, string.match, string.gsub +local find, match, gsub, formatters = string.find, string.match, string.gsub, string.formatters local isfile = lfs.isfile +local max = math.max local longtostring = string.longtostring local helpinfo = [[ @@ -20,15 +21,16 @@ local helpinfo = [[ <metadata> <entry name="name">mtx-synctex</entry> <entry name="detail">SyncTeX Checker</entry> - <entry name="version">1.00</entry> + <entry name="version">1.01</entry> </metadata> <flags> <category name="basic"> <subcategory> <flag name="edit"><short>open file at line: --line=.. --editor=.. sourcefile</short></flag> - <flag name="list"><short>show blob: synctexfile</short></flag> - <flag name="goto"><short>open file at position: --page=.. --x=.. --y=.. --editor=.. synctexfile</short></flag> - <flag name="report"><short>show file and line: --page=.. --x=.. --y=.. --console synctexfile</short></flag> + <flag name="list"><short>show all areas: synctexfile</short></flag> + <flag name="goto"><short>open file at position: --page=.. --x=.. --y=.. [--tolerance=] --editor=.. synctexfile</short></flag> + <flag name="report"><short>show (tex) file and line: [--direct] --page=.. --x=.. --y=.. [--tolerance=] --console synctexfile</short></flag> + <flag name="find"><short>find (pdf) page and box: [--direct] --file=.. --line=.. synctexfile</short></flag> </subcategory> </category> </flags> @@ -37,15 +39,22 @@ local helpinfo = [[ local application = logs.application { name = "mtx-synctex", - banner = "ConTeXt SyncTeX Checker 1.00", + banner = "ConTeXt SyncTeX Checker 1.01", helpinfo = helpinfo, } local report = application.report +local template_show = "page=%i llx=%r lly=%r urx=%r ury=%r" +local template_goto = "filename=%a linenumber=%a tolerance=%a" + +local function reportdirect(template,...) + print(formatters[template](...)) +end + local editors = { console = function(specification) - print(string.formatters["%q %i"](specification.filename,specification.linenumber or 1)) + print(string.formatters["%q %i %i"](specification.filename,specification.linenumber or 1,specification.tolerance)) end, scite = sandbox.registerrunner { name = "scite", @@ -69,7 +78,7 @@ local function validfile(filename) end end -local function editfile(filename,line,editor) +local function editfile(filename,line,tolerance,editor) if not validfile(filename) then return end @@ -77,6 +86,7 @@ local function editfile(filename,line,editor) runner { filename = filename, linenumber = tonumber(line) or 1, + tolerance = tolerance, } end @@ -184,18 +194,142 @@ local function findlocation(filename,page,xpos,ypos) end end -local function showlocation(filename) +local function findlocation(filename,page,xpos,ypos,tolerance) + if not validfile(filename) then + return + elseif not page then + page = 1 + elseif not xpos or not ypos then + report("provide x and y coordinates (unit: basepoints)") + return + end + local files = { } + local found = false + local skip = false + local fi = 0 + local ln = 0 + local tl = 0 + local lines = { } + for line in io.lines(filename) do + if found then + if find(line,"^}") then + local function locate(x,y) + local dx = false + local dy = false + local px = (xpos + x) / factor + local py = (ypos + y) / factor + for i=1,#lines do + local line = lines[i] + -- we only look at positive cases + local f, l, x, y, w, h, d = match(line,"^h(.-),(.-):(.-),(.-):(.-),(.-),(.-)$") + if f and f ~= 0 then +-- print(x,y,f) + x = tonumber(x) + if px >= x then + w = tonumber(w) + if px <= x + w then + y = tonumber(y) + d = tonumber(d) + if py >= y - d then + h = tonumber(h) + if py <= y + h then + if quit then + -- we have no overlapping boxes + fi = f + ln = l + return + else + local lx = px - x + local rx = x + w - px + local by = py - y + d + local ty = y + h - py + mx = lx < rx and lx or rx + my = by < ty and by or ty + if not dx then + dx = mx + dy = my + fi = f + ln = l + else + if mx < dx then + dx = mx + di = f + ln = l + end + if my < dy then + dy = my + fi = f + ln = l + end + end + end + end + end + end + end + end + end + end + locate(0,0) + if fi ~= 0 then + return files[fi], ln, 0 + end + if not tolerance then + tolerance = 10 + end + for s=1,tolerance,max(tolerance//10,1) do + locate( s, 0) if fi ~= 0 then tl = s ; goto done end + locate(-s, 0) if fi ~= 0 then tl = s ; goto done end + locate( s, s) if fi ~= 0 then tl = s ; goto done end + locate( s,-s) if fi ~= 0 then tl = s ; goto done end + locate(-s, s) if fi ~= 0 then tl = s ; goto done end + locate(-s,-s) if fi ~= 0 then tl = s ; goto done end + end + break + else + lines[#lines+1] = line + end + elseif skip then + if find(line,"^}") then + skip = false + end + elseif find(line,"^{(%d+)") then + local p = tonumber(match(line,"^{(%d+)")) + if p == page then + found = true + else + skip = true + end + elseif find(line,"^Input:") then + local id, name = match(line,"^Input:(.-):(.-)$") + if id then + files[id] = name + end + end + end + ::done:: + if fi ~= 0 then + return files[fi], ln, tl + end +end + +local function showlocation(filename,sourcename,linenumber,direct) if not validfile(filename) then return end local files = { } local found = false local page = 0 + if sourcename then + sourcename = file.collapsepath(sourcename) + end for line in io.lines(filename) do if found then if find(line,"^}") then found = false - report("end page: %i",page) + if not sourcename then + report("end page: %i",page) + end else local f, l, x, y, w, h, d = match(line,"^h(.-),(.-):(.-),(.-):(.-),(.-),(.-)$") if f then @@ -206,15 +340,22 @@ local function showlocation(filename) local urx = factor * ( x + tonumber(w) ) local ury = factor * ( y + tonumber(h) ) f = files[f] - if f then + if not f then + -- + elseif not sourcename then report(" [% 4r % 4r % 4r % 4r] : % 5i : %s",llx,lly,urx,ury,l,f) + elseif f == sourcename and l == linenumber then + (direct and reportdirect or report)(template_show,page,llx,lly,urx,ury) + return end end end elseif find(line,"^{(%d+)") then page = tonumber(match(line,"^{(%d+)")) found = true - report("begin page: %i",page) + if not sourcename then + report("begin page: %i",page) + end elseif find(line,"^Input:") then local id, name = match(line,"^Input:(.-):(.-)$") if id then @@ -224,14 +365,14 @@ local function showlocation(filename) end end -local function gotolocation(filename,page,xpos,ypos,editor) +local function gotolocation(filename,page,xpos,ypos,editor,direct,tolerance) if filename then - local target, line = findlocation(filename,tonumber(page),tonumber(xpos),tonumber(ypos)) + local target, line, t = findlocation(filename,tonumber(page),tonumber(xpos),tonumber(ypos),tonumber(tolerance)) if target and line then if editor then - editfile(target,line,editor) + editfile(target,line,t,editor) else - report("filename=%a linenumber=%a",target,line) + (direct and reportdirect or report)(template_goto,target,line,t) end end end @@ -248,11 +389,13 @@ local filename = environment.files[1] if argument("edit") then editfile(filename,argument("line"),argument("editor")) elseif argument("goto") then - gotolocation(filename,argument("page"),argument("x"),argument("y"),argument("editor")) + gotolocation(filename,argument("page"),argument("x"),argument("y"),argument("editor"),argument("direct"),argument("tolerance")) elseif argument("report") then - gotolocation(filename,argument("page"),argument("x"),argument("y"),"console") + gotolocation(filename,argument("page"),argument("x"),argument("y"),"console",argument("direct"),argument("tolerance")) elseif argument("list") then showlocation(filename) +elseif argument("find") then + showlocation(filename,argument("file"),argument("line"),argument("direct")) elseif argument("exporthelp") then application.export(argument("exporthelp"),filename) else diff --git a/Master/texmf-dist/scripts/context/lua/mtx-unicode.lua b/Master/texmf-dist/scripts/context/lua/mtx-unicode.lua index 060e563c642..ad42797b70d 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-unicode.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-unicode.lua @@ -143,6 +143,7 @@ function scripts.unicode.update() local eastasianwidth = texttables.eastasianwidth local standardizedvariants = texttables.standardizedvariants local arabicshaping = texttables.arabicshaping + local casefolding = texttables.casefolding local index = texttables.index local characterdata = characters.data -- @@ -164,6 +165,8 @@ function scripts.unicode.update() local cjkwd = ed and lower(ed[2] or "n") local mirror = bd and tonumber(bd[2],16) local arabic = nil + local lccode = false + local uccode = false descriptions[description] = unicode if sparse and direction == "l" then direction = nil @@ -203,6 +206,40 @@ function scripts.unicode.update() if not combining or combining == 0 then combining = nil end + -- + local cf = casefolding[unicode] + if cf and tonumber(cf[1],16) == unicode then + local how = cf[2] + if how == "C" or how == "S" then + local fold = tonumber(cf[3],16) + if fold == unicode then + -- print("SKIPPING",description) + elseif category == "ll" then + uccode = fold + elseif category == "lu" then + lccode = fold + end + elseif how == "F" then + -- we can use the first + local folding = { } + for s in gmatch(cf[3],"%S+") do + folding[#folding+1] = tonumber(s,16) + end + if category == "ll" then + uccode = folding + elseif category == "ul" then + lccode = folding + end + else + -- we skip these + -- print(description) + -- inspect(cf) + end + end + -- +-- if specials and specials[1] == "font" then +-- specials = nil +-- end if not char then report("%U : adding entry %a",unicode,description) char = { @@ -218,9 +255,34 @@ function scripts.unicode.update() specials = specials, arabic = arabic, combining = combining, + uccode = uccode and uccode or nil, + lccode = lccode and lccode or nil, } characterdata[unicode] = char else + -- we have more case mapping (e.g. cherokee) + if lccode then + if type(lccode) == "table" then + if type(char.lccode) ~= "table" or not are_equal(lccode,char.lccode) then + report("%U : setting lccode to % t, %a",unicode,lccode,description) + char.lccode = lccode + end + elseif char.lccode ~= lccode then + report("%U : setting lccode to %a, %a, %a",unicode,lccode,description) + char.lccode = lccode + end + end + if uccode then + if type(uccode) == "table" then + if type(char.uccode) ~= "table" or not are_equal(uccode,char.uccode) then + report("%U : setting uccode to % t, %a",unicode,uccode,description) + char.uccode = uccode + end + elseif char.uccode ~= uccode then + report("%U : setting uccode to %a, %a",unicode,uccode,description) + char.uccode = uccode + end + end if direction then if char.direction ~= direction then report("%U : setting direction to %a, %a",unicode,direction,description) @@ -295,6 +357,7 @@ function scripts.unicode.update() else local specials = char.specials if specials then +-- if specials and specials[1] ~= "font" then local t = { } for i=2,#specials do t[i] = formatters["%U"](specials[i]) end if false then char.comment = nil @@ -306,7 +369,7 @@ function scripts.unicode.update() elseif not find(comment,"check special") then char.comment = comment .. ", check special" end - report("%U : check specials % + t, %a",unicode,t,description) + -- report("%U : check specials % + t, %a",unicode,t,description) end end end @@ -397,7 +460,7 @@ function scripts.unicode.update() mark = descriptions["SOLIDUS"] -- SLASH end if base and mark then - report("adding extra char special for %a",description) + -- report("adding extra char special for %a",description) data.specials = { "with", base, mark } data.comment = nil end @@ -414,7 +477,7 @@ function scripts.unicode.update() if first then local d = characterdata[first] if d then - local v = d.variants + -- local v = d.variants local v = rawget(d,"variants") if not v then v = { } @@ -429,7 +492,7 @@ function scripts.unicode.update() end for unicode, ud in table.sortedpairs(characterdata) do if not rawget(ud,"category") and rawget(ud,"variants") then - report("stripping %U (variant, takes from metacharacter)",unicode) + -- report("stripping %U (variant, takes from metacharacter)",unicode) characterdata[unicode] = nil end end @@ -437,7 +500,7 @@ end local preamble -local function splitdefinition(str,index) +local function splitdefinition(filename,str,index) local l = splitlines(str) local t = { } if index then @@ -459,7 +522,7 @@ local function splitdefinition(str,index) t[k] = d end else - report("problem: %s",s) + report("problem: %i %s => %s",i,filename,s) end end end @@ -521,6 +584,7 @@ function scripts.unicode.load() eastasianwidth = resolvers.findfile("eastasianwidth.txt") or "", standardizedvariants = resolvers.findfile("standardizedvariants.txt") or "", arabicshaping = resolvers.findfile("arabicshaping.txt") or "", + casefolding = resolvers.findfile("casefolding.txt") or "", index = resolvers.findfile("index.txt") or "", } -- @@ -531,15 +595,17 @@ function scripts.unicode.load() eastasianwidth = textfiles.eastasianwidth ~= "" and io.loaddata(textfiles.eastasianwidth) or "", standardizedvariants = textfiles.standardizedvariants ~= "" and io.loaddata(textfiles.standardizedvariants) or "", arabicshaping = textfiles.arabicshaping ~= "" and io.loaddata(textfiles.arabicshaping) or "", + casefolding = textfiles.casefolding ~= "" and io.loaddata(textfiles.casefolding) or "", index = textfiles.index ~= "" and io.loaddata(textfiles.index) or "", } texttables = { - unicodedata = splitdefinition(textdata.unicodedata,true), - bidimirroring = splitdefinition(textdata.bidimirroring,true), - linebreak = splitdefinition(textdata.linebreak,true), - eastasianwidth = splitdefinition(textdata.eastasianwidth,true), - standardizedvariants = splitdefinition(textdata.standardizedvariants,false), - arabicshaping = splitdefinition(textdata.arabicshaping,true), + unicodedata = splitdefinition(textfiles.unicodedata,textdata.unicodedata,true), + bidimirroring = splitdefinition(textfiles.bidimirroring,textdata.bidimirroring,true), + linebreak = splitdefinition(textfiles.linebreak,textdata.linebreak,true), + eastasianwidth = splitdefinition(textfiles.eastasianwidth,textdata.eastasianwidth,true), + standardizedvariants = splitdefinition(textfiles.standardizedvariants,textdata.standardizedvariants,false), + arabicshaping = splitdefinition(textfiles.arabicshaping,textdata.arabicshaping,true), + casefolding = splitdefinition(textfiles.casefolding,textdata.casefolding,true), index = splitindex(textdata.index), } -- @@ -563,11 +629,88 @@ end -- [0xFE01]="centered form", -- } +-- local variants_style={ +-- [0xFE00]="chancery style", +-- [0xFE01]="roundhand style", +-- } + +-- local variants_90={ +-- [0xFE00]="rotated 90 degrees", +-- } +-- +-- local variants_180={ +-- [0xFE01]="rotated 180 degrees", +-- } +-- +-- local variants_270={ +-- [0xFE02]="rotated 270 degrees", +-- } +-- +-- local variants_expanded={ +-- [0xFE00]="expanded", +-- } +-- +-- local variants_90_180={ +-- [0xFE00]="rotated 90 degrees", +-- [0xFE01]="rotated 180 degrees", +-- } +-- +-- local variants_90_180_270={ +-- [0xFE00]="rotated 90 degrees", +-- [0xFE01]="rotated 180 degrees", +-- [0xFE02]="rotated 270 degrees", +-- } +-- +-- local variants_180_270={ +-- [0xFE01]="rotated 180 degrees", +-- [0xFE02]="rotated 270 degrees", +-- } +-- +-- local variants_90_270={ +-- [0xFE00]="rotated 90 degrees", +-- [0xFE02]="rotated 270 degrees", +-- } + function scripts.unicode.save(filename) if preamble then local data = table.serialize(characters.data,"characters.data", { hexify = true, noquotes = true }) - data = gsub(data,"%{%s+%[0xFE0E%]=\"text style\",%s+%[0xFE0F%]=\"emoji style\",%s+%}","variants_emoji") - data = gsub(data,"%{%s+%[0xFE00%]=\"corner%-justified form\",%s+%[0xFE01%]=\"centered form\",%s+%}","variants_forms") + data = gsub(data, + "%{%s+%[0xFE0E%]=\"text style\",%s+%[0xFE0F%]=\"emoji style\",%s+%}", + "variants_emoji" + ) + data = gsub(data, + "%{%s+%[0xFE00%]=\"corner%-justified form\",%s+%[0xFE01%]=\"centered form\",%s+%}", + "variants_forms" + ) + data = gsub(data, + "%{%s+%[0xFE00%]=\"chancery style\",%s+%[0xFE01%]=\"roundhand style\",%s+%}", + "variants_style" + ) + data = gsub(data, + "%{%s+%[0xFE00%]=\"dotted form\",%s+%}", + "variants_dotted" + ) + data = gsub(data, + "%{%s+%[0xFE00%]=\"expanded\",%s+%}", + "variants_expanded" + ) + data = gsub(data, + "%{%s+%[0xFE0%d%]=\"rotated (%d+) degrees\",%s+%}", + "variants_%1" + ) + data = gsub(data, + "%{%s+%[0xFE0%d%]=\"rotated (%d+) degrees\"," .. + "%s*%[0xFE0%d%]=\"rotated (%d+) degrees\"," .. + "%s+%}", + "variants_%1_%2" + ) + data = gsub(data, + "%{%s+%[0xFE0%d%]=\"rotated (%d+) degrees\"," .. + "%s*%[0xFE0%d%]=\"rotated (%d+) degrees\"," .. + "%s*%[0xFE0%d%]=\"rotated (%d+) degrees\"," .. + "%s+%}", + "variants_%1_%2_%3" + ) io.savedata(filename,preamble .. data) end end @@ -764,7 +907,7 @@ else scripts.unicode.save("char-def-new.lua") scripts.unicode.emoji("char-emj-new.lua") report("saved file %a","char-def-new.lua") - report("saved file %a (current 12.0, check for updates, see above!)","char-emj-new.lua") + report("saved file %a (current 14.0, check for updates, see above!)","char-emj-new.lua") else report("nothing to do") end diff --git a/Master/texmf-dist/scripts/context/lua/mtx-update.lua b/Master/texmf-dist/scripts/context/lua/mtx-update.lua index b0ed9aac7e2..daf23eb0911 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-update.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-update.lua @@ -157,66 +157,6 @@ update.goodies = { }, } --- update.platforms = { --- ["mswin"] = "mswin", --- ["windows"] = "mswin", --- ["win32"] = "mswin", --- ["win"] = "mswin", --- -- ["mswin"] = "win32", --- -- ["windows"] = "win32", --- -- ["win32"] = "win32", --- -- ["win"] = "win32", --- -- --- -- ["mswin-64"] = "mswin-64", --- -- ["windows-64"] = "mswin-64", --- -- ["win64"] = "mswin-64", --- ["mswin-64"] = "win64", --- ["windows-64"] = "win64", --- ["win64"] = "win64", --- -- --- ["linux"] = "linux", --- ["linux-32"] = "linux", --- ["linux32"] = "linux", --- -- --- ["linux-64"] = "linux-64", --- ["linux64"] = "linux-64", --- -- --- ["linuxmusl-64"] = "linuxmusl-64", --- -- --- ["linux-armhf"] = "linux-armhf", --- -- --- ["freebsd"] = "freebsd", --- -- --- ["freebsd-amd64"] = "freebsd-amd64", --- -- --- ["kfreebsd"] = "kfreebsd-i386", --- ["kfreebsd-i386"] = "kfreebsd-i386", --- -- --- ["kfreebsd-amd64"] = "kfreebsd-amd64", --- -- --- ["linux-ppc"] = "linux-ppc", --- ["ppc"] = "linux-ppc", --- -- --- ["osx"] = "osx-intel", --- ["macosx"] = "osx-intel", --- ["osx-intel"] = "osx-intel", --- ["osxintel"] = "osx-intel", --- -- --- ["osx-ppc"] = "osx-ppc", --- ["osx-powerpc"] = "osx-ppc", --- ["osxppc"] = "osx-ppc", --- ["osxpowerpc"] = "osx-ppc", --- -- --- ["osx-64"] = "osx-64", --- -- --- ["solaris-intel"] = "solaris-intel", --- -- --- ["solaris-sparc"] = "solaris-sparc", --- ["solaris"] = "solaris-sparc", --- -- --- ["unknown"] = "unknown", --- } - update.platforms = { ["mswin"] = "mswin", ["windows"] = "mswin", @@ -238,9 +178,9 @@ update.platforms = { -- ["linux-armhf"] = "linux-armhf", -- - ["openbsd"] = "openbsd6.8", - ["openbsd-i386"] = "openbsd6.8", - ["openbsd-amd64"] = "openbsd6.8-amd64", + ["openbsd"] = "openbsd7.2", + ["openbsd-i386"] = "openbsd7.2", + ["openbsd-amd64"] = "openbsd7.2-amd64", -- ["freebsd"] = "freebsd", ["freebsd-i386"] = "freebsd", @@ -266,7 +206,8 @@ update.platforms = { ["macosx"] = "osx-64", ["osx"] = "osx-64", ["osx-64"] = "osx-64", - ["osx-arm64"] = "osx-64", + ["osx-arm"] = "osx-arm64", + ["osx-arm64"] = "osx-arm64", -- -- ["solaris-intel"] = "solaris-intel", -- diff --git a/Master/texmf-dist/scripts/context/lua/mtx-vscode.lua b/Master/texmf-dist/scripts/context/lua/mtx-vscode.lua index 96cc5f9009b..0fd5fd428e4 100644 --- a/Master/texmf-dist/scripts/context/lua/mtx-vscode.lua +++ b/Master/texmf-dist/scripts/context/lua/mtx-vscode.lua @@ -62,7 +62,9 @@ if not modules then modules = { } end modules ['mtx-vscode'] = { -- me (too many different folders with source code, documentation etc). It's kind of -- strange because simple runners are provided by many editors. I don't want to program -- a lot to get such simple things done so, awaiting global tasks I stick to using the --- terminal. But we're prepared. +-- terminal. Also, having .vscode folderd in every place where a file sits makes no +-- sense and clutters my disk too much. There is not much progress in this area but we +-- are prepared. -- Another showstopper is the fact that we cannot disable utf8 for languages (like pdf, -- which is just bytes). I couldn't figure out how to set it in the extension. @@ -138,7 +140,9 @@ local helpinfo = [[ <category name="basic"> <subcategory> <flag name="generate"><short>generate extension in sync with current version</short></flag> + <flag name="program"><short>use the given binary (e.g. codium, default: code)</short></flag> <flag name="start"><short>start vscode with extension context</short></flag> + <flag name="lsfile"><short>generate language server file (work in progress)</short></flag> </subcategory> </category> </flags> @@ -149,6 +153,7 @@ local helpinfo = [[ <example><command>mtxrun --script vscode --generate e:/vscode/extensions</command></example> <example><command>mtxrun --script vscode --generate</command></example> <example><command>mtxrun --script vscode --start</command></example> + <example><command>mtxrun --script vscode --program=codium --start</command></example> </subcategory> </category> </examples> @@ -161,6 +166,8 @@ local application = logs.application { helpinfo = helpinfo, } +local concat = table.concat + local report = application.report require("util-jsn") @@ -278,6 +285,20 @@ function scripts.vscode.generate(targetpath) end + -- local function registersettings() + -- + -- local filename = "./settings.json" + -- + -- local data = { + -- ["editor.bracketPairColorization.enabled"] = false, + -- ["editor.bracketPairColorization.independentColorPoolPerBracketType"] = false, + -- } + -- + -- report("saving settings %a",filename) + -- + -- io.savedata(filename,data) + -- end + local function registertheme(theme) local category = theme.category @@ -294,6 +315,7 @@ function scripts.vscode.generate(targetpath) ["name"] = category, ["colors"] = theme.colors, ["tokenColors"] = theme.styles, + ["settings"] = theme.settings, } report("saving theme %a in %a",category,filename) @@ -353,11 +375,13 @@ function scripts.vscode.generate(targetpath) displayName = "ConTeXt", description = "ConTeXt Syntax Highlighting", publisher = "ConTeXt Development Team", + publisher = "cdt", version = "1.0.0", engines = { vscode = "*" }, categories = { + "Programming Languages", "Lexers", "Syntaxes" }, @@ -414,42 +438,69 @@ function scripts.vscode.generate(targetpath) tippanel = "#444444", right = "#0000FF", wrong = "#FF0000", + default = "#000000", + reverse = "#FFFFFF", + + -- some day a dark: + +-- red = "#CC4444", +-- green = "#44CC44", +-- blue = "#4444FF", +-- cyan = "#55BBBB", +-- magenta = "#BB55BB", +-- yellow = "#BBBB55", +-- orange = "#B07F00", +-- white = "#FFFFFF", +-- light = "#CFCFCF", +-- grey = "#808080", +-- dark = "#4F4F4F", +-- black = "#000000", +-- selection = "#F7F7F7", +-- logpanel = "#E7E7E7", +-- textpanel = "#1E1E1E", -- VS "#101010", +-- linepanel = "#A7A7A7", +-- tippanel = "#444444", +-- right = "#0000FF", +-- wrong = "#FF0000", +-- default = "#D4D4D4", +-- reverse = "#000000", + } local colors = { ["editor.background"] = mycolors.textpanel, - ["editor.foreground"] = mycolors.black, - ["editorLineNumber.foreground"] = mycolors.black, + ["editor.foreground"] = mycolors.default, + ["editorLineNumber.foreground"] = mycolors.default, ["editorIndentGuide.background"] = mycolors.textpanel, ["editorBracketMatch.background"] = mycolors.textpanel, ["editorBracketMatch.border"] = mycolors.orange, ["editor.lineHighlightBackground"] = mycolors.textpanel, - ["focusBorder"] = mycolors.black, + ["focusBorder"] = mycolors.default, - ["activityBar.background"] = mycolors.black, + ["activityBar.background"] = mycolors.default, - ["sideBar.background"] = mycolors.linepanel, - ["sideBar.foreground"] = mycolors.black, - ["sideBar.border"] = mycolors.white, - ["sideBarTitle.foreground"] = mycolors.black, + ["editorGutter.background"] = mycolors.linepanel, + ["editorGutter.foreground"] = mycolors.default, + ["editorGutter.border"] = mycolors.reverse, + ["sideBarTitle.foreground"] = mycolors.default, ["sideBarSectionHeader.background"] = mycolors.linepanel, - ["sideBarSectionHeader.foreground"] = mycolors.black, + ["sideBarSectionHeader.foreground"] = mycolors.default, - ["statusBar.foreground"] = mycolors.black, + ["statusBar.foreground"] = mycolors.default, ["statusBar.background"] = mycolors.linepanel, - ["statusBar.border"] = mycolors.white, - ["statusBar.noFolderForeground"] = mycolors.black, + ["statusBar.border"] = mycolors.reverse, + ["statusBar.noFolderForeground"] = mycolors.default, ["statusBar.noFolderBackground"] = mycolors.linepanel, - ["statusBar.debuggingForeground"] = mycolors.black, + ["statusBar.debuggingForeground"] = mycolors.default, ["statusBar.debuggingBackground"] = mycolors.linepanel, - ["notification.background"] = mycolors.black, + ["notification.background"] = mycolors.default, } local styles = { { scope = "context.whitespace", settings = { } }, - { scope = "context.default", settings = { foreground = mycolors.black } }, + { scope = "context.default", settings = { foreground = mycolors.default } }, { scope = "context.number", settings = { foreground = mycolors.cyan } }, { scope = "context.comment", settings = { foreground = mycolors.yellow } }, { scope = "context.keyword", settings = { foreground = mycolors.blue, fontStyle = "bold" } }, @@ -457,30 +508,30 @@ function scripts.vscode.generate(targetpath) { scope = "context.error", settings = { foreground = mycolors.red } }, { scope = "context.label", settings = { foreground = mycolors.red, fontStyle = "bold" } }, { scope = "context.nothing", settings = { } }, - { scope = "context.class", settings = { foreground = mycolors.black, fontStyle = "bold" } }, - { scope = "context.function", settings = { foreground = mycolors.black, fontStyle = "bold" } }, + { scope = "context.class", settings = { foreground = mycolors.default, fontStyle = "bold" } }, + { scope = "context.function", settings = { foreground = mycolors.default, fontStyle = "bold" } }, { scope = "context.constant", settings = { foreground = mycolors.cyan, fontStyle = "bold" } }, { scope = "context.operator", settings = { foreground = mycolors.blue } }, { scope = "context.regex", settings = { foreground = mycolors.magenta } }, { scope = "context.preprocessor", settings = { foreground = mycolors.yellow, fontStyle = "bold" } }, { scope = "context.tag", settings = { foreground = mycolors.cyan } }, { scope = "context.type", settings = { foreground = mycolors.blue } }, - { scope = "context.variable", settings = { foreground = mycolors.black } }, + { scope = "context.variable", settings = { foreground = mycolors.default } }, { scope = "context.identifier", settings = { } }, { scope = "context.linenumber", settings = { background = mycolors.linepanel } }, { scope = "context.bracelight", settings = { foreground = mycolors.orange, fontStyle = "bold" } }, { scope = "context.bracebad", settings = { foreground = mycolors.orange, fontStyle = "bold" } }, { scope = "context.controlchar", settings = { } }, - { scope = "context.indentguide", settings = { foreground = mycolors.linepanel, back = colors.white } }, - { scope = "context.calltip", settings = { foreground = mycolors.white, back = colors.tippanel } }, + { scope = "context.indentguide", settings = { foreground = mycolors.linepanel, back = colors.reverse } }, + { scope = "context.calltip", settings = { foreground = mycolors.reverse, back = colors.tippanel } }, { scope = "context.invisible", settings = { background = mycolors.orange } }, { scope = "context.quote", settings = { foreground = mycolors.blue, fontStyle = "bold" } }, { scope = "context.special", settings = { foreground = mycolors.blue } }, { scope = "context.extra", settings = { foreground = mycolors.yellow } }, - { scope = "context.embedded", settings = { foreground = mycolors.black, fontStyle = "bold" } }, + { scope = "context.embedded", settings = { foreground = mycolors.default, fontStyle = "bold" } }, { scope = "context.char", settings = { foreground = mycolors.magenta } }, { scope = "context.reserved", settings = { foreground = mycolors.magenta, fontStyle = "bold" } }, - { scope = "context.definition", settings = { foreground = mycolors.black, fontStyle = "bold" } }, + { scope = "context.definition", settings = { foreground = mycolors.default, fontStyle = "bold" } }, { scope = "context.okay", settings = { foreground = mycolors.dark } }, { scope = "context.warning", settings = { foreground = mycolors.orange } }, { scope = "context.standout", settings = { foreground = mycolors.orange, fontStyle = "bold" } }, @@ -492,12 +543,12 @@ function scripts.vscode.generate(targetpath) { scope = "context.plain", settings = { foreground = mycolors.dark, fontStyle = "bold" } }, { scope = "context.user", settings = { foreground = mycolors.green } }, { scope = "context.data", settings = { foreground = mycolors.cyan, fontStyle = "bold" } }, - { scope = "context.text", settings = { foreground = mycolors.black } }, + { scope = "context.text", settings = { foreground = mycolors.default } }, { scope = { "emphasis" }, settings = { fontStyle = "italic" } }, { scope = { "strong" }, settings = { fontStyle = "bold" } }, - { scope = { "comment" }, settings = { foreground = mycolors.black } }, + { scope = { "comment" }, settings = { foreground = mycolors.default } }, { scope = { "string" }, settings = { foreground = mycolors.magenta } }, { @@ -541,7 +592,7 @@ function scripts.vscode.generate(targetpath) "entity.name.function.shell" }, settings = { - foreground = mycolors.black, + foreground = mycolors.default, } }, @@ -550,7 +601,7 @@ function scripts.vscode.generate(targetpath) "entity.name.tag", }, settings = { - foreground = mycolors.black, + foreground = mycolors.default, } }, @@ -563,6 +614,8 @@ function scripts.vscode.generate(targetpath) styles = styles, } + -- registersettings() + end do @@ -576,41 +629,43 @@ function scripts.vscode.generate(targetpath) clear = true, } + -- chcp 65001 ; ... + local tasks = { { group = "build", label = "process tex file", type = "shell", - command = "context --autogenerate --autopdf ${file}", - windows = { command = "chcp 65001 ; context.exe --autogenerate --autopdf ${file}" }, + command = "context --autogenerate --autopdf ${file}", + windows = { command = "context.exe --autogenerate --autopdf ${file}" }, }, { group = "build", label = "check tex file", type = "shell", - command = "mtxrun --autogenerate --script check ${file}", - windows = { command = "chcp 65001 ; mtxrun.exe --autogenerate --script check ${file}" }, + command = "mtxrun --autogenerate --script check ${file}", + windows = { command = "mtxrun.exe --autogenerate --script check ${file}" }, }, { group = "build", label = "identify fonts", type = "shell", - command = "mtxrun --script fonts --reload --force", - windows = { command = "chcp 65001 ; mtxrun.exe --script fonts --reload --force" }, + command = "mtxrun --script fonts --reload --force", + windows = { command = "mtxrun.exe --script fonts --reload --force" }, }, { group = "build", label = "process lua file", type = "shell", - command = "mtxrun --script ${file}", - windows = { command = "chcp 65001 ; mtxrun.exe --script ${file}" }, + command = "mtxrun --script ${file}", + windows = { command = "mtxrun.exe --script ${file}" }, }, } for i=1,#tasks do local task = tasks[i] if not task.windows then - task.windows = { command = "chcp 65001 ; " .. task.command } + task.windows = { command = task.command } end if not task.presentation then task.presentation = presentation @@ -697,7 +752,7 @@ function scripts.vscode.generate(targetpath) for i=1,#t do result[i] = string.gsub(t[i],".",escapes) end - return table.concat(result,"|") + return concat(result,"|") end local function capture(str) @@ -869,12 +924,12 @@ function scripts.vscode.generate(targetpath) -- mp argument {...text} local function words(list) table.sort(list,sorter) - return "\\\\(" .. table.concat(list,"|") .. ")" .. "(?=[^a-zA-Z])" + return "\\\\(" .. concat(list,"|") .. ")" .. "(?=[^a-zA-Z])" end local function bwords(list) table.sort(list,sorter) - return "(\\\\(" .. table.concat(list,"|") .. "))\\s*(\\{)" + return "(\\\\(" .. concat(list,"|") .. "))\\s*(\\{)" end local function ewords() @@ -883,7 +938,7 @@ function scripts.vscode.generate(targetpath) local function environments(list) table.sort(list,sorter) - last = table.concat(list,"|") + last = concat(list,"|") if #list > 1 then last = "(?:" .. last .. ")" end @@ -975,7 +1030,7 @@ function scripts.vscode.generate(targetpath) comment = { name = style("context.comment", "comment"), - match = texcomment, + match = comment, }, constant = { @@ -1188,7 +1243,7 @@ function scripts.vscode.generate(targetpath) local function words(list) table.sort(list,sorter) - return "(" .. table.concat(list,"|") .. ")" .. "(?=[^a-zA-Z\\_@!?\127-\255])" + return "(" .. concat(list,"|") .. ")" .. "(?=[^a-zA-Z\\_@!?\127-\255])" end local capturedshortcuts = oneof(mergedshortcuts) @@ -1401,7 +1456,7 @@ function scripts.vscode.generate(targetpath) local function words(list) table.sort(list,sorter) - return "(" .. table.concat(list,"|") .. ")" .. "(?=[^a-zA-Z])" + return "(" .. concat(list,"|") .. ")" .. "(?=[^a-zA-Z])" end local capturedkeywords = words { @@ -1642,7 +1697,7 @@ function scripts.vscode.generate(targetpath) category = "cld", description = "ConTeXt CLD", - suffixes = { "lua", "luc", "cld", "tuc", "luj", "lum", "tma", "lfg", "luv", "lui" }, + suffixes = { "lmt", "lua", "luc", "cld", "tuc", "luj", "lum", "tma", "lfg", "luv", "lui" }, version = lualexer.version, setup = lualexer.setup, @@ -2118,7 +2173,7 @@ function scripts.vscode.generate(targetpath) local function words(list) table.sort(list,sorter) - local str = table.concat(list,"|") + local str = concat(list,"|") return "(" .. str .. "|" .. string.upper(str) .. ")" .. "(?=[^a-zA-Z])" end @@ -2501,7 +2556,7 @@ function scripts.vscode.generate(targetpath) local function words(list) table.sort(list,sorter) - return "\\b(" .. table.concat(list,"|") .. ")\\b" + return "\\b(" .. concat(list,"|") .. ")\\b" end local capturedkeywords = words { -- copied from cpp.lua @@ -3157,10 +3212,272 @@ function scripts.vscode.generate(targetpath) end +-- {name: 'inherits: \\setupframed'} + +function scripts.vscode.ls(forcedinterface) + + local interfaces = forcedinterfaces or environment.files or userinterfaces + if not interfaces.en then + -- loaded as script so we have "cont-yes.*" as name + interfaces = { "en" } + end + -- + local filename = "context-en.xml" + local xmlfile = resolvers.findfile(filename) or "" + if xmlfile == "" then + report("unable to locate %a",filename) + return + end + -- + local filename = "mult-def.lua" + local deffile = resolvers.findfile(filename) or "" + if deffile == "" then + report("unable to locate %a",filename) + return + end + local interface = dofile(deffile) + if not interface or not next(interface) then + report("invalid file %a",filename) + return + end + local variables = interface.variables + local constants = interface.constants + local commands = interface.commands + local elements = interface.elements + -- + local collected = { } + -- + report("loading %a",xmlfile) + local xmlroot = xml.load(xmlfile) + + local interfaces = { "en" } + +-- <cd:keywords list="yes"> +-- <cd:inherit name="setupalign"/> +-- </cd:keywords> + + local function arguments(e) + local p = { } + for e in xml.collected(e,"/cd:arguments/*") do + local tg = e.tg + if tg == "keywords" then + local a = { } + for e in xml.collected(e,"/*") do + a[#a+1] = { + name = e.at.type + } + end + p[#p+1] = { + type = tg, + attributes = #a > 0 and a or nil, + optional = e.at.optional == "yes" or nil + } + elseif tg == "assignments" then + local a = { } + for e in xml.collected(e,"/parameter") do + -- local c = { e.at.name, "=" } + local c = { } + for e in xml.collected(e,"/constant") do + c[#c+1] = e.at.type + end + -- if #c > 0 then + -- a[#a+1] = { + -- name = concat(c, " ") -- maybe "|" + -- } + -- end + a[#a+1] = { + name = e.at.name .. "=" .. concat(c, " ") -- maybe "|" + } + end + p[#p+1] = { + type = tg, + attributes = #a > 0 and a or nil, + optional = e.at.optional == "yes" or nil + } + else -- e.g. "content" + p[#p+1] = { + type = tg, + optional = e.at.optional == "yes" or nil + } + end + end + return p + end + + local function details(e, f) + local d = { "\\" .. f } + local n = 0 + for e in xml.collected(e,"/cd:arguments/*") do + local tg = e.tg + if tg == "keywords" then + n = n + 1 + if e.at.optional == "yes" then + d[#d+1] = "[optional " .. n .. ":..,..]" + else + d[#d+1] = "[mandate " .. n .. ":..,..]" + end + elseif tg == "assignments" then + n = n + 1 + if e.at.optional == "yes" then + d[#d+1] = "[optional " .. n .. ":key=val,key=val,..]" + else + d[#d+1] = "[mandate " .. n .. ":key=val,key=val,..]" + end + else + d[#d+1] = "{ content }" + end + end + return concat(d, " ") + end + + -- this one is a bit weird as it could be assembled in the languages server on the fly and + -- it bloats the file + + local function documentation(c) + local d = { c.detail } + local p = c.params + if p then + local n = 0 + for i=1,#p do + local pi = p[i] + local ti = pi.type + local ai = pi.attributes + if ti == "keywords" then + n = n + 1 + if pi.optional then + d[#d+1] = "[optional keywords " .. n .. "]" + else + d[#d+1] = "[mandate keywords " .. n .. "]" + end + if ai then + local t = { } + for j=1,#ai do + t[#t+1] = ai[j].name + end + if #t > 0 then + d[#d+1] = concat(t," ") + end + end + elseif ti == "assignments" then + n = n + 1 + if pi.optional then + d[#d+1] = "[optional assignments " .. n .. "]" + else + d[#d+1] = "[mandate assignments " .. n .. "]" + end + if ai then + local t = { } + for j=1,#ai do + t[#t+1] = ai[j].name + end + if #t > 0 then + d[#d+1] = concat(t,"\n") + end + end + else + if pi.optional then + d[#d+1] = "{ optional content }" + else + d[#d+1] = "{ mandate content }" + end + end + end + end + c.documentation = concat(d,"\n") +-- inspect(c.documentation) + end + + if not xml.expand then + -- will be in next version + function xml.expand(root,pattern,whatever) + local collected = xml.applylpath(root,pattern) + if collected then + for c=1,#collected do + local e = collected[c] + local p = e.__p__ + if p then + local d = p.dt + local n = e.ni + local t = whatever(e,p) + if type(t) == "table" then + d[n] = t[1] + for i=2,#t do + n = n + 1 + table.insert(d,n,t[i]) + end + elseif t then + d[n] = t + end + end + end + end + end + end + + do + local c = { } + xml.expand(xmlroot,"/cd:interface/cd:interface/cd:command/**/inherit",function(e) + local f = c[e.at.name] + if not f then + f = xml.first(xmlroot,"/cd:interface/cd:interface/cd:command[@name='" .. e.at.name .. "']/cd:arguments") + c[e.at.name] = f + end + return f and f.dt + end) + end + + for i=1,#interfaces do + local interface = interfaces[i] + local start = elements.start[interface] or elements.start.en + local stop = elements.stop [interface] or elements.stop .en + for e in xml.collected(xmlroot,"cd:interface/cd:command") do + local at = e.at + local name = at["name"] or "" + local type = at["type"] + if name ~= "" then + local c = commands[name] + local n = (c and (c[interface] or c.en)) or c or name + local sequence = xml.all(e,"/cd:sequence/*") + if at.generated == "yes" then + -- skip (for now) + elseif type ~= "environment" then + collected[#collected+1] = { + name = n, + detail = details(e, n), + params = arguments(e), -- why not "parameters" + } + else + local f = start .. n + collected[#collected+1] = { + name = f, + start = f, + stop = stop .. n, + detail = details(e, f), + params = arguments(e), -- why not "parameters" + } + end + end + end + end + for i=1,#collected do + documentation(collected[i]) + end + local jsonname = "vscode-context-ls.json" + -- local exmlname = "vscode-context-ls.xml" + report("") + report("vscode ls file saved: %s",jsonname) + report("") + io.savedata(jsonname,utilities.json.tojson(collected)) + -- io.savedata(exmlname,tostring(xmlroot)) +end + function scripts.vscode.start() local path = locate() if path then - local command = 'start "vs code context" code --reuse-window --ignore-gpu-blacklist --extensions-dir "' .. path .. '" --install-extension context' + local codecmd = environment.arguments.program or "code" -- can be codium + -- local command = 'start "vs code context" ' .. codecmd .. ' --reuse-window --ignore-gpu-blacklist --extensions-dir "' .. path .. '" --install-extension context' + -- local command = 'start "vs code context" ' .. codecmd .. ' --reuse-window --extensions-dir "' .. path .. '" --install-extension context' + local command = 'start "vs code context" ' .. codecmd .. ' --reuse-window --extensions-dir "' .. path .. '" --verbose --force --install-extension cdt.context' report("running command: %s",command) os.execute(command) end @@ -3168,6 +3485,8 @@ end if environment.arguments.generate then scripts.vscode.generate() +elseif environment.arguments.lsfile then + scripts.vscode.ls() elseif environment.arguments.start then scripts.vscode.start() elseif environment.arguments.exporthelp then @@ -3176,4 +3495,6 @@ else application.help() end -scripts.vscode.generate([[t:/vscode/data/context/extensions]]) +-- scripts.vscode.ls() + +-- scripts.vscode.generate([[t:/vscode/data/context/extensions]]) diff --git a/Master/texmf-dist/scripts/context/lua/mtxrun.lua b/Master/texmf-dist/scripts/context/lua/mtxrun.lua index 6fc17adb022..a00dc59288c 100755 --- a/Master/texmf-dist/scripts/context/lua/mtxrun.lua +++ b/Master/texmf-dist/scripts/context/lua/mtxrun.lua @@ -1201,7 +1201,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true --- original size: 38703, stripped down to: 19489 +-- original size: 38742, stripped down to: 19489 if not modules then modules={} end modules ['l-lpeg']={ version=1.001, @@ -2004,7 +2004,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-string"] = package.loaded["l-string"] or true --- original size: 6644, stripped down to: 3410 +-- original size: 6955, stripped down to: 3504 if not modules then modules={} end modules ['l-string']={ version=1.001, @@ -2014,7 +2014,7 @@ if not modules then modules={} end modules ['l-string']={ license="see context related readme files" } local string=string -local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower +local sub,gmatch,format,char,byte,rep,lower,find=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower,string.find local lpegmatch,patterns=lpeg.match,lpeg.patterns local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote @@ -2024,10 +2024,18 @@ end function string.quoted(str) return format("%q",str) end -function string.count(str,pattern) +function string.count(str,pattern) local n=0 - for _ in gmatch(str,pattern) do - n=n+1 + local i=1 + local l=#pattern + while true do + i=find(str,pattern,i) + if i then + n=n+1 + i=i+l + else + break + end end return n end @@ -3285,7 +3293,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-io"] = package.loaded["l-io"] or true --- original size: 11829, stripped down to: 6331 +-- original size: 11988, stripped down to: 6430 if not modules then modules={} end modules ['l-io']={ version=1.001, @@ -3352,9 +3360,12 @@ function io.copydata(source,target,action) flush() end end -function io.savedata(filename,data,joiner) - local f=open(filename,"wb") +function io.savedata(filename,data,joiner,append) + local f=open(filename,append and "ab" or "wb") if f then + if append and joiner and f:seek("end")>0 then + f:write(joiner) + end if type(data)=="table" then f:write(concat(data,joiner or "")) elseif type(data)=="function" then @@ -3637,17 +3648,17 @@ do -- create closure to overcome 200 locals limit package.loaded["l-number"] = package.loaded["l-number"] or true --- original size: 5720, stripped down to: 2176 +-- original size: 4588, stripped down to: 2159 if not modules then modules={} end modules ['l-number']={ version=1.001, - comment="companion to luat-lib.mkiv", + comment="companion to luat-lib.mkxl", author="Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } local tostring,tonumber=tostring,tonumber -local format,floor,match,rep=string.format,math.floor,string.match,string.rep +local format,match,rep=string.format,string.match,string.rep local concat,insert=table.concat,table.insert local lpegmatch=lpeg.match local floor=math.floor @@ -3837,7 +3848,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-os"] = package.loaded["l-os"] or true --- original size: 19409, stripped down to: 10419 +-- original size: 20585, stripped down to: 10701 if not modules then modules={} end modules ['l-os']={ version=1.001, @@ -3847,10 +3858,10 @@ if not modules then modules={} end modules ['l-os']={ license="see context related readme files" } local os=os -local date,time=os.date,os.time +local date,time,difftime=os.date,os.time,os.difftime local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch local concat=table.concat -local random,ceil,randomseed=math.random,math.ceil,math.randomseed +local random,ceil,randomseed,modf=math.random,math.ceil,math.randomseed,math.modf local type,setmetatable,tonumber,tostring=type,setmetatable,tonumber,tostring do local selfdir=os.selfdir @@ -3948,7 +3959,7 @@ if not os.__getenv__ then osenv[K]=v end function os.getenv(k) - local K=upper(k) + local K=upper(k) local v=osenv[K] or osgetenv(K) or osgetenv(k) if v=="" then return nil @@ -3966,22 +3977,6 @@ if not os.__getenv__ then setmetatable(os.env,{ __index=__index,__newindex=__newindex } ) end end -local execute=os.execute -local iopopen=io.popen -local function resultof(command) - local handle=iopopen(command,"r") - if handle then - local result=handle:read("*all") or "" - handle:close() - return result - else - return "" - end -end -os.resultof=resultof -function os.pipeto(command) - return iopopen(command,"w") -end if not io.fileseparator then if find(os.getenv("PATH"),";",1,true) then io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "windows" @@ -3996,228 +3991,231 @@ if os.type=="windows" then else os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' } end -local launchers={ - windows="start %s", - macosx="open %s", - unix="xdg-open %s &> /dev/null &", -} -function os.launch(str) - local command=format(launchers[os.name] or launchers.unix,str) - execute(command) -end -local gettimeofday=os.gettimeofday or os.clock -os.gettimeofday=gettimeofday -local startuptime=gettimeofday() -function os.runtime() - return gettimeofday()-startuptime -end -local resolvers=os.resolvers or {} -os.resolvers=resolvers -setmetatable(os,{ __index=function(t,k) - local r=resolvers[k] - return r and r(t,k) or nil -end }) -local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or "" -if platform~="" then - os.platform=platform -elseif os.type=="windows" then - function resolvers.platform(t,k) - local architecture=os.getenv("PROCESSOR_ARCHITECTURE") or "" - local platform="" - if find(architecture,"AMD64",1,true) then - platform="win64" +do + local execute=os.execute + local iopopen=io.popen + local ostype=os.type + local function resultof(command) + local handle=iopopen(command,ostype=="windows" and "rb" or "r") + if handle then + local result=handle:read("*all") or "" + handle:close() + return result else - platform="mswin" + return "" end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform end -elseif name=="linux" then - function resolvers.platform(t,k) - local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or "" - local platform=os.getenv("MTX_PLATFORM") or "" + os.resultof=resultof + function os.pipeto(command) + return iopopen(command,"w") + end + local launchers={ + windows="start %s", + macosx="open %s", + unix="xdg-open %s &> /dev/null &", + } + function os.launch(str) + local command=format(launchers[os.name] or launchers.unix,str) + execute(command) + end +end +do + local gettimeofday=os.gettimeofday or os.clock + os.gettimeofday=gettimeofday + local startuptime=gettimeofday() + function os.runtime() + return gettimeofday()-startuptime + end +end +do + local name=os.name or "linux" + local platform=os.getenv("MTX_PLATFORM") or "" + local architecture=os.uname and os.uname().machine + local bits=os.getenv("MTX_BITS") or find(platform,"64") and 64 or 32 + if platform~="" then + elseif os.type=="windows" then + architecture=string.lower(architecture or os.getenv("PROCESSOR_ARCHITECTURE") or "") + if architecture=="x86_64" then + bits,platform=64,"win64" + elseif find(architecture,"amd64") then + bits,platform=64,"win64" + elseif find(architecture,"arm64") then + bits,platform=64,"windows-arm64" + elseif find(architecture,"arm32") then + bits,platform=32,"windows-arm32" + else + bits,platform=32,"mswin" + end + elseif name=="linux" then + architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or "" local musl=find(os.selfdir or "","linuxmusl") - if platform~="" then - elseif find(architecture,"x86_64",1,true) then - platform=musl and "linuxmusl" or "linux-64" - elseif find(architecture,"ppc",1,true) then - platform="linux-ppc" + if find(architecture,"x86_64") then + bits,platform=64,musl and "linuxmusl" or "linux-64" + elseif find(architecture,"ppc") then + bits,platform=32,"linux-ppc" else - platform=musl and "linuxmusl" or "linux" + bits,platform=32,musl and "linuxmusl" or "linux" end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="macosx" then - function resolvers.platform(t,k) - local architecture=resultof("echo $HOSTTYPE") or "" - local platform="" + elseif name=="macosx" then + architecture=architecture or resultof("echo $HOSTTYPE") or "" if architecture=="" then - platform="osx-intel" - elseif find(architecture,"i386",1,true) then - platform="osx-intel" - elseif find(architecture,"x86_64",1,true) then - platform="osx-64" - elseif find(architecture,"arm64",1,true) then - platform="osx-64" + bits,platform=64,"osx-intel" + elseif find(architecture,"i386") then + bits,platform=64,"osx-intel" + elseif find(architecture,"x86_64") then + bits,platform=64,"osx-64" + elseif find(architecture,"arm64") then + bits,platform=64,"osx-arm" else - platform="osx-ppc" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="sunos" then - function resolvers.platform(t,k) - local architecture=resultof("uname -m") or "" - local platform="" - if find(architecture,"sparc",1,true) then - platform="solaris-sparc" + bits,platform=32,"osx-ppc" + end + elseif name=="sunos" then + architecture=architecture or resultof("uname -m") or "" + if find(architecture,"sparc") then + bits,platform=32,"solaris-sparc" else - platform="solaris-intel" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="freebsd" then - function resolvers.platform(t,k) - local architecture=resultof("uname -m") or "" - local platform="" - if find(architecture,"amd64",1,true) then - platform="freebsd-amd64" + bits,platform=32,"solaris-intel" + end + elseif name=="freebsd" then + architecture=architecture or os.getenv("MACHTYPE") or resultof("uname -m") or "" + if find(architecture,"amd64") or find(architecture,"AMD64") then + bits,platform=64,"freebsd-amd64" else - platform="freebsd" - end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -elseif name=="kfreebsd" then - function resolvers.platform(t,k) - local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or "" - local platform="" - if find(architecture,"x86_64",1,true) then - platform="kfreebsd-amd64" + bits,platform=32,"freebsd" + end + elseif name=="kfreebsd" then + architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or "" + if architecture=="x86_64" then + bits,platform=64,"kfreebsd-amd64" + else + bits,platform=32,"kfreebsd-i386" + end + else + architecture=architecture or resultof("uname -m") or "" + if find(architecture,"aarch64") then + bits,platform="linux-aarch64" + elseif find(architecture,"armv7l") then + bits,platform=32,"linux-armhf" + elseif find(architecture,"mips64") or find(architecture,"mips64el") then + bits,platform=64,"linux-mipsel" + elseif find(architecture,"mipsel") or find(architecture,"mips") then + bits,platform=32,"linux-mipsel" else - platform="kfreebsd-i386" + bits,platform=64,"linux-64" end - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform end -else - function resolvers.platform(t,k) - local platform="linux" - os.setenv("MTX_PLATFORM",platform) - os.platform=platform - return platform - end -end -os.newline=name=="windows" and "\013\010" or "\010" -function resolvers.bits(t,k) - local bits=find(os.platform,"64",1,true) and 64 or 32 + os.setenv("MTX_PLATFORM",platform) + os.setenv("MTX_BITS",bits) + os.platform=platform os.bits=bits - return bits -end -local t={ 8,9,"a","b" } -function os.uuid() - return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", - random(0xFFFF),random(0xFFFF), - random(0x0FFF), - t[ceil(random(4))] or 8,random(0x0FFF), - random(0xFFFF), - random(0xFFFF),random(0xFFFF),random(0xFFFF) - ) + os.newline=name=="windows" and "\013\010" or "\010" +end +do + local t={ 8,9,"a","b" } + function os.uuid() + return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", + random(0xFFFF),random(0xFFFF), + random(0x0FFF), + t[ceil(random(4))] or 8,random(0x0FFF), + random(0xFFFF), + random(0xFFFF),random(0xFFFF),random(0xFFFF) + ) + end end -local d -function os.timezone(delta) - d=d or ((tonumber(date("%H")) or 0)-(tonumber(date("!%H")) or 0)) - if delta then - if d>0 then - return format("+%02i:00",d) +do + local hour,min + function os.timezone(difference) + if not hour then + local current=time() + local utcdate=date("!*t",current) + local localdate=date("*t",current) + localdate.isdst=false + local timediff=difftime(time(localdate),time(utcdate)) + hour,min=modf(timediff/3600) + min=min*60 + end + if difference then + return hour,min else - return format("-%02i:00",-d) + return format("%+03d:%02d",hour,min) end - else - return 1 end -end -local timeformat=format("%%s%s",os.timezone(true)) -local dateformat="!%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.fulltime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() + local timeformat=format("%%s%s",os.timezone()) + local dateformat="%Y-%m-%d %H:%M:%S" + local lasttime=nil + local lastdate=nil + function os.fulltime(t,default) + t=t and tonumber(t) or 0 + if t>0 then + elseif default then + return default + else + t=time() + end + if t~=lasttime then + lasttime=t + lastdate=format(timeformat,date(dateformat)) + end + return lastdate end - if t~=lasttime then - lasttime=t - lastdate=format(timeformat,date(dateformat)) + local dateformat="%Y-%m-%d %H:%M:%S" + local lasttime=nil + local lastdate=nil + function os.localtime(t,default) + t=t and tonumber(t) or 0 + if t>0 then + elseif default then + return default + else + t=time() + end + if t~=lasttime then + lasttime=t + lastdate=date(dateformat,t) + end + return lastdate end - return lastdate -end -local dateformat="%Y-%m-%d %H:%M:%S" -local lasttime=nil -local lastdate=nil -function os.localtime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() + function os.converttime(t,default) + local t=tonumber(t) + if t and t>0 then + return date(dateformat,t) + else + return default or "-" + end end - if t~=lasttime then - lasttime=t - lastdate=date(dateformat,t) + function os.today() + return date("!*t") end - return lastdate -end -function os.converttime(t,default) - local t=tonumber(t) - if t and t>0 then - return date(dateformat,t) - else - return default or "-" + function os.now() + return date("!%Y-%m-%d %H:%M:%S") end end -local memory={} -local function which(filename) - local fullname=memory[filename] - if fullname==nil then - local suffix=file.suffix(filename) - local suffixes=suffix=="" and os.binsuffixes or { suffix } - for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - local df=file.join(directory,filename) - for i=1,#suffixes do - local dfs=file.addsuffix(df,suffixes[i]) - if io.exists(dfs) then - fullname=dfs - break +do + local cache={} + local function which(filename) + local fullname=cache[filename] + if fullname==nil then + local suffix=file.suffix(filename) + local suffixes=suffix=="" and os.binsuffixes or { suffix } + for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do + local df=file.join(directory,filename) + for i=1,#suffixes do + local dfs=file.addsuffix(df,suffixes[i]) + if io.exists(dfs) then + fullname=dfs + break + end end end + if not fullname then + fullname=false + end + cache[filename]=fullname end - if not fullname then - fullname=false - end - memory[filename]=fullname + return fullname end - return fullname -end -os.which=which -os.where=which -function os.today() - return date("!*t") -end -function os.now() - return date("!%Y-%m-%d %H:%M:%S") + os.which=which + os.where=which end if not os.sleep then local socket=socket @@ -4228,65 +4226,69 @@ if not os.sleep then socket.sleep(n) end end -local function isleapyear(year) - return (year%4==0) and (year%100~=0 or year%400==0) -end -os.isleapyear=isleapyear -local days={ 31,28,31,30,31,30,31,31,30,31,30,31 } -local function nofdays(year,month,day) - if not month then - return isleapyear(year) and 365 or 364 - elseif not day then - return month==2 and isleapyear(year) and 29 or days[month] - else - for i=1,month-1 do - day=day+days[i] - end - if month>2 and isleapyear(year) then - day=day+1 +do + local function isleapyear(year) + return (year%4==0) and (year%100~=0 or year%400==0) + end + os.isleapyear=isleapyear + local days={ 31,28,31,30,31,30,31,31,30,31,30,31 } + local function nofdays(year,month,day) + if not month then + return isleapyear(year) and 365 or 364 + elseif not day then + return month==2 and isleapyear(year) and 29 or days[month] + else + for i=1,month-1 do + day=day+days[i] + end + if month>2 and isleapyear(year) then + day=day+1 + end + return day end - return day end -end -os.nofdays=nofdays -function os.weekday(day,month,year) - return date("%w",time { year=year,month=month,day=day })+1 -end -function os.validdate(year,month,day) - if month<1 then - month=1 - elseif month>12 then - month=12 + os.nofdays=nofdays + function os.weekday(day,month,year) + return date("%w",time { year=year,month=month,day=day })+1 end - if day<1 then - day=1 - else - local max=nofdays(year,month) - if day>max then - day=max + function os.validdate(year,month,day) + if month<1 then + month=1 + elseif month>12 then + month=12 + end + if day<1 then + day=1 + else + local max=nofdays(year,month) + if day>max then + day=max + end end + return year,month,day end - return year,month,day -end -function os.date(fmt,...) - if not fmt then - fmt="%Y-%m-%d %H:%M" + function os.date(fmt,...) + if not fmt then + fmt="%Y-%m-%d %H:%M" + end + return date(fmt,...) end - return date(fmt,...) -end -local osexit=os.exit -local exitcode=nil -function os.setexitcode(code) - exitcode=code end -function os.exit(c) - if exitcode~=nil then - return osexit(exitcode) +do + local osexit=os.exit + local exitcode=nil + function os.setexitcode(code) + exitcode=code end - if c~=nil then - return osexit(c) + function os.exit(c) + if exitcode~=nil then + return osexit(exitcode) + end + if c~=nil then + return osexit(c) + end + return osexit() end - return osexit() end @@ -4296,7 +4298,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-file"] = package.loaded["l-file"] or true --- original size: 22175, stripped down to: 10302 +-- original size: 22186, stripped down to: 10313 if not modules then modules={} end modules ['l-file']={ version=1.001, @@ -4552,7 +4554,7 @@ function file.join(one,two,three,...) if not two then return one=="" and one or lpegmatch(reslasher,one) end - if one=="" then + if not one or one=="" then return lpegmatch(stripper,three and concat({ two,three,... },"/") or two) end if lpegmatch(isnetwork,one) then @@ -4714,7 +4716,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-gzip"] = package.loaded["l-gzip"] or true --- original size: 5115, stripped down to: 1699 +-- original size: 268, stripped down to: 216 if not modules then modules={} end modules ['l-gzip']={ version=1.001, @@ -4722,76 +4724,6 @@ if not modules then modules={} end modules ['l-gzip']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } -gzip=gzip or {} -if not zlib then - zlib=xzip -elseif not xzip then - xzip=zlib -end -if zlib then - local suffix=file.suffix - local suffixes=file.suffixes - local find=string.find - local openfile=io.open - local gzipwindow=15+16 - local gziplevel=3 - local identifier="^\x1F\x8B\x08" - local compress=zlib.compress - local decompress=zlib.decompress - function gzip.load(filename) - local f=openfile(filename,"rb") - if not f then - else - local data=f:read("*all") - f:close() - if data and data~="" then - if suffix(filename)=="gz" then - data=decompress(data,gzipwindow) - end - return data - end - end - end - function gzip.save(filename,data,level) - if suffix(filename)~="gz" then - filename=filename..".gz" - end - local f=openfile(filename,"wb") - if f then - data=compress(data or "",level or gziplevel,nil,gzipwindow) - f:write(data) - f:close() - return #data - end - end - function gzip.suffix(filename) - local suffix,extra=suffixes(filename) - local gzipped=extra=="gz" - return suffix,gzipped - end - function gzip.compressed(s) - return s and find(s,identifier) - end - function gzip.compress(s,level) - if s and not find(s,identifier) then - if not level then - level=gziplevel - elseif level<=0 then - return s - elseif level>9 then - level=9 - end - return compress(s,level or gziplevel,nil,gzipwindow) or s - end - end - function gzip.decompress(s) - if s and find(s,identifier) then - return decompress(s,gzipwindow) - else - return s - end - end -end end -- of closure @@ -4926,7 +4858,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-url"] = package.loaded["l-url"] or true --- original size: 14755, stripped down to: 6981 +-- original size: 14713, stripped down to: 6981 if not modules then modules={} end modules ['l-url']={ version=1.001, @@ -5190,7 +5122,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-dir"] = package.loaded["l-dir"] or true --- original size: 18253, stripped down to: 10816 +-- original size: 18217, stripped down to: 10792 if not modules then modules={} end modules ['l-dir']={ version=1.001, @@ -5380,15 +5312,15 @@ local separator,pattern if onwindows then local slash=S("/\\")/"/" pattern={ - [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - [2]=Cs(((1-S("*?/\\"))^0*slash)^0), - [3]=Cs(P(1)^0) + (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), + Cs(((1-S("*?/\\"))^0*slash)^0), + Cs(P(1)^0) } else pattern={ - [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - [2]=C(((1-S("*?/"))^0*P("/"))^0), - [3]=C(P(1)^0) + (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), + C(((1-S("*?/"))^0*P("/"))^0), + C(P(1)^0) } end local filter=Cs (( @@ -6509,7 +6441,7 @@ do -- create closure to overcome 200 locals limit package.loaded["l-math"] = package.loaded["l-math"] or true --- original size: 2555, stripped down to: 1831 +-- original size: 2679, stripped down to: 1909 if not modules then modules={} end modules ['l-math']={ version=1.001, @@ -6522,8 +6454,14 @@ if not math.ceiling then math.ceiling=math.ceil end if not math.round then - local floor=math.floor - function math.round(x) return floor(x+0.5) end + if xmath then + math.round=xmath.round + else + local floor=math.floor + function math.round(x) + return x<0 and -floor(-x+0.5) or floor(x+0.5) + end + end end if not math.div then local floor=math.floor @@ -6593,7 +6531,7 @@ if not math.tointeger then end if not math.ult then local floor=math.floor - function math.tointeger(m,n) + function math.ult(m,n) return floor(m)<floor(n) end end @@ -6605,7 +6543,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-str"] = package.loaded["util-str"] or true --- original size: 45129, stripped down to: 23525 +-- original size: 46322, stripped down to: 24128 if not modules then modules={} end modules ['util-str']={ version=1.001, @@ -6617,12 +6555,13 @@ if not modules then modules={} end modules ['util-str']={ utilities=utilities or {} utilities.strings=utilities.strings or {} local strings=utilities.strings -local format,gsub,rep,sub,find=string.format,string.gsub,string.rep,string.sub,string.find +local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char local load,dump=load,string.dump local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable local unpack,concat=table.unpack,table.concat local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc local patterns,lpegmatch=lpeg.patterns,lpeg.match +local tsplitat=lpeg.tsplitat local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len local loadstripped=function(str,shortcuts) if shortcuts then @@ -6976,6 +6915,14 @@ patterns.escapedquotes=pattern function string.escapedquotes(s) return lpegmatch(pattern,s) end +local pattern=(1-P("\\"))^1;pattern=Cs ( + pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1 +) +patterns.unescapedquotes=pattern +function string.unescapedquotes(s) + return lpegmatch(pattern,s) or s +end +string.texnewlines=lpeg.replacer(patterns.newline,"\r",true) local preamble="" local environment={ global=global or _G, @@ -7511,7 +7458,6 @@ function number.to16dot16(n) return f_16_16(n/65536.0) end if not string.explode then - local tsplitat=lpeg.tsplitat local p_utf=patterns.utf8character local p_check=C(p_utf)*(P("+")*Cc(true))^0 local p_split=Ct(C(p_utf)^0) @@ -7531,6 +7477,20 @@ if not string.explode then end end end +do + local p_whitespace=patterns.whitespace^1 + local cache=setmetatable({},{ __index=function(t,k) + local p=tsplitat(p_whitespace*P(k)*p_whitespace) + local v=function(s) + return lpegmatch(p,s) + end + t[k]=v + return v + end }) + function string.wordsplitter(s) + return cache[s] + end +end end -- of closure @@ -7539,7 +7499,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-tab"] = package.loaded["util-tab"] or true --- original size: 32815, stripped down to: 18257 +-- original size: 34148, stripped down to: 18419 if not modules then modules={} end modules ['util-tab']={ version=1.001, @@ -7866,9 +7826,6 @@ if JITSUPPORTED then return concat(fastserialize(t,true)) end else - local f_v=formatters["[%q]=%q,"] - local f_t=formatters["[%q]="] - local f_q=formatters["%q,"] function table.fastserialize(t,prefix) local r={ type(prefix)=="string" and prefix or "return" } local m=1 @@ -7880,7 +7837,7 @@ else local v=t[0] if v then m=m+1 - r[m]="[0]='" + r[m]="[0]=" if type(v)=="table" then fastserialize(v) else @@ -8277,6 +8234,21 @@ function table.ordered(t) return function() end end end +function combine(target,source) + if target then + for k,v in next,source do + if type(v)=="table" then + target[k]=combine(target[k],source[k]) + else + target[k]=v + end + end + return target + else + return source + end +end +table.combine=combine end -- of closure @@ -8285,7 +8257,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-fil"] = package.loaded["util-fil"] or true --- original size: 11552, stripped down to: 9023 +-- original size: 11474, stripped down to: 8973 if not modules then modules={} end modules ['util-fil']={ version=1.001, @@ -8452,20 +8424,20 @@ function files.readinteger4le(f) end end function files.readfixed2(f) - local a,b=byte(f:read(2),1,2) - if a>=0x80 then - tonumber((a-0x100).."."..b) - else - tonumber((a ).."."..b) + local n1,n2=byte(f:read(2),1,2) + if n1>=0x80 then + n1=n1-0x100 end + return n1+n2/0xFF end function files.readfixed4(f) local a,b,c,d=byte(f:read(4),1,4) - if a>=0x80 then - tonumber((0x100*a+b-0x10000).."."..(0x100*c+d)) - else - tonumber((0x100*a+b ).."."..(0x100*c+d)) + local n1=0x100*a+b + local n2=0x100*c+d + if n1>=0x8000 then + n1=n1-0x10000 end + return n1+n2/0xFFFF end if bit32 then local extract=bit32.extract @@ -8654,7 +8626,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sac"] = package.loaded["util-sac"] or true --- original size: 12968, stripped down to: 9523 +-- original size: 14071, stripped down to: 10417 if not modules then modules={} end modules ['util-sac']={ version=1.001, @@ -8881,23 +8853,23 @@ function streams.readfixed2(f) local i=f[2] local j=i+1 f[2]=j+1 - local a,b=byte(f[1],i,j) - if a>=0x80 then - return tonumber((a-0x100).."."..b) or 0 - else - return tonumber((a ).."."..b) or 0 + local n1,n2=byte(f[1],i,j) + if n1>=0x80 then + n1=n1-0x100 end + return n1+n2/0xFF end function streams.readfixed4(f) local i=f[2] local j=i+3 f[2]=j+1 local a,b,c,d=byte(f[1],i,j) - if a>=0x80 then - return tonumber((0x100*a+b-0x10000).."."..(0x100*c+d)) or 0 - else - return tonumber((0x100*a+b ).."."..(0x100*c+d)) or 0 + local n1=0x100*a+b + local n2=0x100*c+d + if n1>=0x8000 then + n1=n1-0x10000 end + return n1+n2/0xFFFF end if bit32 then local extract=bit32.extract @@ -8986,10 +8958,10 @@ if sio and sio.readcardinal2 then f[2]=i+4 return readfixed4(f[1],i) end - function streams.read2dot4(f) + function streams.read2dot14(f) local i=f[2] f[2]=i+2 - return read2dot4(f[1],i) + return read2dot14(f[1],i) end function streams.readbytes(f,n) local i=f[2] @@ -9095,10 +9067,10 @@ do function io.newreader(str,method) local f,m if method=="string" then - f=openstring(str) + f=openstring(str,true) m=streams elseif method=="stream" then - f=openstream(str) + f=openstream(str,true) m=streams else f=openfile(str,"rb") @@ -9129,6 +9101,33 @@ do end end end +if bit32 and not streams.tocardinal1 then + local extract=bit32.extract + local char=string.char + streams.tocardinal1=char + function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end + function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end + function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end + streams.tocardinal1le=char + function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end + function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end + function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end +end +if not streams.readcstring then + local readchar=streams.readchar + local concat=table.concat + function streams.readcstring(f) + local t={} + while true do + local c=readchar(f) + if c and c~="\0" then + t[#t+1]=c + else + return concat(t) + end + end + end +end end -- of closure @@ -9308,7 +9307,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-prs"] = package.loaded["util-prs"] or true --- original size: 24683, stripped down to: 16431 +-- original size: 25542, stripped down to: 16783 if not modules then modules={} end modules ['util-prs']={ version=1.001, @@ -9357,8 +9356,8 @@ local noparent=1-(lparent+rparent) local nobracket=1-(lbracket+rbracket) local escape,left,right=P("\\"),P('{'),P('}') lpegpatterns.balanced=P { - [1]=((escape*(left+right))+(1-(left+right))+V(2))^0, - [2]=left*V(1)*right + ((escape*(left+right))+(1-(left+right))+V(2))^0, + left*V(1)*right } local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } local nestedparents=P { lparent*(noparent+V(1))^0*rparent } @@ -9366,11 +9365,12 @@ local nestedbrackets=P { lbracket*(nobracket+V(1))^0*rbracket } local spaces=space^0 local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/"")) local content=(1-endofstring)^0 -lpegpatterns.nestedbraces=nestedbraces -lpegpatterns.nestedparents=nestedparents -lpegpatterns.nested=nestedbraces -lpegpatterns.argument=argument -lpegpatterns.content=content +lpegpatterns.nestedbraces=nestedbraces +lpegpatterns.nestedparents=nestedparents +lpegpatterns.nestedbrackets=nestedbrackets +lpegpatterns.nested=nestedbraces +lpegpatterns.argument=argument +lpegpatterns.content=content local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0) local key=C((1-equal-comma)^1) local pattern_a=(space+comma)^0*(key*equal*value+key*C("")) @@ -9776,15 +9776,24 @@ local function ranger(first,last,n,action) action(first) end end -local cardinal=lpegpatterns.cardinal/tonumber +local cardinal=(lpegpatterns.hexadecimal+lpegpatterns.cardinal)/tonumber local spacers=lpegpatterns.spacer^0 local endofstring=lpegpatterns.endofstring local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1 local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring function parsers.stepper(str,n,action) + local ts=type(str) if type(n)=="function" then - lpegmatch(stepper,str,1,false,n or print) - else + if ts=="number" then + n(str) + elseif ts=="table" then + for i=1,#str do + n(str[i]) + end + else + lpegmatch(stepper,str,1,false,n or print) + end + elseif ts=="string" then lpegmatch(stepper,str,1,n,action or print) end end @@ -9802,7 +9811,7 @@ local cache={} local spaces=lpegpatterns.space^0 local dummy=function() end setmetatableindex(cache,function(t,k) - local separator=P(k) + local separator=S(k) local value=(1-separator)^0 local pattern=spaces*C(value)*separator^0*Cp() t[k]=pattern @@ -9882,8 +9891,11 @@ local p_year=lpegpatterns.digit^4/tonumber local pattern=Cf(Ct("")*( (Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("day")*cardinal) )+(Cg(Cc("day")*cardinal)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) + )+(Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal) + )+(Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) ) - )*P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1 + )*( + P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1+P(-1) ) ,rawset) lpegpatterns.splittime=pattern function parsers.totime(str) @@ -12809,7 +12821,7 @@ do -- create closure to overcome 200 locals limit package.loaded["trac-set"] = package.loaded["trac-set"] or true --- original size: 13901, stripped down to: 9175 +-- original size: 14568, stripped down to: 9644 if not modules then modules={} end modules ['trac-set']={ version=1.001, @@ -12952,6 +12964,9 @@ local function register_setter(t,what,...) end local s=fnc fnc=function(value) set(t,s,value) end + elseif typ=="table" then + functions.values=fnc + fnc=nil elseif typ~="function" then fnc=nil end @@ -12996,35 +13011,42 @@ local function list_setter(t) end return user,system end -local function show_setter(t) +local function show_setter(t,pattern) local list=list_setter(t) t.report() for k=1,#list do local name=list[k] - local functions=t.data[name] - if functions then - local value=functions.value - local default=functions.default - local modules=#functions - if default==nil then - default="unset" - elseif type(default)=="table" then - default=concat(default,"|") - else - default=tostring(default) + if not pattern or find(name,pattern) then + local functions=t.data[name] + if functions then + local value=functions.value + local default=functions.default + local values=functions.values + local modules=#functions + if default==nil then + default="unset" + elseif type(default)=="table" then + default=concat(default,"|") + else + default=tostring(default) + end + if value==nil then + value="unset" + elseif type(value)=="table" then + value=concat(value,"|") + else + value=tostring(value) + end + t.report(name) + t.report(" modules : %i",modules) + t.report(" default : %s",default) + t.report(" value : %s",value) + if values then + local v={} for i=1,#values do v[i]=tostring(values[i]) end + t.report(" values : % t",v) end - if value==nil then - value="unset" - elseif type(value)=="table" then - value=concat(value,"|") - else - value=tostring(value) + t.report() end - t.report(name) - t.report(" modules : %i",modules) - t.report(" default : %s",default) - t.report(" value : %s",value) - t.report() end end end @@ -13043,6 +13065,10 @@ local function setter_value(setter,name) local d=setter.data[name] return d and (d.value or d.default) end +local function setter_values(setter,name) + local d=setter.data[name] + return d and d.values +end local function new_setter(name) local setter setter={ @@ -13057,6 +13083,7 @@ local function new_setter(name) show=function(...) show_setter (setter,...) end, default=function(...) return setter_default (setter,...) end, value=function(...) return setter_value (setter,...) end, + values=function(...) return setter_values (setter,...) end, } data[name]=setter return setter @@ -13128,7 +13155,7 @@ if environment then end if texconfig then local function set(k,v) - v=tonumber(v) + local v=tonumber(v) if v then texconfig[k]=v end @@ -14231,7 +14258,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-deb"] = package.loaded["util-deb"] or true --- original size: 10136, stripped down to: 6832 +-- original size: 10593, stripped down to: 7102 if not modules then modules={} end modules ['util-deb']={ version=1.001, @@ -14525,6 +14552,22 @@ local function showtraceback(rep) end end debugger.showtraceback=showtraceback +if luac then + local show,dump=luac.print,string.dump + function luac.inspect(v) + if type(v)=="function" then + local ok,str=xpcall(dump,function() end,v) + if ok then + v=str + end + end + if type(v)=="string" then + show(v,true) + else + print(v) + end + end +end end -- of closure @@ -14686,7 +14729,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-sbx"] = package.loaded["util-sbx"] or true --- original size: 21084, stripped down to: 13214 +-- original size: 21145, stripped down to: 13271 if not modules then modules={} end modules ['util-sbx']={ version=1.001, @@ -14939,7 +14982,7 @@ local function validcommand(name,program,template,checkers,defaults,variables,re if chktype=="verbose" then else local checker=validators[chktype] - if checker then + if checker and type(value)=="string" then value=checker(unquoted(value),strict) if value then variables[variable]=optionalquoted(value) @@ -14958,7 +15001,7 @@ local function validcommand(name,program,template,checkers,defaults,variables,re if not value or value=="" then local chktype=checkers[variable] if chktype=="verbose" then - else + elseif type(default)=="string" then local checker=validators[chktype] if checker then default=checker(unquoted(default),strict) @@ -15759,7 +15802,7 @@ do -- create closure to overcome 200 locals limit package.loaded["util-zip"] = package.loaded["util-zip"] or true --- original size: 19496, stripped down to: 10858 +-- original size: 23730, stripped down to: 14293 if not modules then modules={} end modules ['util-zip']={ version=1.001, @@ -15768,12 +15811,20 @@ if not modules then modules={} end modules ['util-zip']={ license="see context related readme files" } local type,tostring,tonumber=type,tostring,tonumber -local sort=table.sort +local sort,concat=table.sort,table.concat local find,format,sub,gsub=string.find,string.format,string.sub,string.gsub local osdate,ostime,osclock=os.date,os.time,os.clock local ioopen=io.open local loaddata,savedata=io.loaddata,io.savedata local filejoin,isdir,dirname,mkdirs=file.join,lfs.isdir,file.dirname,dir.mkdirs +local suffix,suffixes=file.suffix,file.suffixes +local openfile=io.open +gzip=gzip or {} +if not zlib then + zlib=xzip +elseif not xzip then + xzip=zlib +end local files=utilities.files local openfile=files.open local closefile=files.close @@ -15785,19 +15836,16 @@ local getposition=files.getposition local band=bit32.band local rshift=bit32.rshift local lshift=bit32.lshift -local decompress,expandsize,calculatecrc - local zlibdecompress=zlib.decompress - local zlibexpandsize=zlib.expandsize - local zlibchecksum=zlib.crc32 - decompress=function(source) - return zlibdecompress(source,-15) - end - expandsize=zlibexpandsize and function(source,targetsize) - return zlibexpandsize(source,targetsize,-15) - end or decompress - calculatecrc=function(buffer,initial) - return zlibchecksum(initial or 0,buffer) - end +local zlibdecompress=zlib.decompress +local zlibdecompresssize=zlib.decompresssize +local zlibchecksum=zlib.crc32 +if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then + local cs=zlibchecksum + zlibchecksum=function(str,n) return cs(n or 0,str) end +end +local decompress=function(source) return zlibdecompress (source,-15) end +local decompresssize=function(source,targetsize) return zlibdecompresssize(source,targetsize,-15) end +local calculatecrc=function(buffer,initial) return zlibchecksum (initial or 0,buffer) end local zipfiles={} utilities.zipfiles=zipfiles local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do @@ -15922,8 +15970,8 @@ local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do setposition(handle,position) local result=readstring(handle,compressed) if data.method==8 then - if expandsize then - result=expandsize(result,data.uncompressed) + if decompresssize then + result=decompresssize(result,data.uncompressed) else result=decompress(result) end @@ -16187,7 +16235,127 @@ if xzip then zipfiles.zipdir=zipdir zipfiles.unzipdir=unzipdir end -zipfiles.gunzipfile=gzip.load +local pattern="^\x1F\x8B\x08" +local gziplevel=3 +function gzip.suffix(filename) + local suffix,extra=suffixes(filename) + local gzipped=extra=="gz" + return suffix,gzipped +end +function gzip.compressed(s) + return s and find(s,pattern) +end +local getdecompressed +local putcompressed +if gzip.compress then + local gzipwindow=15+16 + local compress=zlib.compress + local decompress=zlib.decompress + getdecompressed=function(str) + return decompress(str,gzipwindow) + end + putcompressed=function(str,level) + return compress(str,level or gziplevel,nil,gzipwindow) + end +else + local gzipwindow=-15 + local identifier="\x1F\x8B" + local compress=zlib.compress + local decompress=zlib.decompress + local zlibchecksum=zlib.crc32 + if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then + local cs=zlibchecksum + zlibchecksum=function(str,n) return cs(n or 0,str) end + end + local streams=utilities.streams + local openstream=streams.openstring + local closestream=streams.close + local getposition=streams.getposition + local readbyte=streams.readbyte + local readcardinal4=streams.readcardinal4le + local readcardinal2=streams.readcardinal2le + local readstring=streams.readstring + local readcstring=streams.readcstring + local skipbytes=streams.skip + local tocardinal1=streams.tocardinal1 + local tocardinal4=streams.tocardinal4le + getdecompressed=function(str) + local s=openstream(str) + local identifier=readstring(s,2) + local method=readbyte(s,1) + local flags=readbyte(s,1) + local timestamp=readcardinal4(s) + local compression=readbyte(s,1) + local operating=readbyte(s,1) + local isjusttext=band(flags,0x01)~=0 and true or false + local extrasize=band(flags,0x04)~=0 and readcardinal2(s) or 0 + local filename=band(flags,0x08)~=0 and readcstring(s) or "" + local comment=band(flags,0x10)~=0 and readcstring(s) or "" + local checksum=band(flags,0x02)~=0 and readcardinal2(s) or 0 + local compressed=readstring(s,#str) + local data=decompress(compressed,gzipwindow) + return data + end + putcompressed=function(str,level,originalname) + return concat { + identifier, + tocardinal1(0x08), + tocardinal1(0x08), + tocardinal4(os.time()), + tocardinal1(0x02), + tocardinal1(0xFF), + (originalname or "unknownname").."\0", + compress(str,level,nil,gzipwindow), + tocardinal4(zlibchecksum(str)), + tocardinal4(#str), + } + end +end +function gzip.load(filename) + local f=openfile(filename,"rb") + if not f then + else + local data=f:read("*all") + f:close() + if data and data~="" then + if suffix(filename)=="gz" then + data=getdecompressed(data) + end + return data + end + end +end +function gzip.save(filename,data,level,originalname) + if suffix(filename)~="gz" then + filename=filename..".gz" + end + local f=openfile(filename,"wb") + if f then + data=putcompressed(data or "",level or gziplevel,originalname) + f:write(data) + f:close() + return #data + end +end +function gzip.compress(s,level) + if s and not find(s,pattern) then + if not level then + level=gziplevel + elseif level<=0 then + return s + elseif level>9 then + level=9 + end + return putcompressed(s,level or gziplevel) or s + end +end +function gzip.decompress(s) + if s and find(s,pattern) then + return getdecompressed(s) + else + return s + end +end end -- of closure @@ -16196,7 +16364,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true --- original size: 61808, stripped down to: 36227 +-- original size: 62810, stripped down to: 36225 if not modules then modules={} end modules ['lxml-tab']={ version=1.001, @@ -16430,8 +16598,7 @@ end local function add_text(text) if text=="" then return - end - if cleanup then + elseif cleanup then if nt>0 then local s=dt[nt] if type(s)=="string" then @@ -17001,7 +17168,7 @@ local function install(spacenewline,spacing,anything) local attributes=(attribute+somespace^-1*(((anything-endofattributes)^1)/attribute_specification_error))^0 local parsedtext=text_parsed local unparsedtext=text_unparsed/add_text - local balanced=P { "["*((anything-S"[]")+V(1))^0*"]" } + local balanced=P { "["*((anything-S"[]")+V(1))^0*"]" } local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin local endelement=(spacing*open*slash*name*optionalspace*close)/add_end @@ -17043,8 +17210,7 @@ local function install(spacenewline,spacing,anything) local publicdoctype=doctypename*somespace*P("PUBLIC")*somespace*value*somespace*value*somespace*doctypeset local systemdoctype=doctypename*somespace*P("SYSTEM")*somespace*value*somespace*doctypeset local simpledoctype=(anything-close)^1 - local somedoctype=C((somespace*( -publicentityfile+publicdoctype+systemdoctype+definitiondoctype+simpledoctype)*optionalspace)^0) + local somedoctype=C((somespace*(publicentityfile+publicdoctype+systemdoctype+definitiondoctype+simpledoctype)*optionalspace)^0) local instruction=(spacing*begininstruction*someinstruction*endinstruction)/function(...) add_special("@pi@",...) end local comment=(spacing*begincomment*somecomment*endcomment )/function(...) add_special("@cm@",...) end local cdata=(spacing*begincdata*somecdata*endcdata )/function(...) add_special("@cd@",...) end @@ -17654,7 +17820,7 @@ function xml.kind(e) local tg=d.tg if tg=="@cd@" then return "cdata" - elseif tg=="@cm" then + elseif tg=="@cm@" then return "comment" elseif tg=="@pi@" then return "instruction" @@ -17679,7 +17845,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true --- original size: 54667, stripped down to: 31258 +-- original size: 54733, stripped down to: 31258 if not modules then modules={} end modules ['lxml-lpt']={ version=1.001, @@ -18999,7 +19165,7 @@ do -- create closure to overcome 200 locals limit package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true --- original size: 33708, stripped down to: 20953 +-- original size: 34661, stripped down to: 21511 if not modules then modules={} end modules ['lxml-aux']={ version=1.001, @@ -19265,6 +19431,36 @@ function xml.replace(root,pattern,whatever) end end end +function xml.expand(root,pattern,whatever) + local collected=root and xmlapplylpath(root,pattern) + if collected then + for c=1,#collected do + local e=collected[c] + local p=e.__p__ + if p then + if trace_manipulations then + report('expanding',pattern,c,e) + end + local d=p.dt + local n=e.ni + local t=whatever(e,p) + if t then + if type(t)=="table" then + t=xmlcopy(t) + d[n]=t[1] + for i=2,#t do + n=n+1 + insert(d,n,t[i]) + end + else + d[n]=t + end + redo_ni(d) + end + end + end + end +end local function wrap(e,wrapper) local t={ rn=e.rn, @@ -21199,7 +21395,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-env"] = package.loaded["data-env"] or true --- original size: 9501, stripped down to: 6411 +-- original size: 9501, stripped down to: 6413 if not modules then modules={} end modules ['data-env']={ version=1.001, @@ -21291,8 +21487,8 @@ local relations=allocate { names={ "mp" }, variable='MPINPUTS', suffixes=CONTEXTLMTXMODE>0 - and { 'mp','mpxl','mpvi','mpiv','mpii' } - or { 'mp','mpvi','mpiv','mpii' }, + and { 'mpxl','mpvi','mpiv','mpii','mp' } + or { 'mpvi','mpiv','mpii','mp' }, usertype=true, }, tex={ @@ -21486,7 +21682,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-tmp"] = package.loaded["data-tmp"] or true --- original size: 16409, stripped down to: 11591 +-- original size: 16456, stripped down to: 11636 if not modules then modules={} end modules ['data-tmp']={ version=1.100, @@ -21532,7 +21728,7 @@ local readables={} local usedreadables={} local compilelua=luautilities.compile local luasuffixes=luautilities.suffixes -caches.base=caches.base or "luatex-cache" +caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" caches.more=caches.more or "context" caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } local direct_cache=false @@ -23686,7 +23882,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-pre"] = package.loaded["data-pre"] or true --- original size: 5088, stripped down to: 3144 +-- original size: 5872, stripped down to: 3691 if not modules then modules={} end modules ['data-pre']={ version=1.001, @@ -23695,6 +23891,7 @@ if not modules then modules={} end modules ['data-pre']={ copyright="PRAGMA ADE / ConTeXt Development Team", license="see context related readme files" } +local ipairs=ipairs local insert,remove=table.insert,table.remove local resolvers=resolvers local prefixes=resolvers.prefixes @@ -23706,6 +23903,7 @@ local basename=file.basename local dirname=file.dirname local joinpath=file.join local isfile=lfs.isfile +local isdir=lfs.isdir prefixes.environment=function(str) return cleanpath(expansion(str)) end @@ -23766,6 +23964,30 @@ prefixes.home=function(str) local pth=getenv('HOME') return cleanpath(str and joinpath(pth,str) or pth) end +do + local tmppth + prefixes.temp=function(str) + if not tmppth then + for _,s in ipairs { "TMP","TEMP","TMPDIR","TEMPDIR" } do + tmppth=getenv(s) + if tmppth~="" and isdir(tmppth) then + break + end + end + if not tmppth or tmppth=="" then + tmppth="." + end + end + return cleanpath(str and joinpath(tmppth,str) or tmppth) + end + prefixes.texruns=function(str) + local pth=getenv('TEXRUNS') + if pth=="" then + pth=tmppth + end + return cleanpath(str and joinpath(pth,str) or pth) + end +end prefixes.env=prefixes.environment prefixes.rel=prefixes.relative prefixes.loc=prefixes.locate @@ -23816,7 +24038,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-inp"] = package.loaded["data-inp"] or true --- original size: 910, stripped down to: 818 +-- original size: 1050, stripped down to: 946 if not modules then modules={} end modules ['data-inp']={ version=1.001, @@ -23832,12 +24054,15 @@ local registermethod=resolvers.registermethod local finders=allocate { helpers={},notfound=function() end } local openers=allocate { helpers={},notfound=function() end } local loaders=allocate { helpers={},notfound=function() return false,nil,0 end } +local tracers=allocate { helpers={},notfound=function() end } registermethod("finders",finders,"uri") registermethod("openers",openers,"uri") registermethod("loaders",loaders,"uri") +registermethod("tracers",tracers,"uri") resolvers.finders=finders resolvers.openers=openers resolvers.loaders=loaders +resolvers.tracers=tracers end -- of closure @@ -23846,7 +24071,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-out"] = package.loaded["data-out"] or true --- original size: 551, stripped down to: 470 +-- original size: 682, stripped down to: 579 if not modules then modules={} end modules ['data-out']={ version=1.001, @@ -23860,7 +24085,10 @@ local resolvers=resolvers local registermethod=resolvers.registermethod local savers=allocate { helpers={} } resolvers.savers=savers +local cleaners=allocate { helpers={} } +resolvers.cleaners=cleaners registermethod("savers",savers,"uri") +registermethod("cleaners",cleaners,"uri") end -- of closure @@ -23998,7 +24226,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-con"] = package.loaded["data-con"] or true --- original size: 5388, stripped down to: 3685 +-- original size: 5487, stripped down to: 3757 if not modules then modules={} end modules ['data-con']={ version=1.100, @@ -24036,7 +24264,7 @@ local mt={ end, __storage__=true } -function containers.define(category,subcategory,version,enabled) +function containers.define(category,subcategory,version,enabled,reload) if category and subcategory then local c=allocated[category] if not c then @@ -24050,6 +24278,7 @@ function containers.define(category,subcategory,version,enabled) subcategory=subcategory, storage={}, enabled=enabled, + reload=reload, version=version or math.pi, trace=false, } @@ -24072,7 +24301,8 @@ function containers.is_valid(container,name) end function containers.read(container,name) local storage=container.storage - local stored=storage[name] + local reload=container.reload + local stored=not reload and storage[name] if not stored and container.enabled and caches and containers.usecache then stored=loaddatafromcache(container.readables,name,container.writable) if stored and stored.cache_version==container.version then @@ -24126,7 +24356,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-use"] = package.loaded["data-use"] or true --- original size: 5785, stripped down to: 2905 +-- original size: 5806, stripped down to: 2925 if not modules then modules={} end modules ['data-use']={ version=1.001, @@ -24156,14 +24386,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile,banner) functionality=LUATEXFUNCTIONALITY, } io.savedata(luvname,table.serialize(luvdata,true)) - lua.registerfinalizer(function() + lua.registerinitexfinalizer(function() if jit then logs.report("format banner","%s lua: %s jit",banner,LUAVERSION) else logs.report("format banner","%s lua: %s",banner,LUAVERSION) end logs.newline() - end) + end,"show banner") end end function statistics.checkfmtstatus(texname) @@ -24214,7 +24444,7 @@ do -- create closure to overcome 200 locals limit package.loaded["data-zip"] = package.loaded["data-zip"] or true --- original size: 10725, stripped down to: 7949 +-- original size: 10805, stripped down to: 7951 if not modules then modules={} end modules ['data-zip']={ version=1.001, @@ -24257,10 +24487,10 @@ if zipfiles then local openstream=streams.open local readstring=streams.readstring local streamsize=streams.size - local metatable={ + local metatable={ close=streams.close, read=function(stream,n) - readstring(stream,n=="*a" and streamsize(stream) or n) + readstring(stream,n=="*a" and streamsize(stream) or n) end } filehandle=function(zfile,queryname) @@ -25287,7 +25517,7 @@ do -- create closure to overcome 200 locals limit package.loaded["libs-ini"] = package.loaded["libs-ini"] or true --- original size: 6459, stripped down to: 4006 +-- original size: 6524, stripped down to: 4064 if not modules then modules={} end modules ['libs-ini']={ version=1.001, @@ -25329,10 +25559,10 @@ local function findlib(required) for i=1,#list do local name=list[i] local found=findfile(name,"lib") - if not found then + if not found or found=="" then found=findfile(addsuffix(name,suffix),"lib") end - if found then + if found and found~="" then if trace then report("library %a resolved via %a path to %a",name,"tds lib",found) end @@ -25345,9 +25575,9 @@ local function findlib(required) for i=1,#list do local full=joinfile(list[i],base) local found=isfile(full) and full - if found then + if found and found~="" then if trace then - report("library %a resolved via %a path to %a",name,"system",found) + report("library %a resolved via %a path to %a",full,"system",found) end return found end @@ -25402,7 +25632,7 @@ function libraries.optionalloaded(name,libnames) for i=1,#libnames do local libname=libnames[i] local filename=foundlibraries[libname] - if filename then + if filename and filename~="" then libnames[i]=filename else report("unable to locate library %a",libname) @@ -25842,8 +26072,8 @@ end -- of closure -- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua libs-ini.lua luat-sta.lua luat-fmt.lua -- skipped libraries : - --- original bytes : 1025947 --- stripped bytes : 405652 +-- original bytes : 1034927 +-- stripped bytes : 407861 -- end library merge @@ -27371,6 +27601,10 @@ end if ok == false then ok = 1 elseif ok == true or ok == nil then ok = 0 end +if lua and lua.getexitcode then + ok = lua.getexitcode() +end + -- os.exit(ok,true) -- true forces a cleanup in 5.2+ os.exit(ok) -- true forces a cleanup in 5.2+ but reports a wrong number then |