diff options
Diffstat (limited to 'scripts/context')
32 files changed, 9643 insertions, 9560 deletions
diff --git a/scripts/context/lua/mtx-base.lua b/scripts/context/lua/mtx-base.lua index bd6749717..66fd06624 100644 --- a/scripts/context/lua/mtx-base.lua +++ b/scripts/context/lua/mtx-base.lua @@ -1,134 +1,134 @@ -if not modules then modules = { } end modules ['mtx-base'] = { - version = 1.001, - comment = "formerly known as luatools", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-base</entry> - <entry name="detail">ConTeXt TDS Management Tool (aka luatools)</entry> - <entry name="version">1.35</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="generate"><short>generate file database</short></flag> - <flag name="variables"><short>show configuration variables</short></flag> - <flag name="configurations"><short>show configuration order</short></flag> - <flag name="expand-braces"><short>expand complex variable</short></flag> - <flag name="expand-path"><short>expand variable (resolve paths)</short></flag> - <flag name="expand-var"><short>expand variable (resolve references)</short></flag> - <flag name="show-path"><short>show path expansion of ...</short></flag> - <flag name="var-value"><short>report value of variable</short></flag> - <flag name="find-file"><short>report file location</short></flag> - <flag name="find-path"><short>report path of file</short></flag> - <flag name="make"><short>[or <ref name="ini"/>] make luatex format</short></flag> - <flag name="run"><short>[or <ref name="fmt"/>] run luatex format</short></flag> - <flag name="compile"><short>assemble and compile lua inifile</short></flag> - <flag name="verbose"><short>give a bit more info</short></flag> - <flag name="all"><short>show all found files</short></flag> - <flag name="format" value="str"><short>filter cf format specification (default 'tex', use 'any' for any match)</short></flag> - <flag name="pattern" value="str"><short>filter variables</short></flag> - <flag name="trackers" value="list"><short>enable given trackers</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-base", - banner = "ConTeXt TDS Management Tool (aka luatools) 1.35", - helpinfo = helpinfo, -} - -local report = application.report - --- private option --noluc for testing errors in the stub - -local instance = resolvers.instance - -local pattern = environment.arguments["pattern"] or nil -local fileformat = environment.arguments["format"] or "" -- nil ? -local allresults = environment.arguments["all"] or false -local trace = environment.arguments["trace"] - -if type(pattern) == 'boolean' then - report("invalid pattern specification") - pattern = nil -end - -if trace then - resolvers.settrace(trace) -- move to mtxrun ? -end - -if environment.arguments["find-file"] then - resolvers.load() - if pattern then - resolvers.dowithfilesandreport(resolvers.findfiles, { pattern }, fileformat, allresults) - else - resolvers.dowithfilesandreport(resolvers.findfiles, environment.files, fileformat, allresults) - end -elseif environment.arguments["find-path"] then - resolvers.load() - local path = resolvers.findpath(environment.files[1], fileformat) - print(path) -- quite basic, wil become function in logs -elseif environment.arguments["run"] then - resolvers.load("nofiles") -- ! no need for loading databases - trackers.enable("resolvers.locating") - environment.run_format(environment.files[1] or "",environment.files[2] or "",environment.files[3] or "") -elseif environment.arguments["fmt"] then - resolvers.load("nofiles") -- ! no need for loading databases - trackers.enable("resolvers.locating") - environment.run_format(environment.arguments["fmt"], environment.files[1] or "",environment.files[2] or "") -elseif environment.arguments["expand-braces"] then - resolvers.load("nofiles") - resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files) -elseif environment.arguments["expand-path"] then - resolvers.load("nofiles") - resolvers.dowithfilesandreport(resolvers.expandpath, environment.files) -elseif environment.arguments["expand-var"] or environment.arguments["expand-variable"] then - resolvers.load("nofiles") - resolvers.dowithfilesandreport(resolvers.expansion, environment.files) -elseif environment.arguments["show-path"] or environment.arguments["path-value"] then - resolvers.load("nofiles") - resolvers.dowithfilesandreport(resolvers.showpath, environment.files) -elseif environment.arguments["var-value"] or environment.arguments["show-value"] then - resolvers.load("nofiles") - resolvers.dowithfilesandreport(resolvers.variable, environment.files) -elseif environment.arguments["format-path"] then - resolvers.load() - report(caches.getwritablepath("format")) -elseif pattern then -- brrr - resolvers.load() - resolvers.dowithfilesandreport(resolvers.findfiles, { pattern }, fileformat, allresults) -elseif environment.arguments["generate"] then - instance.renewcache = true - trackers.enable("resolvers.locating") - resolvers.load() -elseif environment.arguments["make"] or environment.arguments["ini"] or environment.arguments["compile"] then - resolvers.load() - trackers.enable("resolvers.locating") - environment.make_format(environment.files[1] or "") -elseif environment.arguments["variables"] or environment.arguments["show-variables"] or environment.arguments["expansions"] or environment.arguments["show-expansions"] then - resolvers.load("nofiles") - resolvers.listers.variables(pattern) -elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then - resolvers.load("nofiles") - resolvers.listers.configurations() -elseif environment.arguments["exporthelp"] then - application.export(environment.arguments["exporthelp"],environment.files[1]) -elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then - application.help() -elseif environment.files[1] == 'texmfcnf.lua' then - resolvers.load("nofiles") - resolvers.listers.configurations() -else - resolvers.load() - resolvers.dowithfilesandreport(resolvers.findfiles, environment.files, fileformat, allresults) -end +if not modules then modules = { } end modules ['mtx-base'] = {
+ version = 1.001,
+ comment = "formerly known as luatools",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-base</entry>
+ <entry name="detail">ConTeXt TDS Management Tool (aka luatools)</entry>
+ <entry name="version">1.35</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="generate"><short>generate file database</short></flag>
+ <flag name="variables"><short>show configuration variables</short></flag>
+ <flag name="configurations"><short>show configuration order</short></flag>
+ <flag name="expand-braces"><short>expand complex variable</short></flag>
+ <flag name="expand-path"><short>expand variable (resolve paths)</short></flag>
+ <flag name="expand-var"><short>expand variable (resolve references)</short></flag>
+ <flag name="show-path"><short>show path expansion of ...</short></flag>
+ <flag name="var-value"><short>report value of variable</short></flag>
+ <flag name="find-file"><short>report file location</short></flag>
+ <flag name="find-path"><short>report path of file</short></flag>
+ <flag name="make"><short>[or <ref name="ini"/>] make luatex format</short></flag>
+ <flag name="run"><short>[or <ref name="fmt"/>] run luatex format</short></flag>
+ <flag name="compile"><short>assemble and compile lua inifile</short></flag>
+ <flag name="verbose"><short>give a bit more info</short></flag>
+ <flag name="all"><short>show all found files</short></flag>
+ <flag name="format" value="str"><short>filter cf format specification (default 'tex', use 'any' for any match)</short></flag>
+ <flag name="pattern" value="str"><short>filter variables</short></flag>
+ <flag name="trackers" value="list"><short>enable given trackers</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-base",
+ banner = "ConTeXt TDS Management Tool (aka luatools) 1.35",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+-- private option --noluc for testing errors in the stub
+
+local instance = resolvers.instance
+
+local pattern = environment.arguments["pattern"] or nil
+local fileformat = environment.arguments["format"] or "" -- nil ?
+local allresults = environment.arguments["all"] or false
+local trace = environment.arguments["trace"]
+
+if type(pattern) == 'boolean' then
+ report("invalid pattern specification")
+ pattern = nil
+end
+
+if trace then
+ resolvers.settrace(trace) -- move to mtxrun ?
+end
+
+if environment.arguments["find-file"] then
+ resolvers.load()
+ if pattern then
+ resolvers.dowithfilesandreport(resolvers.findfiles, { pattern }, fileformat, allresults)
+ else
+ resolvers.dowithfilesandreport(resolvers.findfiles, environment.files, fileformat, allresults)
+ end
+elseif environment.arguments["find-path"] then
+ resolvers.load()
+ local path = resolvers.findpath(environment.files[1], fileformat)
+ print(path) -- quite basic, wil become function in logs
+elseif environment.arguments["run"] then
+ resolvers.load("nofiles") -- ! no need for loading databases
+ trackers.enable("resolvers.locating")
+ environment.run_format(environment.files[1] or "",environment.files[2] or "",environment.files[3] or "")
+elseif environment.arguments["fmt"] then
+ resolvers.load("nofiles") -- ! no need for loading databases
+ trackers.enable("resolvers.locating")
+ environment.run_format(environment.arguments["fmt"], environment.files[1] or "",environment.files[2] or "")
+elseif environment.arguments["expand-braces"] then
+ resolvers.load("nofiles")
+ resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files)
+elseif environment.arguments["expand-path"] then
+ resolvers.load("nofiles")
+ resolvers.dowithfilesandreport(resolvers.expandpath, environment.files)
+elseif environment.arguments["expand-var"] or environment.arguments["expand-variable"] then
+ resolvers.load("nofiles")
+ resolvers.dowithfilesandreport(resolvers.expansion, environment.files)
+elseif environment.arguments["show-path"] or environment.arguments["path-value"] then
+ resolvers.load("nofiles")
+ resolvers.dowithfilesandreport(resolvers.showpath, environment.files)
+elseif environment.arguments["var-value"] or environment.arguments["show-value"] then
+ resolvers.load("nofiles")
+ resolvers.dowithfilesandreport(resolvers.variable, environment.files)
+elseif environment.arguments["format-path"] then
+ resolvers.load()
+ report(caches.getwritablepath("format"))
+elseif pattern then -- brrr
+ resolvers.load()
+ resolvers.dowithfilesandreport(resolvers.findfiles, { pattern }, fileformat, allresults)
+elseif environment.arguments["generate"] then
+ instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+elseif environment.arguments["make"] or environment.arguments["ini"] or environment.arguments["compile"] then
+ resolvers.load()
+ trackers.enable("resolvers.locating")
+ environment.make_format(environment.files[1] or "")
+elseif environment.arguments["variables"] or environment.arguments["show-variables"] or environment.arguments["expansions"] or environment.arguments["show-expansions"] then
+ resolvers.load("nofiles")
+ resolvers.listers.variables(pattern)
+elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then
+ resolvers.load("nofiles")
+ resolvers.listers.configurations()
+elseif environment.arguments["exporthelp"] then
+ application.export(environment.arguments["exporthelp"],environment.files[1])
+elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then
+ application.help()
+elseif environment.files[1] == 'texmfcnf.lua' then
+ resolvers.load("nofiles")
+ resolvers.listers.configurations()
+else
+ resolvers.load()
+ resolvers.dowithfilesandreport(resolvers.findfiles, environment.files, fileformat, allresults)
+end
diff --git a/scripts/context/lua/mtx-cache.lua b/scripts/context/lua/mtx-cache.lua index bff1cb496..7ce5e21be 100644 --- a/scripts/context/lua/mtx-cache.lua +++ b/scripts/context/lua/mtx-cache.lua @@ -1,137 +1,137 @@ -if not modules then modules = { } end modules ['mtx-cache'] = { - 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 helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-cache</entry> - <entry name="detail">ConTeXt & MetaTeX Cache Management</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="purge"><short>remove not used files</short></flag> - <flag name="erase"><short>completely remove cache</short></flag> - <flag name="list"><short>show cache</short></flag> - </subcategory> - <subcategory> - <flag name="all"><short>all (not yet implemented)</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-cache", - banner = "ConTeXt & MetaTeX Cache Management 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.cache = scripts.cache or { } - -local function collect(path) - local all = dir.glob(path .. "/**/*") - local tmas, tmcs, rest = { }, { }, { } - for i=1,#all do - local name = all[i] - local suffix = file.suffix(name) - if suffix == "tma" then - tmas[#tmas+1] = name - elseif suffix == "tmc" then - tmcs[#tmcs+1] = name - else - rest[#rest+1] = name - end - end - return tmas, tmcs, rest, all -end - -local function list(banner,path,tmas,tmcs,rest) - report("%s: %s",banner,path) - report() - report("tma : %4i",#tmas) - report("tmc : %4i",#tmcs) - report("rest : %4i",#rest) - report("total : %4i",#tmas+#tmcs+#rest) - report() -end - -local function purge(banner,path,list,all) - report("%s: %s",banner,path) - report() - local n = 0 - for i=1,#list do - local filename = list[i] - if string.find(filename,"luatex%-cache") then -- safeguard - if all then - os.remove(filename) - n = n + 1 - else - local suffix = file.suffix(filename) - if suffix == "tma" then - local checkname = file.replacesuffix(filename,"tma","tmc") - if lfs.isfile(checkname) then - os.remove(filename) - n = n + 1 - end - end - end - end - end - report("removed tma files : %i",n) - report() - return n -end - -function scripts.cache.purge() - local writable = caches.getwritablepath() - local tmas, tmcs, rest = collect(writable) - list("writable path",writable,tmas,tmcs,rest) - purge("writable path",writable,tmas) - list("writable path",writable,tmas,tmcs,rest) -end - -function scripts.cache.erase() - local writable = caches.getwritablepath() - local tmas, tmcs, rest, all = collect(writable) - list("writable path",writable,tmas,tmcs,rest) - purge("writable path",writable,all,true) - list("writable path",writable,tmas,tmcs,rest) -end - -function scripts.cache.list() - local readables = caches.getreadablepaths() - local writable = caches.getwritablepath() - local tmas, tmcs, rest = collect(writable) - list("writable path",writable,tmas,tmcs,rest) - for i=1,#readables do - local readable = readables[i] - if readable ~= writable then - local tmas, tmcs = collect(readable) - list("readable path",readable,tmas,tmcs,rest) - end - end -end - -if environment.argument("purge") then - scripts.cache.purge() -elseif environment.argument("erase") then - scripts.cache.erase() -elseif environment.argument("list") then - scripts.cache.list() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-cache'] = {
+ 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 helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-cache</entry>
+ <entry name="detail">ConTeXt & MetaTeX Cache Management</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="purge"><short>remove not used files</short></flag>
+ <flag name="erase"><short>completely remove cache</short></flag>
+ <flag name="list"><short>show cache</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="all"><short>all (not yet implemented)</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-cache",
+ banner = "ConTeXt & MetaTeX Cache Management 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.cache = scripts.cache or { }
+
+local function collect(path)
+ local all = dir.glob(path .. "/**/*")
+ local tmas, tmcs, rest = { }, { }, { }
+ for i=1,#all do
+ local name = all[i]
+ local suffix = file.suffix(name)
+ if suffix == "tma" then
+ tmas[#tmas+1] = name
+ elseif suffix == "tmc" then
+ tmcs[#tmcs+1] = name
+ else
+ rest[#rest+1] = name
+ end
+ end
+ return tmas, tmcs, rest, all
+end
+
+local function list(banner,path,tmas,tmcs,rest)
+ report("%s: %s",banner,path)
+ report()
+ report("tma : %4i",#tmas)
+ report("tmc : %4i",#tmcs)
+ report("rest : %4i",#rest)
+ report("total : %4i",#tmas+#tmcs+#rest)
+ report()
+end
+
+local function purge(banner,path,list,all)
+ report("%s: %s",banner,path)
+ report()
+ local n = 0
+ for i=1,#list do
+ local filename = list[i]
+ if string.find(filename,"luatex%-cache") then -- safeguard
+ if all then
+ os.remove(filename)
+ n = n + 1
+ else
+ local suffix = file.suffix(filename)
+ if suffix == "tma" then
+ local checkname = file.replacesuffix(filename,"tma","tmc")
+ if lfs.isfile(checkname) then
+ os.remove(filename)
+ n = n + 1
+ end
+ end
+ end
+ end
+ end
+ report("removed tma files : %i",n)
+ report()
+ return n
+end
+
+function scripts.cache.purge()
+ local writable = caches.getwritablepath()
+ local tmas, tmcs, rest = collect(writable)
+ list("writable path",writable,tmas,tmcs,rest)
+ purge("writable path",writable,tmas)
+ list("writable path",writable,tmas,tmcs,rest)
+end
+
+function scripts.cache.erase()
+ local writable = caches.getwritablepath()
+ local tmas, tmcs, rest, all = collect(writable)
+ list("writable path",writable,tmas,tmcs,rest)
+ purge("writable path",writable,all,true)
+ list("writable path",writable,tmas,tmcs,rest)
+end
+
+function scripts.cache.list()
+ local readables = caches.getreadablepaths()
+ local writable = caches.getwritablepath()
+ local tmas, tmcs, rest = collect(writable)
+ list("writable path",writable,tmas,tmcs,rest)
+ for i=1,#readables do
+ local readable = readables[i]
+ if readable ~= writable then
+ local tmas, tmcs = collect(readable)
+ list("readable path",readable,tmas,tmcs,rest)
+ end
+ end
+end
+
+if environment.argument("purge") then
+ scripts.cache.purge()
+elseif environment.argument("erase") then
+ scripts.cache.erase()
+elseif environment.argument("list") then
+ scripts.cache.list()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-chars.lua b/scripts/context/lua/mtx-chars.lua index 9f6852da2..fa3b3d353 100644 --- a/scripts/context/lua/mtx-chars.lua +++ b/scripts/context/lua/mtx-chars.lua @@ -1,433 +1,433 @@ -if not modules then modules = { } end modules ['mtx-chars'] = { - 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" -} - --- obsolete: --stix convert stix table to math table - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-chars</entry> - <entry name="detail">MkII Character Table Generators</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="xtx"><short>generate xetx-*.tex (used by xetex)</short></flag> - <flag name="pdf"><short>generate pdfr-def.tex (used by pdftex)</short></flag> - <flag name="entities"><short>generate entities table</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-chars", - banner = "MkII Character Table Generators 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -local format, gmatch, upper, lower = string.format, string.gmatch, string.upper, string.lower -local tonumber = tonumber -local concat = table.concat -local utfchar = utf.char - -scripts = scripts or { } -scripts.chars = scripts.chars or { } - ---~ local banner = [[ ---~ -- filename : char-mth.lua ---~ -- comment : companion to char-mth.tex (in ConTeXt) ---~ -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL ---~ -- license : see context related readme files ---~ -- comment : generated from data file downloaded from STIX website ---~ ---~ if not versions then versions = { } end versions['char-mth'] = 1.001 ---~ if not characters then characters = { } end ---~ ]] ---~ ---~ function scripts.chars.stixtomkiv(inname,outname) ---~ if inname == "" then ---~ report("aquiring math data, invalid datafilename") ---~ end ---~ local f = io.open(inname) ---~ if not f then ---~ report("aquiring math data, invalid datafile") ---~ else ---~ report("aquiring math data, processing %s",inname) ---~ if not outname or outname == "" then ---~ outname = "char-mth.lua" ---~ end ---~ local classes = { ---~ N = "normal", ---~ A = "alphabetic", ---~ D = "diacritic", ---~ P = "punctuation", ---~ B = "binary", ---~ R = "relation", ---~ L = "large", ---~ O = "opening", ---~ C = "closing", ---~ F = "fence" ---~ } ---~ local valid, done = false, { } ---~ local g = io.open(outname,'w') ---~ g:write(banner) ---~ g:write(format("\ncharacters.math = {\n")) ---~ for l in f:lines() do ---~ if not valid then ---~ valid = l:find("AMS/TeX name") ---~ end ---~ if valid then ---~ local unicode = l:sub(2,6) ---~ if unicode:sub(1,1) ~= " " and unicode ~= "" and not done[unicode] then ---~ local mathclass, adobename, texname = l:sub(57,57) or "", l:sub(13,36) or "", l:sub(84,109) or "" ---~ texname, adobename = texname:gsub("[\\ ]",""), adobename:gsub("[\\ ]","") ---~ local t = { } ---~ if mathclass ~= "" then t[#t+1] = format("mathclass='%s'", classes[mathclass] or "unknown") end ---~ if adobename ~= "" then t[#t+1] = format("adobename='%s'", adobename ) end ---~ if texname ~= "" then t[#t+1] = format("texname='%s'" , texname ) end ---~ if #t > 0 then ---~ g:write(format("\t[0x%s] = { %s },\n",unicode, concat(t,", "))) ---~ end ---~ done[unicode] = true ---~ end ---~ end ---~ end ---~ if not valid then ---~ g:write("\t-- The data file is corrupt, invalid or maybe the format has changed.\n") ---~ report("aquiring math data, problems with data table") ---~ else ---~ report("aquiring math data, table saved in %s",outname) ---~ end ---~ g:write("}\n") ---~ g:close() ---~ f:close() ---~ end ---~ end - -function scripts.chars.stixtomkiv(inname,outname) - report("we no longer use this options but use our own tables instead") -end - -local banner_pdf_1 = [[ -% filename : pdfr-def.tex -% comment : generated by mtxrun --script chars --pdf -% author : Hans Hagen, PRAGMA-ADE, Hasselt NL -% copyright: PRAGMA ADE / ConTeXt Development Team -% license : see context related readme files -% -]] - -local banner_pdf_2 = [[ -% -\endinput -]] - -function scripts.chars.makepdfr() - local chartable = resolvers.findfile("char-def.lua") or "" - if chartable ~= "" then - dofile(chartable) - if characters and characters.data then - local f = io.open("pdfr-def.tex", 'w') - if f then - f:write(banner_pdf_1) - local cd = characters.data - local sd = table.sortedkeys(cd) - for i=1,#sd do - local char = cd[sd[i]] - if char.adobename then - f:write(format("\\pdfglyphtounicode{%s}{%04X}%%\n",char.adobename,char.unicodeslot)) - end - end - f:write(banner_pdf_2) - f:close() - end - end - end -end - -local banner_utf_module = [[ -%% filename : %s -%% comment : generated by mtxrun --script chars --xtx -%% author : Hans Hagen, PRAGMA-ADE, Hasselt NL -%% copyright: PRAGMA ADE / ConTeXt Development Team -%% license : see context related readme files -]] - -local banner_utf_mappings = [[ - -% lc/uc/catcode mappings - -]] - -local banner_utf_patch = [[ - -% patch needed for turkish - -\setXTXcharcodes "201C "201C "201C -\setXTXcharcodes "201D "201D "201D - -% patch needed for french - -\setXTXcharcodes "2019 "2019 "2019 - -]] - -local banner_utf_names = [[ - -% named characters mapped onto utf (\\char is needed for accents) - -]] - -local banner_utf_classes = [[ - -% some character classes for xetex; seems to be rather hard coded, these numbers -% and also a mix of several classes; here we do linebreaks - -]] - -local banner_utf_finish = [[ - -\endinput -]] - -local xtxclasses = { - id = 1, - ex = 3, - is = 3, - cm = 256, - op = 2, - ns = 3, - cl = 3, -} - -function scripts.chars.makeencoutf() - local chartable = resolvers.findfile("char-def.lua") or "" - if chartable ~= "" then - dofile(chartable) - local function open(name,banner) - local f = io.open(name,'w') - if f then - report("writing '%s'",name) - f:write(format(banner_utf_module,name)) - f:write(banner) - f:write() - return f - end - end - local function close(f) - f:write(banner_utf_finish) - f:close() - end - local data = characters and characters.data - if data then - local list = table.sortedkeys(characters.data) - local f = open("xetx-utf.tex",banner_utf_mappings) - if f then - for i=1,#list do - local code = list[i] - if code <= 0xFFFF then - local chr = data[code] - local cc = chr.category - if cc == 'll' or cc == 'lu' or cc == 'lt' then - if not chr.lccode then chr.lccode = code end - if not chr.uccode then chr.uccode = code end - f:write(format('\\setXTXcharcodes "%05X "%05X "%05X %% %s\n',code,chr.lccode,chr.uccode,chr.description)) - end - end - end - f:write("\n") - for i=1,#list do - local code = list[i] - local chr = data[code] - if chr and chr.range then - local cc = chr.category - if cc == 'lo' then - f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharcodes\\recurselevel\\recurselevel\\recurselevel}\n',code,chr.range)) - end - end - end - f:write(banner_utf_patch) - close(f) - end - local f = open("xetx-chr.tex",banner_utf_names) - if f then - local length = 0 - for i=1,#list do - local code = list[i] - if code > 0x5B and code <= 0xFFFF then - local chr = data[code] - if chr and #(chr.contextname or "") > length then - length = #chr.contextname - end - end - end - local template = "\\def\\%-".. length .. "s{\\char\"%05X } %% %s: %s\n" - for i=1,#list do - local code = list[i] - if code > 0x5B and code <= 0xFFFF then - local chr = data[code] - if chr and chr.contextname then - local ch = utfchar(code) - f:write(format(template, chr.contextname, code, chr.description, ch)) - end - end - end - close(f) - end - local f = open("xetx-cls.tex",banner_utf_classes) - if f then - for k, v in next, xtxclasses do - f:write(format("\\defineXTXcharinjectionclass[lb:%s]\n",k)) - end - f:write("\n") - local i_first, i_last, i_clb = nil, nil, nil - local function flush() - if i_first then - if i_first == i_last then - f:write(format('\\dosetXTXcharacterclass{"%05X}{lb:%s}\n',i_first,i_clb)) - else - f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharacterclass\\fastrecursecounter{lb:%s}}\n',i_first,i_last,i_clb)) - end - end - i_first, i_last, i_clb = nil, nil, nil - end - for i=1,#list do - local code = list[i] - local code_next = list[i+1] - local chr = data[code] - local chr_next = data[code_next] - local clb = chr and chr.linebreak - local lbc = xtxclasses[clb] - if not lbc then - flush() - elseif clb == i_clb then - if i_first then - i_last = code - else - i_first, i_last, i_clb = code, code, clb - end - else - flush() - i_first, i_last, i_clb = code, code, clb - end - end - flush() - f:write("\n") - for i=1,#list do - local code = list[i] - local chr = data[code] - if chr and chr.range then - local lbc = chr.linebreak - if xtxclasses[lbc] then - f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharacterclass\\fastrecursecounter{lb:%s}}\n',code,chr.range,lbc)) - end - end - end - close(f) - end - end - end -end - -local entityfiles = { - "http://www.w3.org/2003/entities/2007/w3centities-f.ent", - "http://www.w3.org/2003/entities/2007/htmlmathml-f.ent", -} - -function scripts.chars.xmlentities() - local done = { } - local entities = { "local entities = utilities.storage.allocate {" } - for i=1,#entityfiles do - local f = entityfiles[i] - local s = url.hashed(f) - local b = file.basename(s.path) - local n = resolvers.findfile(b) - local data = io.loaddata(n) - for name, value in gmatch(data,'<!ENTITY +(%S+) +"(.-)" *>') do - if not done[name] then - done[name] = true - local str, hex - local low = lower(name) - if name == "newline" then - -- let's forget about that one - elseif name == "lt" then - str, hex = "<", format("%s %05X",hex,c) - elseif name == "gt" then - str, hex = ">", format("%s %05X",hex,c) - elseif name == "amp" then - str, hex = "&", format("%s %05X",hex,c) - else - for t, c in gmatch(value,"&#([x]*)([^;]+);") do - if t == "x" then - c = tonumber(c,16) - else - c = tonumber(c) - end - if str then - str, hex = str .. utfchar(c), format("%s %05X",hex,c) - else - str, hex = utfchar(c), format("U+%05X",c) - end - end - end - if str and hex then - entities[#entities+1] = format(' ["%s"] = %q, -- %s',name,str,hex) - end - end - end - end - entities[#entities+1] = "}" - io.savedata("xmlentities.tmp",concat(entities,"\n")) -end - -if environment.argument("stix") then - local inname = environment.files[1] or "" - local outname = environment.files[2] or "" - scripts.chars.stixtomkiv(inname,outname) -elseif environment.argument("entities") then - scripts.chars.xmlentities() -elseif environment.argument("xtx") then - scripts.chars.makeencoutf() -elseif environment.argument("pdf") then - scripts.chars.makepdfr() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end - --- local http = require("socket.http") --- local ltn12 = require("ltn12") --- --- local t = { } --- local status, message = http.request { --- url = f, --- sink = ltn12.sink.table(t) --- } --- --- local template = [[ --- <?xml version='1.0' ?> --- --- <!DOCTYPE dummy [ --- --- %s --- --- ]> --- --- <dummy>This is just a placeholder.</dummy> --- ]] --- --- local e = string.format(template,io.loaddata(n)) --- local x = xml.convert(e, { utfize_entities = true } ) --- local entities = x.entities +if not modules then modules = { } end modules ['mtx-chars'] = {
+ 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"
+}
+
+-- obsolete: --stix convert stix table to math table
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-chars</entry>
+ <entry name="detail">MkII Character Table Generators</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="xtx"><short>generate xetx-*.tex (used by xetex)</short></flag>
+ <flag name="pdf"><short>generate pdfr-def.tex (used by pdftex)</short></flag>
+ <flag name="entities"><short>generate entities table</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-chars",
+ banner = "MkII Character Table Generators 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+local format, gmatch, upper, lower = string.format, string.gmatch, string.upper, string.lower
+local tonumber = tonumber
+local concat = table.concat
+local utfchar = utf.char
+
+scripts = scripts or { }
+scripts.chars = scripts.chars or { }
+
+--~ local banner = [[
+--~ -- filename : char-mth.lua
+--~ -- comment : companion to char-mth.tex (in ConTeXt)
+--~ -- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+--~ -- license : see context related readme files
+--~ -- comment : generated from data file downloaded from STIX website
+--~
+--~ if not versions then versions = { } end versions['char-mth'] = 1.001
+--~ if not characters then characters = { } end
+--~ ]]
+--~
+--~ function scripts.chars.stixtomkiv(inname,outname)
+--~ if inname == "" then
+--~ report("aquiring math data, invalid datafilename")
+--~ end
+--~ local f = io.open(inname)
+--~ if not f then
+--~ report("aquiring math data, invalid datafile")
+--~ else
+--~ report("aquiring math data, processing %s",inname)
+--~ if not outname or outname == "" then
+--~ outname = "char-mth.lua"
+--~ end
+--~ local classes = {
+--~ N = "normal",
+--~ A = "alphabetic",
+--~ D = "diacritic",
+--~ P = "punctuation",
+--~ B = "binary",
+--~ R = "relation",
+--~ L = "large",
+--~ O = "opening",
+--~ C = "closing",
+--~ F = "fence"
+--~ }
+--~ local valid, done = false, { }
+--~ local g = io.open(outname,'w')
+--~ g:write(banner)
+--~ g:write(format("\ncharacters.math = {\n"))
+--~ for l in f:lines() do
+--~ if not valid then
+--~ valid = l:find("AMS/TeX name")
+--~ end
+--~ if valid then
+--~ local unicode = l:sub(2,6)
+--~ if unicode:sub(1,1) ~= " " and unicode ~= "" and not done[unicode] then
+--~ local mathclass, adobename, texname = l:sub(57,57) or "", l:sub(13,36) or "", l:sub(84,109) or ""
+--~ texname, adobename = texname:gsub("[\\ ]",""), adobename:gsub("[\\ ]","")
+--~ local t = { }
+--~ if mathclass ~= "" then t[#t+1] = format("mathclass='%s'", classes[mathclass] or "unknown") end
+--~ if adobename ~= "" then t[#t+1] = format("adobename='%s'", adobename ) end
+--~ if texname ~= "" then t[#t+1] = format("texname='%s'" , texname ) end
+--~ if #t > 0 then
+--~ g:write(format("\t[0x%s] = { %s },\n",unicode, concat(t,", ")))
+--~ end
+--~ done[unicode] = true
+--~ end
+--~ end
+--~ end
+--~ if not valid then
+--~ g:write("\t-- The data file is corrupt, invalid or maybe the format has changed.\n")
+--~ report("aquiring math data, problems with data table")
+--~ else
+--~ report("aquiring math data, table saved in %s",outname)
+--~ end
+--~ g:write("}\n")
+--~ g:close()
+--~ f:close()
+--~ end
+--~ end
+
+function scripts.chars.stixtomkiv(inname,outname)
+ report("we no longer use this options but use our own tables instead")
+end
+
+local banner_pdf_1 = [[
+% filename : pdfr-def.tex
+% comment : generated by mtxrun --script chars --pdf
+% author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+% copyright: PRAGMA ADE / ConTeXt Development Team
+% license : see context related readme files
+%
+]]
+
+local banner_pdf_2 = [[
+%
+\endinput
+]]
+
+function scripts.chars.makepdfr()
+ local chartable = resolvers.findfile("char-def.lua") or ""
+ if chartable ~= "" then
+ dofile(chartable)
+ if characters and characters.data then
+ local f = io.open("pdfr-def.tex", 'w')
+ if f then
+ f:write(banner_pdf_1)
+ local cd = characters.data
+ local sd = table.sortedkeys(cd)
+ for i=1,#sd do
+ local char = cd[sd[i]]
+ if char.adobename then
+ f:write(format("\\pdfglyphtounicode{%s}{%04X}%%\n",char.adobename,char.unicodeslot))
+ end
+ end
+ f:write(banner_pdf_2)
+ f:close()
+ end
+ end
+ end
+end
+
+local banner_utf_module = [[
+%% filename : %s
+%% comment : generated by mtxrun --script chars --xtx
+%% author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+%% copyright: PRAGMA ADE / ConTeXt Development Team
+%% license : see context related readme files
+]]
+
+local banner_utf_mappings = [[
+
+% lc/uc/catcode mappings
+
+]]
+
+local banner_utf_patch = [[
+
+% patch needed for turkish
+
+\setXTXcharcodes "201C "201C "201C
+\setXTXcharcodes "201D "201D "201D
+
+% patch needed for french
+
+\setXTXcharcodes "2019 "2019 "2019
+
+]]
+
+local banner_utf_names = [[
+
+% named characters mapped onto utf (\\char is needed for accents)
+
+]]
+
+local banner_utf_classes = [[
+
+% some character classes for xetex; seems to be rather hard coded, these numbers
+% and also a mix of several classes; here we do linebreaks
+
+]]
+
+local banner_utf_finish = [[
+
+\endinput
+]]
+
+local xtxclasses = {
+ id = 1,
+ ex = 3,
+ is = 3,
+ cm = 256,
+ op = 2,
+ ns = 3,
+ cl = 3,
+}
+
+function scripts.chars.makeencoutf()
+ local chartable = resolvers.findfile("char-def.lua") or ""
+ if chartable ~= "" then
+ dofile(chartable)
+ local function open(name,banner)
+ local f = io.open(name,'w')
+ if f then
+ report("writing '%s'",name)
+ f:write(format(banner_utf_module,name))
+ f:write(banner)
+ f:write()
+ return f
+ end
+ end
+ local function close(f)
+ f:write(banner_utf_finish)
+ f:close()
+ end
+ local data = characters and characters.data
+ if data then
+ local list = table.sortedkeys(characters.data)
+ local f = open("xetx-utf.tex",banner_utf_mappings)
+ if f then
+ for i=1,#list do
+ local code = list[i]
+ if code <= 0xFFFF then
+ local chr = data[code]
+ local cc = chr.category
+ if cc == 'll' or cc == 'lu' or cc == 'lt' then
+ if not chr.lccode then chr.lccode = code end
+ if not chr.uccode then chr.uccode = code end
+ f:write(format('\\setXTXcharcodes "%05X "%05X "%05X %% %s\n',code,chr.lccode,chr.uccode,chr.description))
+ end
+ end
+ end
+ f:write("\n")
+ for i=1,#list do
+ local code = list[i]
+ local chr = data[code]
+ if chr and chr.range then
+ local cc = chr.category
+ if cc == 'lo' then
+ f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharcodes\\recurselevel\\recurselevel\\recurselevel}\n',code,chr.range))
+ end
+ end
+ end
+ f:write(banner_utf_patch)
+ close(f)
+ end
+ local f = open("xetx-chr.tex",banner_utf_names)
+ if f then
+ local length = 0
+ for i=1,#list do
+ local code = list[i]
+ if code > 0x5B and code <= 0xFFFF then
+ local chr = data[code]
+ if chr and #(chr.contextname or "") > length then
+ length = #chr.contextname
+ end
+ end
+ end
+ local template = "\\def\\%-".. length .. "s{\\char\"%05X } %% %s: %s\n"
+ for i=1,#list do
+ local code = list[i]
+ if code > 0x5B and code <= 0xFFFF then
+ local chr = data[code]
+ if chr and chr.contextname then
+ local ch = utfchar(code)
+ f:write(format(template, chr.contextname, code, chr.description, ch))
+ end
+ end
+ end
+ close(f)
+ end
+ local f = open("xetx-cls.tex",banner_utf_classes)
+ if f then
+ for k, v in next, xtxclasses do
+ f:write(format("\\defineXTXcharinjectionclass[lb:%s]\n",k))
+ end
+ f:write("\n")
+ local i_first, i_last, i_clb = nil, nil, nil
+ local function flush()
+ if i_first then
+ if i_first == i_last then
+ f:write(format('\\dosetXTXcharacterclass{"%05X}{lb:%s}\n',i_first,i_clb))
+ else
+ f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharacterclass\\fastrecursecounter{lb:%s}}\n',i_first,i_last,i_clb))
+ end
+ end
+ i_first, i_last, i_clb = nil, nil, nil
+ end
+ for i=1,#list do
+ local code = list[i]
+ local code_next = list[i+1]
+ local chr = data[code]
+ local chr_next = data[code_next]
+ local clb = chr and chr.linebreak
+ local lbc = xtxclasses[clb]
+ if not lbc then
+ flush()
+ elseif clb == i_clb then
+ if i_first then
+ i_last = code
+ else
+ i_first, i_last, i_clb = code, code, clb
+ end
+ else
+ flush()
+ i_first, i_last, i_clb = code, code, clb
+ end
+ end
+ flush()
+ f:write("\n")
+ for i=1,#list do
+ local code = list[i]
+ local chr = data[code]
+ if chr and chr.range then
+ local lbc = chr.linebreak
+ if xtxclasses[lbc] then
+ f:write(format('\\dofastrecurse{"%05X}{"%05X}{1}{\\dosetXTXcharacterclass\\fastrecursecounter{lb:%s}}\n',code,chr.range,lbc))
+ end
+ end
+ end
+ close(f)
+ end
+ end
+ end
+end
+
+local entityfiles = {
+ "http://www.w3.org/2003/entities/2007/w3centities-f.ent",
+ "http://www.w3.org/2003/entities/2007/htmlmathml-f.ent",
+}
+
+function scripts.chars.xmlentities()
+ local done = { }
+ local entities = { "local entities = utilities.storage.allocate {" }
+ for i=1,#entityfiles do
+ local f = entityfiles[i]
+ local s = url.hashed(f)
+ local b = file.basename(s.path)
+ local n = resolvers.findfile(b)
+ local data = io.loaddata(n)
+ for name, value in gmatch(data,'<!ENTITY +(%S+) +"(.-)" *>') do
+ if not done[name] then
+ done[name] = true
+ local str, hex
+ local low = lower(name)
+ if name == "newline" then
+ -- let's forget about that one
+ elseif name == "lt" then
+ str, hex = "<", format("%s %05X",hex,c)
+ elseif name == "gt" then
+ str, hex = ">", format("%s %05X",hex,c)
+ elseif name == "amp" then
+ str, hex = "&", format("%s %05X",hex,c)
+ else
+ for t, c in gmatch(value,"&#([x]*)([^;]+);") do
+ if t == "x" then
+ c = tonumber(c,16)
+ else
+ c = tonumber(c)
+ end
+ if str then
+ str, hex = str .. utfchar(c), format("%s %05X",hex,c)
+ else
+ str, hex = utfchar(c), format("U+%05X",c)
+ end
+ end
+ end
+ if str and hex then
+ entities[#entities+1] = format(' ["%s"] = %q, -- %s',name,str,hex)
+ end
+ end
+ end
+ end
+ entities[#entities+1] = "}"
+ io.savedata("xmlentities.tmp",concat(entities,"\n"))
+end
+
+if environment.argument("stix") then
+ local inname = environment.files[1] or ""
+ local outname = environment.files[2] or ""
+ scripts.chars.stixtomkiv(inname,outname)
+elseif environment.argument("entities") then
+ scripts.chars.xmlentities()
+elseif environment.argument("xtx") then
+ scripts.chars.makeencoutf()
+elseif environment.argument("pdf") then
+ scripts.chars.makepdfr()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
+
+-- local http = require("socket.http")
+-- local ltn12 = require("ltn12")
+--
+-- local t = { }
+-- local status, message = http.request {
+-- url = f,
+-- sink = ltn12.sink.table(t)
+-- }
+--
+-- local template = [[
+-- <?xml version='1.0' ?>
+--
+-- <!DOCTYPE dummy [
+--
+-- %s
+--
+-- ]>
+--
+-- <dummy>This is just a placeholder.</dummy>
+-- ]]
+--
+-- local e = string.format(template,io.loaddata(n))
+-- local x = xml.convert(e, { utfize_entities = true } )
+-- local entities = x.entities
diff --git a/scripts/context/lua/mtx-check.lua b/scripts/context/lua/mtx-check.lua index 9f52509ec..bddb2e139 100644 --- a/scripts/context/lua/mtx-check.lua +++ b/scripts/context/lua/mtx-check.lua @@ -1,253 +1,253 @@ -if not modules then modules = { } end modules ['mtx-check'] = { - 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 P, R, S, V, C, CP, CC, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc, lpeg.match -local gsub, sub, format = string.gsub, string.sub, string.format -local insert, remove = table.insert, table.remove - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-check</entry> - <entry name="detail">Basic ConTeXt Syntax Checking</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="convert"><short>check tex file for errors</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-check", - banner = "Basic ConTeXt Syntax Checking 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.checker = scripts.checker or { } - -local validator = { } - -validator.n = 1 -validator.errors = { } -validator.trace = false -validator.direct = false - -validator.printer = print -validator.tracer = print - -local message = function(position, kind, extra) - local ve = validator.errors - ve[#ve+1] = { kind, position, validator.n, extra } - if validator.direct then - position = position or "eof" - if extra then - validator.printer(format("%s error at position %s (line %s) (%s)",kind,position,validator.n,extra)) - else - validator.printer(format("%s error at position %s (line %s)",kind,position,validator.n)) - end - end -end - -local progress = function(position, data, kind) - if validator.trace then - validator.tracer(format("%s at position %s: %s", kind, position, data or "")) - end -end - -local i_m, d_m = P("$"), P("$$") -local l_s, r_s = P("["), P("]") -local l_g, r_g = P("{"), P("}") - -local okay = lpeg.P("{[}") + lpeg.P("{]}") - -local esc = P("\\") -local cr = P("\r") -local lf = P("\n") -local crlf = P("\r\n") -local space = S(" \t\f\v") -local newline = crlf + cr + lf - -local line = newline / function() validator.n = validator.n + 1 end - -local startluacode = P("\\startluacode") -local stopluacode = P("\\stopluacode") - -local somecode = startluacode * (1-stopluacode)^1 * stopluacode - -local stack = { } - -local function push(p,s) --- print("start",p,s) - insert(stack,{ p, s, validator.n }) -end - -local function pop(p,s) --- print("stop",p,s) - local top = remove(stack) - if not top then - message(p,"missing start") - elseif top[2] ~= s then - message(p,"missing stop",format("see line %s",top[3])) - else - -- okay - end -end - -local cstoken = R("az","AZ","\127\255") - -local start = CP() * P("\\start") * C(cstoken^0) / push -local stop = CP() * P("\\stop") * C(cstoken^0) / pop - -local contextgrammar = P { "tokens", - ["tokens"] = (V("ignore") + V("start") + V("stop") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0, - ["start"] = start, - ["stop"] = stop, - ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0), - ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g, - ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s, - ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m, - ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m, - ["errors"] = V("gerror") + V("serror") + V("derror") + V("ierror"), - ["gerror"] = CP() * (l_g + r_g) * CC("grouping error") / message, - ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message, - ["derror"] = CP() * d_m * CC("display math error") / message, - ["ierror"] = CP() * i_m * CC("inline math error") / message, - ["ignore"] = somecode, -} - --- metafun variant - -local function push(p,s) - insert(stack,{ p, s, validator.n }) -end - -local function pop(p,s) - local top = remove(stack) - if not top then - message(p,"missing <some>def") - end -end - -local function finish(p) - local bot = stack[1] - if bot then - message(false,format("missing enddef for %s",bot[2]),format("see line %s",bot[3])) - end - stack = { } -end - -local l_b, r_b = P("["), P("]") -local l_g, r_g = P("{"), P("}") -local l_p, r_p = P("("), P(")") - -local start = CP() * C( P("vardef") + P("primarydef") + P("secondarydef") + P("tertiarydef") + P("def") ) / push -local stop = CP() * C( P("enddef") ) / pop - -local dstring = P('"') * (1-P('"'))^0 * P('"') -local semicolon = P(";") - -local separator = line + space + semicolon - --- todo: start/stop also in () - -local metafungrammar = P { "tokens", - ["tokens"] = (V("start") + V("stop") + V("string") + V("whatever") + V("braces") + V("brackets") + V("parentheses") + V("errors") + 1)^0 - * (CP() / finish), - ["start"] = separator * start * #separator, - ["stop"] = separator * stop * #separator, - ["string"] = dstring, - ["whatever"] = line + C(P("%") * (1-line)^0), - ["braces"] = l_g * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_g - r_g))^0 * r_g, - ["brackets"] = l_b * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_b - r_b))^0 * r_b, - ["parentheses"] = l_p * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_p - r_p))^0 * r_p, - ["errors"] = V("gerror") + V("berror") + V("perror"), - ["gerror"] = CP() * (l_g + r_g) * CC("braces error") / message, - ["berror"] = CP() * (l_b + r_b) * CC("brackets error") / message, - ["perror"] = CP() * (l_p + r_p) * CC("parentheses error") / message, -} - -local grammars = { - mp = metafungrammar, - mpii = metafungrammar, - mpiv = metafungrammar, - tex = contextgrammar, - mkii = contextgrammar, - mkiv = contextgrammar, -} - -function validator.check(str,filetype) - validator.n = 1 - validator.errors = { } - local grammar = grammars[filetype] or grammars.tex - lpegmatch(grammar,str) -end - ---~ str = [[ ---~ a{oeps {oe\{\}ps} } ---~ test { oeps \} \[\] oeps \setupxxx[oeps=bla]} ---~ test $$ \hbox{$ oeps \} \[\] oeps $} $$ ---~ {$x\$xx$ $ ---~ ]] ---~ str = string.rep(str,10) - -local remapper = { - ["\n"] = " <lf> ", - ["\r"] = " <cr> ", - ["\t"] = " <tab> ", -} - -function scripts.checker.check(filename) - local str = io.loaddata(filename) - if str then - validator.check(str,file.suffix(filename)) - local errors = validator.errors - if #errors > 0 then - for k=1,#errors do - local v = errors[k] - local kind, position, line, extra = v[1], v[2], v[3], v[4] - if not position then - position = #str - end - local data = sub(str,position-30,position+30) - data = gsub(data,".", remapper) - data = gsub(data,"^ *","") - if extra then - print(format("% 5i %-10s %s (%s)", line, kind, data, extra)) - else - print(format("% 5i %-10s %s", line, kind, data)) - end - end - else - print("no error") - end - else - print("no file") - end -end - -if environment.argument("check") then - scripts.checker.check(environment.files[1]) -elseif environment.argument("help") then - application.help() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -elseif environment.files[1] then - scripts.checker.check(environment.files[1]) -else - application.help() -end - +if not modules then modules = { } end modules ['mtx-check'] = {
+ 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 P, R, S, V, C, CP, CC, lpegmatch = lpeg.P, lpeg.R, lpeg.S, lpeg.V, lpeg.C, lpeg.Cp, lpeg.Cc, lpeg.match
+local gsub, sub, format = string.gsub, string.sub, string.format
+local insert, remove = table.insert, table.remove
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-check</entry>
+ <entry name="detail">Basic ConTeXt Syntax Checking</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="convert"><short>check tex file for errors</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-check",
+ banner = "Basic ConTeXt Syntax Checking 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.checker = scripts.checker or { }
+
+local validator = { }
+
+validator.n = 1
+validator.errors = { }
+validator.trace = false
+validator.direct = false
+
+validator.printer = print
+validator.tracer = print
+
+local message = function(position, kind, extra)
+ local ve = validator.errors
+ ve[#ve+1] = { kind, position, validator.n, extra }
+ if validator.direct then
+ position = position or "eof"
+ if extra then
+ validator.printer(format("%s error at position %s (line %s) (%s)",kind,position,validator.n,extra))
+ else
+ validator.printer(format("%s error at position %s (line %s)",kind,position,validator.n))
+ end
+ end
+end
+
+local progress = function(position, data, kind)
+ if validator.trace then
+ validator.tracer(format("%s at position %s: %s", kind, position, data or ""))
+ end
+end
+
+local i_m, d_m = P("$"), P("$$")
+local l_s, r_s = P("["), P("]")
+local l_g, r_g = P("{"), P("}")
+
+local okay = lpeg.P("{[}") + lpeg.P("{]}")
+
+local esc = P("\\")
+local cr = P("\r")
+local lf = P("\n")
+local crlf = P("\r\n")
+local space = S(" \t\f\v")
+local newline = crlf + cr + lf
+
+local line = newline / function() validator.n = validator.n + 1 end
+
+local startluacode = P("\\startluacode")
+local stopluacode = P("\\stopluacode")
+
+local somecode = startluacode * (1-stopluacode)^1 * stopluacode
+
+local stack = { }
+
+local function push(p,s)
+-- print("start",p,s)
+ insert(stack,{ p, s, validator.n })
+end
+
+local function pop(p,s)
+-- print("stop",p,s)
+ local top = remove(stack)
+ if not top then
+ message(p,"missing start")
+ elseif top[2] ~= s then
+ message(p,"missing stop",format("see line %s",top[3]))
+ else
+ -- okay
+ end
+end
+
+local cstoken = R("az","AZ","\127\255")
+
+local start = CP() * P("\\start") * C(cstoken^0) / push
+local stop = CP() * P("\\stop") * C(cstoken^0) / pop
+
+local contextgrammar = P { "tokens",
+ ["tokens"] = (V("ignore") + V("start") + V("stop") + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + V("errors") + 1)^0,
+ ["start"] = start,
+ ["stop"] = stop,
+ ["whatever"] = line + esc * 1 + C(P("%") * (1-line)^0),
+ ["grouped"] = l_g * (V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_g - r_g))^0 * r_g,
+ ["setup"] = l_s * (okay + V("whatever") + V("grouped") + V("setup") + V("display") + V("inline") + (1 - l_s - r_s))^0 * r_s,
+ ["display"] = d_m * (V("whatever") + V("grouped") + (1 - d_m))^0 * d_m,
+ ["inline"] = i_m * (V("whatever") + V("grouped") + (1 - i_m))^0 * i_m,
+ ["errors"] = V("gerror") + V("serror") + V("derror") + V("ierror"),
+ ["gerror"] = CP() * (l_g + r_g) * CC("grouping error") / message,
+ ["serror"] = CP() * (l_s + r_g) * CC("setup error") / message,
+ ["derror"] = CP() * d_m * CC("display math error") / message,
+ ["ierror"] = CP() * i_m * CC("inline math error") / message,
+ ["ignore"] = somecode,
+}
+
+-- metafun variant
+
+local function push(p,s)
+ insert(stack,{ p, s, validator.n })
+end
+
+local function pop(p,s)
+ local top = remove(stack)
+ if not top then
+ message(p,"missing <some>def")
+ end
+end
+
+local function finish(p)
+ local bot = stack[1]
+ if bot then
+ message(false,format("missing enddef for %s",bot[2]),format("see line %s",bot[3]))
+ end
+ stack = { }
+end
+
+local l_b, r_b = P("["), P("]")
+local l_g, r_g = P("{"), P("}")
+local l_p, r_p = P("("), P(")")
+
+local start = CP() * C( P("vardef") + P("primarydef") + P("secondarydef") + P("tertiarydef") + P("def") ) / push
+local stop = CP() * C( P("enddef") ) / pop
+
+local dstring = P('"') * (1-P('"'))^0 * P('"')
+local semicolon = P(";")
+
+local separator = line + space + semicolon
+
+-- todo: start/stop also in ()
+
+local metafungrammar = P { "tokens",
+ ["tokens"] = (V("start") + V("stop") + V("string") + V("whatever") + V("braces") + V("brackets") + V("parentheses") + V("errors") + 1)^0
+ * (CP() / finish),
+ ["start"] = separator * start * #separator,
+ ["stop"] = separator * stop * #separator,
+ ["string"] = dstring,
+ ["whatever"] = line + C(P("%") * (1-line)^0),
+ ["braces"] = l_g * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_g - r_g))^0 * r_g,
+ ["brackets"] = l_b * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_b - r_b))^0 * r_b,
+ ["parentheses"] = l_p * (V("whatever") + V("string") + V("braces") + V("brackets") + V("parentheses") + (1 - l_p - r_p))^0 * r_p,
+ ["errors"] = V("gerror") + V("berror") + V("perror"),
+ ["gerror"] = CP() * (l_g + r_g) * CC("braces error") / message,
+ ["berror"] = CP() * (l_b + r_b) * CC("brackets error") / message,
+ ["perror"] = CP() * (l_p + r_p) * CC("parentheses error") / message,
+}
+
+local grammars = {
+ mp = metafungrammar,
+ mpii = metafungrammar,
+ mpiv = metafungrammar,
+ tex = contextgrammar,
+ mkii = contextgrammar,
+ mkiv = contextgrammar,
+}
+
+function validator.check(str,filetype)
+ validator.n = 1
+ validator.errors = { }
+ local grammar = grammars[filetype] or grammars.tex
+ lpegmatch(grammar,str)
+end
+
+--~ str = [[
+--~ a{oeps {oe\{\}ps} }
+--~ test { oeps \} \[\] oeps \setupxxx[oeps=bla]}
+--~ test $$ \hbox{$ oeps \} \[\] oeps $} $$
+--~ {$x\$xx$ $
+--~ ]]
+--~ str = string.rep(str,10)
+
+local remapper = {
+ ["\n"] = " <lf> ",
+ ["\r"] = " <cr> ",
+ ["\t"] = " <tab> ",
+}
+
+function scripts.checker.check(filename)
+ local str = io.loaddata(filename)
+ if str then
+ validator.check(str,file.suffix(filename))
+ local errors = validator.errors
+ if #errors > 0 then
+ for k=1,#errors do
+ local v = errors[k]
+ local kind, position, line, extra = v[1], v[2], v[3], v[4]
+ if not position then
+ position = #str
+ end
+ local data = sub(str,position-30,position+30)
+ data = gsub(data,".", remapper)
+ data = gsub(data,"^ *","")
+ if extra then
+ print(format("% 5i %-10s %s (%s)", line, kind, data, extra))
+ else
+ print(format("% 5i %-10s %s", line, kind, data))
+ end
+ end
+ else
+ print("no error")
+ end
+ else
+ print("no file")
+ end
+end
+
+if environment.argument("check") then
+ scripts.checker.check(environment.files[1])
+elseif environment.argument("help") then
+ application.help()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+elseif environment.files[1] then
+ scripts.checker.check(environment.files[1])
+else
+ application.help()
+end
+
diff --git a/scripts/context/lua/mtx-colors.lua b/scripts/context/lua/mtx-colors.lua index 7dd1b4ac4..cd7dcce62 100644 --- a/scripts/context/lua/mtx-colors.lua +++ b/scripts/context/lua/mtx-colors.lua @@ -1,77 +1,77 @@ -if not modules then modules = { } end modules ['mtx-colors'] = { - 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" -} - --- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-colors</entry> - <entry name="detail">ConTeXt Color Management</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="table"><short>show icc table</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Example</title> - <subcategory> - <example><command>mtxrun --script color --table somename</command></example> - </subcategory> - </category> - </examples> -</application> -]] - -local application = logs.application { - name = "mtx-colors", - banner = "ConTeXt Color Management 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -if not fontloader then fontloader = fontforge end - -dofile(resolvers.findfile("colo-icc.lua","tex")) - -scripts = scripts or { } -scripts.colors = scripts.colors or { } - -function scripts.colors.table() - local files = environment.files - if #files > 0 then - for i=1,#files do - local profile, okay, message = colors.iccprofile(files[i]) - if not okay then - report(message) - else - report(table.serialize(profile,"profile")) - end - end - else - report("no file(s) given" ) - end -end - ---~ local track = environment.argument("track") ---~ if track then trackers.enable(track) end - -if environment.argument("table") then - scripts.colors.table() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-colors'] = {
+ 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"
+}
+
+-- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-colors</entry>
+ <entry name="detail">ConTeXt Color Management</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="table"><short>show icc table</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+ <examples>
+ <category>
+ <title>Example</title>
+ <subcategory>
+ <example><command>mtxrun --script color --table somename</command></example>
+ </subcategory>
+ </category>
+ </examples>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-colors",
+ banner = "ConTeXt Color Management 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+if not fontloader then fontloader = fontforge end
+
+dofile(resolvers.findfile("colo-icc.lua","tex"))
+
+scripts = scripts or { }
+scripts.colors = scripts.colors or { }
+
+function scripts.colors.table()
+ local files = environment.files
+ if #files > 0 then
+ for i=1,#files do
+ local profile, okay, message = colors.iccprofile(files[i])
+ if not okay then
+ report(message)
+ else
+ report(table.serialize(profile,"profile"))
+ end
+ end
+ else
+ report("no file(s) given" )
+ end
+end
+
+--~ local track = environment.argument("track")
+--~ if track then trackers.enable(track) end
+
+if environment.argument("table") then
+ scripts.colors.table()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-context.lua b/scripts/context/lua/mtx-context.lua index 87ed3475d..3c2311eef 100644 --- a/scripts/context/lua/mtx-context.lua +++ b/scripts/context/lua/mtx-context.lua @@ -1,1492 +1,1492 @@ -if not modules then modules = { } end modules ['mtx-context'] = { - 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" -} - --- todo: more local functions --- todo: pass jobticket/ctxdata table around - -local type, next, tostring, tonumber = type, next, tostring, tonumber -local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find -local quote, validstring = string.quote, string.valid -local concat = table.concat -local settings_to_array = utilities.parsers.settings_to_array -local appendtable = table.append -local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P - -local getargument = environment.getargument or environment.argument -local setargument = environment.setargument - -local application = logs.application { - name = "mtx-context", - banner = "ConTeXt Process Management 0.60", - -- helpinfo = helpinfo, -- table with { category_a = text_1, category_b = text_2 } or helpstring or xml_blob - helpinfo = "mtx-context.xml", -} - --- local luatexflags = { --- ["8bit"] = true, -- ignored, input is assumed to be in UTF-8 encoding --- ["default-translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding --- ["translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding --- ["etex"] = true, -- ignored, the etex extensions are always active --- --- ["credits"] = true, -- display credits and exit --- ["debug-format"] = true, -- enable format debugging --- ["disable-write18"] = true, -- disable \write18{SHELL COMMAND} --- ["draftmode"] = true, -- switch on draft mode (generates no output PDF) --- ["enable-write18"] = true, -- enable \write18{SHELL COMMAND} --- ["file-line-error"] = true, -- enable file:line:error style messages --- ["file-line-error-style"] = true, -- aliases of --file-line-error --- ["no-file-line-error"] = true, -- disable file:line:error style messages --- ["no-file-line-error-style"] = true, -- aliases of --no-file-line-error --- ["fmt"] = true, -- load the format file FORMAT --- ["halt-on-error"] = true, -- stop processing at the first error --- ["help"] = true, -- display help and exit --- ["ini"] = true, -- be iniluatex, for dumping formats --- ["interaction"] = true, -- set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode) --- ["jobname"] = true, -- set the job name to STRING --- ["kpathsea-debug"] = true, -- set path searching debugging flags according to the bits of NUMBER --- ["lua"] = true, -- load and execute a lua initialization script --- ["mktex"] = true, -- enable mktexFMT generation (FMT=tex/tfm) --- ["no-mktex"] = true, -- disable mktexFMT generation (FMT=tex/tfm) --- ["nosocket"] = true, -- disable the lua socket library --- ["output-comment"] = true, -- use STRING for DVI file comment instead of date (no effect for PDF) --- ["output-directory"] = true, -- use existing DIR as the directory to write files in --- ["output-format"] = true, -- use FORMAT for job output; FORMAT is 'dvi' or 'pdf' --- ["parse-first-line"] = true, -- enable parsing of the first line of the input file --- ["no-parse-first-line"] = true, -- disable parsing of the first line of the input file --- ["progname"] = true, -- set the program name to STRING --- ["recorder"] = true, -- enable filename recorder --- ["safer"] = true, -- disable easily exploitable lua commands --- ["shell-escape"] = true, -- enable \write18{SHELL COMMAND} --- ["no-shell-escape"] = true, -- disable \write18{SHELL COMMAND} --- ["shell-restricted"] = true, -- restrict \write18 to a list of commands given in texmf.cnf --- ["synctex"] = true, -- enable synctex --- ["version"] = true, -- display version and exit --- ["luaonly"] = true, -- run a lua file, then exit --- ["luaconly"] = true, -- byte-compile a lua file, then exit --- ["jiton"] = false, --- } - -local report = application.report - -scripts = scripts or { } -scripts.context = scripts.context or { } - --- for the moment here - -if getargument("jit") or getargument("jiton") then - -- bonus shortcut, we assume than --jit also indicates the engine - -- although --jit and --engine=luajittex are independent - setargument("engine","luajittex") -end - -local engine_new = getargument("engine") or directives.value("system.engine") -local engine_old = environment.ownbin - -local function restart(engine_old,engine_new) - local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline()) - report(format("redirect %s -> %s: %s",engine_old,engine_new,command)) - local result = os.execute(command) - os.exit(result) -end - -if getargument("redirected") then - setargument("engine",engine_old) -- later on we need this -elseif engine_new == engine_old then - setargument("engine",engine_new) -- later on we need this -elseif environment.validengines[engine_new] and engine_new ~= environment.basicengines[engine_old] then - restart(engine_old,engine_new) -else - setargument("engine",engine_new) -- later on we need this -end - --- so far - --- constants - -local usedfiles = { - nop = "cont-nop.mkiv", - yes = "cont-yes.mkiv", -} - -local usedsuffixes = { - before = { - "tuc" - }, - after = { - "pdf", "tuc", "log" - }, - keep = { - "log" - }, -} - -local formatofinterface = { - en = "cont-en", - uk = "cont-uk", - de = "cont-de", - fr = "cont-fr", - nl = "cont-nl", - cs = "cont-cs", - it = "cont-it", - ro = "cont-ro", - pe = "cont-pe", -} - -local defaultformats = { - "cont-en", - "cont-nl", -} - --- process information - -local ctxrunner = { } -- namespace will go - -local ctx_locations = { '..', '../..' } - -function ctxrunner.new() - return { - ctxname = "", - jobname = "", - flags = { }, - } -end - -function ctxrunner.checkfile(ctxdata,ctxname,defaultname) - - if not ctxdata.jobname or ctxdata.jobname == "" then - return - end - - ctxdata.ctxname = ctxname or file.removesuffix(ctxdata.jobname) or "" - - if ctxdata.ctxname == "" then - return - end - - ctxdata.jobname = file.addsuffix(ctxdata.jobname,'tex') - ctxdata.ctxname = file.addsuffix(ctxdata.ctxname,'ctx') - - report("jobname: %s",ctxdata.jobname) - report("ctxname: %s",ctxdata.ctxname) - - -- mtxrun should resolve kpse: and file: - - local usedname = ctxdata.ctxname - local found = lfs.isfile(usedname) - - -- no further test if qualified path - - if not found then - for _, path in next, ctx_locations do - local fullname = file.join(path,ctxdata.ctxname) - if lfs.isfile(fullname) then - usedname = fullname - found = true - break - end - end - end - - if not found then - usedname = resolvers.findfile(ctxdata.ctxname,"tex") - found = usedname ~= "" - end - - if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then - usedname = defaultname - found = true - end - - if not found then - return - end - - local xmldata = xml.load(usedname) - - if not xmldata then - return - else - -- test for valid, can be text file - end - - local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations) - - xml.include(xmldata,'ctx:include','name', ctxpaths) - - local flags = ctxdata.flags - - for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do - local flag = xml.text(e) or "" - local key, value = match(flag,"^(.-)=(.+)$") - if key and value then - flags[key] = value - else - flags[flag] = true - end - end - -end - -function ctxrunner.checkflags(ctxdata) - if ctxdata then - for k,v in next, ctxdata.flags do - if getargument(k) == nil then - setargument(k,v) - end - end - end -end - --- multipass control - -local multipass_suffixes = { ".tuc" } -local multipass_nofruns = 8 -- or 7 to test oscillation - -local function multipass_hashfiles(jobname) - local hash = { } - for i=1,#multipass_suffixes do - local suffix = multipass_suffixes[i] - local full = jobname .. suffix - hash[full] = md5.hex(io.loaddata(full) or "unknown") - end - return hash -end - -local function multipass_changed(oldhash, newhash) - for k,v in next, oldhash do - if v ~= newhash[k] then - return true - end - end - return false -end - -local function multipass_copyluafile(jobname) - local tuaname, tucname = jobname..".tua", jobname..".tuc" - if lfs.isfile(tuaname) then - os.remove(tucname) - os.rename(tuaname,tucname) - end -end - --- - -local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1) - -local function preamble_analyze(filename) -- only files on current path - local t = { } - local line = io.loadlines(file.addsuffix(filename,"tex")) - if line then - local preamble = lpegmatch(pattern,line) - if preamble then - for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do - t[key] = value - end - t.type = "tex" - elseif find(line,"^<?xml ") then - t.type = "xml" - end - if t.nofruns then - multipass_nofruns = t.nofruns - end - if not t.engine then - t.engine = environment.basicengines[engine_old] --'luatex' - end - if t.engine ~= engine_old then -- hack - if environment.validengines[t.engine] and t.engine ~= environment.basicengines[engine_old] then - restart(engine_old,t.engine) - end - end - end - return t -end - --- automatically opening and closing pdf files - -local pdfview -- delayed - -local function pdf_open(name,method) - pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex")) - pdfview.setmethod(method) - report(pdfview.status()) - pdfview.open(file.replacesuffix(name,"pdf")) -end - -local function pdf_close(name,method) - pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex")) - pdfview.setmethod(method) - pdfview.close(file.replacesuffix(name,"pdf")) -end - --- result file handling - -local function result_push_purge(oldbase,newbase) - for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) - os.remove(newname) - os.remove(oldname) - end -end - -local function result_push_keep(oldbase,newbase) - for _, suffix in next, usedsuffixes.before do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) - local tmpname = "keep-"..oldname - os.remove(tmpname) - os.rename(oldname,tmpname) - os.remove(oldname) - os.rename(newname,oldname) - end -end - -local function result_save_error(oldbase,newbase) - for _, suffix in next, usedsuffixes.keep do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) - os.remove(newname) -- to be sure - os.rename(oldname,newname) - end -end - -local function result_save_purge(oldbase,newbase) - for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) - os.remove(newname) -- to be sure - os.rename(oldname,newname) - end -end - -local function result_save_keep(oldbase,newbase) - for _, suffix in next, usedsuffixes.after do - local oldname = file.addsuffix(oldbase,suffix) - local newname = file.addsuffix(newbase,suffix) - local tmpname = "keep-"..oldname - os.remove(newname) - os.rename(oldname,newname) - os.rename(tmpname,oldname) - end -end - --- executing luatex - -local function flags_to_string(flags,prefix) -- context flags get prepended by c: - local t = { } - for k, v in table.sortedhash(flags) do - if prefix then - k = format("c:%s",k) - end - if not v or v == "" or v == '""' then - -- no need to flag false - elseif v == true then - t[#t+1] = format('--%s',k) - elseif type(v) == "string" then - t[#t+1] = format('--%s=%s',k,quote(v)) - else - t[#t+1] = format('--%s=%s',k,tostring(v)) - end - end - return concat(t," ") -end - -local function luatex_command(l_flags,c_flags,filename,engine) - return format('%s %s %s "%s"', - engine or "luatex", - flags_to_string(l_flags), - flags_to_string(c_flags,true), - filename - ) -end - -local plain_formats = { - ["plain"] = "plain", - ["luatex-plain"] = "luatex-plain", -} - -local function plain_format(plainformat) - return plainformat and plain_formats[plainformat] -end - -local function run_plain(plainformat,filename) - local plainformat = plain_formats[plainformat] - if plainformat then - local command = format("mtxrun --script --texformat=%s plain %s",plainformat,filename) - report("running command: %s\n\n",command) - -- todo: load and run - local resultname = file.replacesuffix(filename,"pdf") - local pdfview = getargument("autopdf") or getargument("closepdf") - if pdfview then - pdf_close(resultname,pdfview) - os.execute(command) - pdf_open(resultname,pdfview) - else - os.execute(command) - end - end -end - -local function run_texexec(filename,a_purge,a_purgeall) - if false then - -- we need to write a top etc too and run mp etc so it's not worth the - -- trouble, so it will take a while before the next is finished - -- - -- context --extra=texutil --convert myfile - else - local texexec = resolvers.findfile("texexec.rb") or "" - if texexec ~= "" then - os.setenv("RUBYOPT","") - local options = environment.reconstructcommandline(environment.arguments_after) - options = gsub(options,"--purge","") - options = gsub(options,"--purgeall","") - local command = format("ruby %s %s",texexec,options) - report("running command: %s\n\n",command) - if a_purge then - os.execute(command) - scripts.context.purge_job(filename,false,true) - elseif a_purgeall then - os.execute(command) - scripts.context.purge_job(filename,true,true) - else - os.execute(command) -- we can use os.exec but that doesn't give back timing - end - end - end -end - --- - -function scripts.context.run(ctxdata,filename) - -- - local a_nofile = getargument("nofile") - local a_engine = getargument("engine") - -- - local files = environment.files or { } - -- - local filelist, mainfile - -- - if filename then - -- the given forced name is processed, the filelist is passed to context - mainfile = filename - filelist = { filename } - -- files = files - elseif a_nofile then - -- the list of given files is processed using the dummy file - mainfile = usedfiles.nop - filelist = { usedfiles.nop } - -- files = { } - elseif #files > 0 then - -- the list of given files is processed using the stub file - mainfile = usedfiles.yes - filelist = files - files = { } - else - return - end - -- - local interface = validstring(getargument("interface")) or "en" - local formatname = formatofinterface[interface] or "cont-en" - local formatfile, scriptfile = resolvers.locateformat(formatname) -- regular engine ! - if not formatfile or not scriptfile then - report("warning: no format found, forcing remake (commandline driven)") - scripts.context.make(formatname) - formatfile, scriptfile = resolvers.locateformat(formatname) -- variant - end - if formatfile and scriptfile then - -- okay - elseif formatname then - report("error, no format found with name: %s, aborting",formatname) - return - else - report("error, no format found (provide formatname or interface)") - return - end - -- - local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex") - local a_purge = getargument("purge") - local a_purgeall = getargument("purgeall") - local a_purgeresult = getargument("purgeresult") - local a_global = getargument("global") - local a_timing = getargument("timing") - local a_profile = getargument("profile") - local a_batchmode = getargument("batchmode") - local a_nonstopmode = getargument("nonstopmode") - local a_once = getargument("once") - local a_synctex = getargument("synctex") - local a_backend = getargument("backend") - local a_arrange = getargument("arrange") - local a_noarrange = getargument("noarrange") - local a_jiton = getargument("jiton") - local a_texformat = getargument("texformat") - -- - a_batchmode = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil - a_synctex = tonumber(a_synctex) or (toboolean(a_synctex,true) and 1) or (a_synctex == "zipped" and 1) or (a_synctex == "unzipped" and -1) or nil - -- - for i=1,#filelist do - -- - local filename = filelist[i] - local basename = file.basename(filename) -- use splitter - local pathname = file.dirname(filename) - -- - if pathname == "" and not a_global and filename ~= usedfiles.nop then - filename = "./" .. filename - if not lfs.isfile(filename) then - report("warning: no (local) file %a, proceeding",filename) - end - end - -- - local jobname = file.removesuffix(basename) - -- local jobname = file.removesuffix(filename) - local ctxname = ctxdata and ctxdata.ctxname - -- - local analysis = preamble_analyze(filename) - -- - if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then - run_texexec(filename,a_purge,a_purgeall) - elseif plain_format(a_texformat or analysis.texformat) then - run_plain(a_texformat or analysis.texformat,filename) - else - if analysis.interface and analysis.interface ~= interface then - formatname = formatofinterface[analysis.interface] or formatname - formatfile, scriptfile = resolvers.locateformat(formatname) - end - -- - a_jiton = (a_jiton or toboolean(analysis.jiton,true)) and true or nil - -- - if not formatfile or not scriptfile then - report("warning: no format found, forcing remake (source driven)") - scripts.context.make(formatname,a_engine) - formatfile, scriptfile = resolvers.locateformat(formatname) - end - if formatfile and scriptfile then - local suffix = validstring(getargument("suffix")) - local resultname = validstring(getargument("result")) - if suffix then - resultname = file.removesuffix(jobname) .. suffix - end - local oldbase = "" - local newbase = "" - if resultname then - oldbase = file.removesuffix(jobname) - newbase = file.removesuffix(resultname) - if oldbase ~= newbase then - if a_purgeresult then - result_push_purge(oldbase,newbase) - else - result_push_keep(oldbase,newbase) - end - else - resultname = nil - end - end - -- - local pdfview = getargument("autopdf") or getargument("closepdf") - if pdfview then - pdf_close(filename,pdfview) - if resultname then - pdf_close(resultname,pdfview) - end - end - -- - -- we could do this when locating the format and exit from luatex when - -- there is a version mismatch .. that way we can use stock luatex - -- plus mtxrun to run luajittex instead .. this saves a restart but is - -- also cleaner as then mtxrun only has to check for a special return - -- code (signaling a make + rerun) .. maybe some day - -- - local okay = statistics.checkfmtstatus(formatfile,a_engine) - if okay ~= true then - report("warning: %s, forcing remake",tostring(okay)) - scripts.context.make(formatname) - end - -- - local oldhash = multipass_hashfiles(jobname) - local newhash = { } - local maxnofruns = once and 1 or multipass_nofruns - -- - local c_flags = { - directives = validstring(environment.directives), -- gets passed via mtxrun - trackers = validstring(environment.trackers), -- gets passed via mtxrun - experiments = validstring(environment.experiments), -- gets passed via mtxrun - -- - result = validstring(resultname), - input = validstring(getargument("input") or filename), -- alternative input - fulljobname = validstring(filename), - files = concat(files,","), - ctx = validstring(ctxname), - } - -- - for k, v in next, environment.arguments do - -- the raw arguments - if c_flags[k] == nil then - c_flags[k] = v - end - end - -- - -- - local l_flags = { - ["interaction"] = a_batchmode, - ["synctex"] = a_synctex, - ["no-parse-first-line"] = true, - -- ["no-mktex"] = true, - -- ["file-line-error-style"] = true, - ["fmt"] = formatfile, - ["lua"] = scriptfile, - ["jobname"] = jobname, - ["jiton"] = a_jiton, - } - -- - if a_synctex then - report("warning: synctex is enabled") -- can add upto 5% runtime - end - -- - if not a_timing then - -- okay - elseif c_flags.usemodule then - c_flags.usemodule = format("timing,%s",c_flags.usemodule) - else - c_flags.usemodule = "timing" - end - -- - if not a_profile then - -- okay - elseif c_flags.directives then - c_flags.directives = format("system.profile,%s",c_flags.directives) - else - c_flags.directives = "system.profile" - end - -- - -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns - -- - for currentrun=1,maxnofruns do - -- - c_flags.final = false - c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2 - c_flags.maxnofruns = maxnofruns - c_flags.currentrun = currentrun - c_flags.noarrange = a_noarrange or a_arrange or nil - -- - local command = luatex_command(l_flags,c_flags,mainfile,a_engine) - -- - report("run %s: %s",i,command) - print("") -- cleaner, else continuation on same line - local returncode, errorstring = os.spawn(command) - if not returncode then - report("fatal error: no return code, message: %s",errorstring or "?") - if resultname then - result_save_error(oldbase,newbase) - end - os.exit(1) - break - elseif returncode == 0 then - multipass_copyluafile(jobname) - newhash = multipass_hashfiles(jobname) - if multipass_changed(oldhash,newhash) then - oldhash = newhash - else - break - end - else - report("fatal error: return code: %s",returncode or "?") - if resultname then - result_save_error(oldbase,newbase) - end - os.exit(1) -- (returncode) - break - end - -- - end - -- - if a_arrange then - -- - c_flags.final = true - c_flags.kindofrun = 3 - c_flags.currentrun = c_flags.currentrun + 1 - c_flags.noarrange = nil - -- - local command = luatex_command(l_flags,c_flags,mainfile,a_engine) - -- - report("arrange run: %s",command) - local returncode, errorstring = os.spawn(command) - if not returncode then - report("fatal error: no return code, message: %s",errorstring or "?") - os.exit(1) - elseif returncode > 0 then - report("fatal error: return code: %s",returncode or "?") - os.exit(returncode) - end - -- - end - -- - if a_purge then - scripts.context.purge_job(jobname) - elseif a_purgeall then - scripts.context.purge_job(jobname,true) - end - -- - if resultname then - if a_purgeresult then - -- so, if there is no result then we don't get the old one, but - -- related files (log etc) are still there for tracing purposes - result_save_purge(oldbase,newbase) - else - result_save_keep(oldbase,newbase) - end - report("result renamed to: %s",newbase) - end - -- - if purge then - scripts.context.purge_job(resultname) - elseif purgeall then - scripts.context.purge_job(resultname,true) - end - -- - local pdfview = getargument("autopdf") - if pdfview then - pdf_open(resultname or jobname,pdfview) - end - -- - if a_timing then - report() - report("you can process (timing) statistics with:",jobname) - report() - report("context --extra=timing '%s'",jobname) - report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname) - report() - end - else - if formatname then - report("error, no format found with name: %s, skipping",formatname) - else - report("error, no format found (provide formatname or interface)") - end - break - end - end - end - -- -end - -function scripts.context.pipe() -- still used? - -- context --pipe - -- context --pipe --purge --dummyfile=whatever.tmp - local interface = getargument("interface") - interface = (type(interface) == "string" and interface) or "en" - local formatname = formatofinterface[interface] or "cont-en" - local formatfile, scriptfile = resolvers.locateformat(formatname) - if not formatfile or not scriptfile then - report("warning: no format found, forcing remake (commandline driven)") - scripts.context.make(formatname) - formatfile, scriptfile = resolvers.locateformat(formatname) - end - if formatfile and scriptfile then - local okay = statistics.checkfmtstatus(formatfile) - if okay ~= true then - report("warning: %s, forcing remake",tostring(okay)) - scripts.context.make(formatname) - end - local l_flags = { - interaction = "scrollmode", - fmt = formatfile, - lua = scriptfile, - } - local c_flags = { - backend = "pdf", - final = false, - kindofrun = 3, - currentrun = 1, - } - local filename = getargument("dummyfile") or "" - if filename == "" then - filename = "\\relax" - report("entering scrollmode, end job with \\end") - else - filename = file.addsuffix(filename,"tmp") - io.savedata(filename,"\\relax") - report("entering scrollmode using '%s' with optionfile, end job with \\end",filename) - end - local command = luatex_command(l_flags,c_flags,filename) - os.spawn(command) - if getargument("purge") then - scripts.context.purge_job(filename) - elseif getargument("purgeall") then - scripts.context.purge_job(filename,true) - os.remove(filename) - end - else - if formatname then - report("error, no format found with name: %s, aborting",formatname) - else - report("error, no format found (provide formatname or interface)") - end - end -end - -local function make_mkiv_format(name,engine) - environment.make_format(name) -- jit is picked up later -end - -local function make_mkii_format(name,engine) - local command = format("mtxrun texexec.rb --make --%s %s",name,engine) - report("running command: %s",command) - os.spawn(command) -end - -function scripts.context.generate() - resolvers.instance.renewcache = true - trackers.enable("resolvers.locating") - resolvers.load() -end - -function scripts.context.make(name) - if not getargument("fast") then -- as in texexec - scripts.context.generate() - end - local list = (name and { name }) or (environment.files[1] and environment.files) or defaultformats - local engine = getargument("engine") or "luatex" - if getargument("jit") or getargument("jiton") then - engine = "luajittex" - end - for i=1,#list do - local name = list[i] - name = formatofinterface[name] or name or "" - if name == "" then - -- nothing - elseif engine == "luatex" or engine == "luajittex" then - make_mkiv_format(name,engine) - elseif engine == "pdftex" or engine == "xetex" then - make_mkii_format(name,engine) - end - end -end - -function scripts.context.ctx() - local ctxdata = ctxrunner.new() - ctxdata.jobname = environment.files[1] - ctxrunner.checkfile(ctxdata,getargument("ctx")) - ctxrunner.checkflags(ctxdata) - scripts.context.run(ctxdata) -end - -function scripts.context.autoctx() - local ctxdata = nil - local files = environment.files - local firstfile = #files > 0 and files[1] - if firstfile then - local suffix = file.suffix(firstfile) - if suffix == "xml" then - local chunk = io.loadchunk(firstfile) -- 1024 - if chunk then - local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>") - if ctxname then - ctxdata = ctxrunner.new() - ctxdata.jobname = firstfile - ctxrunner.checkfile(ctxdata,ctxname) - ctxrunner.checkflags(ctxdata) - end - end - elseif suffix == "tex" then - -- maybe but we scan the preamble later too - end - end - scripts.context.run(ctxdata) -end - --- no longer ok as mlib-run misses something: - --- local template = [[ --- \starttext --- \directMPgraphic{%s}{input "%s"} --- \stoptext --- ]] --- --- local loaded = false --- --- function scripts.context.metapost() --- local filename = environment.files[1] or "" --- if not loaded then --- dofile(resolvers.findfile("mlib-run.lua")) --- loaded = true --- commands = commands or { } --- commands.writestatus = report -- no longer needed --- end --- local formatname = getargument("format") or "metafun" --- if formatname == "" or type(formatname) == "boolean" then --- formatname = "metafun" --- end --- if getargument("pdf") then --- local basename = file.removesuffix(filename) --- local resultname = getargument("result") or basename --- local jobname = "mtx-context-metapost" --- local tempname = file.addsuffix(jobname,"tex") --- io.savedata(tempname,format(template,"metafun",filename)) --- environment.files[1] = tempname --- setargument("result",resultname) --- setargument("once",true) --- scripts.context.run() --- scripts.context.purge_job(jobname,true) --- scripts.context.purge_job(resultname,true) --- elseif getargument("svg") then --- metapost.directrun(formatname,filename,"svg") --- else --- metapost.directrun(formatname,filename,"mps") --- end --- end - --- -- - -function scripts.context.version() - local name = resolvers.findfile("context.mkiv") - if name ~= "" then - report("main context file: %s",name) - local data = io.loaddata(name) - if data then - local version = match(data,"\\edef\\contextversion{(.-)}") - if version then - report("current version: %s",version) - else - report("context version: unknown, no timestamp found") - end - else - report("context version: unknown, load error") - end - else - report("main context file: unknown, 'context.mkiv' not found") - end -end - --- purging files - -local generic_files = { - "texexec.tex", "texexec.tui", "texexec.tuo", - "texexec.tuc", "texexec.tua", - "texexec.ps", "texexec.pdf", "texexec.dvi", - "cont-opt.tex", "cont-opt.bak" -} - -local obsolete_results = { - "dvi", -} - -local temporary_runfiles = { - "tui", "tua", "tup", "ted", "tes", "top", - "log", "tmp", "run", "bck", "rlg", - "mpt", "mpx", "mpd", "mpo", "mpb", "ctl", - "synctex", "synctex.gz", "pgf", - "prep", -} - -local persistent_runfiles = { - "tuo", "tub", "top", "tuc" -} - -local special_runfiles = { - "-mpgraph", "-mprun", "-temp-" -} - -local function purge_file(dfile,cfile) - if cfile and lfs.isfile(cfile) then - if os.remove(dfile) then - return file.basename(dfile) - end - elseif dfile then - if os.remove(dfile) then - return file.basename(dfile) - end - end -end - -function scripts.context.purge_job(jobname,all,mkiitoo) - if jobname and jobname ~= "" then - jobname = file.basename(jobname) - local filebase = file.removesuffix(jobname) - if mkiitoo then - scripts.context.purge(all,filebase,true) -- leading "./" - else - local deleted = { } - for i=1,#obsolete_results do - deleted[#deleted+1] = purge_file(filebase.."."..obsolete_results[i],filebase..".pdf") - end - for i=1,#temporary_runfiles do - deleted[#deleted+1] = purge_file(filebase.."."..temporary_runfiles[i]) - end - if all then - for i=1,#persistent_runfiles do - deleted[#deleted+1] = purge_file(filebase.."."..persistent_runfiles[i]) - end - end - if #deleted > 0 then - report("purged files: %s", concat(deleted,", ")) - end - end - end -end - -function scripts.context.purge(all,pattern,mkiitoo) - local all = all or getargument("all") - local pattern = getargument("pattern") or (pattern and (pattern.."*")) or "*.*" - local files = dir.glob(pattern) - local obsolete = table.tohash(obsolete_results) - local temporary = table.tohash(temporary_runfiles) - local persistent = table.tohash(persistent_runfiles) - local generic = table.tohash(generic_files) - local deleted = { } - for i=1,#files do - local name = files[i] - local suffix = file.suffix(name) - local basename = file.basename(name) - if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then - deleted[#deleted+1] = purge_file(name) - elseif mkiitoo then - for i=1,#special_runfiles do - if find(name,special_runfiles[i]) then - deleted[#deleted+1] = purge_file(name) - end - end - end - end - if #deleted > 0 then - report("purged files: %s", concat(deleted,", ")) - end -end - --- touching files (signals regeneration of formats) - -local function touch(path,name,versionpattern,kind,kindpattern) - if path and path ~= "" then - name = file.join(path,name) -print(name) - else - name = resolvers.findfile(name) - end - local olddata = io.loaddata(name) - if olddata then - local oldkind, newkind = "", kind or "" - local oldversion, newversion = "", os.date("%Y.%m.%d %H:%M") - local newdata - if versionpattern then - newdata = gsub(olddata,versionpattern,function(pre,mid,post) - oldversion = mid - return pre .. newversion .. post - end) or olddata - end - if kind and kindpattern then - newdata = gsub(newdata,kindpattern,function(pre,mid,post) - oldkind = mid - return pre .. newkind .. post - end) or newdata - end - if newdata ~= "" and (oldversion ~= newversion or oldkind ~= newkind or newdata ~= olddata) then - local backup = file.replacesuffix(name,"tmp") - os.remove(backup) - os.rename(name,backup) - io.savedata(name,newdata) - return name, oldversion, newversion, oldkind, newkind - end - end -end - -local p_contextkind = "(\\edef\\contextkind%s*{)(.-)(})" -local p_contextversion = "(\\edef\\contextversion%s*{)(.-)(})" -local p_newcontextversion = "(\\newcontextversion%s*{)(.-)(})" - -local function touchfiles(suffix,kind,path) - local foundname, oldversion, newversion, oldkind, newkind = touch(path,file.addsuffix("context",suffix),p_contextversion,kind,p_contextkind) - if foundname then - report("old version : %s (%s)",oldversion,oldkind) - report("new version : %s (%s)",newversion,newkind) - report("touched file : %s",foundname) - local foundname = touch(path,file.addsuffix("cont-new",suffix),p_newcontextversion) - if foundname then - report("touched file : %s", foundname) - end - else - report("nothing touched") - end -end - -function scripts.context.touch() - if getargument("expert") then - local touch = getargument("touch") - local kind = getargument("kind") - local path = getargument("basepath") - if touch == "mkii" or touch == "mkiv" or touch == "mkvi" then -- mkix mkxi - touchfiles(touch,kind,path) - else - touchfiles("mkii",kind,path) - touchfiles("mkiv",kind,path) - touchfiles("mkvi",kind,path) - end - else - report("touching needs --expert") - end -end - --- modules - -local labels = { "title", "comment", "status" } -local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" } - -function scripts.context.modules(pattern) - local list = { } - local found = resolvers.findfile("context.mkiv") - if not pattern or pattern == "" then - -- official files in the tree - for i=1,#cards do - resolvers.findwildcardfiles(cards[i],list) - end - -- my dev path - for i=1,#cards do - dir.glob(file.join(file.dirname(found),cards[i]),list) - end - else - resolvers.findwildcardfiles(pattern,list) - dir.glob(file.join(file.dirname(found,pattern)),list) - end - local done = { } -- todo : sort - for i=1,#list do - local v = list[i] - local base = file.basename(v) - if not done[base] then - done[base] = true - local suffix = file.suffix(base) - if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then - local prefix = match(base,"^([xmst])%-") - if prefix then - v = resolvers.findfile(base) -- so that files on my dev path are seen - local data = io.loaddata(v) or "" - data = match(data,"%% begin info(.-)%% end info") - if data then - local info = { } - for label, text in gmatch(data,"%% +([^ ]+) *: *(.-)[\n\r]") do - info[label] = text - end - report() - report("%-7s : %s","module",base) - report() - for i=1,#labels do - local l = labels[i] - if info[l] then - report("%-7s : %s",l,info[l]) - end - end - report() - end - end - end - end - end -end - --- extras - -function scripts.context.extras(pattern) - -- only in base path, i.e. only official ones - if type(pattern) ~= "string" then - pattern = "*" - end - local found = resolvers.findfile("context.mkiv") - if found ~= "" then - pattern = file.join(dir.expandname(file.dirname(found)),format("mtx-context-%s.tex",pattern or "*")) - local list = dir.glob(pattern) - for i=1,#list do - local v = list[i] - local data = io.loaddata(v) or "" - data = match(data,"%% begin help(.-)%% end help") - if data then - report() - report("extra: %s (%s)",(gsub(v,"^.*mtx%-context%-(.-)%.tex$","%1")),v) - for s in gmatch(data,"%% *(.-)[\n\r]") do - report(s) - end - report() - end - end - end -end - -function scripts.context.extra() - local extra = getargument("extra") - if type(extra) ~= "string" then - scripts.context.extras() - elseif getargument("help") then - scripts.context.extras(extra) - else - local fullextra = extra - if not find(fullextra,"mtx%-context%-") then - fullextra = "mtx-context-" .. extra - end - local foundextra = resolvers.findfile(fullextra) - if foundextra == "" then - scripts.context.extras() - return - else - report("processing extra: %s", foundextra) - end - setargument("purgeall",true) - local result = getargument("result") or "" - if result == "" then - setargument("result","context-extra") - end - scripts.context.run(nil,foundextra) - end -end - --- todo: we need to do a dummy run - -function scripts.context.trackers() - environment.files = { resolvers.findfile("m-trackers.mkiv") } - 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 - -function scripts.context.logcategories() - environment.files = { resolvers.findfile("m-logcategories.mkiv") } - multipass_nofruns = 1 - setargument("purgeall",true) - scripts.context.run() -end - --- updating (often one will use mtx-update instead) - -function scripts.context.timed(action) - statistics.timed(action) -end - -local zipname = "cont-tmf.zip" -local mainzip = "http://www.pragma-ade.com/context/latest/" .. zipname -local validtrees = { "texmf-local", "texmf-context" } -local selfscripts = { "mtxrun.lua" } -- was: { "luatools.lua", "mtxrun.lua" } - -function zip.loaddata(zipfile,filename) -- should be in zip lib - local f = zipfile:open(filename) - if f then - local data = f:read("*a") - f:close() - return data - end - return nil -end - -function scripts.context.update() - local force = getargument("force") - local socket = require("socket") - local http = require("socket.http") - local basepath = resolvers.findfile("context.mkiv") or "" - if basepath == "" then - report("quiting, no 'context.mkiv' found") - return - end - local basetree = basepath.match(basepath,"^(.-)tex/context/base/context.mkiv$") or "" - if basetree == "" then - report("quiting, no proper tds structure (%s)",basepath) - return - end - local function is_okay(basetree) - for _, tree in next, validtrees do - local pattern = gsub(tree,"%-","%%-") - if find(basetree,pattern) then - return tree - end - end - return false - end - local okay = is_okay(basetree) - if not okay then - report("quiting, tree '%s' is protected",okay) - return - else - report("updating tree '%s'",okay) - end - if not lfs.chdir(basetree) then - report("quiting, unable to change to '%s'",okay) - return - end - report("fetching '%s'",mainzip) - local latest = http.request(mainzip) - if not latest then - report("context tree '%s' can be updated, use --force",okay) - return - end - io.savedata("cont-tmf.zip",latest) - if false then - -- variant 1 - os.execute("mtxrun --script unzip cont-tmf.zip") - else - -- variant 2 - local zipfile = zip.open(zipname) - if not zipfile then - report("quiting, unable to open '%s'",zipname) - return - end - local newfile = zip.loaddata(zipfile,"tex/context/base/context.mkiv") - if not newfile then - report("quiting, unable to open '%s'","context.mkiv") - return - end - local oldfile = io.loaddata(resolvers.findfile("context.mkiv")) or "" - local function versiontonumber(what,str) - local version = match(str,"\\edef\\contextversion{(.-)}") or "" - local year, month, day, hour, minute = match(str,"\\edef\\contextversion{(%d+)%.(%d+)%.(%d+) *(%d+)%:(%d+)}") - if year and minute then - local time = os.time { year=year,month=month,day=day,hour=hour,minute=minute} - report("%s version: %s (%s)",what,version,time) - return time - else - report("%s version: %s (unknown)",what,version) - return nil - end - end - local oldversion = versiontonumber("old",oldfile) - local newversion = versiontonumber("new",newfile) - if not oldversion or not newversion then - report("quiting, version cannot be determined") - return - elseif oldversion == newversion then - report("quiting, your current version is up-to-date") - return - elseif oldversion > newversion then - report("quiting, your current version is newer") - return - end - for k in zipfile:files() do - local filename = k.filename - if find(filename,"/$") then - lfs.mkdir(filename) - else - local data = zip.loaddata(zipfile,filename) - if data then - if force then - io.savedata(filename,data) - end - report(filename) - end - end - end - for _, scriptname in next, selfscripts do - local oldscript = resolvers.findfile(scriptname) or "" - if oldscript ~= "" and is_okay(oldscript) then - local newscript = "./scripts/context/lua/" .. scriptname - local data = io.loaddata(newscript) or "" - if data ~= "" then - report("replacing script '%s' by '%s'",oldscript,newscript) - if force then - io.savedata(oldscript,data) - end - end - else - report("keeping script '%s'",oldscript) - end - end - if force then - scripts.context.make() - end - end - if force then - report("context tree '%s' has been updated",okay) - else - report("context tree '%s' can been updated (use --force)",okay) - end -end - --- getting it done - -if getargument("nostats") then - setargument("nostatistics",true) - setargument("nostat",nil) -end - -if getargument("batch") then - setargument("batchmode",true) - setargument("batch",nil) -end - -if getargument("nonstop") then - setargument("nonstopmode",true) - setargument("nonstop",nil) -end - -do - - local silent = getargument("silent") - if type(silent) == "string" then - directives.enable(format("logs.blocked={%s}",silent)) - elseif silent then - directives.enable("logs.blocked") - end - -end - -if getargument("once") then - multipass_nofruns = 1 -elseif getargument("runs") then - multipass_nofruns = tonumber(getargument("runs")) or nil -end - -if getargument("run") then - scripts.context.timed(scripts.context.autoctx) -elseif getargument("make") then - scripts.context.timed(function() scripts.context.make() end) -elseif getargument("generate") then - scripts.context.timed(function() scripts.context.generate() end) -elseif getargument("ctx") then - scripts.context.timed(scripts.context.ctx) --- elseif getargument("mp") or getargument("metapost") then --- scripts.context.timed(scripts.context.metapost) -elseif getargument("version") then - application.identify() - scripts.context.version() -elseif getargument("touch") then - scripts.context.touch() -elseif getargument("update") then - scripts.context.update() -elseif getargument("expert") then - application.help("expert", "special") -elseif getargument("modules") then - scripts.context.modules() -elseif getargument("extras") then - scripts.context.extras(environment.files[1] or getargument("extras")) -elseif getargument("extra") then - scripts.context.extra() -elseif getargument("exporthelp") then - -- application.export(getargument("exporthelp"),environment.files[1]) - application.export() -elseif getargument("help") then - if environment.files[1] == "extras" then - scripts.context.extras() - else - application.help("basic") - end -elseif getargument("showtrackers") or getargument("trackers") == true then - scripts.context.trackers() -elseif getargument("showdirectives") or getargument("directives") == true then - scripts.context.directives() -elseif getargument("showlogcategories") then - scripts.context.logcategories() -elseif environment.files[1] or getargument("nofile") then - scripts.context.timed(scripts.context.autoctx) -elseif getargument("pipe") then - scripts.context.timed(scripts.context.pipe) -elseif getargument("purge") then - -- only when no filename given, supports --pattern - scripts.context.purge() -elseif getargument("purgeall") then - -- only when no filename given, supports --pattern - scripts.context.purge(true,nil,true) -else - application.help("basic") -end +if not modules then modules = { } end modules ['mtx-context'] = {
+ 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"
+}
+
+-- todo: more local functions
+-- todo: pass jobticket/ctxdata table around
+
+local type, next, tostring, tonumber = type, next, tostring, tonumber
+local format, gmatch, match, gsub, find = string.format, string.gmatch, string.match, string.gsub, string.find
+local quote, validstring = string.quote, string.valid
+local concat = table.concat
+local settings_to_array = utilities.parsers.settings_to_array
+local appendtable = table.append
+local lpegpatterns, lpegmatch, Cs, P = lpeg.patterns, lpeg.match, lpeg.Cs, lpeg.P
+
+local getargument = environment.getargument or environment.argument
+local setargument = environment.setargument
+
+local application = logs.application {
+ name = "mtx-context",
+ banner = "ConTeXt Process Management 0.60",
+ -- helpinfo = helpinfo, -- table with { category_a = text_1, category_b = text_2 } or helpstring or xml_blob
+ helpinfo = "mtx-context.xml",
+}
+
+-- local luatexflags = {
+-- ["8bit"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["default-translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["translate-file"] = true, -- ignored, input is assumed to be in UTF-8 encoding
+-- ["etex"] = true, -- ignored, the etex extensions are always active
+--
+-- ["credits"] = true, -- display credits and exit
+-- ["debug-format"] = true, -- enable format debugging
+-- ["disable-write18"] = true, -- disable \write18{SHELL COMMAND}
+-- ["draftmode"] = true, -- switch on draft mode (generates no output PDF)
+-- ["enable-write18"] = true, -- enable \write18{SHELL COMMAND}
+-- ["file-line-error"] = true, -- enable file:line:error style messages
+-- ["file-line-error-style"] = true, -- aliases of --file-line-error
+-- ["no-file-line-error"] = true, -- disable file:line:error style messages
+-- ["no-file-line-error-style"] = true, -- aliases of --no-file-line-error
+-- ["fmt"] = true, -- load the format file FORMAT
+-- ["halt-on-error"] = true, -- stop processing at the first error
+-- ["help"] = true, -- display help and exit
+-- ["ini"] = true, -- be iniluatex, for dumping formats
+-- ["interaction"] = true, -- set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)
+-- ["jobname"] = true, -- set the job name to STRING
+-- ["kpathsea-debug"] = true, -- set path searching debugging flags according to the bits of NUMBER
+-- ["lua"] = true, -- load and execute a lua initialization script
+-- ["mktex"] = true, -- enable mktexFMT generation (FMT=tex/tfm)
+-- ["no-mktex"] = true, -- disable mktexFMT generation (FMT=tex/tfm)
+-- ["nosocket"] = true, -- disable the lua socket library
+-- ["output-comment"] = true, -- use STRING for DVI file comment instead of date (no effect for PDF)
+-- ["output-directory"] = true, -- use existing DIR as the directory to write files in
+-- ["output-format"] = true, -- use FORMAT for job output; FORMAT is 'dvi' or 'pdf'
+-- ["parse-first-line"] = true, -- enable parsing of the first line of the input file
+-- ["no-parse-first-line"] = true, -- disable parsing of the first line of the input file
+-- ["progname"] = true, -- set the program name to STRING
+-- ["recorder"] = true, -- enable filename recorder
+-- ["safer"] = true, -- disable easily exploitable lua commands
+-- ["shell-escape"] = true, -- enable \write18{SHELL COMMAND}
+-- ["no-shell-escape"] = true, -- disable \write18{SHELL COMMAND}
+-- ["shell-restricted"] = true, -- restrict \write18 to a list of commands given in texmf.cnf
+-- ["synctex"] = true, -- enable synctex
+-- ["version"] = true, -- display version and exit
+-- ["luaonly"] = true, -- run a lua file, then exit
+-- ["luaconly"] = true, -- byte-compile a lua file, then exit
+-- ["jiton"] = false,
+-- }
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.context = scripts.context or { }
+
+-- for the moment here
+
+if getargument("jit") or getargument("jiton") then
+ -- bonus shortcut, we assume than --jit also indicates the engine
+ -- although --jit and --engine=luajittex are independent
+ setargument("engine","luajittex")
+end
+
+local engine_new = getargument("engine") or directives.value("system.engine")
+local engine_old = environment.ownbin
+
+local function restart(engine_old,engine_new)
+ local command = format("%s --luaonly %q %s --redirected",engine_new,environment.ownname,environment.reconstructcommandline())
+ report(format("redirect %s -> %s: %s",engine_old,engine_new,command))
+ local result = os.execute(command)
+ os.exit(result)
+end
+
+if getargument("redirected") then
+ setargument("engine",engine_old) -- later on we need this
+elseif engine_new == engine_old then
+ setargument("engine",engine_new) -- later on we need this
+elseif environment.validengines[engine_new] and engine_new ~= environment.basicengines[engine_old] then
+ restart(engine_old,engine_new)
+else
+ setargument("engine",engine_new) -- later on we need this
+end
+
+-- so far
+
+-- constants
+
+local usedfiles = {
+ nop = "cont-nop.mkiv",
+ yes = "cont-yes.mkiv",
+}
+
+local usedsuffixes = {
+ before = {
+ "tuc"
+ },
+ after = {
+ "pdf", "tuc", "log"
+ },
+ keep = {
+ "log"
+ },
+}
+
+local formatofinterface = {
+ en = "cont-en",
+ uk = "cont-uk",
+ de = "cont-de",
+ fr = "cont-fr",
+ nl = "cont-nl",
+ cs = "cont-cs",
+ it = "cont-it",
+ ro = "cont-ro",
+ pe = "cont-pe",
+}
+
+local defaultformats = {
+ "cont-en",
+ "cont-nl",
+}
+
+-- process information
+
+local ctxrunner = { } -- namespace will go
+
+local ctx_locations = { '..', '../..' }
+
+function ctxrunner.new()
+ return {
+ ctxname = "",
+ jobname = "",
+ flags = { },
+ }
+end
+
+function ctxrunner.checkfile(ctxdata,ctxname,defaultname)
+
+ if not ctxdata.jobname or ctxdata.jobname == "" then
+ return
+ end
+
+ ctxdata.ctxname = ctxname or file.removesuffix(ctxdata.jobname) or ""
+
+ if ctxdata.ctxname == "" then
+ return
+ end
+
+ ctxdata.jobname = file.addsuffix(ctxdata.jobname,'tex')
+ ctxdata.ctxname = file.addsuffix(ctxdata.ctxname,'ctx')
+
+ report("jobname: %s",ctxdata.jobname)
+ report("ctxname: %s",ctxdata.ctxname)
+
+ -- mtxrun should resolve kpse: and file:
+
+ local usedname = ctxdata.ctxname
+ local found = lfs.isfile(usedname)
+
+ -- no further test if qualified path
+
+ if not found then
+ for _, path in next, ctx_locations do
+ local fullname = file.join(path,ctxdata.ctxname)
+ if lfs.isfile(fullname) then
+ usedname = fullname
+ found = true
+ break
+ end
+ end
+ end
+
+ if not found then
+ usedname = resolvers.findfile(ctxdata.ctxname,"tex")
+ found = usedname ~= ""
+ end
+
+ if not found and defaultname and defaultname ~= "" and lfs.isfile(defaultname) then
+ usedname = defaultname
+ found = true
+ end
+
+ if not found then
+ return
+ end
+
+ local xmldata = xml.load(usedname)
+
+ if not xmldata then
+ return
+ else
+ -- test for valid, can be text file
+ end
+
+ local ctxpaths = table.append({'.', file.dirname(ctxdata.ctxname)}, ctx_locations)
+
+ xml.include(xmldata,'ctx:include','name', ctxpaths)
+
+ local flags = ctxdata.flags
+
+ for e in xml.collected(xmldata,"/ctx:job/ctx:flags/ctx:flag") do
+ local flag = xml.text(e) or ""
+ local key, value = match(flag,"^(.-)=(.+)$")
+ if key and value then
+ flags[key] = value
+ else
+ flags[flag] = true
+ end
+ end
+
+end
+
+function ctxrunner.checkflags(ctxdata)
+ if ctxdata then
+ for k,v in next, ctxdata.flags do
+ if getargument(k) == nil then
+ setargument(k,v)
+ end
+ end
+ end
+end
+
+-- multipass control
+
+local multipass_suffixes = { ".tuc" }
+local multipass_nofruns = 8 -- or 7 to test oscillation
+
+local function multipass_hashfiles(jobname)
+ local hash = { }
+ for i=1,#multipass_suffixes do
+ local suffix = multipass_suffixes[i]
+ local full = jobname .. suffix
+ hash[full] = md5.hex(io.loaddata(full) or "unknown")
+ end
+ return hash
+end
+
+local function multipass_changed(oldhash, newhash)
+ for k,v in next, oldhash do
+ if v ~= newhash[k] then
+ return true
+ end
+ end
+ return false
+end
+
+local function multipass_copyluafile(jobname)
+ local tuaname, tucname = jobname..".tua", jobname..".tuc"
+ if lfs.isfile(tuaname) then
+ os.remove(tucname)
+ os.rename(tuaname,tucname)
+ end
+end
+
+--
+
+local pattern = lpegpatterns.utfbom^-1 * (P("%% ") + P("% ")) * Cs((1-lpegpatterns.newline)^1)
+
+local function preamble_analyze(filename) -- only files on current path
+ local t = { }
+ local line = io.loadlines(file.addsuffix(filename,"tex"))
+ if line then
+ local preamble = lpegmatch(pattern,line)
+ if preamble then
+ for key, value in gmatch(preamble,"(%S+)%s*=%s*(%S+)") do
+ t[key] = value
+ end
+ t.type = "tex"
+ elseif find(line,"^<?xml ") then
+ t.type = "xml"
+ end
+ if t.nofruns then
+ multipass_nofruns = t.nofruns
+ end
+ if not t.engine then
+ t.engine = environment.basicengines[engine_old] --'luatex'
+ end
+ if t.engine ~= engine_old then -- hack
+ if environment.validengines[t.engine] and t.engine ~= environment.basicengines[engine_old] then
+ restart(engine_old,t.engine)
+ end
+ end
+ end
+ return t
+end
+
+-- automatically opening and closing pdf files
+
+local pdfview -- delayed
+
+local function pdf_open(name,method)
+ pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
+ pdfview.setmethod(method)
+ report(pdfview.status())
+ pdfview.open(file.replacesuffix(name,"pdf"))
+end
+
+local function pdf_close(name,method)
+ pdfview = pdfview or dofile(resolvers.findfile("l-pdfview.lua","tex"))
+ pdfview.setmethod(method)
+ pdfview.close(file.replacesuffix(name,"pdf"))
+end
+
+-- result file handling
+
+local function result_push_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
+ local oldname = file.addsuffix(oldbase,suffix)
+ local newname = file.addsuffix(newbase,suffix)
+ os.remove(newname)
+ os.remove(oldname)
+ end
+end
+
+local function result_push_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.before do
+ local oldname = file.addsuffix(oldbase,suffix)
+ local newname = file.addsuffix(newbase,suffix)
+ local tmpname = "keep-"..oldname
+ os.remove(tmpname)
+ os.rename(oldname,tmpname)
+ os.remove(oldname)
+ os.rename(newname,oldname)
+ end
+end
+
+local function result_save_error(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.keep do
+ local oldname = file.addsuffix(oldbase,suffix)
+ local newname = file.addsuffix(newbase,suffix)
+ os.remove(newname) -- to be sure
+ os.rename(oldname,newname)
+ end
+end
+
+local function result_save_purge(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
+ local oldname = file.addsuffix(oldbase,suffix)
+ local newname = file.addsuffix(newbase,suffix)
+ os.remove(newname) -- to be sure
+ os.rename(oldname,newname)
+ end
+end
+
+local function result_save_keep(oldbase,newbase)
+ for _, suffix in next, usedsuffixes.after do
+ local oldname = file.addsuffix(oldbase,suffix)
+ local newname = file.addsuffix(newbase,suffix)
+ local tmpname = "keep-"..oldname
+ os.remove(newname)
+ os.rename(oldname,newname)
+ os.rename(tmpname,oldname)
+ end
+end
+
+-- executing luatex
+
+local function flags_to_string(flags,prefix) -- context flags get prepended by c:
+ local t = { }
+ for k, v in table.sortedhash(flags) do
+ if prefix then
+ k = format("c:%s",k)
+ end
+ if not v or v == "" or v == '""' then
+ -- no need to flag false
+ elseif v == true then
+ t[#t+1] = format('--%s',k)
+ elseif type(v) == "string" then
+ t[#t+1] = format('--%s=%s',k,quote(v))
+ else
+ t[#t+1] = format('--%s=%s',k,tostring(v))
+ end
+ end
+ return concat(t," ")
+end
+
+local function luatex_command(l_flags,c_flags,filename,engine)
+ return format('%s %s %s "%s"',
+ engine or "luatex",
+ flags_to_string(l_flags),
+ flags_to_string(c_flags,true),
+ filename
+ )
+end
+
+local plain_formats = {
+ ["plain"] = "plain",
+ ["luatex-plain"] = "luatex-plain",
+}
+
+local function plain_format(plainformat)
+ return plainformat and plain_formats[plainformat]
+end
+
+local function run_plain(plainformat,filename)
+ local plainformat = plain_formats[plainformat]
+ if plainformat then
+ local command = format("mtxrun --script --texformat=%s plain %s",plainformat,filename)
+ report("running command: %s\n\n",command)
+ -- todo: load and run
+ local resultname = file.replacesuffix(filename,"pdf")
+ local pdfview = getargument("autopdf") or getargument("closepdf")
+ if pdfview then
+ pdf_close(resultname,pdfview)
+ os.execute(command)
+ pdf_open(resultname,pdfview)
+ else
+ os.execute(command)
+ end
+ end
+end
+
+local function run_texexec(filename,a_purge,a_purgeall)
+ if false then
+ -- we need to write a top etc too and run mp etc so it's not worth the
+ -- trouble, so it will take a while before the next is finished
+ --
+ -- context --extra=texutil --convert myfile
+ else
+ local texexec = resolvers.findfile("texexec.rb") or ""
+ if texexec ~= "" then
+ os.setenv("RUBYOPT","")
+ local options = environment.reconstructcommandline(environment.arguments_after)
+ options = gsub(options,"--purge","")
+ options = gsub(options,"--purgeall","")
+ local command = format("ruby %s %s",texexec,options)
+ report("running command: %s\n\n",command)
+ if a_purge then
+ os.execute(command)
+ scripts.context.purge_job(filename,false,true)
+ elseif a_purgeall then
+ os.execute(command)
+ scripts.context.purge_job(filename,true,true)
+ else
+ os.execute(command) -- we can use os.exec but that doesn't give back timing
+ end
+ end
+ end
+end
+
+--
+
+function scripts.context.run(ctxdata,filename)
+ --
+ local a_nofile = getargument("nofile")
+ local a_engine = getargument("engine")
+ --
+ local files = environment.files or { }
+ --
+ local filelist, mainfile
+ --
+ if filename then
+ -- the given forced name is processed, the filelist is passed to context
+ mainfile = filename
+ filelist = { filename }
+ -- files = files
+ elseif a_nofile then
+ -- the list of given files is processed using the dummy file
+ mainfile = usedfiles.nop
+ filelist = { usedfiles.nop }
+ -- files = { }
+ elseif #files > 0 then
+ -- the list of given files is processed using the stub file
+ mainfile = usedfiles.yes
+ filelist = files
+ files = { }
+ else
+ return
+ end
+ --
+ local interface = validstring(getargument("interface")) or "en"
+ local formatname = formatofinterface[interface] or "cont-en"
+ local formatfile, scriptfile = resolvers.locateformat(formatname) -- regular engine !
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (commandline driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname) -- variant
+ end
+ if formatfile and scriptfile then
+ -- okay
+ elseif formatname then
+ report("error, no format found with name: %s, aborting",formatname)
+ return
+ else
+ report("error, no format found (provide formatname or interface)")
+ return
+ end
+ --
+ local a_mkii = getargument("mkii") or getargument("pdftex") or getargument("xetex")
+ local a_purge = getargument("purge")
+ local a_purgeall = getargument("purgeall")
+ local a_purgeresult = getargument("purgeresult")
+ local a_global = getargument("global")
+ local a_timing = getargument("timing")
+ local a_profile = getargument("profile")
+ local a_batchmode = getargument("batchmode")
+ local a_nonstopmode = getargument("nonstopmode")
+ local a_once = getargument("once")
+ local a_synctex = getargument("synctex")
+ local a_backend = getargument("backend")
+ local a_arrange = getargument("arrange")
+ local a_noarrange = getargument("noarrange")
+ local a_jiton = getargument("jiton")
+ local a_texformat = getargument("texformat")
+ --
+ a_batchmode = (a_batchmode and "batchmode") or (a_nonstopmode and "nonstopmode") or nil
+ a_synctex = tonumber(a_synctex) or (toboolean(a_synctex,true) and 1) or (a_synctex == "zipped" and 1) or (a_synctex == "unzipped" and -1) or nil
+ --
+ for i=1,#filelist do
+ --
+ local filename = filelist[i]
+ local basename = file.basename(filename) -- use splitter
+ local pathname = file.dirname(filename)
+ --
+ if pathname == "" and not a_global and filename ~= usedfiles.nop then
+ filename = "./" .. filename
+ if not lfs.isfile(filename) then
+ report("warning: no (local) file %a, proceeding",filename)
+ end
+ end
+ --
+ local jobname = file.removesuffix(basename)
+ -- local jobname = file.removesuffix(filename)
+ local ctxname = ctxdata and ctxdata.ctxname
+ --
+ local analysis = preamble_analyze(filename)
+ --
+ if a_mkii or analysis.engine == 'pdftex' or analysis.engine == 'xetex' then
+ run_texexec(filename,a_purge,a_purgeall)
+ elseif plain_format(a_texformat or analysis.texformat) then
+ run_plain(a_texformat or analysis.texformat,filename)
+ else
+ if analysis.interface and analysis.interface ~= interface then
+ formatname = formatofinterface[analysis.interface] or formatname
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ --
+ a_jiton = (a_jiton or toboolean(analysis.jiton,true)) and true or nil
+ --
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (source driven)")
+ scripts.context.make(formatname,a_engine)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if formatfile and scriptfile then
+ local suffix = validstring(getargument("suffix"))
+ local resultname = validstring(getargument("result"))
+ if suffix then
+ resultname = file.removesuffix(jobname) .. suffix
+ end
+ local oldbase = ""
+ local newbase = ""
+ if resultname then
+ oldbase = file.removesuffix(jobname)
+ newbase = file.removesuffix(resultname)
+ if oldbase ~= newbase then
+ if a_purgeresult then
+ result_push_purge(oldbase,newbase)
+ else
+ result_push_keep(oldbase,newbase)
+ end
+ else
+ resultname = nil
+ end
+ end
+ --
+ local pdfview = getargument("autopdf") or getargument("closepdf")
+ if pdfview then
+ pdf_close(filename,pdfview)
+ if resultname then
+ pdf_close(resultname,pdfview)
+ end
+ end
+ --
+ -- we could do this when locating the format and exit from luatex when
+ -- there is a version mismatch .. that way we can use stock luatex
+ -- plus mtxrun to run luajittex instead .. this saves a restart but is
+ -- also cleaner as then mtxrun only has to check for a special return
+ -- code (signaling a make + rerun) .. maybe some day
+ --
+ local okay = statistics.checkfmtstatus(formatfile,a_engine)
+ if okay ~= true then
+ report("warning: %s, forcing remake",tostring(okay))
+ scripts.context.make(formatname)
+ end
+ --
+ local oldhash = multipass_hashfiles(jobname)
+ local newhash = { }
+ local maxnofruns = once and 1 or multipass_nofruns
+ --
+ local c_flags = {
+ directives = validstring(environment.directives), -- gets passed via mtxrun
+ trackers = validstring(environment.trackers), -- gets passed via mtxrun
+ experiments = validstring(environment.experiments), -- gets passed via mtxrun
+ --
+ result = validstring(resultname),
+ input = validstring(getargument("input") or filename), -- alternative input
+ fulljobname = validstring(filename),
+ files = concat(files,","),
+ ctx = validstring(ctxname),
+ }
+ --
+ for k, v in next, environment.arguments do
+ -- the raw arguments
+ if c_flags[k] == nil then
+ c_flags[k] = v
+ end
+ end
+ --
+ --
+ local l_flags = {
+ ["interaction"] = a_batchmode,
+ ["synctex"] = a_synctex,
+ ["no-parse-first-line"] = true,
+ -- ["no-mktex"] = true,
+ -- ["file-line-error-style"] = true,
+ ["fmt"] = formatfile,
+ ["lua"] = scriptfile,
+ ["jobname"] = jobname,
+ ["jiton"] = a_jiton,
+ }
+ --
+ if a_synctex then
+ report("warning: synctex is enabled") -- can add upto 5% runtime
+ end
+ --
+ if not a_timing then
+ -- okay
+ elseif c_flags.usemodule then
+ c_flags.usemodule = format("timing,%s",c_flags.usemodule)
+ else
+ c_flags.usemodule = "timing"
+ end
+ --
+ if not a_profile then
+ -- okay
+ elseif c_flags.directives then
+ c_flags.directives = format("system.profile,%s",c_flags.directives)
+ else
+ c_flags.directives = "system.profile"
+ end
+ --
+ -- kindofrun: 1:first run, 2:successive run, 3:once, 4:last of maxruns
+ --
+ for currentrun=1,maxnofruns do
+ --
+ c_flags.final = false
+ c_flags.kindofrun = (a_once and 3) or (currentrun==1 and 1) or (currentrun==maxnofruns and 4) or 2
+ c_flags.maxnofruns = maxnofruns
+ c_flags.currentrun = currentrun
+ c_flags.noarrange = a_noarrange or a_arrange or nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
+ --
+ report("run %s: %s",i,command)
+ print("") -- cleaner, else continuation on same line
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ if resultname then
+ result_save_error(oldbase,newbase)
+ end
+ os.exit(1)
+ break
+ elseif returncode == 0 then
+ multipass_copyluafile(jobname)
+ newhash = multipass_hashfiles(jobname)
+ if multipass_changed(oldhash,newhash) then
+ oldhash = newhash
+ else
+ break
+ end
+ else
+ report("fatal error: return code: %s",returncode or "?")
+ if resultname then
+ result_save_error(oldbase,newbase)
+ end
+ os.exit(1) -- (returncode)
+ break
+ end
+ --
+ end
+ --
+ if a_arrange then
+ --
+ c_flags.final = true
+ c_flags.kindofrun = 3
+ c_flags.currentrun = c_flags.currentrun + 1
+ c_flags.noarrange = nil
+ --
+ local command = luatex_command(l_flags,c_flags,mainfile,a_engine)
+ --
+ report("arrange run: %s",command)
+ local returncode, errorstring = os.spawn(command)
+ if not returncode then
+ report("fatal error: no return code, message: %s",errorstring or "?")
+ os.exit(1)
+ elseif returncode > 0 then
+ report("fatal error: return code: %s",returncode or "?")
+ os.exit(returncode)
+ end
+ --
+ end
+ --
+ if a_purge then
+ scripts.context.purge_job(jobname)
+ elseif a_purgeall then
+ scripts.context.purge_job(jobname,true)
+ end
+ --
+ if resultname then
+ if a_purgeresult then
+ -- so, if there is no result then we don't get the old one, but
+ -- related files (log etc) are still there for tracing purposes
+ result_save_purge(oldbase,newbase)
+ else
+ result_save_keep(oldbase,newbase)
+ end
+ report("result renamed to: %s",newbase)
+ end
+ --
+ if purge then
+ scripts.context.purge_job(resultname)
+ elseif purgeall then
+ scripts.context.purge_job(resultname,true)
+ end
+ --
+ local pdfview = getargument("autopdf")
+ if pdfview then
+ pdf_open(resultname or jobname,pdfview)
+ end
+ --
+ if a_timing then
+ report()
+ report("you can process (timing) statistics with:",jobname)
+ report()
+ report("context --extra=timing '%s'",jobname)
+ report("mtxrun --script timing --xhtml [--launch --remove] '%s'",jobname)
+ report()
+ end
+ else
+ if formatname then
+ report("error, no format found with name: %s, skipping",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ break
+ end
+ end
+ end
+ --
+end
+
+function scripts.context.pipe() -- still used?
+ -- context --pipe
+ -- context --pipe --purge --dummyfile=whatever.tmp
+ local interface = getargument("interface")
+ interface = (type(interface) == "string" and interface) or "en"
+ local formatname = formatofinterface[interface] or "cont-en"
+ local formatfile, scriptfile = resolvers.locateformat(formatname)
+ if not formatfile or not scriptfile then
+ report("warning: no format found, forcing remake (commandline driven)")
+ scripts.context.make(formatname)
+ formatfile, scriptfile = resolvers.locateformat(formatname)
+ end
+ if formatfile and scriptfile then
+ local okay = statistics.checkfmtstatus(formatfile)
+ if okay ~= true then
+ report("warning: %s, forcing remake",tostring(okay))
+ scripts.context.make(formatname)
+ end
+ local l_flags = {
+ interaction = "scrollmode",
+ fmt = formatfile,
+ lua = scriptfile,
+ }
+ local c_flags = {
+ backend = "pdf",
+ final = false,
+ kindofrun = 3,
+ currentrun = 1,
+ }
+ local filename = getargument("dummyfile") or ""
+ if filename == "" then
+ filename = "\\relax"
+ report("entering scrollmode, end job with \\end")
+ else
+ filename = file.addsuffix(filename,"tmp")
+ io.savedata(filename,"\\relax")
+ report("entering scrollmode using '%s' with optionfile, end job with \\end",filename)
+ end
+ local command = luatex_command(l_flags,c_flags,filename)
+ os.spawn(command)
+ if getargument("purge") then
+ scripts.context.purge_job(filename)
+ elseif getargument("purgeall") then
+ scripts.context.purge_job(filename,true)
+ os.remove(filename)
+ end
+ else
+ if formatname then
+ report("error, no format found with name: %s, aborting",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ end
+end
+
+local function make_mkiv_format(name,engine)
+ environment.make_format(name) -- jit is picked up later
+end
+
+local function make_mkii_format(name,engine)
+ local command = format("mtxrun texexec.rb --make --%s %s",name,engine)
+ report("running command: %s",command)
+ os.spawn(command)
+end
+
+function scripts.context.generate()
+ resolvers.instance.renewcache = true
+ trackers.enable("resolvers.locating")
+ resolvers.load()
+end
+
+function scripts.context.make(name)
+ if not getargument("fast") then -- as in texexec
+ scripts.context.generate()
+ end
+ local list = (name and { name }) or (environment.files[1] and environment.files) or defaultformats
+ local engine = getargument("engine") or "luatex"
+ if getargument("jit") or getargument("jiton") then
+ engine = "luajittex"
+ end
+ for i=1,#list do
+ local name = list[i]
+ name = formatofinterface[name] or name or ""
+ if name == "" then
+ -- nothing
+ elseif engine == "luatex" or engine == "luajittex" then
+ make_mkiv_format(name,engine)
+ elseif engine == "pdftex" or engine == "xetex" then
+ make_mkii_format(name,engine)
+ end
+ end
+end
+
+function scripts.context.ctx()
+ local ctxdata = ctxrunner.new()
+ ctxdata.jobname = environment.files[1]
+ ctxrunner.checkfile(ctxdata,getargument("ctx"))
+ ctxrunner.checkflags(ctxdata)
+ scripts.context.run(ctxdata)
+end
+
+function scripts.context.autoctx()
+ local ctxdata = nil
+ local files = environment.files
+ local firstfile = #files > 0 and files[1]
+ if firstfile then
+ local suffix = file.suffix(firstfile)
+ if suffix == "xml" then
+ local chunk = io.loadchunk(firstfile) -- 1024
+ if chunk then
+ local ctxname = match(chunk,"<%?context%-directive%s+job%s+ctxfile%s+([^ ]-)%s*?>")
+ if ctxname then
+ ctxdata = ctxrunner.new()
+ ctxdata.jobname = firstfile
+ ctxrunner.checkfile(ctxdata,ctxname)
+ ctxrunner.checkflags(ctxdata)
+ end
+ end
+ elseif suffix == "tex" then
+ -- maybe but we scan the preamble later too
+ end
+ end
+ scripts.context.run(ctxdata)
+end
+
+-- no longer ok as mlib-run misses something:
+
+-- local template = [[
+-- \starttext
+-- \directMPgraphic{%s}{input "%s"}
+-- \stoptext
+-- ]]
+--
+-- local loaded = false
+--
+-- function scripts.context.metapost()
+-- local filename = environment.files[1] or ""
+-- if not loaded then
+-- dofile(resolvers.findfile("mlib-run.lua"))
+-- loaded = true
+-- commands = commands or { }
+-- commands.writestatus = report -- no longer needed
+-- end
+-- local formatname = getargument("format") or "metafun"
+-- if formatname == "" or type(formatname) == "boolean" then
+-- formatname = "metafun"
+-- end
+-- if getargument("pdf") then
+-- local basename = file.removesuffix(filename)
+-- local resultname = getargument("result") or basename
+-- local jobname = "mtx-context-metapost"
+-- local tempname = file.addsuffix(jobname,"tex")
+-- io.savedata(tempname,format(template,"metafun",filename))
+-- environment.files[1] = tempname
+-- setargument("result",resultname)
+-- setargument("once",true)
+-- scripts.context.run()
+-- scripts.context.purge_job(jobname,true)
+-- scripts.context.purge_job(resultname,true)
+-- elseif getargument("svg") then
+-- metapost.directrun(formatname,filename,"svg")
+-- else
+-- metapost.directrun(formatname,filename,"mps")
+-- end
+-- end
+
+-- --
+
+function scripts.context.version()
+ local name = resolvers.findfile("context.mkiv")
+ if name ~= "" then
+ report("main context file: %s",name)
+ local data = io.loaddata(name)
+ if data then
+ local version = match(data,"\\edef\\contextversion{(.-)}")
+ if version then
+ report("current version: %s",version)
+ else
+ report("context version: unknown, no timestamp found")
+ end
+ else
+ report("context version: unknown, load error")
+ end
+ else
+ report("main context file: unknown, 'context.mkiv' not found")
+ end
+end
+
+-- purging files
+
+local generic_files = {
+ "texexec.tex", "texexec.tui", "texexec.tuo",
+ "texexec.tuc", "texexec.tua",
+ "texexec.ps", "texexec.pdf", "texexec.dvi",
+ "cont-opt.tex", "cont-opt.bak"
+}
+
+local obsolete_results = {
+ "dvi",
+}
+
+local temporary_runfiles = {
+ "tui", "tua", "tup", "ted", "tes", "top",
+ "log", "tmp", "run", "bck", "rlg",
+ "mpt", "mpx", "mpd", "mpo", "mpb", "ctl",
+ "synctex", "synctex.gz", "pgf",
+ "prep",
+}
+
+local persistent_runfiles = {
+ "tuo", "tub", "top", "tuc"
+}
+
+local special_runfiles = {
+ "-mpgraph", "-mprun", "-temp-"
+}
+
+local function purge_file(dfile,cfile)
+ if cfile and lfs.isfile(cfile) then
+ if os.remove(dfile) then
+ return file.basename(dfile)
+ end
+ elseif dfile then
+ if os.remove(dfile) then
+ return file.basename(dfile)
+ end
+ end
+end
+
+function scripts.context.purge_job(jobname,all,mkiitoo)
+ if jobname and jobname ~= "" then
+ jobname = file.basename(jobname)
+ local filebase = file.removesuffix(jobname)
+ if mkiitoo then
+ scripts.context.purge(all,filebase,true) -- leading "./"
+ else
+ local deleted = { }
+ for i=1,#obsolete_results do
+ deleted[#deleted+1] = purge_file(filebase.."."..obsolete_results[i],filebase..".pdf")
+ end
+ for i=1,#temporary_runfiles do
+ deleted[#deleted+1] = purge_file(filebase.."."..temporary_runfiles[i])
+ end
+ if all then
+ for i=1,#persistent_runfiles do
+ deleted[#deleted+1] = purge_file(filebase.."."..persistent_runfiles[i])
+ end
+ end
+ if #deleted > 0 then
+ report("purged files: %s", concat(deleted,", "))
+ end
+ end
+ end
+end
+
+function scripts.context.purge(all,pattern,mkiitoo)
+ local all = all or getargument("all")
+ local pattern = getargument("pattern") or (pattern and (pattern.."*")) or "*.*"
+ local files = dir.glob(pattern)
+ local obsolete = table.tohash(obsolete_results)
+ local temporary = table.tohash(temporary_runfiles)
+ local persistent = table.tohash(persistent_runfiles)
+ local generic = table.tohash(generic_files)
+ local deleted = { }
+ for i=1,#files do
+ local name = files[i]
+ local suffix = file.suffix(name)
+ local basename = file.basename(name)
+ if obsolete[suffix] or temporary[suffix] or persistent[suffix] or generic[basename] then
+ deleted[#deleted+1] = purge_file(name)
+ elseif mkiitoo then
+ for i=1,#special_runfiles do
+ if find(name,special_runfiles[i]) then
+ deleted[#deleted+1] = purge_file(name)
+ end
+ end
+ end
+ end
+ if #deleted > 0 then
+ report("purged files: %s", concat(deleted,", "))
+ end
+end
+
+-- touching files (signals regeneration of formats)
+
+local function touch(path,name,versionpattern,kind,kindpattern)
+ if path and path ~= "" then
+ name = file.join(path,name)
+print(name)
+ else
+ name = resolvers.findfile(name)
+ end
+ local olddata = io.loaddata(name)
+ if olddata then
+ local oldkind, newkind = "", kind or ""
+ local oldversion, newversion = "", os.date("%Y.%m.%d %H:%M")
+ local newdata
+ if versionpattern then
+ newdata = gsub(olddata,versionpattern,function(pre,mid,post)
+ oldversion = mid
+ return pre .. newversion .. post
+ end) or olddata
+ end
+ if kind and kindpattern then
+ newdata = gsub(newdata,kindpattern,function(pre,mid,post)
+ oldkind = mid
+ return pre .. newkind .. post
+ end) or newdata
+ end
+ if newdata ~= "" and (oldversion ~= newversion or oldkind ~= newkind or newdata ~= olddata) then
+ local backup = file.replacesuffix(name,"tmp")
+ os.remove(backup)
+ os.rename(name,backup)
+ io.savedata(name,newdata)
+ return name, oldversion, newversion, oldkind, newkind
+ end
+ end
+end
+
+local p_contextkind = "(\\edef\\contextkind%s*{)(.-)(})"
+local p_contextversion = "(\\edef\\contextversion%s*{)(.-)(})"
+local p_newcontextversion = "(\\newcontextversion%s*{)(.-)(})"
+
+local function touchfiles(suffix,kind,path)
+ local foundname, oldversion, newversion, oldkind, newkind = touch(path,file.addsuffix("context",suffix),p_contextversion,kind,p_contextkind)
+ if foundname then
+ report("old version : %s (%s)",oldversion,oldkind)
+ report("new version : %s (%s)",newversion,newkind)
+ report("touched file : %s",foundname)
+ local foundname = touch(path,file.addsuffix("cont-new",suffix),p_newcontextversion)
+ if foundname then
+ report("touched file : %s", foundname)
+ end
+ else
+ report("nothing touched")
+ end
+end
+
+function scripts.context.touch()
+ if getargument("expert") then
+ local touch = getargument("touch")
+ local kind = getargument("kind")
+ local path = getargument("basepath")
+ if touch == "mkii" or touch == "mkiv" or touch == "mkvi" then -- mkix mkxi
+ touchfiles(touch,kind,path)
+ else
+ touchfiles("mkii",kind,path)
+ touchfiles("mkiv",kind,path)
+ touchfiles("mkvi",kind,path)
+ end
+ else
+ report("touching needs --expert")
+ end
+end
+
+-- modules
+
+local labels = { "title", "comment", "status" }
+local cards = { "*.mkvi", "*.mkiv", "*.mkxi", "*.mkix", "*.tex" }
+
+function scripts.context.modules(pattern)
+ local list = { }
+ local found = resolvers.findfile("context.mkiv")
+ if not pattern or pattern == "" then
+ -- official files in the tree
+ for i=1,#cards do
+ resolvers.findwildcardfiles(cards[i],list)
+ end
+ -- my dev path
+ for i=1,#cards do
+ dir.glob(file.join(file.dirname(found),cards[i]),list)
+ end
+ else
+ resolvers.findwildcardfiles(pattern,list)
+ dir.glob(file.join(file.dirname(found,pattern)),list)
+ end
+ local done = { } -- todo : sort
+ for i=1,#list do
+ local v = list[i]
+ local base = file.basename(v)
+ if not done[base] then
+ done[base] = true
+ local suffix = file.suffix(base)
+ if suffix == "tex" or suffix == "mkiv" or suffix == "mkvi" or suffix == "mkix" or suffix == "mkxi" then
+ local prefix = match(base,"^([xmst])%-")
+ if prefix then
+ v = resolvers.findfile(base) -- so that files on my dev path are seen
+ local data = io.loaddata(v) or ""
+ data = match(data,"%% begin info(.-)%% end info")
+ if data then
+ local info = { }
+ for label, text in gmatch(data,"%% +([^ ]+) *: *(.-)[\n\r]") do
+ info[label] = text
+ end
+ report()
+ report("%-7s : %s","module",base)
+ report()
+ for i=1,#labels do
+ local l = labels[i]
+ if info[l] then
+ report("%-7s : %s",l,info[l])
+ end
+ end
+ report()
+ end
+ end
+ end
+ end
+ end
+end
+
+-- extras
+
+function scripts.context.extras(pattern)
+ -- only in base path, i.e. only official ones
+ if type(pattern) ~= "string" then
+ pattern = "*"
+ end
+ local found = resolvers.findfile("context.mkiv")
+ if found ~= "" then
+ pattern = file.join(dir.expandname(file.dirname(found)),format("mtx-context-%s.tex",pattern or "*"))
+ local list = dir.glob(pattern)
+ for i=1,#list do
+ local v = list[i]
+ local data = io.loaddata(v) or ""
+ data = match(data,"%% begin help(.-)%% end help")
+ if data then
+ report()
+ report("extra: %s (%s)",(gsub(v,"^.*mtx%-context%-(.-)%.tex$","%1")),v)
+ for s in gmatch(data,"%% *(.-)[\n\r]") do
+ report(s)
+ end
+ report()
+ end
+ end
+ end
+end
+
+function scripts.context.extra()
+ local extra = getargument("extra")
+ if type(extra) ~= "string" then
+ scripts.context.extras()
+ elseif getargument("help") then
+ scripts.context.extras(extra)
+ else
+ local fullextra = extra
+ if not find(fullextra,"mtx%-context%-") then
+ fullextra = "mtx-context-" .. extra
+ end
+ local foundextra = resolvers.findfile(fullextra)
+ if foundextra == "" then
+ scripts.context.extras()
+ return
+ else
+ report("processing extra: %s", foundextra)
+ end
+ setargument("purgeall",true)
+ local result = getargument("result") or ""
+ if result == "" then
+ setargument("result","context-extra")
+ end
+ scripts.context.run(nil,foundextra)
+ end
+end
+
+-- todo: we need to do a dummy run
+
+function scripts.context.trackers()
+ environment.files = { resolvers.findfile("m-trackers.mkiv") }
+ 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
+
+function scripts.context.logcategories()
+ environment.files = { resolvers.findfile("m-logcategories.mkiv") }
+ multipass_nofruns = 1
+ setargument("purgeall",true)
+ scripts.context.run()
+end
+
+-- updating (often one will use mtx-update instead)
+
+function scripts.context.timed(action)
+ statistics.timed(action)
+end
+
+local zipname = "cont-tmf.zip"
+local mainzip = "http://www.pragma-ade.com/context/latest/" .. zipname
+local validtrees = { "texmf-local", "texmf-context" }
+local selfscripts = { "mtxrun.lua" } -- was: { "luatools.lua", "mtxrun.lua" }
+
+function zip.loaddata(zipfile,filename) -- should be in zip lib
+ local f = zipfile:open(filename)
+ if f then
+ local data = f:read("*a")
+ f:close()
+ return data
+ end
+ return nil
+end
+
+function scripts.context.update()
+ local force = getargument("force")
+ local socket = require("socket")
+ local http = require("socket.http")
+ local basepath = resolvers.findfile("context.mkiv") or ""
+ if basepath == "" then
+ report("quiting, no 'context.mkiv' found")
+ return
+ end
+ local basetree = basepath.match(basepath,"^(.-)tex/context/base/context.mkiv$") or ""
+ if basetree == "" then
+ report("quiting, no proper tds structure (%s)",basepath)
+ return
+ end
+ local function is_okay(basetree)
+ for _, tree in next, validtrees do
+ local pattern = gsub(tree,"%-","%%-")
+ if find(basetree,pattern) then
+ return tree
+ end
+ end
+ return false
+ end
+ local okay = is_okay(basetree)
+ if not okay then
+ report("quiting, tree '%s' is protected",okay)
+ return
+ else
+ report("updating tree '%s'",okay)
+ end
+ if not lfs.chdir(basetree) then
+ report("quiting, unable to change to '%s'",okay)
+ return
+ end
+ report("fetching '%s'",mainzip)
+ local latest = http.request(mainzip)
+ if not latest then
+ report("context tree '%s' can be updated, use --force",okay)
+ return
+ end
+ io.savedata("cont-tmf.zip",latest)
+ if false then
+ -- variant 1
+ os.execute("mtxrun --script unzip cont-tmf.zip")
+ else
+ -- variant 2
+ local zipfile = zip.open(zipname)
+ if not zipfile then
+ report("quiting, unable to open '%s'",zipname)
+ return
+ end
+ local newfile = zip.loaddata(zipfile,"tex/context/base/context.mkiv")
+ if not newfile then
+ report("quiting, unable to open '%s'","context.mkiv")
+ return
+ end
+ local oldfile = io.loaddata(resolvers.findfile("context.mkiv")) or ""
+ local function versiontonumber(what,str)
+ local version = match(str,"\\edef\\contextversion{(.-)}") or ""
+ local year, month, day, hour, minute = match(str,"\\edef\\contextversion{(%d+)%.(%d+)%.(%d+) *(%d+)%:(%d+)}")
+ if year and minute then
+ local time = os.time { year=year,month=month,day=day,hour=hour,minute=minute}
+ report("%s version: %s (%s)",what,version,time)
+ return time
+ else
+ report("%s version: %s (unknown)",what,version)
+ return nil
+ end
+ end
+ local oldversion = versiontonumber("old",oldfile)
+ local newversion = versiontonumber("new",newfile)
+ if not oldversion or not newversion then
+ report("quiting, version cannot be determined")
+ return
+ elseif oldversion == newversion then
+ report("quiting, your current version is up-to-date")
+ return
+ elseif oldversion > newversion then
+ report("quiting, your current version is newer")
+ return
+ end
+ for k in zipfile:files() do
+ local filename = k.filename
+ if find(filename,"/$") then
+ lfs.mkdir(filename)
+ else
+ local data = zip.loaddata(zipfile,filename)
+ if data then
+ if force then
+ io.savedata(filename,data)
+ end
+ report(filename)
+ end
+ end
+ end
+ for _, scriptname in next, selfscripts do
+ local oldscript = resolvers.findfile(scriptname) or ""
+ if oldscript ~= "" and is_okay(oldscript) then
+ local newscript = "./scripts/context/lua/" .. scriptname
+ local data = io.loaddata(newscript) or ""
+ if data ~= "" then
+ report("replacing script '%s' by '%s'",oldscript,newscript)
+ if force then
+ io.savedata(oldscript,data)
+ end
+ end
+ else
+ report("keeping script '%s'",oldscript)
+ end
+ end
+ if force then
+ scripts.context.make()
+ end
+ end
+ if force then
+ report("context tree '%s' has been updated",okay)
+ else
+ report("context tree '%s' can been updated (use --force)",okay)
+ end
+end
+
+-- getting it done
+
+if getargument("nostats") then
+ setargument("nostatistics",true)
+ setargument("nostat",nil)
+end
+
+if getargument("batch") then
+ setargument("batchmode",true)
+ setargument("batch",nil)
+end
+
+if getargument("nonstop") then
+ setargument("nonstopmode",true)
+ setargument("nonstop",nil)
+end
+
+do
+
+ local silent = getargument("silent")
+ if type(silent) == "string" then
+ directives.enable(format("logs.blocked={%s}",silent))
+ elseif silent then
+ directives.enable("logs.blocked")
+ end
+
+end
+
+if getargument("once") then
+ multipass_nofruns = 1
+elseif getargument("runs") then
+ multipass_nofruns = tonumber(getargument("runs")) or nil
+end
+
+if getargument("run") then
+ scripts.context.timed(scripts.context.autoctx)
+elseif getargument("make") then
+ scripts.context.timed(function() scripts.context.make() end)
+elseif getargument("generate") then
+ scripts.context.timed(function() scripts.context.generate() end)
+elseif getargument("ctx") then
+ scripts.context.timed(scripts.context.ctx)
+-- elseif getargument("mp") or getargument("metapost") then
+-- scripts.context.timed(scripts.context.metapost)
+elseif getargument("version") then
+ application.identify()
+ scripts.context.version()
+elseif getargument("touch") then
+ scripts.context.touch()
+elseif getargument("update") then
+ scripts.context.update()
+elseif getargument("expert") then
+ application.help("expert", "special")
+elseif getargument("modules") then
+ scripts.context.modules()
+elseif getargument("extras") then
+ scripts.context.extras(environment.files[1] or getargument("extras"))
+elseif getargument("extra") then
+ scripts.context.extra()
+elseif getargument("exporthelp") then
+ -- application.export(getargument("exporthelp"),environment.files[1])
+ application.export()
+elseif getargument("help") then
+ if environment.files[1] == "extras" then
+ scripts.context.extras()
+ else
+ application.help("basic")
+ end
+elseif getargument("showtrackers") or getargument("trackers") == true then
+ scripts.context.trackers()
+elseif getargument("showdirectives") or getargument("directives") == true then
+ scripts.context.directives()
+elseif getargument("showlogcategories") then
+ scripts.context.logcategories()
+elseif environment.files[1] or getargument("nofile") then
+ scripts.context.timed(scripts.context.autoctx)
+elseif getargument("pipe") then
+ scripts.context.timed(scripts.context.pipe)
+elseif getargument("purge") then
+ -- only when no filename given, supports --pattern
+ scripts.context.purge()
+elseif getargument("purgeall") then
+ -- only when no filename given, supports --pattern
+ scripts.context.purge(true,nil,true)
+else
+ application.help("basic")
+end
diff --git a/scripts/context/lua/mtx-convert.lua b/scripts/context/lua/mtx-convert.lua index b76b3baaf..e6de9356e 100644 --- a/scripts/context/lua/mtx-convert.lua +++ b/scripts/context/lua/mtx-convert.lua @@ -1,175 +1,175 @@ -if not modules then modules = { } end modules ['mtx-convert'] = { - 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" -} - --- todo: eps and svg - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-convert</entry> - <entry name="detail">ConTeXT Graphic Conversion Helpers</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="convertall"><short>convert all graphics on path</short></flag> - <flag name="inputpath" value="string"><short>original graphics path</short></flag> - <flag name="outputpath" value="string"><short>converted graphics path</short></flag> - <flag name="watch"><short>watch folders</short></flag> - <flag name="force"><short>force conversion (even if older)</short></flag> - <flag name="delay"><short>time between sweeps</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-convert", - banner = "ConTeXT Graphic Conversion Helpers 0.10", - helpinfo = helpinfo, -} - -local format, find = string.format, string.find -local concat = table.concat - -local report = application.report - -scripts = scripts or { } -scripts.convert = scripts.convert or { } -local convert = scripts.convert -convert.converters = convert.converters or { } -local converters = convert.converters - -local gsprogram = os.type == "windows" and "gswin32c" or "gs" -local gstemplate_eps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dEPSCrop -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit" -local gstemplate_ps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit" - -function converters.eps(oldname,newname) - return format(gstemplate_eps,gsprogram,newname,oldname) -end - -function converters.ps(oldname,newname) - return format(gstemplate_ps,gsprogram,newname,oldname) -end - -local improgram = "convert" -local imtemplate = { - low = "%s -quality 0 -compress zip %s pdf:%s", - medium = "%s -quality 75 -compress zip %s pdf:%s", - high = "%s -quality 100 -compress zip %s pdf:%s", -} - -function converters.jpg(oldname,newname) - local ea = environment.arguments - local quality = (ea.high and 'high') or (ea.medium and 'medium') or (ea.low and 'low') or 'high' - return format(imtemplate[quality],improgram,oldname,newname) -end - -converters.gif = converters.jpg -converters.tif = converters.jpg -converters.tiff = converters.jpg -converters.png = converters.jpg - -function converters.convertgraphic(kind,oldname,newname) - if converters[kind] then -- extra test - local tmpname = file.replacesuffix(newname,"tmp") - local command = converters[kind](oldname,tmpname) - report("command: %s",command) - io.flush() - os.spawn(command) - os.remove(newname) - os.rename(tmpname,newname) - if lfs.attributes(newname,"size") == 0 then - os.remove(newname) - end - end -end - -function converters.convertpath(inputpath,outputpath) - inputpath = inputpath or "." - outputpath = outputpath or "." - for name in lfs.dir(inputpath) do - local suffix = file.suffix(name) - if find(name,"%.$") then - -- skip . and .. - elseif converters[suffix] then - local oldname = file.join(inputpath,name) - local newname = file.join(outputpath,file.replacesuffix(name,"pdf")) - local et = lfs.attributes(oldname,"modification") - local pt = lfs.attributes(newname,"modification") - if not pt or et > pt then - dir.mkdirs(outputpath) - converters.convertgraphic(suffix,oldname,newname) - end - elseif lfs.isdir(inputpath .. "/".. name) then - converters.convertpath(inputpath .. "/".. name,outputpath .. "/".. name) - end - end -end - -function converters.convertfile(oldname) - local suffix = file.suffix(oldname) - if converters[suffix] then - local newname = file.replacesuffix(oldname,"pdf") - if oldname == newname then - -- todo: downsample, crop etc - elseif environment.argument("force") then - converters.convertgraphic(suffix,oldname,newname) - else - local et = lfs.attributes(oldname,"modification") - local pt = lfs.attributes(newname,"modification") - if not pt or et > pt then - converters.convertgraphic(suffix,oldname,newname) - end - end - end -end - -if environment.ownscript then - -- stand alone -else - report(application.banner) - return convert -end - -convert.delay = 5 * 60 -- 5 minutes - -function convert.convertall() - local watch = environment.arguments.watch or false - local delay = environment.arguments.delay or convert.delay - local input = environment.arguments.inputpath or "." - local output = environment.arguments.outputpath or "." - while true do - converters.convertpath(input, output) - if watch then - os.sleep(delay) - else - break - end - end -end - -function convert.convertgiven() - local files = environment.files - for i=1,#files do - converters.convertfile(files[i]) - end -end - -if environment.arguments.convertall then - convert.convertall() -elseif environment.files[1] then - convert.convertgiven() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-convert'] = {
+ 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"
+}
+
+-- todo: eps and svg
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-convert</entry>
+ <entry name="detail">ConTeXT Graphic Conversion Helpers</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="convertall"><short>convert all graphics on path</short></flag>
+ <flag name="inputpath" value="string"><short>original graphics path</short></flag>
+ <flag name="outputpath" value="string"><short>converted graphics path</short></flag>
+ <flag name="watch"><short>watch folders</short></flag>
+ <flag name="force"><short>force conversion (even if older)</short></flag>
+ <flag name="delay"><short>time between sweeps</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-convert",
+ banner = "ConTeXT Graphic Conversion Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+local format, find = string.format, string.find
+local concat = table.concat
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.convert = scripts.convert or { }
+local convert = scripts.convert
+convert.converters = convert.converters or { }
+local converters = convert.converters
+
+local gsprogram = os.type == "windows" and "gswin32c" or "gs"
+local gstemplate_eps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dEPSCrop -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
+local gstemplate_ps = "%s -q -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -dNOPAUSE -dSAFER -dNOCACHE -dBATCH -dAutoRotatePages=/None -dProcessColorModel=/DeviceCMYK -sOutputFile=%s %s -c quit"
+
+function converters.eps(oldname,newname)
+ return format(gstemplate_eps,gsprogram,newname,oldname)
+end
+
+function converters.ps(oldname,newname)
+ return format(gstemplate_ps,gsprogram,newname,oldname)
+end
+
+local improgram = "convert"
+local imtemplate = {
+ low = "%s -quality 0 -compress zip %s pdf:%s",
+ medium = "%s -quality 75 -compress zip %s pdf:%s",
+ high = "%s -quality 100 -compress zip %s pdf:%s",
+}
+
+function converters.jpg(oldname,newname)
+ local ea = environment.arguments
+ local quality = (ea.high and 'high') or (ea.medium and 'medium') or (ea.low and 'low') or 'high'
+ return format(imtemplate[quality],improgram,oldname,newname)
+end
+
+converters.gif = converters.jpg
+converters.tif = converters.jpg
+converters.tiff = converters.jpg
+converters.png = converters.jpg
+
+function converters.convertgraphic(kind,oldname,newname)
+ if converters[kind] then -- extra test
+ local tmpname = file.replacesuffix(newname,"tmp")
+ local command = converters[kind](oldname,tmpname)
+ report("command: %s",command)
+ io.flush()
+ os.spawn(command)
+ os.remove(newname)
+ os.rename(tmpname,newname)
+ if lfs.attributes(newname,"size") == 0 then
+ os.remove(newname)
+ end
+ end
+end
+
+function converters.convertpath(inputpath,outputpath)
+ inputpath = inputpath or "."
+ outputpath = outputpath or "."
+ for name in lfs.dir(inputpath) do
+ local suffix = file.suffix(name)
+ if find(name,"%.$") then
+ -- skip . and ..
+ elseif converters[suffix] then
+ local oldname = file.join(inputpath,name)
+ local newname = file.join(outputpath,file.replacesuffix(name,"pdf"))
+ local et = lfs.attributes(oldname,"modification")
+ local pt = lfs.attributes(newname,"modification")
+ if not pt or et > pt then
+ dir.mkdirs(outputpath)
+ converters.convertgraphic(suffix,oldname,newname)
+ end
+ elseif lfs.isdir(inputpath .. "/".. name) then
+ converters.convertpath(inputpath .. "/".. name,outputpath .. "/".. name)
+ end
+ end
+end
+
+function converters.convertfile(oldname)
+ local suffix = file.suffix(oldname)
+ if converters[suffix] then
+ local newname = file.replacesuffix(oldname,"pdf")
+ if oldname == newname then
+ -- todo: downsample, crop etc
+ elseif environment.argument("force") then
+ converters.convertgraphic(suffix,oldname,newname)
+ else
+ local et = lfs.attributes(oldname,"modification")
+ local pt = lfs.attributes(newname,"modification")
+ if not pt or et > pt then
+ converters.convertgraphic(suffix,oldname,newname)
+ end
+ end
+ end
+end
+
+if environment.ownscript then
+ -- stand alone
+else
+ report(application.banner)
+ return convert
+end
+
+convert.delay = 5 * 60 -- 5 minutes
+
+function convert.convertall()
+ local watch = environment.arguments.watch or false
+ local delay = environment.arguments.delay or convert.delay
+ local input = environment.arguments.inputpath or "."
+ local output = environment.arguments.outputpath or "."
+ while true do
+ converters.convertpath(input, output)
+ if watch then
+ os.sleep(delay)
+ else
+ break
+ end
+ end
+end
+
+function convert.convertgiven()
+ local files = environment.files
+ for i=1,#files do
+ converters.convertfile(files[i])
+ end
+end
+
+if environment.arguments.convertall then
+ convert.convertall()
+elseif environment.files[1] then
+ convert.convertgiven()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-fcd.lua b/scripts/context/lua/mtx-fcd.lua index ba9299020..81e67ca2f 100644 --- a/scripts/context/lua/mtx-fcd.lua +++ b/scripts/context/lua/mtx-fcd.lua @@ -1,386 +1,386 @@ -if not modules then modules = { } end modules ['mtx-fcd'] = { - version = 1.002, - comment = "companion to mtxrun.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files", - comment = "based on the ruby version from 2005", -} - --- This is a kind of variant of the good old ncd (norton change directory) program. This --- script uses the same indirect cmd trick as Erwin Waterlander's wcd program. --- --- The program is called via the stubs fcd.cmd or fcd.sh. On unix one should probably source --- the file: ". fcd args" in order to make the chdir persistent. --- --- You need to create a stub with: --- --- mtxrun --script fcd --stub > fcd.cmd --- mtxrun --script fcd --stub > fcd.sh --- --- The stub starts this script and afterwards runs the created directory change script as --- part if the same run, so that indeed we change. - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-fcd</entry> - <entry name="detail">Fast Directory Change</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="clear"><short>clear the cache</short></flag> - <flag name="clear"><short><ref name="history"/> [entry] clear the history</short></flag> - <flag name="scan"><short>clear the cache and add given path(s)</short></flag> - <flag name="add"><short>add given path(s)</short></flag> - <flag name="find"><short>find given path (can be substring)</short></flag> - <flag name="find"><short><ref name="nohistory"/> find given path (can be substring) but don't use history</short></flag> - <flag name="stub"><short>print platform stub file</short></flag> - <flag name="list"><short>show roots of cached dirs</short></flag> - <flag name="list"><short><ref name="history"/> show history of chosen dirs</short></flag> - <flag name="help"><short>show this help</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Example</title> - <subcategory> - <example><command>fcd --scan t:\</command></example> - <example><command>fcd --add f:\project</command></example> - <example><command>fcd [--find] whatever</command></example> - <example><command>fcd --list</command></example> - </subcategory> - </category> - </examples> -</application> -]] - -local application = logs.application { - name = "mtx-fcd", - banner = "Fast Directory Change 1.00", - helpinfo = helpinfo, -} - -local report = application.report -local writeln = print -- texio.write_nl - -local find, char, byte, lower, gsub, format = string.find, string.char, string.byte, string.lower, string.gsub, string.format - -local mswinstub = [[@echo off - -rem this is: fcd.cmd - -@echo off - -if not exist "%HOME%" goto homepath - -:home - -mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9 - -if exist "%HOME%\mtx-fcd-goto.cmd" call "%HOME%\mtx-fcd-goto.cmd" - -goto end - -:homepath - -if not exist "%HOMEDRIVE%\%HOMEPATH%" goto end - -mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9 - -if exist "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd" call "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd" - -goto end - -:end -]] - -local unixstub = [[#!/usr/bin/env sh - -# this is: fcd.sh - -# mv fcd.sh fcd -# chmod fcd 755 -# . fcd [args] - -ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9 - -if test -f "$HOME/fcd_stage.sh" ; then - . $HOME/fcd_stage.sh ; -fi; - -]] - -local gotofile -local datafile -local stubfile -local stubdata -local stubdummy -local stubchdir - -if os.platform == 'mswin' then - gotofile = 'mtx-fcd-goto.cmd' - datafile = 'mtx-fcd-data.lua' - stubfile = 'fcd.cmd' - stubdata = mswinstub - stubdummy = 'rem no dir to change to' - stubchdir = 'cd /d "%s"' -else - gotofile = 'mtx-fcd-goto.sh' - datafile = 'mtx-fcd-data.lua' - stubfile = 'fcd.sh' - stubdata = unixstub - stubdummy = '# no dir to change to' - stubchdir = '# cd "%s"' -end - -local homedir = os.env["HOME"] or "" -- no longer TMP etc - -if homedir == "" then - homedir = format("%s/%s",os.env["HOMEDRIVE"] or "",os.env["HOMEPATH"] or "") -end - -if homedir == "/" or not lfs.isdir(homedir) then - os.exit() -end - -local datafile = file.join(homedir,datafile) -local gotofile = file.join(homedir,gotofile) -local hash = nil -local found = { } -local pattern = "" -local version = modules['mtx-fcd'].version - -io.savedata(gotofile,stubdummy) - -if not lfs.isfile(gotofile) then - -- write error - os.exit() -end - -local function fcd_clear(onlyhistory,what) - if onlyhistory and hash and hash.history then - if what and what ~= "" then - hash.history[what] = nil - else - hash.history = { } - end - else - hash = { - name = "fcd cache", - comment = "generated by mtx-fcd.lua", - created = os.date(), - version = version, - paths = { }, - history = { }, - } - end -end - -local function fcd_changeto(dir) - if dir and dir ~= "" then - io.savedata(gotofile,format(stubchdir,dir)) - end -end - -local function fcd_load(forcecreate) - if lfs.isfile(datafile) then - hash = dofile(datafile) - end - if not hash or hash.version ~= version then - if forcecache then - fcd_clear() - else - writeln("empty dir cache") - fcd_clear() - os.exit() - end - end -end - -local function fcd_save() - if hash then - io.savedata(datafile,table.serialize(hash,true)) - end -end - -local function fcd_list(onlyhistory) - if hash then - writeln("") - if onlyhistory then - if next(hash.history) then - for k, v in table.sortedhash(hash.history) do - writeln(format("%s => %s",k,v)) - end - else - writeln("no history") - end - else - local paths = hash.paths - if #paths > 0 then - for i=1,#paths do - local path = paths[i] - writeln(format("%4i %s",#path[2],path[1])) - end - else - writeln("empty cache") - end - end - end -end - -local function fcd_find() - found = { } - pattern = environment.files[1] or "" - if pattern ~= "" then - pattern = string.escapedpattern(pattern) - local paths = hash.paths - for i=1,#paths do - local paths = paths[i][2] - for i=1,#paths do - local path = paths[i] - if find(path,pattern) then - found[#found+1] = path - end - end - end - end -end - -local function fcd_choose(new) - if pattern == "" then - writeln(format("staying in dir %q",(gsub(lfs.currentdir(),"\\","/")))) - return - end - if #found == 0 then - writeln(format("dir %q not found",pattern)) - return - end - local okay = #found == 1 and found[1] or (not new and hash.history[pattern]) - if okay then - writeln(format("changing to %q",okay)) - fcd_changeto(okay) - return - end - local offset = 0 - while true do - if not found[offset] then - offset = 0 - end - io.write("\n") - for i=1,26 do - local v = found[i+offset] - if v then - writeln(format("%s %3i %s",char(i+96),offset+i,v)) - else - break - end - end - offset = offset + 26 - if found[offset+1] then - io.write("\n[press enter for more or select letter]\n\n>> ") - else - io.write("\n[select letter]\n\n>> ") - end - local answer = lower(io.read() or "") - if not answer or answer == 'quit' then - break - elseif #answer > 0 then - local choice = tonumber(answer) - if not choice then - if answer >= "a" and answer <= "z" then - choice = byte(answer) - 96 + offset - 26 - end - end - local newdir = found[choice] - if newdir then - hash.history[pattern] = newdir - writeln(format("changing to %q",newdir)) - fcd_changeto(newdir) - fcd_save() - return - end - else - -- try again - end - end -end - -local function globdirs(path,dirs) - local dirs = dirs or { } - for name in lfs.dir(path) do - if not find(name,"%.$") then - local fullname = path .. "/" .. name - if lfs.isdir(fullname) and not find(fullname,"/%.") then - dirs[#dirs+1] = fullname - globdirs(fullname,dirs) - end - end - end - return dirs -end - -local function fcd_scan() - if hash then - local paths = hash.paths - for i=1,#environment.files do - local name = environment.files[i] - local name = gsub(name,"\\","/") - local name = gsub(name,"/$","") - local list = globdirs(name) - local done = false - for i=1,#paths do - if paths[i][1] == name then - paths[i][2] = list - done = true - break - end - end - if not done then - paths[#paths+1] = { name, list } - end - end - end -end - -local argument = environment.argument - -if argument("clear") then - if argument("history") then - fcd_load() - fcd_clear(true) - else - fcd_clear() - end - fcd_save() -elseif argument("scan") then - fcd_clear() - fcd_scan() - fcd_save() -elseif argument("add") then - fcd_load(true) - fcd_scan() - fcd_save() -elseif argument("stub") then - writeln(stubdata) -elseif argument("list") then - fcd_load() - if argument("history") then - fcd_list(true) - else - fcd_list() - end -elseif argument("help") then - application.help() -elseif argument("exporthelp") then - application.export(argument("exporthelp"),environment.files[1]) -else -- also argument("find") - fcd_load() - fcd_find() - fcd_choose(argument("nohistory")) -end - +if not modules then modules = { } end modules ['mtx-fcd'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "based on the ruby version from 2005",
+}
+
+-- This is a kind of variant of the good old ncd (norton change directory) program. This
+-- script uses the same indirect cmd trick as Erwin Waterlander's wcd program.
+--
+-- The program is called via the stubs fcd.cmd or fcd.sh. On unix one should probably source
+-- the file: ". fcd args" in order to make the chdir persistent.
+--
+-- You need to create a stub with:
+--
+-- mtxrun --script fcd --stub > fcd.cmd
+-- mtxrun --script fcd --stub > fcd.sh
+--
+-- The stub starts this script and afterwards runs the created directory change script as
+-- part if the same run, so that indeed we change.
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-fcd</entry>
+ <entry name="detail">Fast Directory Change</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="clear"><short>clear the cache</short></flag>
+ <flag name="clear"><short><ref name="history"/> [entry] clear the history</short></flag>
+ <flag name="scan"><short>clear the cache and add given path(s)</short></flag>
+ <flag name="add"><short>add given path(s)</short></flag>
+ <flag name="find"><short>find given path (can be substring)</short></flag>
+ <flag name="find"><short><ref name="nohistory"/> find given path (can be substring) but don't use history</short></flag>
+ <flag name="stub"><short>print platform stub file</short></flag>
+ <flag name="list"><short>show roots of cached dirs</short></flag>
+ <flag name="list"><short><ref name="history"/> show history of chosen dirs</short></flag>
+ <flag name="help"><short>show this help</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+ <examples>
+ <category>
+ <title>Example</title>
+ <subcategory>
+ <example><command>fcd --scan t:\</command></example>
+ <example><command>fcd --add f:\project</command></example>
+ <example><command>fcd [--find] whatever</command></example>
+ <example><command>fcd --list</command></example>
+ </subcategory>
+ </category>
+ </examples>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-fcd",
+ banner = "Fast Directory Change 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+local writeln = print -- texio.write_nl
+
+local find, char, byte, lower, gsub, format = string.find, string.char, string.byte, string.lower, string.gsub, string.format
+
+local mswinstub = [[@echo off
+
+rem this is: fcd.cmd
+
+@echo off
+
+if not exist "%HOME%" goto homepath
+
+:home
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOME%\mtx-fcd-goto.cmd" call "%HOME%\mtx-fcd-goto.cmd"
+
+goto end
+
+:homepath
+
+if not exist "%HOMEDRIVE%\%HOMEPATH%" goto end
+
+mtxrun --script mtx-fcd.lua %1 %2 %3 %4 %5 %6 %7 %8 %9
+
+if exist "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd" call "%HOMEDRIVE%\%HOMEPATH%\mtx-fcd-goto.cmd"
+
+goto end
+
+:end
+]]
+
+local unixstub = [[#!/usr/bin/env sh
+
+# this is: fcd.sh
+
+# mv fcd.sh fcd
+# chmod fcd 755
+# . fcd [args]
+
+ruby -S fcd_start.rb $1 $2 $3 $4 $5 $6 $7 $8 $9
+
+if test -f "$HOME/fcd_stage.sh" ; then
+ . $HOME/fcd_stage.sh ;
+fi;
+
+]]
+
+local gotofile
+local datafile
+local stubfile
+local stubdata
+local stubdummy
+local stubchdir
+
+if os.platform == 'mswin' then
+ gotofile = 'mtx-fcd-goto.cmd'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.cmd'
+ stubdata = mswinstub
+ stubdummy = 'rem no dir to change to'
+ stubchdir = 'cd /d "%s"'
+else
+ gotofile = 'mtx-fcd-goto.sh'
+ datafile = 'mtx-fcd-data.lua'
+ stubfile = 'fcd.sh'
+ stubdata = unixstub
+ stubdummy = '# no dir to change to'
+ stubchdir = '# cd "%s"'
+end
+
+local homedir = os.env["HOME"] or "" -- no longer TMP etc
+
+if homedir == "" then
+ homedir = format("%s/%s",os.env["HOMEDRIVE"] or "",os.env["HOMEPATH"] or "")
+end
+
+if homedir == "/" or not lfs.isdir(homedir) then
+ os.exit()
+end
+
+local datafile = file.join(homedir,datafile)
+local gotofile = file.join(homedir,gotofile)
+local hash = nil
+local found = { }
+local pattern = ""
+local version = modules['mtx-fcd'].version
+
+io.savedata(gotofile,stubdummy)
+
+if not lfs.isfile(gotofile) then
+ -- write error
+ os.exit()
+end
+
+local function fcd_clear(onlyhistory,what)
+ if onlyhistory and hash and hash.history then
+ if what and what ~= "" then
+ hash.history[what] = nil
+ else
+ hash.history = { }
+ end
+ else
+ hash = {
+ name = "fcd cache",
+ comment = "generated by mtx-fcd.lua",
+ created = os.date(),
+ version = version,
+ paths = { },
+ history = { },
+ }
+ end
+end
+
+local function fcd_changeto(dir)
+ if dir and dir ~= "" then
+ io.savedata(gotofile,format(stubchdir,dir))
+ end
+end
+
+local function fcd_load(forcecreate)
+ if lfs.isfile(datafile) then
+ hash = dofile(datafile)
+ end
+ if not hash or hash.version ~= version then
+ if forcecache then
+ fcd_clear()
+ else
+ writeln("empty dir cache")
+ fcd_clear()
+ os.exit()
+ end
+ end
+end
+
+local function fcd_save()
+ if hash then
+ io.savedata(datafile,table.serialize(hash,true))
+ end
+end
+
+local function fcd_list(onlyhistory)
+ if hash then
+ writeln("")
+ if onlyhistory then
+ if next(hash.history) then
+ for k, v in table.sortedhash(hash.history) do
+ writeln(format("%s => %s",k,v))
+ end
+ else
+ writeln("no history")
+ end
+ else
+ local paths = hash.paths
+ if #paths > 0 then
+ for i=1,#paths do
+ local path = paths[i]
+ writeln(format("%4i %s",#path[2],path[1]))
+ end
+ else
+ writeln("empty cache")
+ end
+ end
+ end
+end
+
+local function fcd_find()
+ found = { }
+ pattern = environment.files[1] or ""
+ if pattern ~= "" then
+ pattern = string.escapedpattern(pattern)
+ local paths = hash.paths
+ for i=1,#paths do
+ local paths = paths[i][2]
+ for i=1,#paths do
+ local path = paths[i]
+ if find(path,pattern) then
+ found[#found+1] = path
+ end
+ end
+ end
+ end
+end
+
+local function fcd_choose(new)
+ if pattern == "" then
+ writeln(format("staying in dir %q",(gsub(lfs.currentdir(),"\\","/"))))
+ return
+ end
+ if #found == 0 then
+ writeln(format("dir %q not found",pattern))
+ return
+ end
+ local okay = #found == 1 and found[1] or (not new and hash.history[pattern])
+ if okay then
+ writeln(format("changing to %q",okay))
+ fcd_changeto(okay)
+ return
+ end
+ local offset = 0
+ while true do
+ if not found[offset] then
+ offset = 0
+ end
+ io.write("\n")
+ for i=1,26 do
+ local v = found[i+offset]
+ if v then
+ writeln(format("%s %3i %s",char(i+96),offset+i,v))
+ else
+ break
+ end
+ end
+ offset = offset + 26
+ if found[offset+1] then
+ io.write("\n[press enter for more or select letter]\n\n>> ")
+ else
+ io.write("\n[select letter]\n\n>> ")
+ end
+ local answer = lower(io.read() or "")
+ if not answer or answer == 'quit' then
+ break
+ elseif #answer > 0 then
+ local choice = tonumber(answer)
+ if not choice then
+ if answer >= "a" and answer <= "z" then
+ choice = byte(answer) - 96 + offset - 26
+ end
+ end
+ local newdir = found[choice]
+ if newdir then
+ hash.history[pattern] = newdir
+ writeln(format("changing to %q",newdir))
+ fcd_changeto(newdir)
+ fcd_save()
+ return
+ end
+ else
+ -- try again
+ end
+ end
+end
+
+local function globdirs(path,dirs)
+ local dirs = dirs or { }
+ for name in lfs.dir(path) do
+ if not find(name,"%.$") then
+ local fullname = path .. "/" .. name
+ if lfs.isdir(fullname) and not find(fullname,"/%.") then
+ dirs[#dirs+1] = fullname
+ globdirs(fullname,dirs)
+ end
+ end
+ end
+ return dirs
+end
+
+local function fcd_scan()
+ if hash then
+ local paths = hash.paths
+ for i=1,#environment.files do
+ local name = environment.files[i]
+ local name = gsub(name,"\\","/")
+ local name = gsub(name,"/$","")
+ local list = globdirs(name)
+ local done = false
+ for i=1,#paths do
+ if paths[i][1] == name then
+ paths[i][2] = list
+ done = true
+ break
+ end
+ end
+ if not done then
+ paths[#paths+1] = { name, list }
+ end
+ end
+ end
+end
+
+local argument = environment.argument
+
+if argument("clear") then
+ if argument("history") then
+ fcd_load()
+ fcd_clear(true)
+ else
+ fcd_clear()
+ end
+ fcd_save()
+elseif argument("scan") then
+ fcd_clear()
+ fcd_scan()
+ fcd_save()
+elseif argument("add") then
+ fcd_load(true)
+ fcd_scan()
+ fcd_save()
+elseif argument("stub") then
+ writeln(stubdata)
+elseif argument("list") then
+ fcd_load()
+ if argument("history") then
+ fcd_list(true)
+ else
+ fcd_list()
+ end
+elseif argument("help") then
+ application.help()
+elseif argument("exporthelp") then
+ application.export(argument("exporthelp"),environment.files[1])
+else -- also argument("find")
+ fcd_load()
+ fcd_find()
+ fcd_choose(argument("nohistory"))
+end
+
diff --git a/scripts/context/lua/mtx-flac.lua b/scripts/context/lua/mtx-flac.lua index 2155b24be..2e988b412 100644 --- a/scripts/context/lua/mtx-flac.lua +++ b/scripts/context/lua/mtx-flac.lua @@ -1,238 +1,238 @@ -if not modules then modules = { } end modules ['mtx-flac'] = { - 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 sub, match, byte, lower = string.sub, string.match, string.byte, string.lower -local readstring, readnumber = io.readstring, io.readnumber -local concat, sortedpairs = table.concat, table.sortedpairs -local tonumber = tonumber -local tobitstring = number.tobitstring -local lpegmatch = lpeg.match -local p_escaped = lpeg.patterns.xml.escaped - --- rather silly: pack info in bits while a flac file is large anyway - -flac = flac or { } - -flac.report = string.format - -local splitter = lpeg.splitat("=") -local readers = { } - -readers[0] = function(f,size,target) -- not yet ok .. todo: use bit32 lib - local info = { } - target.info = info - info.minimum_block_size = readnumber(f,-2) - info.maximum_block_size = readnumber(f,-2) - info.minimum_frame_size = readnumber(f,-3) - info.maximum_frame_size = readnumber(f,-3) - local buffer = { } - for i=1,8 do - buffer[i] = tobitstring(readnumber(f,1)) - end - local bytes = concat(buffer) - info.sample_rate_in_hz = tonumber(sub(bytes, 1,20),2) -- 20 - info.number_of_channels = tonumber(sub(bytes,21,23),2) -- 3 - info.bits_per_sample = tonumber(sub(bytes,24,28),2) -- 5 - info.samples_in_stream = tonumber(sub(bytes,29,64),2) -- 36 - info.md5_signature = readstring(f,16) -- 128 -end - -readers[4] = function(f,size,target,banner) - local tags = { } - target.tags = tags - target.vendor = readstring(f,readnumber(f,-4)) - for i=1,readnumber(f,-4) do - local key, value = lpeg.match(splitter,readstring(f,readnumber(f,-4))) - tags[lower(key)] = value - end -end - -readers.default = function(f,size,target) - f:seek("cur",size) -end - -function flac.getmetadata(filename) - local f = io.open(filename, "rb") - if f then - local banner = readstring(f,4) - if banner == "fLaC" then - local data = { - banner = banner, - filename = filename, - filesize = lfs.attributes(filename,"size"), - } - while true do - local flag = readnumber(f,1) - local size = readnumber(f,3) - local last = flag > 127 - if last then - flag = flag - 128 - end - local reader = readers[flag] or readers.default - reader(f,size,data,banner) - if last then - f:close() - return data - end - end - else - flac.report("no flac file: %s (%s)",filename,banner) - end - f:close() - else - flac.report("no file: %s",filename) - end -end - -function flac.savecollection(pattern,filename) - pattern = (pattern ~= "" and pattern) or "**/*.flac" - filename = (filename ~= "" and filename) or "music-collection.xml" - flac.report("identifying files using pattern %q" ,pattern) - local files = dir.glob(pattern) - flac.report("%s files found, analyzing files",#files) - local music = { } - for i=1,#files do - local data = flac.getmetadata(files[i]) - if data then - local tags = data.tags - local info = data.info - local artist = tags.artist - local album = tags.album - local albums = music[artist] - if not albums then - albums = { } - music[artist] = albums - end - local albumx = albums[album] - if not albumx then - albumx = { - year = tags.date, - tracks = { }, - } - albums[album] = albumx - end - albumx.tracks[tonumber(tags.tracknumber) or 0] = { - title = tags.title, - length = math.round((info.samples_in_stream/info.sample_rate_in_hz)), - } - end - end - -- inspect(music) - local nofartists, nofalbums, noftracks, noferrors = 0, 0, 0, 0 - local f = io.open(filename,"wb") - if f then - flac.report("saving data in file %q",filename) - f:write("<?xml version='1.0' standalone='yes'?>\n\n") - f:write("<collection>\n") - for artist, albums in sortedpairs(music) do - nofartists = nofartists + 1 - f:write("\t<artist>\n") - f:write("\t\t<name>",lpegmatch(p_escaped,artist),"</name>\n") - f:write("\t\t<albums>\n") - for album, data in sortedpairs(albums) do - nofalbums = nofalbums + 1 - f:write("\t\t\t<album year='",data.year or 0,"'>\n") - f:write("\t\t\t\t<name>",lpegmatch(p_escaped,album),"</name>\n") - f:write("\t\t\t\t<tracks>\n") - local tracks = data.tracks - for i=1,#tracks do - local track = tracks[i] - if track then - noftracks = noftracks + 1 - f:write("\t\t\t\t\t<track length='",track.length,"'>",lpegmatch(p_escaped,track.title),"</track>\n") - else - noferrors = noferrors + 1 - flac.report("error in album: %q of %q, no track %s",album,artist,i) - f:write("\t\t\t\t\t<error track='",i,"'/>\n") - end - end - f:write("\t\t\t\t</tracks>\n") - f:write("\t\t\t</album>\n") - end - f:write("\t\t</albums>\n") - f:write("\t</artist>\n") - end - f:write("</collection>\n") - f:close() - flac.report("%s tracks of %s albums of %s artists saved in %q (%s errors)",noftracks,nofalbums,nofartists,filename,noferrors) - else - flac.report("unable to save data in file %q",filename) - end -end - --- - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-flac</entry> - <entry name="detail">ConTeXt Flac Helpers</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="collect"><short>collect albums in xml file</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Example</title> - <subcategory> - <example><command>mtxrun --script flac --collect somename.flac</command></example> - <example><command>mtxrun --script flac --collect --pattern="m:/music/**")</command></example> - </subcategory> - </category> - </examples> -</application> -]] - -local application = logs.application { - name = "mtx-flac", - banner = "ConTeXt Flac Helpers 0.10", - helpinfo = helpinfo, -} - -flac.report = application.report - --- script code - -scripts = scripts or { } -scripts.flac = scripts.flac or { } - -function scripts.flac.collect() - local files = environment.files - local pattern = environment.arguments.pattern - if #files > 0 then - for i=1,#files do - local filename = files[1] - if file.suffix(filename) == "flac" then - flac.savecollection(filename,file.replacesuffix(filename,"xml")) - elseif lfs.isdir(filename) then - local pattern = filename .. "/**.flac" - flac.savecollection(pattern,file.addsuffix(file.basename(filename),"xml")) - else - flac.savecollection(file.replacesuffix(filename,"flac"),file.replacesuffix(filename,"xml")) - end - end - elseif pattern then - flac.savecollection(file.addsuffix(pattern,"flac"),"music-collection.xml") - else - flac.report("no file(s) or pattern given" ) - end -end - -if environment.argument("collect") then - scripts.flac.collect() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-flac'] = {
+ 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 sub, match, byte, lower = string.sub, string.match, string.byte, string.lower
+local readstring, readnumber = io.readstring, io.readnumber
+local concat, sortedpairs = table.concat, table.sortedpairs
+local tonumber = tonumber
+local tobitstring = number.tobitstring
+local lpegmatch = lpeg.match
+local p_escaped = lpeg.patterns.xml.escaped
+
+-- rather silly: pack info in bits while a flac file is large anyway
+
+flac = flac or { }
+
+flac.report = string.format
+
+local splitter = lpeg.splitat("=")
+local readers = { }
+
+readers[0] = function(f,size,target) -- not yet ok .. todo: use bit32 lib
+ local info = { }
+ target.info = info
+ info.minimum_block_size = readnumber(f,-2)
+ info.maximum_block_size = readnumber(f,-2)
+ info.minimum_frame_size = readnumber(f,-3)
+ info.maximum_frame_size = readnumber(f,-3)
+ local buffer = { }
+ for i=1,8 do
+ buffer[i] = tobitstring(readnumber(f,1))
+ end
+ local bytes = concat(buffer)
+ info.sample_rate_in_hz = tonumber(sub(bytes, 1,20),2) -- 20
+ info.number_of_channels = tonumber(sub(bytes,21,23),2) -- 3
+ info.bits_per_sample = tonumber(sub(bytes,24,28),2) -- 5
+ info.samples_in_stream = tonumber(sub(bytes,29,64),2) -- 36
+ info.md5_signature = readstring(f,16) -- 128
+end
+
+readers[4] = function(f,size,target,banner)
+ local tags = { }
+ target.tags = tags
+ target.vendor = readstring(f,readnumber(f,-4))
+ for i=1,readnumber(f,-4) do
+ local key, value = lpeg.match(splitter,readstring(f,readnumber(f,-4)))
+ tags[lower(key)] = value
+ end
+end
+
+readers.default = function(f,size,target)
+ f:seek("cur",size)
+end
+
+function flac.getmetadata(filename)
+ local f = io.open(filename, "rb")
+ if f then
+ local banner = readstring(f,4)
+ if banner == "fLaC" then
+ local data = {
+ banner = banner,
+ filename = filename,
+ filesize = lfs.attributes(filename,"size"),
+ }
+ while true do
+ local flag = readnumber(f,1)
+ local size = readnumber(f,3)
+ local last = flag > 127
+ if last then
+ flag = flag - 128
+ end
+ local reader = readers[flag] or readers.default
+ reader(f,size,data,banner)
+ if last then
+ f:close()
+ return data
+ end
+ end
+ else
+ flac.report("no flac file: %s (%s)",filename,banner)
+ end
+ f:close()
+ else
+ flac.report("no file: %s",filename)
+ end
+end
+
+function flac.savecollection(pattern,filename)
+ pattern = (pattern ~= "" and pattern) or "**/*.flac"
+ filename = (filename ~= "" and filename) or "music-collection.xml"
+ flac.report("identifying files using pattern %q" ,pattern)
+ local files = dir.glob(pattern)
+ flac.report("%s files found, analyzing files",#files)
+ local music = { }
+ for i=1,#files do
+ local data = flac.getmetadata(files[i])
+ if data then
+ local tags = data.tags
+ local info = data.info
+ local artist = tags.artist
+ local album = tags.album
+ local albums = music[artist]
+ if not albums then
+ albums = { }
+ music[artist] = albums
+ end
+ local albumx = albums[album]
+ if not albumx then
+ albumx = {
+ year = tags.date,
+ tracks = { },
+ }
+ albums[album] = albumx
+ end
+ albumx.tracks[tonumber(tags.tracknumber) or 0] = {
+ title = tags.title,
+ length = math.round((info.samples_in_stream/info.sample_rate_in_hz)),
+ }
+ end
+ end
+ -- inspect(music)
+ local nofartists, nofalbums, noftracks, noferrors = 0, 0, 0, 0
+ local f = io.open(filename,"wb")
+ if f then
+ flac.report("saving data in file %q",filename)
+ f:write("<?xml version='1.0' standalone='yes'?>\n\n")
+ f:write("<collection>\n")
+ for artist, albums in sortedpairs(music) do
+ nofartists = nofartists + 1
+ f:write("\t<artist>\n")
+ f:write("\t\t<name>",lpegmatch(p_escaped,artist),"</name>\n")
+ f:write("\t\t<albums>\n")
+ for album, data in sortedpairs(albums) do
+ nofalbums = nofalbums + 1
+ f:write("\t\t\t<album year='",data.year or 0,"'>\n")
+ f:write("\t\t\t\t<name>",lpegmatch(p_escaped,album),"</name>\n")
+ f:write("\t\t\t\t<tracks>\n")
+ local tracks = data.tracks
+ for i=1,#tracks do
+ local track = tracks[i]
+ if track then
+ noftracks = noftracks + 1
+ f:write("\t\t\t\t\t<track length='",track.length,"'>",lpegmatch(p_escaped,track.title),"</track>\n")
+ else
+ noferrors = noferrors + 1
+ flac.report("error in album: %q of %q, no track %s",album,artist,i)
+ f:write("\t\t\t\t\t<error track='",i,"'/>\n")
+ end
+ end
+ f:write("\t\t\t\t</tracks>\n")
+ f:write("\t\t\t</album>\n")
+ end
+ f:write("\t\t</albums>\n")
+ f:write("\t</artist>\n")
+ end
+ f:write("</collection>\n")
+ f:close()
+ flac.report("%s tracks of %s albums of %s artists saved in %q (%s errors)",noftracks,nofalbums,nofartists,filename,noferrors)
+ else
+ flac.report("unable to save data in file %q",filename)
+ end
+end
+
+--
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-flac</entry>
+ <entry name="detail">ConTeXt Flac Helpers</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="collect"><short>collect albums in xml file</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+ <examples>
+ <category>
+ <title>Example</title>
+ <subcategory>
+ <example><command>mtxrun --script flac --collect somename.flac</command></example>
+ <example><command>mtxrun --script flac --collect --pattern="m:/music/**")</command></example>
+ </subcategory>
+ </category>
+ </examples>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-flac",
+ banner = "ConTeXt Flac Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+flac.report = application.report
+
+-- script code
+
+scripts = scripts or { }
+scripts.flac = scripts.flac or { }
+
+function scripts.flac.collect()
+ local files = environment.files
+ local pattern = environment.arguments.pattern
+ if #files > 0 then
+ for i=1,#files do
+ local filename = files[1]
+ if file.suffix(filename) == "flac" then
+ flac.savecollection(filename,file.replacesuffix(filename,"xml"))
+ elseif lfs.isdir(filename) then
+ local pattern = filename .. "/**.flac"
+ flac.savecollection(pattern,file.addsuffix(file.basename(filename),"xml"))
+ else
+ flac.savecollection(file.replacesuffix(filename,"flac"),file.replacesuffix(filename,"xml"))
+ end
+ end
+ elseif pattern then
+ flac.savecollection(file.addsuffix(pattern,"flac"),"music-collection.xml")
+ else
+ flac.report("no file(s) or pattern given" )
+ end
+end
+
+if environment.argument("collect") then
+ scripts.flac.collect()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-fonts.lua b/scripts/context/lua/mtx-fonts.lua index b171dd611..2c28f63d9 100644 --- a/scripts/context/lua/mtx-fonts.lua +++ b/scripts/context/lua/mtx-fonts.lua @@ -1,472 +1,472 @@ -if not modules then modules = { } end modules ['mtx-fonts'] = { - 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 getargument = environment.getargument -local setargument = environment.setargument -local givenfiles = environment.files - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-fonts</entry> - <entry name="detail">ConTeXt Font Database Management</entry> - <entry name="version">0.21</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="save"><short>save open type font in raw table</short></flag> - <flag name="unpack"><short>save a tma file in a more readable format</short></flag> - </subcategory> - <subcategory> - <flag name="reload"><short>generate new font database (use <ref name="force"/> when in doubt)</short></flag> - <flag name="reload"><short><ref name="simple"/>:generate luatex-fonts-names.lua (not for context!)</short></flag> - </subcategory> - <subcategory> - <flag name="list"><short><ref name="name"/>: list installed fonts, filter by name [<ref name="pattern"/>]</short></flag> - <flag name="list"><short><ref name="spec"/>: list installed fonts, filter by spec [<ref name="filter"/>]</short></flag> - <flag name="list"><short><ref name="file"/>: list installed fonts, filter by file [<ref name="pattern"/>]</short></flag> - </subcategory> - <subcategory> - <flag name="pattern" value="str"><short>filter files using pattern</short></flag> - <flag name="filter" value="list"><short>key-value pairs</short></flag> - <flag name="all"><short>show all found instances (combined with other flags)</short></flag> - <flag name="info"><short>give more details</short></flag> - <flag name="track" value="list"><short>enable trackers</short></flag> - <flag name="statistics"><short>some info about the database</short></flag> - </subcategory> - </category> - </flags> - <examples> - <category> - <title>Examples</title> - <subcategory> - <example><command>mtxrun --script font --list somename (== --pattern=*somename*)</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> - <subcategory> - <example><command>mtxrun --script font --list --spec somename</command></example> - <example><command>mtxrun --script font --list --spec somename-bold-italic</command></example> - <example><command>mtxrun --script font --list --spec --pattern=*somename*</command></example> - <example><command>mtxrun --script font --list --spec --filter="fontname=somename"</command></example> - <example><command>mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"</command></example> - <example><command>mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"</command></example> - </subcategory> - <subcategory> - <example><command>mtxrun --script font --list --all</command></example> - <example><command>mtxrun --script font --list --file somename</command></example> - <example><command>mtxrun --script font --list --file --all somename</command></example> - <example><command>mtxrun --script font --list --file --pattern=*somename*</command></example> - </subcategory> - </category> - </examples> -</application> -]] - -local application = logs.application { - name = "mtx-fonts", - banner = "ConTeXt Font Database Management 0.21", - helpinfo = helpinfo, -} - -local report = application.report - --- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory - -if not fontloader then fontloader = fontforge end - -dofile(resolvers.findfile("font-otp.lua","tex")) -- we need to unpack the font for analysis -dofile(resolvers.findfile("font-trt.lua","tex")) -dofile(resolvers.findfile("font-syn.lua","tex")) -dofile(resolvers.findfile("font-mis.lua","tex")) - -scripts = scripts or { } -scripts.fonts = scripts.fonts or { } - -function fonts.names.statistics() - fonts.names.load() - - local data = fonts.names.data - local statistics = data.statistics - - local function counted(t) - local n = { } - for k, v in next, t do - n[k] = table.count(v) - end - return table.sequenced(n) - end - - report("cache uuid : %s", data.cache_uuid) - report("cache version : %s", data.cache_version) - report("number of trees : %s", #data.datastate) - report() - report("number of fonts : %s", statistics.fonts or 0) - report("used files : %s", statistics.readfiles or 0) - report("skipped files : %s", statistics.skippedfiles or 0) - report("duplicate files : %s", statistics.duplicatefiles or 0) - report("specifications : %s", #data.specifications) - report("families : %s", table.count(data.families)) - report() - report("mappings : %s", counted(data.mappings)) - report("fallbacks : %s", counted(data.fallbacks)) - report() - report("used styles : %s", table.sequenced(statistics.used_styles)) - report("used variants : %s", table.sequenced(statistics.used_variants)) - report("used weights : %s", table.sequenced(statistics.used_weights)) - report("used widths : %s", table.sequenced(statistics.used_widths)) - report() - report("found styles : %s", table.sequenced(statistics.styles)) - report("found variants : %s", table.sequenced(statistics.variants)) - report("found weights : %s", table.sequenced(statistics.weights)) - report("found widths : %s", table.sequenced(statistics.widths)) - -end - -function fonts.names.simple() - local simpleversion = 1.001 - local simplelist = { "ttf", "otf", "ttc", "dfont" } - local name = "luatex-fonts-names.lua" - local path = file.collapsepath(caches.getwritablepath("..","..","generic","fonts","data")) - 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) - fonts.names.identify(true) - local data = fonts.names.data - if data then - local simplemappings = { } - local simplified = { - mappings = simplemappings, - version = simpleversion, - cache_version = simpleversion, - } - local specifications = data.specifications - for i=1,#simplelist do - local format = simplelist[i] - for tag, index in next, data.mappings[format] do - local s = specifications[index] - simplemappings[tag] = { s.rawname, s.filename, s.subfont } - end - end - if environment.arguments.nocache then - report("not using cache path %a",path) - else - dir.mkdirs(path) - if lfs.isdir(path) then - report("saving names on cache path %a",path) - name = file.join(path,name) - else - report("invalid cache path %a",path) - end - end - report("saving names in %a",name) - io.savedata(name,table.serialize(simplified,true)) - local data = io.loaddata(resolvers.findfile("luatex-fonts-syn.lua","tex")) or "" - local dummy = string.match(data,"fonts%.names%.version%s*=%s*([%d%.]+)") - if tonumber(dummy) ~= simpleversion then - report("warning: version number %s in 'font-dum' does not match database version number %s",dummy or "?",simpleversion) - end - elseif lfs.isfile(name) then - os.remove(name) - end -end - -function scripts.fonts.reload() - if getargument("simple") then - fonts.names.simple() - else - fonts.names.load(true,getargument("force")) - end -end - -local function subfont(sf) - if sf then - return string.format("index: % 2s", sf) - else - return "" - end -end - -local function fontweight(fw) - if fw then - return string.format("conflict: %s", fw) - else - return "" - end -end - -local function showfeatures(tag,specification) - report() - report("mapping : %s",tag) - report("fontname: %s",specification.fontname) - report("fullname: %s",specification.fullname) - report("filename: %s",specification.filename) - report("family : %s",specification.familyname or "<nofamily>") - report("weight : %s",specification.weight or "<noweight>") - report("style : %s",specification.style or "<nostyle>") - report("width : %s",specification.width or "<nowidth>") - report("variant : %s",specification.variant or "<novariant>") - report("subfont : %s",subfont(specification.subfont)) - report("fweight : %s",fontweight(specification.fontweight)) - -- maybe more - local features = fonts.helpers.getfeatures(specification.filename,specification.format) - if features then - for what, v in table.sortedhash(features) do - local data = features[what] - if data and next(data) then - report() - report("%s features:",what) - report() - report("feature script languages") - report() - for f,ff in table.sortedhash(data) do - local done = false - for s, ss in table.sortedhash(ff) do - if s == "*" then s = "all" end - if ss ["*"] then ss["*"] = nil ss.all = true end - if done then - f = "" - else - done = true - end - report("% -8s % -8s % -8s",f,s,table.concat(table.sortedkeys(ss), " ")) -- todo: padd 4 - end - end - end - end - else - report("no features") - end - report() -end - -local function reloadbase(reload) - if reload then - report("fontnames, reloading font database") - names.load(true,getargument("force")) - report("fontnames, done\n\n") - end -end - -local function list_specifications(t,info) - if t then - local s = table.sortedkeys(t) - if info then - for k=1,#s do - local v = s[k] - showfeatures(v,t[v]) - end - else - for k=1,#s do - local v = s[k] - local entry = t[v] - s[k] = { - entry.familyname or "<nofamily>", - entry.weight or "<noweight>", - entry.style or "<nostyle>", - entry.width or "<nowidth>", - entry.variant or "<novariant>", - entry.fontname, - entry.filename, - subfont(entry.subfont), - fontweight(entry.fontweight), - } - end - utilities.formatters.formatcolumns(s) - for k=1,#s do - texio.write_nl(s[k]) - end - end - end -end - -local function list_matches(t,info) - if t then - local s, w = table.sortedkeys(t), { 0, 0, 0 } - if info then - for k=1,#s do - local v = s[k] - showfeatures(v,t[v]) - end - else - for k=1,#s do - local v = s[k] - local entry = t[v] - s[k] = { - v, - entry.fontname, - entry.filename, - subfont(entry.subfont) - } - end - utilities.formatters.formatcolumns(s) - for k=1,#s do - texio.write_nl(s[k]) - end - end - end -end - -function scripts.fonts.list() - - local all = getargument("all") - local info = getargument("info") - local reload = getargument("reload") - local pattern = getargument("pattern") - local filter = getargument("filter") - local given = givenfiles[1] - - reloadbase(reload) - - if getargument("name") then - if pattern then - --~ 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 - 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* - report("not supported: --list --spec --pattern",name) - elseif filter then - --~ mtxrun --script font --list --spec --filter="fontname=somename" - list_specifications(fonts.names.getlookups(filter),info) - elseif given then - --~ 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* - 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 - 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* - list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info) - elseif given then - --~ mtxrun --script font --list somename - list_matches(fonts.names.list(given,reload,all),info) - elseif all then - pattern = "*" - list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info) - else - report("not supported: --list <no specification>",name) - end - -end - -function scripts.fonts.justload() - local fullname = environment.files[1] - if fullname then - local result = fontloader.open(fullname) - if type(result) == "table" then - report("loading %s: %s","succeeded",fullname) - end - end - report("loading %s: %s","failed",fullname) -end - -function scripts.fonts.unpack() - local name = file.removesuffix(file.basename(givenfiles[1] or "")) - if name and name ~= "" then - local cache = containers.define("fonts", "otf", 2.742, true) - local cleanname = containers.cleanname(name) - local data = containers.read(cache,cleanname) - if data then - local savename = file.addsuffix(cleanname .. "-unpacked","tma") - report("fontsave, saving data in %s",savename) - fonts.handlers.otf.enhancers.unpack(data) - io.savedata(savename,table.serialize(data,true)) - else - report("unknown file %a",name) - end - end -end - -function scripts.fonts.save() - local name = givenfiles[1] or "" - local sub = givenfiles[2] or "" - local function save(savename,fontblob) - if fontblob then - savename = file.addsuffix(string.lower(savename),"lua") - report("fontsave, saving data in %s",savename) - table.tofile(savename,fontloader.to_table(fontblob),"return") - fontloader.close(fontblob) - end - end - if name and name ~= "" then - local filename = resolvers.findfile(name) -- maybe also search for opentype - if filename and filename ~= "" then - local suffix = string.lower(file.suffix(filename)) - if suffix == 'ttf' or suffix == 'otf' or suffix == 'ttc' or suffix == "dfont" then - local fontinfo = fontloader.info(filename) - if fontinfo then - report("font: %s located as %s",name,filename) - if fontinfo[1] then - for k=1,#fontinfo do - local v = fontinfo[k] - save(v.fontname,fontloader.open(filename,v.fullname)) - end - else - save(fontinfo.fullname,fontloader.open(filename)) - end - else - report("font: %s cannot be read",filename) - end - else - report("font: %s not saved",filename) - end - else - report("font: %s not found",name) - end - else - report("font: no name given") - end -end - -if getargument("names") then - setargument("reload",true) - setargument("simple",true) -end - -if getargument("list") then - scripts.fonts.list() -elseif getargument("reload") then - scripts.fonts.reload() -elseif getargument("save") then - scripts.fonts.save() -elseif getargument("justload") then - scripts.fonts.justload() -elseif getargument("unpack") then - scripts.fonts.unpack() -elseif getargument("statistics") then - fonts.names.statistics() -elseif getargument("exporthelp") then - application.export(getargument("exporthelp"),givenfiles[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-fonts'] = {
+ 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 getargument = environment.getargument
+local setargument = environment.setargument
+local givenfiles = environment.files
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-fonts</entry>
+ <entry name="detail">ConTeXt Font Database Management</entry>
+ <entry name="version">0.21</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="save"><short>save open type font in raw table</short></flag>
+ <flag name="unpack"><short>save a tma file in a more readable format</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="reload"><short>generate new font database (use <ref name="force"/> when in doubt)</short></flag>
+ <flag name="reload"><short><ref name="simple"/>:generate luatex-fonts-names.lua (not for context!)</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="list"><short><ref name="name"/>: list installed fonts, filter by name [<ref name="pattern"/>]</short></flag>
+ <flag name="list"><short><ref name="spec"/>: list installed fonts, filter by spec [<ref name="filter"/>]</short></flag>
+ <flag name="list"><short><ref name="file"/>: list installed fonts, filter by file [<ref name="pattern"/>]</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="pattern" value="str"><short>filter files using pattern</short></flag>
+ <flag name="filter" value="list"><short>key-value pairs</short></flag>
+ <flag name="all"><short>show all found instances (combined with other flags)</short></flag>
+ <flag name="info"><short>give more details</short></flag>
+ <flag name="track" value="list"><short>enable trackers</short></flag>
+ <flag name="statistics"><short>some info about the database</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+ <examples>
+ <category>
+ <title>Examples</title>
+ <subcategory>
+ <example><command>mtxrun --script font --list somename (== --pattern=*somename*)</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>
+ <subcategory>
+ <example><command>mtxrun --script font --list --spec somename</command></example>
+ <example><command>mtxrun --script font --list --spec somename-bold-italic</command></example>
+ <example><command>mtxrun --script font --list --spec --pattern=*somename*</command></example>
+ <example><command>mtxrun --script font --list --spec --filter="fontname=somename"</command></example>
+ <example><command>mtxrun --script font --list --spec --filter="familyname=somename,weight=bold,style=italic,width=condensed"</command></example>
+ <example><command>mtxrun --script font --list --spec --filter="familyname=crap*,weight=bold,style=italic"</command></example>
+ </subcategory>
+ <subcategory>
+ <example><command>mtxrun --script font --list --all</command></example>
+ <example><command>mtxrun --script font --list --file somename</command></example>
+ <example><command>mtxrun --script font --list --file --all somename</command></example>
+ <example><command>mtxrun --script font --list --file --pattern=*somename*</command></example>
+ </subcategory>
+ </category>
+ </examples>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-fonts",
+ banner = "ConTeXt Font Database Management 0.21",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+-- todo: fc-cache -v en check dirs, or better is: fc-cat -v | grep Directory
+
+if not fontloader then fontloader = fontforge end
+
+dofile(resolvers.findfile("font-otp.lua","tex")) -- we need to unpack the font for analysis
+dofile(resolvers.findfile("font-trt.lua","tex"))
+dofile(resolvers.findfile("font-syn.lua","tex"))
+dofile(resolvers.findfile("font-mis.lua","tex"))
+
+scripts = scripts or { }
+scripts.fonts = scripts.fonts or { }
+
+function fonts.names.statistics()
+ fonts.names.load()
+
+ local data = fonts.names.data
+ local statistics = data.statistics
+
+ local function counted(t)
+ local n = { }
+ for k, v in next, t do
+ n[k] = table.count(v)
+ end
+ return table.sequenced(n)
+ end
+
+ report("cache uuid : %s", data.cache_uuid)
+ report("cache version : %s", data.cache_version)
+ report("number of trees : %s", #data.datastate)
+ report()
+ report("number of fonts : %s", statistics.fonts or 0)
+ report("used files : %s", statistics.readfiles or 0)
+ report("skipped files : %s", statistics.skippedfiles or 0)
+ report("duplicate files : %s", statistics.duplicatefiles or 0)
+ report("specifications : %s", #data.specifications)
+ report("families : %s", table.count(data.families))
+ report()
+ report("mappings : %s", counted(data.mappings))
+ report("fallbacks : %s", counted(data.fallbacks))
+ report()
+ report("used styles : %s", table.sequenced(statistics.used_styles))
+ report("used variants : %s", table.sequenced(statistics.used_variants))
+ report("used weights : %s", table.sequenced(statistics.used_weights))
+ report("used widths : %s", table.sequenced(statistics.used_widths))
+ report()
+ report("found styles : %s", table.sequenced(statistics.styles))
+ report("found variants : %s", table.sequenced(statistics.variants))
+ report("found weights : %s", table.sequenced(statistics.weights))
+ report("found widths : %s", table.sequenced(statistics.widths))
+
+end
+
+function fonts.names.simple()
+ local simpleversion = 1.001
+ local simplelist = { "ttf", "otf", "ttc", "dfont" }
+ local name = "luatex-fonts-names.lua"
+ local path = file.collapsepath(caches.getwritablepath("..","..","generic","fonts","data"))
+ 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)
+ fonts.names.identify(true)
+ local data = fonts.names.data
+ if data then
+ local simplemappings = { }
+ local simplified = {
+ mappings = simplemappings,
+ version = simpleversion,
+ cache_version = simpleversion,
+ }
+ local specifications = data.specifications
+ for i=1,#simplelist do
+ local format = simplelist[i]
+ for tag, index in next, data.mappings[format] do
+ local s = specifications[index]
+ simplemappings[tag] = { s.rawname, s.filename, s.subfont }
+ end
+ end
+ if environment.arguments.nocache then
+ report("not using cache path %a",path)
+ else
+ dir.mkdirs(path)
+ if lfs.isdir(path) then
+ report("saving names on cache path %a",path)
+ name = file.join(path,name)
+ else
+ report("invalid cache path %a",path)
+ end
+ end
+ report("saving names in %a",name)
+ io.savedata(name,table.serialize(simplified,true))
+ local data = io.loaddata(resolvers.findfile("luatex-fonts-syn.lua","tex")) or ""
+ local dummy = string.match(data,"fonts%.names%.version%s*=%s*([%d%.]+)")
+ if tonumber(dummy) ~= simpleversion then
+ report("warning: version number %s in 'font-dum' does not match database version number %s",dummy or "?",simpleversion)
+ end
+ elseif lfs.isfile(name) then
+ os.remove(name)
+ end
+end
+
+function scripts.fonts.reload()
+ if getargument("simple") then
+ fonts.names.simple()
+ else
+ fonts.names.load(true,getargument("force"))
+ end
+end
+
+local function subfont(sf)
+ if sf then
+ return string.format("index: % 2s", sf)
+ else
+ return ""
+ end
+end
+
+local function fontweight(fw)
+ if fw then
+ return string.format("conflict: %s", fw)
+ else
+ return ""
+ end
+end
+
+local function showfeatures(tag,specification)
+ report()
+ report("mapping : %s",tag)
+ report("fontname: %s",specification.fontname)
+ report("fullname: %s",specification.fullname)
+ report("filename: %s",specification.filename)
+ report("family : %s",specification.familyname or "<nofamily>")
+ report("weight : %s",specification.weight or "<noweight>")
+ report("style : %s",specification.style or "<nostyle>")
+ report("width : %s",specification.width or "<nowidth>")
+ report("variant : %s",specification.variant or "<novariant>")
+ report("subfont : %s",subfont(specification.subfont))
+ report("fweight : %s",fontweight(specification.fontweight))
+ -- maybe more
+ local features = fonts.helpers.getfeatures(specification.filename,specification.format)
+ if features then
+ for what, v in table.sortedhash(features) do
+ local data = features[what]
+ if data and next(data) then
+ report()
+ report("%s features:",what)
+ report()
+ report("feature script languages")
+ report()
+ for f,ff in table.sortedhash(data) do
+ local done = false
+ for s, ss in table.sortedhash(ff) do
+ if s == "*" then s = "all" end
+ if ss ["*"] then ss["*"] = nil ss.all = true end
+ if done then
+ f = ""
+ else
+ done = true
+ end
+ report("% -8s % -8s % -8s",f,s,table.concat(table.sortedkeys(ss), " ")) -- todo: padd 4
+ end
+ end
+ end
+ end
+ else
+ report("no features")
+ end
+ report()
+end
+
+local function reloadbase(reload)
+ if reload then
+ report("fontnames, reloading font database")
+ names.load(true,getargument("force"))
+ report("fontnames, done\n\n")
+ end
+end
+
+local function list_specifications(t,info)
+ if t then
+ local s = table.sortedkeys(t)
+ if info then
+ for k=1,#s do
+ local v = s[k]
+ showfeatures(v,t[v])
+ end
+ else
+ for k=1,#s do
+ local v = s[k]
+ local entry = t[v]
+ s[k] = {
+ entry.familyname or "<nofamily>",
+ entry.weight or "<noweight>",
+ entry.style or "<nostyle>",
+ entry.width or "<nowidth>",
+ entry.variant or "<novariant>",
+ entry.fontname,
+ entry.filename,
+ subfont(entry.subfont),
+ fontweight(entry.fontweight),
+ }
+ end
+ utilities.formatters.formatcolumns(s)
+ for k=1,#s do
+ texio.write_nl(s[k])
+ end
+ end
+ end
+end
+
+local function list_matches(t,info)
+ if t then
+ local s, w = table.sortedkeys(t), { 0, 0, 0 }
+ if info then
+ for k=1,#s do
+ local v = s[k]
+ showfeatures(v,t[v])
+ end
+ else
+ for k=1,#s do
+ local v = s[k]
+ local entry = t[v]
+ s[k] = {
+ v,
+ entry.fontname,
+ entry.filename,
+ subfont(entry.subfont)
+ }
+ end
+ utilities.formatters.formatcolumns(s)
+ for k=1,#s do
+ texio.write_nl(s[k])
+ end
+ end
+ end
+end
+
+function scripts.fonts.list()
+
+ local all = getargument("all")
+ local info = getargument("info")
+ local reload = getargument("reload")
+ local pattern = getargument("pattern")
+ local filter = getargument("filter")
+ local given = givenfiles[1]
+
+ reloadbase(reload)
+
+ if getargument("name") then
+ if pattern then
+ --~ 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
+ 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*
+ report("not supported: --list --spec --pattern",name)
+ elseif filter then
+ --~ mtxrun --script font --list --spec --filter="fontname=somename"
+ list_specifications(fonts.names.getlookups(filter),info)
+ elseif given then
+ --~ 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*
+ 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
+ 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*
+ list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info)
+ elseif given then
+ --~ mtxrun --script font --list somename
+ list_matches(fonts.names.list(given,reload,all),info)
+ elseif all then
+ pattern = "*"
+ list_matches(fonts.names.list(string.topattern(pattern,true),reload,all),info)
+ else
+ report("not supported: --list <no specification>",name)
+ end
+
+end
+
+function scripts.fonts.justload()
+ local fullname = environment.files[1]
+ if fullname then
+ local result = fontloader.open(fullname)
+ if type(result) == "table" then
+ report("loading %s: %s","succeeded",fullname)
+ end
+ end
+ report("loading %s: %s","failed",fullname)
+end
+
+function scripts.fonts.unpack()
+ local name = file.removesuffix(file.basename(givenfiles[1] or ""))
+ if name and name ~= "" then
+ local cache = containers.define("fonts", "otf", 2.742, true)
+ local cleanname = containers.cleanname(name)
+ local data = containers.read(cache,cleanname)
+ if data then
+ local savename = file.addsuffix(cleanname .. "-unpacked","tma")
+ report("fontsave, saving data in %s",savename)
+ fonts.handlers.otf.enhancers.unpack(data)
+ io.savedata(savename,table.serialize(data,true))
+ else
+ report("unknown file %a",name)
+ end
+ end
+end
+
+function scripts.fonts.save()
+ local name = givenfiles[1] or ""
+ local sub = givenfiles[2] or ""
+ local function save(savename,fontblob)
+ if fontblob then
+ savename = file.addsuffix(string.lower(savename),"lua")
+ report("fontsave, saving data in %s",savename)
+ table.tofile(savename,fontloader.to_table(fontblob),"return")
+ fontloader.close(fontblob)
+ end
+ end
+ if name and name ~= "" then
+ local filename = resolvers.findfile(name) -- maybe also search for opentype
+ if filename and filename ~= "" then
+ local suffix = string.lower(file.suffix(filename))
+ if suffix == 'ttf' or suffix == 'otf' or suffix == 'ttc' or suffix == "dfont" then
+ local fontinfo = fontloader.info(filename)
+ if fontinfo then
+ report("font: %s located as %s",name,filename)
+ if fontinfo[1] then
+ for k=1,#fontinfo do
+ local v = fontinfo[k]
+ save(v.fontname,fontloader.open(filename,v.fullname))
+ end
+ else
+ save(fontinfo.fullname,fontloader.open(filename))
+ end
+ else
+ report("font: %s cannot be read",filename)
+ end
+ else
+ report("font: %s not saved",filename)
+ end
+ else
+ report("font: %s not found",name)
+ end
+ else
+ report("font: no name given")
+ end
+end
+
+if getargument("names") then
+ setargument("reload",true)
+ setargument("simple",true)
+end
+
+if getargument("list") then
+ scripts.fonts.list()
+elseif getargument("reload") then
+ scripts.fonts.reload()
+elseif getargument("save") then
+ scripts.fonts.save()
+elseif getargument("justload") then
+ scripts.fonts.justload()
+elseif getargument("unpack") then
+ scripts.fonts.unpack()
+elseif getargument("statistics") then
+ fonts.names.statistics()
+elseif getargument("exporthelp") then
+ application.export(getargument("exporthelp"),givenfiles[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-grep.lua b/scripts/context/lua/mtx-grep.lua index dbcce67f6..cd4856040 100644 --- a/scripts/context/lua/mtx-grep.lua +++ b/scripts/context/lua/mtx-grep.lua @@ -1,170 +1,170 @@ -if not modules then modules = { } end modules ['mtx-babel'] = { - 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 helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-grep</entry> - <entry name="detail">Simple Grepper</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="pattern"><short>search for pattern (optional)</short></flag> - <flag name="count"><short>count matches only</short></flag> - <flag name="nocomment"><short>skip lines that start with %% or #</short></flag> - <flag name="xml"><short>pattern is lpath expression</short></flag> - </subcategory> - </category> - </flags> - <comments> - <comment>patterns are lua patterns and need to be escaped accordingly</comment> - </comments> -</application> -]] - -local application = logs.application { - name = "mtx-grep", - banner = "Simple Grepper 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.grep = scripts.grep or { } - -local find, format = string.find, string.format - -local cr = lpeg.P("\r") -local lf = lpeg.P("\n") -local crlf = cr * lf -local newline = crlf + cr + lf -local content = lpeg.C((1-newline)^0) * newline + lpeg.C(lpeg.P(1)^1) - -local write_nl = texio.write_nl - - -- local pattern = "LIJST[@TYPE='BULLET']/LIJSTITEM[contains(text(),'Kern')]" - -function scripts.grep.find(pattern, files, offset) - if pattern and pattern ~= "" then - statistics.starttiming(scripts.grep) - local nofmatches, noffiles, nofmatchedfiles = 0, 0, 0 - local n, m, name, check = 0, 0, "", nil - local count, nocomment = environment.argument("count"), environment.argument("nocomment") - if environment.argument("xml") then - for i=offset or 1, #files do - local globbed = dir.glob(files[i]) - for i=1,#globbed do - local nam = globbed[i] - name = nam - local data = xml.load(name) - if data and not data.error then - n, m, noffiles = 0, 0, noffiles + 1 - if count then - for c in xml.collected(data,pattern) do - m = m + 1 - end - if m > 0 then - nofmatches = nofmatches + m - nofmatchedfiles = nofmatchedfiles + 1 - write_nl(format("%5i %s",m,name)) - io.flush() - end - else - for c in xml.collected(data,pattern) do - m = m + 1 - write_nl(format("%s: %s",name,xml.tostring(c))) - end - end - end - end - end - else - if nocomment then - if count then - check = function(line) - n = n + 1 - if find(line,"^[%%#]") then - -- skip - elseif find(line,pattern) then - m = m + 1 - end - end - else - check = function(line) - n = n + 1 - if find(line,"^[%%#]") then - -- skip - elseif find(line,pattern) then - m = m + 1 - write_nl(format("%s %6i: %s",name,n,line)) - io.flush() - end - end - end - else - if count then - check = function(line) - n = n + 1 - if find(line,pattern) then - m = m + 1 - end - end - else - check = function(line) - n = n + 1 - if find(line,pattern) then - m = m + 1 - write_nl(format("%s %6i: %s",name,n,line)) - io.flush() - end - end - end - end - local capture = (content/check)^0 - for i=offset or 1, #files do - local globbed = dir.glob(files[i]) - for i=1,#globbed do - local nam = globbed[i] - name = nam - local data = io.loaddata(name) - if data then - n, m, noffiles = 0, 0, noffiles + 1 - capture:match(data) - if count and m > 0 then - nofmatches = nofmatches + m - nofmatchedfiles = nofmatchedfiles + 1 - write_nl(format("%5i %s",m,name)) - io.flush() - end - end - end - end - end - statistics.stoptiming(scripts.grep) - if count and nofmatches > 0 then - write_nl(format("\nfiles: %s, matches: %s, matched files: %s, runtime: %0.3f seconds",noffiles,nofmatches,nofmatchedfiles,statistics.elapsedtime(scripts.grep))) - end - end -end - -local pattern = environment.argument("pattern") -local files = environment.files and #environment.files > 0 and environment.files - -if environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),files[1]) -elseif pattern and files then - scripts.grep.find(pattern, files) -elseif files then - scripts.grep.find(files[1], files, 2) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-babel'] = {
+ 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 helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-grep</entry>
+ <entry name="detail">Simple Grepper</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="pattern"><short>search for pattern (optional)</short></flag>
+ <flag name="count"><short>count matches only</short></flag>
+ <flag name="nocomment"><short>skip lines that start with %% or #</short></flag>
+ <flag name="xml"><short>pattern is lpath expression</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+ <comments>
+ <comment>patterns are lua patterns and need to be escaped accordingly</comment>
+ </comments>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-grep",
+ banner = "Simple Grepper 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.grep = scripts.grep or { }
+
+local find, format = string.find, string.format
+
+local cr = lpeg.P("\r")
+local lf = lpeg.P("\n")
+local crlf = cr * lf
+local newline = crlf + cr + lf
+local content = lpeg.C((1-newline)^0) * newline + lpeg.C(lpeg.P(1)^1)
+
+local write_nl = texio.write_nl
+
+ -- local pattern = "LIJST[@TYPE='BULLET']/LIJSTITEM[contains(text(),'Kern')]"
+
+function scripts.grep.find(pattern, files, offset)
+ if pattern and pattern ~= "" then
+ statistics.starttiming(scripts.grep)
+ local nofmatches, noffiles, nofmatchedfiles = 0, 0, 0
+ local n, m, name, check = 0, 0, "", nil
+ local count, nocomment = environment.argument("count"), environment.argument("nocomment")
+ if environment.argument("xml") then
+ for i=offset or 1, #files do
+ local globbed = dir.glob(files[i])
+ for i=1,#globbed do
+ local nam = globbed[i]
+ name = nam
+ local data = xml.load(name)
+ if data and not data.error then
+ n, m, noffiles = 0, 0, noffiles + 1
+ if count then
+ for c in xml.collected(data,pattern) do
+ m = m + 1
+ end
+ if m > 0 then
+ nofmatches = nofmatches + m
+ nofmatchedfiles = nofmatchedfiles + 1
+ write_nl(format("%5i %s",m,name))
+ io.flush()
+ end
+ else
+ for c in xml.collected(data,pattern) do
+ m = m + 1
+ write_nl(format("%s: %s",name,xml.tostring(c)))
+ end
+ end
+ end
+ end
+ end
+ else
+ if nocomment then
+ if count then
+ check = function(line)
+ n = n + 1
+ if find(line,"^[%%#]") then
+ -- skip
+ elseif find(line,pattern) then
+ m = m + 1
+ end
+ end
+ else
+ check = function(line)
+ n = n + 1
+ if find(line,"^[%%#]") then
+ -- skip
+ elseif find(line,pattern) then
+ m = m + 1
+ write_nl(format("%s %6i: %s",name,n,line))
+ io.flush()
+ end
+ end
+ end
+ else
+ if count then
+ check = function(line)
+ n = n + 1
+ if find(line,pattern) then
+ m = m + 1
+ end
+ end
+ else
+ check = function(line)
+ n = n + 1
+ if find(line,pattern) then
+ m = m + 1
+ write_nl(format("%s %6i: %s",name,n,line))
+ io.flush()
+ end
+ end
+ end
+ end
+ local capture = (content/check)^0
+ for i=offset or 1, #files do
+ local globbed = dir.glob(files[i])
+ for i=1,#globbed do
+ local nam = globbed[i]
+ name = nam
+ local data = io.loaddata(name)
+ if data then
+ n, m, noffiles = 0, 0, noffiles + 1
+ capture:match(data)
+ if count and m > 0 then
+ nofmatches = nofmatches + m
+ nofmatchedfiles = nofmatchedfiles + 1
+ write_nl(format("%5i %s",m,name))
+ io.flush()
+ end
+ end
+ end
+ end
+ end
+ statistics.stoptiming(scripts.grep)
+ if count and nofmatches > 0 then
+ write_nl(format("\nfiles: %s, matches: %s, matched files: %s, runtime: %0.3f seconds",noffiles,nofmatches,nofmatchedfiles,statistics.elapsedtime(scripts.grep)))
+ end
+ end
+end
+
+local pattern = environment.argument("pattern")
+local files = environment.files and #environment.files > 0 and environment.files
+
+if environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),files[1])
+elseif pattern and files then
+ scripts.grep.find(pattern, files)
+elseif files then
+ scripts.grep.find(files[1], files, 2)
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-metatex.lua b/scripts/context/lua/mtx-metatex.lua index 455ecbd52..ff13d00e3 100644 --- a/scripts/context/lua/mtx-metatex.lua +++ b/scripts/context/lua/mtx-metatex.lua @@ -1,80 +1,80 @@ -if not modules then modules = { } end modules ['mtx-metatex'] = { - 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" -} - --- future versions will deal with specific variants of metatex - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-metatex</entry> - <entry name="detail">MetaTeX Process Management</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="run"><short>process (one or more) files (default action)</short></flag> - <flag name="make"><short>create metatex format(s)</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-metatex", - banner = "MetaTeX Process Management 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.metatex = scripts.metatex or { } - --- metatex - -function scripts.metatex.make() - environment.make_format("metatex") -end - -function scripts.metatex.run(ctxdata,filename) - local filename = environment.files[1] or "" - if filename ~= "" then - local formatfile, scriptfile = resolvers.locateformat("metatex") - if formatfile and scriptfile then - local command = string.format("luatex --fmt=%s --lua=%s %s", - string.quote(formatfile), string.quote(scriptfile), string.quote(filename)) - report("running command: %s",command) - os.spawn(command) - elseif formatname then - report("error, no format found with name: %s",formatname) - else - report("error, no format found (provide formatname or interface)") - end - end -end - -function scripts.metatex.timed(action) - statistics.timed(action) -end - -if environment.argument("run") then - scripts.metatex.timed(scripts.metatex.run) -elseif environment.argument("make") then - scripts.metatex.timed(scripts.metatex.make) -elseif environment.argument("help") then - logs.help(messages.help,false) -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -elseif environment.files[1] then - scripts.metatex.timed(scripts.metatex.run) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-metatex'] = {
+ 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"
+}
+
+-- future versions will deal with specific variants of metatex
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-metatex</entry>
+ <entry name="detail">MetaTeX Process Management</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="run"><short>process (one or more) files (default action)</short></flag>
+ <flag name="make"><short>create metatex format(s)</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-metatex",
+ banner = "MetaTeX Process Management 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.metatex = scripts.metatex or { }
+
+-- metatex
+
+function scripts.metatex.make()
+ environment.make_format("metatex")
+end
+
+function scripts.metatex.run(ctxdata,filename)
+ local filename = environment.files[1] or ""
+ if filename ~= "" then
+ local formatfile, scriptfile = resolvers.locateformat("metatex")
+ if formatfile and scriptfile then
+ local command = string.format("luatex --fmt=%s --lua=%s %s",
+ string.quote(formatfile), string.quote(scriptfile), string.quote(filename))
+ report("running command: %s",command)
+ os.spawn(command)
+ elseif formatname then
+ report("error, no format found with name: %s",formatname)
+ else
+ report("error, no format found (provide formatname or interface)")
+ end
+ end
+end
+
+function scripts.metatex.timed(action)
+ statistics.timed(action)
+end
+
+if environment.argument("run") then
+ scripts.metatex.timed(scripts.metatex.run)
+elseif environment.argument("make") then
+ scripts.metatex.timed(scripts.metatex.make)
+elseif environment.argument("help") then
+ logs.help(messages.help,false)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+elseif environment.files[1] then
+ scripts.metatex.timed(scripts.metatex.run)
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-mk-help.lua b/scripts/context/lua/mtx-mk-help.lua index 794bbca37..68ad16f93 100644 --- a/scripts/context/lua/mtx-mk-help.lua +++ b/scripts/context/lua/mtx-mk-help.lua @@ -1,473 +1,473 @@ -if not modules then modules = { } end modules ['mtx-mk-help'] = { - version = 1.001, - comment = "a script for making help files", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - ---[[ - -mtxrun --exporthelp=all %targetpath%\mkiv\mtxrun.tmp -context --exporthelp=all %targetpath%\mkiv\context.tmp -mtxrun --script context --exporthelp=all %targetpath%\mkiv\mtx-context.tmp - -mtxrun --script babel --exporthelp=all %targetpath%\mkiv\mtx-babel.tmp -mtxrun --script base --exporthelp=all %targetpath%\mkiv\mtx-base.tmp -mtxrun --script cache --exporthelp=all %targetpath%\mkiv\mtx-cache.tmp -mtxrun --script chars --exporthelp=all %targetpath%\mkiv\mtx-chars.tmp -mtxrun --script check --exporthelp=all %targetpath%\mkiv\mtx-check.tmp -mtxrun --script colors --exporthelp=all %targetpath%\mkiv\mtx-colors.tmp -mtxrun --script convert --exporthelp=all %targetpath%\mkiv\mtx-convert.tmp -mtxrun --script epub --exporthelp=all %targetpath%\mkiv\mtx-epub.tmp -mtxrun --script fcd --exporthelp=all %targetpath%\mkiv\mtx-fcd.tmp -mtxrun --script flac --exporthelp=all %targetpath%\mkiv\mtx-flac.tmp -mtxrun --script fonts --exporthelp=all %targetpath%\mkiv\mtx-fonts.tmp -mtxrun --script grep --exporthelp=all %targetpath%\mkiv\mtx-grep.tmp -mtxrun --script interface --exporthelp=all %targetpath%\mkiv\mtx-interface.tmp -mtxrun --script metapost --exporthelp=all %targetpath%\mkiv\mtx-metapost.tmp -mtxrun --script metatex --exporthelp=all %targetpath%\mkiv\mtx-metatex.tmp -mtxrun --script modules --exporthelp=all %targetpath%\mkiv\mtx-modules.tmp -mtxrun --script mtxworks --exporthelp=all %targetpath%\mkiv\mtx-mtxworks.tmp -mtxrun --script package --exporthelp=all %targetpath%\mkiv\mtx-package.tmp -mtxrun --script patterns --exporthelp=all %targetpath%\mkiv\mtx-patterns.tmp -mtxrun --script pdf --exporthelp=all %targetpath%\mkiv\mtx-pdf.tmp -mtxrun --script profile --exporthelp=all %targetpath%\mkiv\mtx-profile.tmp -mtxrun --script rsync --exporthelp=all %targetpath%\mkiv\mtx-rsync.tmp -mtxrun --script scite --exporthelp=all %targetpath%\mkiv\mtx-scite.tmp -mtxrun --script server --exporthelp=all %targetpath%\mkiv\mtx-server.tmp -mtxrun --script texworks --exporthelp=all %targetpath%\mkiv\mtx-texworks.tmp -mtxrun --script timing --exporthelp=all %targetpath%\mkiv\mtx-timing.tmp -mtxrun --script tools --exporthelp=all %targetpath%\mkiv\mtx-tools.tmp -mtxrun --script unzip --exporthelp=all %targetpath%\mkiv\mtx-unzip.tmp -mtxrun --script update --exporthelp=all %targetpath%\mkiv\mtx-update.tmp -mtxrun --script watch --exporthelp=all %targetpath%\mkiv\mtx-watch.tmp - -mtxrun --script mk-help luatools --exporthelp=all %targetpath%\mkiv\luatools.tmp - -mtxrun --script mk-help texmfstart --exporthelp=all %targetpath%\mkii\texmfstart.tmp -mtxrun --script mk-help texexec --exporthelp=all %targetpath%\mkii\texexec.tmp -mtxrun --script mk-help texutil --exporthelp=all %targetpath%\mkii\texutil.tmp -mtxrun --script mk-help ctxtools --exporthelp=all %targetpath%\mkii\ctxtools.tmp -mtxrun --script mk-help textools --exporthelp=all %targetpath%\mkii\textools.tmp -mtxrun --script mk-help pdftools --exporthelp=all %targetpath%\mkii\pdftools.tmp -mtxrun --script mk-help tmftools --exporthelp=all %targetpath%\mkii\tmftools.tmp -mtxrun --script mk-help xmltools --exporthelp=all %targetpath%\mkii\xmltools.tmp -mtxrun --script mk-help pstopdf --exporthelp=all %targetpath%\mkii\pstopdf.tmp -mtxrun --script mk-help rlxtools --exporthelp=all %targetpath%\mkii\rlxtools.tmp -mtxrun --script mk-help imgtopdf --exporthelp=all %targetpath%\mkii\imgtopdf.tmp - -]]-- - -local helpinfo = os.resultof("mtxrun --exporthelp") or "" -local helpinfo = string.match(helpinfo,[[^.-(<application>.-</application>)]]) or [[<application></application>]] - -local texmfstart = logs.application { - name = "texmfstart", - banner = "texmfstart 7.0.0", - helpinfo = [[<?xml version="1.0"?>]] .. helpinfo, -} - --- let's also put luatools here: - -local helpinfo = os.resultof("luatools --exporthelp") or "" -local helpinfo = string.match(helpinfo,[[^.-(<application>.-</application>)]]) or [[<application></application>]] -local helpinfo = string.gsub(helpinfo,"mtx%-base","luatools") - -local luatools = logs.application { - name = "luatools", - banner = "luatools 1.35", - helpinfo = [[<?xml version="1.0"?>]] .. helpinfo, -} - --- - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">texexec</entry> - <entry name="detail">TeXExec</entry> - <entry name="version">6.2.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="make"><short>make formats</short></flag> - <flag name="check"><short>check versions</short></flag> - <flag name="process"><short>process file</short></flag> - <flag name="mptex"><short>process mp file</short></flag> - <flag name="mpxtex"><short>process mpx file</short></flag> - <flag name="mpgraphic"><short>process mp file to stand-alone graphics</short></flag> - <flag name="mpstatic"><short>process mp/ctx file to stand-alone graphics</short></flag> - <flag name="listing"><short>list of file content</short></flag> - <flag name="figures"><short>generate overview of figures</short></flag> - <flag name="modules"><short>generate module documentation</short></flag> - <flag name="pdfarrange"><short>impose pages (booklets)</short></flag> - <flag name="pdfselect"><short>select pages from file(s)</short></flag> - <flag name="pdfcopy"><short>copy pages from file(s)</short></flag> - <flag name="pdftrim"><short>trim pages from file(s)</short></flag> - <flag name="pdfcombine"><short>combine multiple pages</short></flag> - <flag name="pdfsplit"><short>split file in pages</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local texexec = logs.application { - name = "texexec", - banner = "TeXExec 6.2.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">texutil</entry> - <entry name="detail">TeXUtil</entry> - <entry name="version">9.1.0</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="references"><short>convert tui file into tuo file</short></flag> - <flag name="figures"><short>generate figure dimensions file</short></flag> - <flag name="logfile"><short>filter essential log messages</short></flag> - <flag name="purgefiles"><short>remove most temporary files</short></flag> - <flag name="purgeallfiles"><short>remove all temporary files</short></flag> - <flag name="documentation"><short>generate documentation file from source</short></flag> - <flag name="analyzefile"><short>analyze pdf file</short></flag> - </subcategory> - </category> - </flags> -</application>]] - -local texutil = logs.application { - name = "texutil", - banner = "TeXUtil 9.1.0", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">ctxtools</entry> - <entry name="detail">CtxTools</entry> - <entry name="version">1.3.5</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="touchcontextfile"><short>update context version</short></flag> - <flag name="contextversion"><short>report context version</short></flag> - <flag name="jeditinterface"><short>generate jedit syntax files [<ref name="pipe]"/></short></flag> - <flag name="bbeditinterface"><short>generate bbedit syntax files [<ref name="pipe]"/></short></flag> - <flag name="sciteinterface"><short>generate scite syntax files [<ref name="pipe]"/></short></flag> - <flag name="rawinterface"><short>generate raw syntax files [<ref name="pipe]"/></short></flag> - <flag name="translateinterface"><short>generate interface files (xml) [nl de ..]</short></flag> - <flag name="purgefiles"><short>remove temporary files [<ref name="all"/> <ref name="recurse]"/> [basename]</short></flag> - <flag name="documentation generate documentation [--type" value="]"><short>[filename]</short></flag> - <flag name="filterpages'"><short>) # no help, hidden temporary feature</short></flag> - <flag name="dpxmapfiles"><short>convert pdftex mapfiles to dvipdfmx [<ref name="force]"/> [texmfroot]</short></flag> - <flag name="listentities"><short>create doctype entity definition from enco-uc.tex</short></flag> - <flag name="brandfiles"><short>add context copyright notice [<ref name="force]"/></short></flag> - <flag name="platformize"><short>replace line-endings [<ref name="recurse"/> <ref name="force]"/> [pattern]</short></flag> - <flag name="dependencies analyze depedencies within context [--save --compact --filter" value="[macros|filenames] ]"><short>[filename]</short></flag> - <flag name="updatecontext"><short>download latest version and remake formats [<ref name="proxy]"/></short></flag> - <flag name="disarmutfbom"><short>remove utf bom [<ref name="force]"/></short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local ctxtools = logs.application { - name = "ctxtools", - banner = "CtxTools 1.3.5", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">textools</entry> - <entry name="detail">TeXTools</entry> - <entry name="version">1.3.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="removemapnames"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="restoremapnames"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="hidemapnames"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="videmapnames"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="findfile"><short>filename [<ref name="recurse]"/></short></flag> - <flag name="unzipfiles"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="fixafmfiles"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="mactodos"><short>[pattern] [<ref name="recurse]"/></short></flag> - <flag name="fixtexmftrees"><short>[texmfroot] [<ref name="force]"/></short></flag> - <flag name="replacefile"><short>filename [<ref name="force]"/></short></flag> - <flag name="updatetree"><short>fromroot toroot [<ref name="force"/> <ref name="nocheck"/> <ref name="merge"/> <ref name="delete]"/></short></flag> - <flag name="downcasefilenames"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag> - <flag name="stripformfeeds"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag> - <flag name="showfont"><short>filename</short></flag> - <flag name="encmake"><short>afmfile encodingname</short></flag> - <flag name="tpmmake"><short>tpm file (run in texmf root)</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local textools = logs.application { - name = "textools", - banner = "TeXTools 1.3.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">pdftools</entry> - <entry name="detail">PDFTools</entry> - <entry name="version">1.2.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="spotimage filename --colorspec" value=""><short><ref name="colorname="/> [<ref name="retain"/> <ref name="invert"/> <ref name="subpath=]"/></short></flag> - <flag name="colorimage filename --colorspec" value=""><short>[<ref name="retain"/> <ref name="invert"/> <ref name="colorname="/> ]</short></flag> - <flag name="convertimage"><short>filename [<ref name="retain"/> <ref name="subpath]"/></short></flag> - <flag name="downsampleimage"><short>filename [<ref name="retain"/> <ref name="subpath"/> <ref name="lowres"/> <ref name="normal]"/></short></flag> - <flag name="info"><short>filename</short></flag> - <flag name="countpages"><short>[<ref name="pattern"/> <ref name="threshold]"/></short></flag> - <flag name="checkembedded"><short>[<ref name="pattern]"/></short></flag> - <flag name="analyzefile"><short>filename</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local pdftools = logs.application { - name = "pdftools", - banner = "PDFTools 1.2.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">tmftools</entry> - <entry name="detail">TMFTools</entry> - <entry name="version">1.1.0</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="analyze"><short>[<ref name="strict"/> <ref name="sort"/> <ref name="rootpath"/> <ref name="treepath"/> <ref name="delete"/> <ref name="force"/>] [pattern]</short></flag> - </subcategory> - <subcategory> - <flag name="serve"><short>act as kpse server</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local tmftools = logs.application { - name = "tmftools", - banner = "TMFTools 1.2.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">xmltools</entry> - <entry name="detail">XMLTools</entry> - <entry name="version">1.2.2</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="dir"><short>generate directory listing</short></flag> - <flag name="mmlpages"><short>generate graphic from mathml</short></flag> - <flag name="analyze"><short>report entities and elements [<ref name="utf"/> <ref name="process"/>]</short></flag> - <flag name="cleanup"><short>cleanup xml file [<ref name="force"/>]</short></flag> - <flag name="enhance"><short>enhance xml file (partial)</short></flag> - <flag name="filter"><short>filter elements from xml file [<ref name="element"/>]</short></flag> - <flag name="dir"><short>generate ddirectory listing</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local xmltools = logs.application { - name = "xmltools", - banner = "XMLTools 1.2.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">pstopdf</entry> - <entry name="detail">PStoPDF</entry> - <entry name="version">2.0.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="request"><short>handles exa request file</short></flag> - <flag name="watch"><short>watch folders for conversions (untested)</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local pstopdf = logs.application { - name = "pstopdf", - banner = "PStoPDF 2.0.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">rlxtools</entry> - <entry name="detail">RlxTools</entry> - <entry name="version">1.0.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="manipulate"><short>[<ref name="test]"/> manipulatorfile resourselog</short></flag> - <flag name="identify"><short>[<ref name="collect]"/> filename</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local rlxtools = logs.application { - name = "rlxtools", - banner = "RlxTools 1.0.1", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">imgtopdf</entry> - <entry name="detail">ImgToPdf</entry> - <entry name="version">1.1.2</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="convert"><short>convert image into pdf</short></flag> - <flag name="compression"><short>level of compression in percent</short></flag> - <flag name="depth"><short>image depth in bits</short></flag> - <flag name="colorspace"><short> colorspace (rgb,cmyk,gray)</short></flag> - <flag name="quality"><short>quality in percent</short></flag> - <flag name="inputpath"><short>path where files are looked for</short></flag> - <flag name="outputpath"><short>path where files end up</short></flag> - <flag name="auto"><short>determine settings automatically</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local imgtopdf = logs.application { - name = "imgtopdf", - banner = "ImgToPdf 1.1.2", - helpinfo = helpinfo, -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mptopdf</entry> - <entry name="detail">convert MetaPost to PDF</entry> - <entry name="version">1.4.1</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="metafun"><short>use the metafun format to process the file (default is mpost)</short></flag> - <flag name="texexec"><short>use texexec (context) to process text snippets</short></flag> - <flag name="latex"><short>use latex to process text snippets</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local mptopdf = logs.application { - name = "mptopdf", - banner = "MPtoPDF 1.4.1", - helpinfo = helpinfo, -} - --- texmfstart.rb is normally replaced by mtxrun --- runtools.rb is run from within context --- concheck.rb is run from within editors --- texsync.rb is no longer in the zip --- mpstools.rb is no longer in the zip --- rscortool.rb is only run indirectly --- rsfiltool.rb is only run indirectly --- rslibtool.rb is only run indirectly - -local application = logs.application { - name = "mk-help", - banner = "Mk Help generator 1.00", -} - -local filename = environment.files[1] - -if not filename then - application.report("no mk script given") - return -end - -local mkapplication - -if filename == "texmfstart" then mkapplication = texmfstart -elseif filename == "luatools" then mkapplication = luatools -elseif filename == "texexec" then mkapplication = texexec -elseif filename == "texutil" then mkapplication = texutil -elseif filename == "ctxtools" then mkapplication = ctxtools -elseif filename == "textools" then mkapplication = textools -elseif filename == "pdftools" then mkapplication = pdftools -elseif filename == "tmftools" then mkapplication = tmftools -elseif filename == "xmltools" then mkapplication = xmltools -elseif filename == "pstopdf" then mkapplication = pstopdf -elseif filename == "rlxtools" then mkapplication = rlxtools -elseif filename == "imgtopdf" then mkapplication = imgtopdf -elseif filename == "mptopdf" then mkapplication = mptopdf end - -if not mkapplication then - application.report("no valid mk script given") - return -end - -if environment.argument("exporthelp") then - mkapplication.export(environment.argument("exporthelp"),environment.files[2]) -else - mkapplication.help() -end +if not modules then modules = { } end modules ['mtx-mk-help'] = {
+ version = 1.001,
+ comment = "a script for making help files",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+--[[
+
+mtxrun --exporthelp=all %targetpath%\mkiv\mtxrun.tmp
+context --exporthelp=all %targetpath%\mkiv\context.tmp
+mtxrun --script context --exporthelp=all %targetpath%\mkiv\mtx-context.tmp
+
+mtxrun --script babel --exporthelp=all %targetpath%\mkiv\mtx-babel.tmp
+mtxrun --script base --exporthelp=all %targetpath%\mkiv\mtx-base.tmp
+mtxrun --script cache --exporthelp=all %targetpath%\mkiv\mtx-cache.tmp
+mtxrun --script chars --exporthelp=all %targetpath%\mkiv\mtx-chars.tmp
+mtxrun --script check --exporthelp=all %targetpath%\mkiv\mtx-check.tmp
+mtxrun --script colors --exporthelp=all %targetpath%\mkiv\mtx-colors.tmp
+mtxrun --script convert --exporthelp=all %targetpath%\mkiv\mtx-convert.tmp
+mtxrun --script epub --exporthelp=all %targetpath%\mkiv\mtx-epub.tmp
+mtxrun --script fcd --exporthelp=all %targetpath%\mkiv\mtx-fcd.tmp
+mtxrun --script flac --exporthelp=all %targetpath%\mkiv\mtx-flac.tmp
+mtxrun --script fonts --exporthelp=all %targetpath%\mkiv\mtx-fonts.tmp
+mtxrun --script grep --exporthelp=all %targetpath%\mkiv\mtx-grep.tmp
+mtxrun --script interface --exporthelp=all %targetpath%\mkiv\mtx-interface.tmp
+mtxrun --script metapost --exporthelp=all %targetpath%\mkiv\mtx-metapost.tmp
+mtxrun --script metatex --exporthelp=all %targetpath%\mkiv\mtx-metatex.tmp
+mtxrun --script modules --exporthelp=all %targetpath%\mkiv\mtx-modules.tmp
+mtxrun --script mtxworks --exporthelp=all %targetpath%\mkiv\mtx-mtxworks.tmp
+mtxrun --script package --exporthelp=all %targetpath%\mkiv\mtx-package.tmp
+mtxrun --script patterns --exporthelp=all %targetpath%\mkiv\mtx-patterns.tmp
+mtxrun --script pdf --exporthelp=all %targetpath%\mkiv\mtx-pdf.tmp
+mtxrun --script profile --exporthelp=all %targetpath%\mkiv\mtx-profile.tmp
+mtxrun --script rsync --exporthelp=all %targetpath%\mkiv\mtx-rsync.tmp
+mtxrun --script scite --exporthelp=all %targetpath%\mkiv\mtx-scite.tmp
+mtxrun --script server --exporthelp=all %targetpath%\mkiv\mtx-server.tmp
+mtxrun --script texworks --exporthelp=all %targetpath%\mkiv\mtx-texworks.tmp
+mtxrun --script timing --exporthelp=all %targetpath%\mkiv\mtx-timing.tmp
+mtxrun --script tools --exporthelp=all %targetpath%\mkiv\mtx-tools.tmp
+mtxrun --script unzip --exporthelp=all %targetpath%\mkiv\mtx-unzip.tmp
+mtxrun --script update --exporthelp=all %targetpath%\mkiv\mtx-update.tmp
+mtxrun --script watch --exporthelp=all %targetpath%\mkiv\mtx-watch.tmp
+
+mtxrun --script mk-help luatools --exporthelp=all %targetpath%\mkiv\luatools.tmp
+
+mtxrun --script mk-help texmfstart --exporthelp=all %targetpath%\mkii\texmfstart.tmp
+mtxrun --script mk-help texexec --exporthelp=all %targetpath%\mkii\texexec.tmp
+mtxrun --script mk-help texutil --exporthelp=all %targetpath%\mkii\texutil.tmp
+mtxrun --script mk-help ctxtools --exporthelp=all %targetpath%\mkii\ctxtools.tmp
+mtxrun --script mk-help textools --exporthelp=all %targetpath%\mkii\textools.tmp
+mtxrun --script mk-help pdftools --exporthelp=all %targetpath%\mkii\pdftools.tmp
+mtxrun --script mk-help tmftools --exporthelp=all %targetpath%\mkii\tmftools.tmp
+mtxrun --script mk-help xmltools --exporthelp=all %targetpath%\mkii\xmltools.tmp
+mtxrun --script mk-help pstopdf --exporthelp=all %targetpath%\mkii\pstopdf.tmp
+mtxrun --script mk-help rlxtools --exporthelp=all %targetpath%\mkii\rlxtools.tmp
+mtxrun --script mk-help imgtopdf --exporthelp=all %targetpath%\mkii\imgtopdf.tmp
+
+]]--
+
+local helpinfo = os.resultof("mtxrun --exporthelp") or ""
+local helpinfo = string.match(helpinfo,[[^.-(<application>.-</application>)]]) or [[<application></application>]]
+
+local texmfstart = logs.application {
+ name = "texmfstart",
+ banner = "texmfstart 7.0.0",
+ helpinfo = [[<?xml version="1.0"?>]] .. helpinfo,
+}
+
+-- let's also put luatools here:
+
+local helpinfo = os.resultof("luatools --exporthelp") or ""
+local helpinfo = string.match(helpinfo,[[^.-(<application>.-</application>)]]) or [[<application></application>]]
+local helpinfo = string.gsub(helpinfo,"mtx%-base","luatools")
+
+local luatools = logs.application {
+ name = "luatools",
+ banner = "luatools 1.35",
+ helpinfo = [[<?xml version="1.0"?>]] .. helpinfo,
+}
+
+--
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">texexec</entry>
+ <entry name="detail">TeXExec</entry>
+ <entry name="version">6.2.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="make"><short>make formats</short></flag>
+ <flag name="check"><short>check versions</short></flag>
+ <flag name="process"><short>process file</short></flag>
+ <flag name="mptex"><short>process mp file</short></flag>
+ <flag name="mpxtex"><short>process mpx file</short></flag>
+ <flag name="mpgraphic"><short>process mp file to stand-alone graphics</short></flag>
+ <flag name="mpstatic"><short>process mp/ctx file to stand-alone graphics</short></flag>
+ <flag name="listing"><short>list of file content</short></flag>
+ <flag name="figures"><short>generate overview of figures</short></flag>
+ <flag name="modules"><short>generate module documentation</short></flag>
+ <flag name="pdfarrange"><short>impose pages (booklets)</short></flag>
+ <flag name="pdfselect"><short>select pages from file(s)</short></flag>
+ <flag name="pdfcopy"><short>copy pages from file(s)</short></flag>
+ <flag name="pdftrim"><short>trim pages from file(s)</short></flag>
+ <flag name="pdfcombine"><short>combine multiple pages</short></flag>
+ <flag name="pdfsplit"><short>split file in pages</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local texexec = logs.application {
+ name = "texexec",
+ banner = "TeXExec 6.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">texutil</entry>
+ <entry name="detail">TeXUtil</entry>
+ <entry name="version">9.1.0</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="references"><short>convert tui file into tuo file</short></flag>
+ <flag name="figures"><short>generate figure dimensions file</short></flag>
+ <flag name="logfile"><short>filter essential log messages</short></flag>
+ <flag name="purgefiles"><short>remove most temporary files</short></flag>
+ <flag name="purgeallfiles"><short>remove all temporary files</short></flag>
+ <flag name="documentation"><short>generate documentation file from source</short></flag>
+ <flag name="analyzefile"><short>analyze pdf file</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>]]
+
+local texutil = logs.application {
+ name = "texutil",
+ banner = "TeXUtil 9.1.0",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">ctxtools</entry>
+ <entry name="detail">CtxTools</entry>
+ <entry name="version">1.3.5</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="touchcontextfile"><short>update context version</short></flag>
+ <flag name="contextversion"><short>report context version</short></flag>
+ <flag name="jeditinterface"><short>generate jedit syntax files [<ref name="pipe]"/></short></flag>
+ <flag name="bbeditinterface"><short>generate bbedit syntax files [<ref name="pipe]"/></short></flag>
+ <flag name="sciteinterface"><short>generate scite syntax files [<ref name="pipe]"/></short></flag>
+ <flag name="rawinterface"><short>generate raw syntax files [<ref name="pipe]"/></short></flag>
+ <flag name="translateinterface"><short>generate interface files (xml) [nl de ..]</short></flag>
+ <flag name="purgefiles"><short>remove temporary files [<ref name="all"/> <ref name="recurse]"/> [basename]</short></flag>
+ <flag name="documentation generate documentation [--type" value="]"><short>[filename]</short></flag>
+ <flag name="filterpages'"><short>) # no help, hidden temporary feature</short></flag>
+ <flag name="dpxmapfiles"><short>convert pdftex mapfiles to dvipdfmx [<ref name="force]"/> [texmfroot]</short></flag>
+ <flag name="listentities"><short>create doctype entity definition from enco-uc.tex</short></flag>
+ <flag name="brandfiles"><short>add context copyright notice [<ref name="force]"/></short></flag>
+ <flag name="platformize"><short>replace line-endings [<ref name="recurse"/> <ref name="force]"/> [pattern]</short></flag>
+ <flag name="dependencies analyze depedencies within context [--save --compact --filter" value="[macros|filenames] ]"><short>[filename]</short></flag>
+ <flag name="updatecontext"><short>download latest version and remake formats [<ref name="proxy]"/></short></flag>
+ <flag name="disarmutfbom"><short>remove utf bom [<ref name="force]"/></short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local ctxtools = logs.application {
+ name = "ctxtools",
+ banner = "CtxTools 1.3.5",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">textools</entry>
+ <entry name="detail">TeXTools</entry>
+ <entry name="version">1.3.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="removemapnames"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="restoremapnames"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="hidemapnames"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="videmapnames"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="findfile"><short>filename [<ref name="recurse]"/></short></flag>
+ <flag name="unzipfiles"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="fixafmfiles"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="mactodos"><short>[pattern] [<ref name="recurse]"/></short></flag>
+ <flag name="fixtexmftrees"><short>[texmfroot] [<ref name="force]"/></short></flag>
+ <flag name="replacefile"><short>filename [<ref name="force]"/></short></flag>
+ <flag name="updatetree"><short>fromroot toroot [<ref name="force"/> <ref name="nocheck"/> <ref name="merge"/> <ref name="delete]"/></short></flag>
+ <flag name="downcasefilenames"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag>
+ <flag name="stripformfeeds"><short>[<ref name="recurse]"/> [<ref name="force]"/></short></flag>
+ <flag name="showfont"><short>filename</short></flag>
+ <flag name="encmake"><short>afmfile encodingname</short></flag>
+ <flag name="tpmmake"><short>tpm file (run in texmf root)</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local textools = logs.application {
+ name = "textools",
+ banner = "TeXTools 1.3.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">pdftools</entry>
+ <entry name="detail">PDFTools</entry>
+ <entry name="version">1.2.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="spotimage filename --colorspec" value=""><short><ref name="colorname="/> [<ref name="retain"/> <ref name="invert"/> <ref name="subpath=]"/></short></flag>
+ <flag name="colorimage filename --colorspec" value=""><short>[<ref name="retain"/> <ref name="invert"/> <ref name="colorname="/> ]</short></flag>
+ <flag name="convertimage"><short>filename [<ref name="retain"/> <ref name="subpath]"/></short></flag>
+ <flag name="downsampleimage"><short>filename [<ref name="retain"/> <ref name="subpath"/> <ref name="lowres"/> <ref name="normal]"/></short></flag>
+ <flag name="info"><short>filename</short></flag>
+ <flag name="countpages"><short>[<ref name="pattern"/> <ref name="threshold]"/></short></flag>
+ <flag name="checkembedded"><short>[<ref name="pattern]"/></short></flag>
+ <flag name="analyzefile"><short>filename</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local pdftools = logs.application {
+ name = "pdftools",
+ banner = "PDFTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">tmftools</entry>
+ <entry name="detail">TMFTools</entry>
+ <entry name="version">1.1.0</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="analyze"><short>[<ref name="strict"/> <ref name="sort"/> <ref name="rootpath"/> <ref name="treepath"/> <ref name="delete"/> <ref name="force"/>] [pattern]</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="serve"><short>act as kpse server</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local tmftools = logs.application {
+ name = "tmftools",
+ banner = "TMFTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">xmltools</entry>
+ <entry name="detail">XMLTools</entry>
+ <entry name="version">1.2.2</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="dir"><short>generate directory listing</short></flag>
+ <flag name="mmlpages"><short>generate graphic from mathml</short></flag>
+ <flag name="analyze"><short>report entities and elements [<ref name="utf"/> <ref name="process"/>]</short></flag>
+ <flag name="cleanup"><short>cleanup xml file [<ref name="force"/>]</short></flag>
+ <flag name="enhance"><short>enhance xml file (partial)</short></flag>
+ <flag name="filter"><short>filter elements from xml file [<ref name="element"/>]</short></flag>
+ <flag name="dir"><short>generate ddirectory listing</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local xmltools = logs.application {
+ name = "xmltools",
+ banner = "XMLTools 1.2.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">pstopdf</entry>
+ <entry name="detail">PStoPDF</entry>
+ <entry name="version">2.0.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="request"><short>handles exa request file</short></flag>
+ <flag name="watch"><short>watch folders for conversions (untested)</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local pstopdf = logs.application {
+ name = "pstopdf",
+ banner = "PStoPDF 2.0.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">rlxtools</entry>
+ <entry name="detail">RlxTools</entry>
+ <entry name="version">1.0.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="manipulate"><short>[<ref name="test]"/> manipulatorfile resourselog</short></flag>
+ <flag name="identify"><short>[<ref name="collect]"/> filename</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local rlxtools = logs.application {
+ name = "rlxtools",
+ banner = "RlxTools 1.0.1",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">imgtopdf</entry>
+ <entry name="detail">ImgToPdf</entry>
+ <entry name="version">1.1.2</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="convert"><short>convert image into pdf</short></flag>
+ <flag name="compression"><short>level of compression in percent</short></flag>
+ <flag name="depth"><short>image depth in bits</short></flag>
+ <flag name="colorspace"><short> colorspace (rgb,cmyk,gray)</short></flag>
+ <flag name="quality"><short>quality in percent</short></flag>
+ <flag name="inputpath"><short>path where files are looked for</short></flag>
+ <flag name="outputpath"><short>path where files end up</short></flag>
+ <flag name="auto"><short>determine settings automatically</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local imgtopdf = logs.application {
+ name = "imgtopdf",
+ banner = "ImgToPdf 1.1.2",
+ helpinfo = helpinfo,
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mptopdf</entry>
+ <entry name="detail">convert MetaPost to PDF</entry>
+ <entry name="version">1.4.1</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="metafun"><short>use the metafun format to process the file (default is mpost)</short></flag>
+ <flag name="texexec"><short>use texexec (context) to process text snippets</short></flag>
+ <flag name="latex"><short>use latex to process text snippets</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local mptopdf = logs.application {
+ name = "mptopdf",
+ banner = "MPtoPDF 1.4.1",
+ helpinfo = helpinfo,
+}
+
+-- texmfstart.rb is normally replaced by mtxrun
+-- runtools.rb is run from within context
+-- concheck.rb is run from within editors
+-- texsync.rb is no longer in the zip
+-- mpstools.rb is no longer in the zip
+-- rscortool.rb is only run indirectly
+-- rsfiltool.rb is only run indirectly
+-- rslibtool.rb is only run indirectly
+
+local application = logs.application {
+ name = "mk-help",
+ banner = "Mk Help generator 1.00",
+}
+
+local filename = environment.files[1]
+
+if not filename then
+ application.report("no mk script given")
+ return
+end
+
+local mkapplication
+
+if filename == "texmfstart" then mkapplication = texmfstart
+elseif filename == "luatools" then mkapplication = luatools
+elseif filename == "texexec" then mkapplication = texexec
+elseif filename == "texutil" then mkapplication = texutil
+elseif filename == "ctxtools" then mkapplication = ctxtools
+elseif filename == "textools" then mkapplication = textools
+elseif filename == "pdftools" then mkapplication = pdftools
+elseif filename == "tmftools" then mkapplication = tmftools
+elseif filename == "xmltools" then mkapplication = xmltools
+elseif filename == "pstopdf" then mkapplication = pstopdf
+elseif filename == "rlxtools" then mkapplication = rlxtools
+elseif filename == "imgtopdf" then mkapplication = imgtopdf
+elseif filename == "mptopdf" then mkapplication = mptopdf end
+
+if not mkapplication then
+ application.report("no valid mk script given")
+ return
+end
+
+if environment.argument("exporthelp") then
+ mkapplication.export(environment.argument("exporthelp"),environment.files[2])
+else
+ mkapplication.help()
+end
diff --git a/scripts/context/lua/mtx-modules.lua b/scripts/context/lua/mtx-modules.lua index f4003c1db..766be6b49 100644 --- a/scripts/context/lua/mtx-modules.lua +++ b/scripts/context/lua/mtx-modules.lua @@ -1,202 +1,202 @@ -if not modules then modules = { } end modules ['mtx-modules'] = { - version = 1.002, - comment = "companion to mtxrun.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -scripts = scripts or { } -scripts.modules = scripts.modules or { } - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-modules</entry> - <entry name="detail">ConTeXt Module Documentation Generators</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="convert"><short>convert source files (tex, mkii, mkiv, mp) to 'ted' files</short></flag> - <flag name="process"><short>process source files (tex, mkii, mkiv, mp) to 'pdf' files</short></flag> - <flag name="prep"><short>use original name with suffix 'prep' appended</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-modules", - banner = "ConTeXt Module Documentation Generators 1.00", - helpinfo = helpinfo, -} - -local report = application.report - --- Documentation can be woven into a source file. This script can generates --- a file with the documentation and source fragments properly tagged. The --- documentation is included as comment: --- --- %D ...... some kind of documentation --- %M ...... macros needed for documenation --- %S B begin skipping --- %S E end skipping --- --- The generated file is structured as: --- --- \starttypen --- \startmodule[type=suffix] --- \startdocumentation --- \stopdocumentation --- \startdefinition --- \stopdefinition --- \stopmodule --- \stoptypen --- --- Macro definitions specific to the documentation are not surrounded by --- start-stop commands. The suffix specificaction can be overruled at runtime, --- but defaults to the file extension. This specification can be used for language --- depended verbatim typesetting. --- --- In the mkiv variant we filter the \module settings so that we don't have --- to mess with global document settings. - -local find, format, sub, is_empty, strip, gsub = string.find, string.format, string.sub, string.is_empty, string.strip, string.gsub - -local function source_to_ted(inpname,outname,filetype) - local data = io.loaddata(inpname) - if not data or data == "" then - report("invalid module name '%s'",inpname) - return - end - report("converting '%s' to '%s'",inpname,outname) - local skiplevel, indocument, indefinition = 0, false, false - local started = false - local settings = format("type=%s",filetype or file.suffix(inpname)) - local preamble, n = lpeg.match(lpeg.Cs((1-lpeg.patterns.newline^2)^1) * lpeg.Cp(),data) - if preamble then - preamble = string.match(preamble,"\\module.-%[(.-)%]") - if preamble then - preamble = gsub(preamble,"%%D *","") - preamble = gsub(preamble,"%%(.-)[\n\r]","") - preamble = gsub(preamble,"[\n\r]","") - preamble = strip(preamble) - settings = format("%s,%s",settings,preamble) - data = string.sub(data,n,#data) - end - end - local lines = string.splitlines(data) - local result = { } - result[#result+1] = format("\\startmoduledocumentation[%s]",settings) - for i=1,#lines do - local line = lines[i] - if find(line,"^%%D ") or find(line,"^%%D$") then - if skiplevel == 0 then - local someline = #line < 3 and "" or sub(line,4,#line) - if indocument then - result[#result+1] = someline - else - if indefinition then - result[#result+1] = "\\stopdefinition" - indefinition = false - end - if not indocument then - result[#result+1] = "\\startdocumentation" - end - result[#result+1] = someline - indocument = true - end - end - elseif find(line,"^%%M ") or find(line,"^%%M$") then - if skiplevel == 0 then - local someline = (#line < 3 and "") or sub(line,4,#line) - result[#result+1] = someline - end - elseif find(line,"^%%S B") then - skiplevel = skiplevel + 1 - elseif find(line,"^%%S E") then - skiplevel = skiplevel - 1 - elseif find(line,"^%%") then - -- nothing - elseif skiplevel == 0 then - inlocaldocument = indocument - inlocaldocument = false - local someline = line - if indocument then - result[#result+1] = "\\stopdocumentation" - indocument = false - end - if indefinition then - if is_empty(someline) then - result[#result+1] = "\\stopdefinition" - indefinition = false - else - result[#result+1] = someline - end - elseif not is_empty(someline) then - result[#result+1] = "\n" - result[#result+1] = "\\startdefinition" - indefinition = true - if inlocaldocument then - -- nothing - else - result[#result+1] = someline - end - end - end - end - if indocument then - result[#result+1] = "\\stopdocumentation" - end - if indefinition then - result[#result+1] = "\\stopdefinition" - end - result[#result+1] = "\\stopmoduledocumentation" - io.savedata(outname,table.concat(result,"\n")) - return true -end - -local suffixes = table.tohash { 'tex','mkii','mkiv', 'mkvi', 'mp' } - -function scripts.modules.process(runtex) - local processed = { } - local prep = environment.argument("prep") - local files = environment.files - for i=1,#files do - local shortname = files[i] - local suffix = file.suffix(shortname) - if suffixes[suffix] then - local longname - if prep then - longname = shortname .. ".prep" - else - longname = file.removesuffix(shortname) .. "-" .. suffix .. ".ted" - end - local done = source_to_ted(shortname,longname) - if done and runtex then - os.execute(format("mtxrun --script context --usemodule=mod-01 --purge %s",longname)) - processed[#processed+1] = longname - end - end - end - for i=1,#processed do - local name = processed[i] - report("modules","processed: %s",name) - end -end - --- context --ctx=m-modules.ctx xxx.mkiv - -if environment.argument("process") then - scripts.modules.process(true) -elseif environment.argument("convert") then - scripts.modules.process(false) -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-modules'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+scripts = scripts or { }
+scripts.modules = scripts.modules or { }
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-modules</entry>
+ <entry name="detail">ConTeXt Module Documentation Generators</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="convert"><short>convert source files (tex, mkii, mkiv, mp) to 'ted' files</short></flag>
+ <flag name="process"><short>process source files (tex, mkii, mkiv, mp) to 'pdf' files</short></flag>
+ <flag name="prep"><short>use original name with suffix 'prep' appended</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-modules",
+ banner = "ConTeXt Module Documentation Generators 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+-- Documentation can be woven into a source file. This script can generates
+-- a file with the documentation and source fragments properly tagged. The
+-- documentation is included as comment:
+--
+-- %D ...... some kind of documentation
+-- %M ...... macros needed for documenation
+-- %S B begin skipping
+-- %S E end skipping
+--
+-- The generated file is structured as:
+--
+-- \starttypen
+-- \startmodule[type=suffix]
+-- \startdocumentation
+-- \stopdocumentation
+-- \startdefinition
+-- \stopdefinition
+-- \stopmodule
+-- \stoptypen
+--
+-- Macro definitions specific to the documentation are not surrounded by
+-- start-stop commands. The suffix specificaction can be overruled at runtime,
+-- but defaults to the file extension. This specification can be used for language
+-- depended verbatim typesetting.
+--
+-- In the mkiv variant we filter the \module settings so that we don't have
+-- to mess with global document settings.
+
+local find, format, sub, is_empty, strip, gsub = string.find, string.format, string.sub, string.is_empty, string.strip, string.gsub
+
+local function source_to_ted(inpname,outname,filetype)
+ local data = io.loaddata(inpname)
+ if not data or data == "" then
+ report("invalid module name '%s'",inpname)
+ return
+ end
+ report("converting '%s' to '%s'",inpname,outname)
+ local skiplevel, indocument, indefinition = 0, false, false
+ local started = false
+ local settings = format("type=%s",filetype or file.suffix(inpname))
+ local preamble, n = lpeg.match(lpeg.Cs((1-lpeg.patterns.newline^2)^1) * lpeg.Cp(),data)
+ if preamble then
+ preamble = string.match(preamble,"\\module.-%[(.-)%]")
+ if preamble then
+ preamble = gsub(preamble,"%%D *","")
+ preamble = gsub(preamble,"%%(.-)[\n\r]","")
+ preamble = gsub(preamble,"[\n\r]","")
+ preamble = strip(preamble)
+ settings = format("%s,%s",settings,preamble)
+ data = string.sub(data,n,#data)
+ end
+ end
+ local lines = string.splitlines(data)
+ local result = { }
+ result[#result+1] = format("\\startmoduledocumentation[%s]",settings)
+ for i=1,#lines do
+ local line = lines[i]
+ if find(line,"^%%D ") or find(line,"^%%D$") then
+ if skiplevel == 0 then
+ local someline = #line < 3 and "" or sub(line,4,#line)
+ if indocument then
+ result[#result+1] = someline
+ else
+ if indefinition then
+ result[#result+1] = "\\stopdefinition"
+ indefinition = false
+ end
+ if not indocument then
+ result[#result+1] = "\\startdocumentation"
+ end
+ result[#result+1] = someline
+ indocument = true
+ end
+ end
+ elseif find(line,"^%%M ") or find(line,"^%%M$") then
+ if skiplevel == 0 then
+ local someline = (#line < 3 and "") or sub(line,4,#line)
+ result[#result+1] = someline
+ end
+ elseif find(line,"^%%S B") then
+ skiplevel = skiplevel + 1
+ elseif find(line,"^%%S E") then
+ skiplevel = skiplevel - 1
+ elseif find(line,"^%%") then
+ -- nothing
+ elseif skiplevel == 0 then
+ inlocaldocument = indocument
+ inlocaldocument = false
+ local someline = line
+ if indocument then
+ result[#result+1] = "\\stopdocumentation"
+ indocument = false
+ end
+ if indefinition then
+ if is_empty(someline) then
+ result[#result+1] = "\\stopdefinition"
+ indefinition = false
+ else
+ result[#result+1] = someline
+ end
+ elseif not is_empty(someline) then
+ result[#result+1] = "\n"
+ result[#result+1] = "\\startdefinition"
+ indefinition = true
+ if inlocaldocument then
+ -- nothing
+ else
+ result[#result+1] = someline
+ end
+ end
+ end
+ end
+ if indocument then
+ result[#result+1] = "\\stopdocumentation"
+ end
+ if indefinition then
+ result[#result+1] = "\\stopdefinition"
+ end
+ result[#result+1] = "\\stopmoduledocumentation"
+ io.savedata(outname,table.concat(result,"\n"))
+ return true
+end
+
+local suffixes = table.tohash { 'tex','mkii','mkiv', 'mkvi', 'mp' }
+
+function scripts.modules.process(runtex)
+ local processed = { }
+ local prep = environment.argument("prep")
+ local files = environment.files
+ for i=1,#files do
+ local shortname = files[i]
+ local suffix = file.suffix(shortname)
+ if suffixes[suffix] then
+ local longname
+ if prep then
+ longname = shortname .. ".prep"
+ else
+ longname = file.removesuffix(shortname) .. "-" .. suffix .. ".ted"
+ end
+ local done = source_to_ted(shortname,longname)
+ if done and runtex then
+ os.execute(format("mtxrun --script context --usemodule=mod-01 --purge %s",longname))
+ processed[#processed+1] = longname
+ end
+ end
+ end
+ for i=1,#processed do
+ local name = processed[i]
+ report("modules","processed: %s",name)
+ end
+end
+
+-- context --ctx=m-modules.ctx xxx.mkiv
+
+if environment.argument("process") then
+ scripts.modules.process(true)
+elseif environment.argument("convert") then
+ scripts.modules.process(false)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-mtxworks.lua b/scripts/context/lua/mtx-mtxworks.lua index 1239ae4c5..e6517dd95 100644 --- a/scripts/context/lua/mtx-mtxworks.lua +++ b/scripts/context/lua/mtx-mtxworks.lua @@ -1,14 +1,14 @@ -if not modules then modules = { } end modules ['mtx-mtxworks'] = { - version = 1.002, - 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 a shortcut to "mtxrun --script texworks --start" - -environment.setargument("start",true) - -require "mtx-texworks" - +if not modules then modules = { } end modules ['mtx-mtxworks'] = {
+ version = 1.002,
+ 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 a shortcut to "mtxrun --script texworks --start"
+
+environment.setargument("start",true)
+
+require "mtx-texworks"
+
diff --git a/scripts/context/lua/mtx-package.lua b/scripts/context/lua/mtx-package.lua index 8c9e6b9fc..a5792ec4f 100644 --- a/scripts/context/lua/mtx-package.lua +++ b/scripts/context/lua/mtx-package.lua @@ -1,84 +1,84 @@ -if not modules then modules = { } end modules ['mtx-package'] = { - version = 1.002, - 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 format, gsub, gmatch = string.format, string.gsub, string.gmatch - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-package</entry> - <entry name="detail">Distribution Related Goodies</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="merge"><short>merge 'loadmodule' into merge file</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-package", - banner = "Distribution Related Goodies 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -messages = messages or { } -scripts.package = scripts.package or { } - -function scripts.package.merge_luatex_files(name) - local oldname = resolvers.findfile(name) or "" - oldname = file.replacesuffix(oldname,"lua") - if oldname == "" then - report("missing %q",name) - else - local newname = file.removesuffix(oldname) .. "-merged.lua" - local data = io.loaddata(oldname) or "" - if data == "" then - report("missing %q",newname) - else - report("loading %q",oldname) - local collected = { } - collected[#collected+1] = format("-- merged file : %s\n",newname) - collected[#collected+1] = format("-- parent file : %s\n",oldname) - collected[#collected+1] = format("-- merge date : %s\n",os.date()) - -- loadmodule can have extra arguments - for lib in gmatch(data,"loadmodule *%([\'\"](.-)[\'\"]") do - if file.basename(lib) ~= file.basename(newname) then - local fullname = resolvers.findfile(lib) or "" - if fullname == "" then - report("missing %q",lib) - else - report("fetching %q",fullname) - local data = io.loaddata(fullname) - collected[#collected+1] = "\ndo -- begin closure to overcome local limits and interference\n\n" - collected[#collected+1] = utilities.merger.compact(data) - collected[#collected+1] = "\nend -- closure\n" - end - end - end - report("saving %q",newname) - io.savedata(newname,table.concat(collected)) - end - end -end - -if environment.argument("merge") then - scripts.package.merge_luatex_files(environment.files[1] or "") -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-package'] = {
+ version = 1.002,
+ 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 format, gsub, gmatch = string.format, string.gsub, string.gmatch
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-package</entry>
+ <entry name="detail">Distribution Related Goodies</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="merge"><short>merge 'loadmodule' into merge file</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-package",
+ banner = "Distribution Related Goodies 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+messages = messages or { }
+scripts.package = scripts.package or { }
+
+function scripts.package.merge_luatex_files(name)
+ local oldname = resolvers.findfile(name) or ""
+ oldname = file.replacesuffix(oldname,"lua")
+ if oldname == "" then
+ report("missing %q",name)
+ else
+ local newname = file.removesuffix(oldname) .. "-merged.lua"
+ local data = io.loaddata(oldname) or ""
+ if data == "" then
+ report("missing %q",newname)
+ else
+ report("loading %q",oldname)
+ local collected = { }
+ collected[#collected+1] = format("-- merged file : %s\n",newname)
+ collected[#collected+1] = format("-- parent file : %s\n",oldname)
+ collected[#collected+1] = format("-- merge date : %s\n",os.date())
+ -- loadmodule can have extra arguments
+ for lib in gmatch(data,"loadmodule *%([\'\"](.-)[\'\"]") do
+ if file.basename(lib) ~= file.basename(newname) then
+ local fullname = resolvers.findfile(lib) or ""
+ if fullname == "" then
+ report("missing %q",lib)
+ else
+ report("fetching %q",fullname)
+ local data = io.loaddata(fullname)
+ collected[#collected+1] = "\ndo -- begin closure to overcome local limits and interference\n\n"
+ collected[#collected+1] = utilities.merger.compact(data)
+ collected[#collected+1] = "\nend -- closure\n"
+ end
+ end
+ end
+ report("saving %q",newname)
+ io.savedata(newname,table.concat(collected))
+ end
+ end
+end
+
+if environment.argument("merge") then
+ scripts.package.merge_luatex_files(environment.files[1] or "")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-patterns.lua b/scripts/context/lua/mtx-patterns.lua index 2dcd3db54..1abe90385 100644 --- a/scripts/context/lua/mtx-patterns.lua +++ b/scripts/context/lua/mtx-patterns.lua @@ -27,6 +27,8 @@ local helpinfo = [[ <flag name="path"><short>source path where hyph-foo.tex files are stored</short></flag> <flag name="destination"><short>destination path</short></flag> <flag name="specification"><short>additional patterns: e.g.: =cy,hyph-cy,welsh</short></flag> + <flag name="compress"><short>compress data</short></flag> + <flag name="words"><short>update words in given file</short></flag> </subcategory> </category> </flags> @@ -413,6 +415,8 @@ function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenation if not comment or comment == "" then comment = "% no comment" end if not type(destination) == "string" then destination = "." end + local compression = environment.arguments.compress and "zlib" or nil + local lines = string.splitlines(comment) for i=1,#lines do if not find(lines[i],"^%%") then @@ -429,9 +433,12 @@ function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenation local patterndata, hyphenationdata if nofpatternsnew > 0 then + local data = concat(patternsnew," ") patterndata = { n = nofpatternsnew, - data = concat(patternsnew," ") or nil, + compression = compression, + length = #data, + data = compression and zlib.compress(data,9) or data, characters = concat(table.sortedkeys(pusednew),""), minhyphenmin = 1, -- determined by pattern author minhyphenmax = 1, -- determined by pattern author @@ -442,10 +449,13 @@ function scripts.patterns.save(destination,mnemonic,name,patternsnew,hyphenation } end if nofhyphenationsnew > 0 then + local data = concat(hyphenationsnew," ") hyphenationdata = { - n = nofhyphenationsnew, - data = concat(hyphenationsnew," "), - characters = concat(table.sortedkeys(husednew),""), + n = nofhyphenationsnew, + compression = compression, + length = #data, + data = compression and zlib.compress(data,9) or data, + characters = concat(table.sortedkeys(husednew),""), } else hyphenationdata = { @@ -543,12 +553,83 @@ function scripts.patterns.convert() end end +local function valid(filename) + local specification = table.load(filename) + if not specification then + return false + end + local lists = specification.lists + if not lists then + return false + end + return specification, lists +end + +function scripts.patterns.words() + if environment.arguments.update then + local compress = environment.arguments.compress + for i=1,#environment.files do + local filename = environment.files[i] + local fullname = resolvers.findfile(filename) + if fullname and fullname ~= "" then + report("checking file %a",fullname) + local specification, lists = valid(fullname) + if specification and #lists> 0 then + report("updating %a of language %a",filename,specification.language) + for i=1,#lists do + local entry = lists[i] + local filename = entry.filename + if filename then + local fullname = resolvers.findfile(filename) + if fullname then + report("adding words from %a",fullname) + local data = io.loaddata(fullname) or "" + data = string.strip(data) + data = string.gsub(data,"%s+"," ") + if compress then + entry.data = zlib.compress(data,9) + entry.compression = "zlib" + entry.length = #data + else + entry.data = data + entry.compression = nil + entry.length = #data + end + else + entry.data = "" + entry.compression = nil + entry.length = 0 + end + else + entry.data = "" + entry.compression = nil + entry.length = 0 + end + end + specification.version = "1.00" + specification.timestamp = os.localtime() + report("updated file %a is saved",filename) + table.save(filename,specification) + else + report("no file %a",filename) + end + else + report("nothing done") + end + end + else + report("provide --update") + end +end + if environment.argument("check") then scripts.patterns.prepare() scripts.patterns.check() elseif environment.argument("convert") then scripts.patterns.prepare() scripts.patterns.convert() +elseif environment.argument("words") then + scripts.patterns.words() -- for the moment here elseif environment.argument("exporthelp") then application.export(environment.argument("exporthelp"),environment.files[1]) else @@ -558,7 +639,7 @@ end -- mtxrun --script pattern --check hyph-*.tex -- mtxrun --script pattern --check --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns -- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/tex --destination=e:/tmp/patterns --- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns +-- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns --compress -- copy /Y *.hyp e:\tex-context\tex\texmf-context\tex\context\patterns -- copy /Y *.pat e:\tex-context\tex\texmf-context\tex\context\patterns @@ -569,3 +650,5 @@ end -- move /Y *.pat e:\tex-context\tex\texmf-mine\tex\context\patterns -- move /Y *.rme e:\tex-context\tex\texmf-mine\tex\context\patterns -- move /Y *.lua e:\tex-context\tex\texmf-mine\tex\context\patterns + +-- mtxrun --script pattern --words --update word-th.lua --compress diff --git a/scripts/context/lua/mtx-pdf.lua b/scripts/context/lua/mtx-pdf.lua index 551aa5b37..2ff22e07f 100644 --- a/scripts/context/lua/mtx-pdf.lua +++ b/scripts/context/lua/mtx-pdf.lua @@ -1,299 +1,299 @@ -if not modules then modules = { } end modules ['mtx-pdf'] = { - 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 tonumber = tonumber -local format, gmatch = string.format, string.gmatch -local utfchar = utf.char -local concat = table.concat -local setmetatableindex, sortedhash, sortedkeys = table.setmetatableindex, table.sortedhash, table.sortedkeys - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-pdf</entry> - <entry name="detail">ConTeXt PDF Helpers</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="info"><short>show some info about the given file</short></flag> - <flag name="metadata"><short>show metadata xml blob</short></flag> - <flag name="fonts"><short>show used fonts (<ref name="detail)"/></short></flag> - <flag name="linearize"><short>linearize given file</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-pdf", - banner = "ConTeXt PDF Helpers 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -dofile(resolvers.findfile("lpdf-epd.lua","tex")) - -scripts = scripts or { } -scripts.pdf = scripts.pdf or { } - -local function loadpdffile(filename) - if not filename or filename == "" then - report("no filename given") - elseif not lfs.isfile(filename) then - report("unknown file '%s'",filename) - else - local pdffile = lpdf.epdf.load(filename) - if pdffile then - return pdffile - else - report("no valid pdf file '%s'",filename) - end - end -end - -function scripts.pdf.info(filename) - local pdffile = loadpdffile(filename) - if pdffile then - local catalog = pdffile.Catalog - local info = pdffile.Info - local pages = pdffile.pages - local nofpages = pages.n -- no # yet. will be in 5.2 - - report("filename > %s",filename) - report("pdf version > %s",catalog.Version) - report("number of pages > %s",nofpages) - report("title > %s",info.Title) - report("creator > %s",info.Creator) - report("producer > %s",info.Producer) - report("creation date > %s",info.CreationDate) - report("modification date > %s",info.ModDate) - - local width, height, start - for i=1, nofpages do - local page = pages[i] - local bbox = page.CropBox or page.MediaBox - local w, h = bbox[4]-bbox[2],bbox[3]-bbox[1] - if w ~= width or h ~= height then - if start then - report("cropbox > pages: %s-%s, width: %s, height: %s",start,i-1,width,height) - end - width, height, start = w, h, i - end - end - report("cropbox > pages: %s-%s, width: %s, height: %s",start,nofpages,width,height) - end -end - -function scripts.pdf.metadata(filename) - local pdffile = loadpdffile(filename) - if pdffile then - local catalog = pdffile.Catalog - local metadata = catalog.Metadata - if metadata then - report("metadata > \n\n%s\n",metadata()) - else - report("no metadata") - end - end -end - -local function getfonts(pdffile) - local usedfonts = { } - for i=1,pdffile.pages.n do - local page = pdffile.pages[i] - local fontlist = page.Resources.Font - for k, v in next, lpdf.epdf.expand(fontlist) do - usedfonts[k] = lpdf.epdf.expand(v) - end - end - return usedfonts -end - -local function getunicodes(font) - local cid = font.ToUnicode - if cid then - cid = cid() - local counts = { } - -- for s in gmatch(cid,"begincodespacerange%s*(.-)%s*endcodespacerange") do - -- for a, b in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do - -- print(a,b) - -- end - -- end - setmetatableindex(counts, function(t,k) t[k] = 0 return 0 end) - for s in gmatch(cid,"beginbfrange%s*(.-)%s*endbfrange") do - for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do - first = tonumber(first,16) - last = tonumber(last,16) - offset = tonumber(offset,16) - offset = offset - first - for i=first,last do - local c = i + offset - counts[c] = counts[c] + 1 - end - end - end - for s in gmatch(cid,"beginbfchar%s*(.-)%s*endbfchar") do - for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do - for n in gmatch(new,"....") do - local c = tonumber(n,16) - counts[c] = counts[c] + 1 - end - end - end - return counts - end -end - -function scripts.pdf.fonts(filename) - local pdffile = loadpdffile(filename) - if pdffile then - local usedfonts = getfonts(pdffile) - local found = { } - for k, v in table.sortedhash(usedfonts) do - local counts = getunicodes(v) - local codes = { } - local chars = { } - local freqs = { } - if counts then - codes = sortedkeys(counts) - for i=1,#codes do - local k = codes[i] - local c = utfchar(k) - chars[i] = c - freqs[i] = format("U+%05X %s %s",k,counts[k] > 1 and "+" or " ", c) - end - for i=1,#codes do - codes[i] = format("U+%05X",codes[i]) - end - end - found[k] = { - basefont = v.BaseFont or "no basefont", - encoding = v.Encoding or "no encoding", - subtype = v.Subtype or "no subtype", - unicode = v.ToUnicode and "unicode" or "no unicode", - chars = chars, - codes = codes, - freqs = freqs, - } - end - - if environment.argument("detail") then - for k, v in sortedhash(found) do - report("id : %s",k) - report("basefont : %s",v.basefont) - report("encoding : %s",v.encoding) - report("subtype : %s",v.subtype) - report("unicode : %s",v.unicode) - report("characters : %s", concat(v.chars," ")) - report("codepoints : %s", concat(v.codes," ")) - report("") - end - else - local results = { { "id", "basefont", "encoding", "subtype", "unicode", "characters" } } - for k, v in sortedhash(found) do - results[#results+1] = { k, v.basefont, v.encoding, v.subtype, v.unicode, concat(v.chars," ") } - end - utilities.formatters.formatcolumns(results) - report(results[1]) - report("") - for i=2,#results do - report(results[i]) - end - report("") - end - end -end - --- this is a quick hack ... proof of concept .. will change (derived from luigi's example) ... --- i will make a ctx wrapper - -local qpdf - -function scripts.pdf.linearize(filename) - qpdf = qpdf or swiglib("qpdf.core") - local oldfile = filename or environment.files[1] - if not oldfile then - return - end - file.addsuffix(oldfile,"pdf") - if not lfs.isfile(oldfile) then - return - end - local newfile = environment.files[2] - if not newfile or file.removesuffix(oldfile) == file.removesuffix(newfile)then - newfile = file.addsuffix(file.removesuffix(oldfile) .. "-linearized","pdf") - end - local password = environment.arguments.password - local instance = qpdf.qpdf_init() - if bit32.band(qpdf.qpdf_read(instance,oldfile,password),qpdf.QPDF_ERRORS) ~= 0 then - report("unable to open input file") - elseif bit32.band(qpdf.qpdf_init_write(instance,newfile),qpdf.QPDF_ERRORS) ~= 0 then - report("unable to open output file") - else - report("linearizing %a into %a",oldfile,newfile) - qpdf.qpdf_set_static_ID(instance,qpdf.QPDF_TRUE) - qpdf.qpdf_set_linearization(instance,qpdf.QPDF_TRUE) - qpdf.qpdf_write(instance) - end - while qpdf.qpdf_more_warnings(instance) ~= 0 do - report("warning: %s",qpdf.qpdf_get_error_full_text(instance,qpdf.qpdf_next_warning(qpdf))) - end - if qpdf.qpdf_has_error(instance) ~= 0 then - report("error: %s",qpdf.qpdf_get_error_full_text(instance,qpdf.qpdf_get_error(qpdf))) - end - qpdf.qpdf_cleanup_p(instance) -end - --- scripts.pdf.info("e:/tmp/oeps.pdf") --- scripts.pdf.metadata("e:/tmp/oeps.pdf") --- scripts.pdf.fonts("e:/tmp/oeps.pdf") --- scripts.pdf.linearize("e:/tmp/oeps.pdf") - -local filename = environment.files[1] or "" - -if filename == "" then - application.help() -elseif environment.argument("info") then - scripts.pdf.info(filename) -elseif environment.argument("metadata") then - scripts.pdf.metadata(filename) -elseif environment.argument("fonts") then - scripts.pdf.fonts(filename) -elseif environment.argument("linearize") then - scripts.pdf.linearize(filename) -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),filename) -else - application.help() -end - --- a variant on an experiment by hartmut - ---~ function downloadlinks(filename) ---~ local document = lpdf.epdf.load(filename) ---~ if document then ---~ local pages = document.pages ---~ for p = 1,#pages do ---~ local annotations = pages[p].Annots ---~ if annotations then ---~ for a=1,#annotations do ---~ local annotation = annotations[a] ---~ local uri = annotation.Subtype == "Link" and annotation.A and annotation.A.URI ---~ if uri and string.find(uri,"^http") then ---~ os.execute("wget " .. uri) ---~ end ---~ end ---~ end ---~ end ---~ end ---~ end +if not modules then modules = { } end modules ['mtx-pdf'] = {
+ 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 tonumber = tonumber
+local format, gmatch = string.format, string.gmatch
+local utfchar = utf.char
+local concat = table.concat
+local setmetatableindex, sortedhash, sortedkeys = table.setmetatableindex, table.sortedhash, table.sortedkeys
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-pdf</entry>
+ <entry name="detail">ConTeXt PDF Helpers</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="info"><short>show some info about the given file</short></flag>
+ <flag name="metadata"><short>show metadata xml blob</short></flag>
+ <flag name="fonts"><short>show used fonts (<ref name="detail)"/></short></flag>
+ <flag name="linearize"><short>linearize given file</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-pdf",
+ banner = "ConTeXt PDF Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+dofile(resolvers.findfile("lpdf-epd.lua","tex"))
+
+scripts = scripts or { }
+scripts.pdf = scripts.pdf or { }
+
+local function loadpdffile(filename)
+ if not filename or filename == "" then
+ report("no filename given")
+ elseif not lfs.isfile(filename) then
+ report("unknown file '%s'",filename)
+ else
+ local pdffile = lpdf.epdf.load(filename)
+ if pdffile then
+ return pdffile
+ else
+ report("no valid pdf file '%s'",filename)
+ end
+ end
+end
+
+function scripts.pdf.info(filename)
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local catalog = pdffile.Catalog
+ local info = pdffile.Info
+ local pages = pdffile.pages
+ local nofpages = pages.n -- no # yet. will be in 5.2
+
+ report("filename > %s",filename)
+ report("pdf version > %s",catalog.Version)
+ report("number of pages > %s",nofpages)
+ report("title > %s",info.Title)
+ report("creator > %s",info.Creator)
+ report("producer > %s",info.Producer)
+ report("creation date > %s",info.CreationDate)
+ report("modification date > %s",info.ModDate)
+
+ local width, height, start
+ for i=1, nofpages do
+ local page = pages[i]
+ local bbox = page.CropBox or page.MediaBox
+ local w, h = bbox[4]-bbox[2],bbox[3]-bbox[1]
+ if w ~= width or h ~= height then
+ if start then
+ report("cropbox > pages: %s-%s, width: %s, height: %s",start,i-1,width,height)
+ end
+ width, height, start = w, h, i
+ end
+ end
+ report("cropbox > pages: %s-%s, width: %s, height: %s",start,nofpages,width,height)
+ end
+end
+
+function scripts.pdf.metadata(filename)
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local catalog = pdffile.Catalog
+ local metadata = catalog.Metadata
+ if metadata then
+ report("metadata > \n\n%s\n",metadata())
+ else
+ report("no metadata")
+ end
+ end
+end
+
+local function getfonts(pdffile)
+ local usedfonts = { }
+ for i=1,pdffile.pages.n do
+ local page = pdffile.pages[i]
+ local fontlist = page.Resources.Font
+ for k, v in next, lpdf.epdf.expand(fontlist) do
+ usedfonts[k] = lpdf.epdf.expand(v)
+ end
+ end
+ return usedfonts
+end
+
+local function getunicodes(font)
+ local cid = font.ToUnicode
+ if cid then
+ cid = cid()
+ local counts = { }
+ -- for s in gmatch(cid,"begincodespacerange%s*(.-)%s*endcodespacerange") do
+ -- for a, b in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ -- print(a,b)
+ -- end
+ -- end
+ setmetatableindex(counts, function(t,k) t[k] = 0 return 0 end)
+ for s in gmatch(cid,"beginbfrange%s*(.-)%s*endbfrange") do
+ for first, last, offset in gmatch(s,"<([^>]+)>%s+<([^>]+)>%s+<([^>]+)>") do
+ first = tonumber(first,16)
+ last = tonumber(last,16)
+ offset = tonumber(offset,16)
+ offset = offset - first
+ for i=first,last do
+ local c = i + offset
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ for s in gmatch(cid,"beginbfchar%s*(.-)%s*endbfchar") do
+ for old, new in gmatch(s,"<([^>]+)>%s+<([^>]+)>") do
+ for n in gmatch(new,"....") do
+ local c = tonumber(n,16)
+ counts[c] = counts[c] + 1
+ end
+ end
+ end
+ return counts
+ end
+end
+
+function scripts.pdf.fonts(filename)
+ local pdffile = loadpdffile(filename)
+ if pdffile then
+ local usedfonts = getfonts(pdffile)
+ local found = { }
+ for k, v in table.sortedhash(usedfonts) do
+ local counts = getunicodes(v)
+ local codes = { }
+ local chars = { }
+ local freqs = { }
+ if counts then
+ codes = sortedkeys(counts)
+ for i=1,#codes do
+ local k = codes[i]
+ local c = utfchar(k)
+ chars[i] = c
+ freqs[i] = format("U+%05X %s %s",k,counts[k] > 1 and "+" or " ", c)
+ end
+ for i=1,#codes do
+ codes[i] = format("U+%05X",codes[i])
+ end
+ end
+ found[k] = {
+ basefont = v.BaseFont or "no basefont",
+ encoding = v.Encoding or "no encoding",
+ subtype = v.Subtype or "no subtype",
+ unicode = v.ToUnicode and "unicode" or "no unicode",
+ chars = chars,
+ codes = codes,
+ freqs = freqs,
+ }
+ end
+
+ if environment.argument("detail") then
+ for k, v in sortedhash(found) do
+ report("id : %s",k)
+ report("basefont : %s",v.basefont)
+ report("encoding : %s",v.encoding)
+ report("subtype : %s",v.subtype)
+ report("unicode : %s",v.unicode)
+ report("characters : %s", concat(v.chars," "))
+ report("codepoints : %s", concat(v.codes," "))
+ report("")
+ end
+ else
+ local results = { { "id", "basefont", "encoding", "subtype", "unicode", "characters" } }
+ for k, v in sortedhash(found) do
+ results[#results+1] = { k, v.basefont, v.encoding, v.subtype, v.unicode, concat(v.chars," ") }
+ end
+ utilities.formatters.formatcolumns(results)
+ report(results[1])
+ report("")
+ for i=2,#results do
+ report(results[i])
+ end
+ report("")
+ end
+ end
+end
+
+-- this is a quick hack ... proof of concept .. will change (derived from luigi's example) ...
+-- i will make a ctx wrapper
+
+local qpdf
+
+function scripts.pdf.linearize(filename)
+ qpdf = qpdf or swiglib("qpdf.core")
+ local oldfile = filename or environment.files[1]
+ if not oldfile then
+ return
+ end
+ file.addsuffix(oldfile,"pdf")
+ if not lfs.isfile(oldfile) then
+ return
+ end
+ local newfile = environment.files[2]
+ if not newfile or file.removesuffix(oldfile) == file.removesuffix(newfile)then
+ newfile = file.addsuffix(file.removesuffix(oldfile) .. "-linearized","pdf")
+ end
+ local password = environment.arguments.password
+ local instance = qpdf.qpdf_init()
+ if bit32.band(qpdf.qpdf_read(instance,oldfile,password),qpdf.QPDF_ERRORS) ~= 0 then
+ report("unable to open input file")
+ elseif bit32.band(qpdf.qpdf_init_write(instance,newfile),qpdf.QPDF_ERRORS) ~= 0 then
+ report("unable to open output file")
+ else
+ report("linearizing %a into %a",oldfile,newfile)
+ qpdf.qpdf_set_static_ID(instance,qpdf.QPDF_TRUE)
+ qpdf.qpdf_set_linearization(instance,qpdf.QPDF_TRUE)
+ qpdf.qpdf_write(instance)
+ end
+ while qpdf.qpdf_more_warnings(instance) ~= 0 do
+ report("warning: %s",qpdf.qpdf_get_error_full_text(instance,qpdf.qpdf_next_warning(qpdf)))
+ end
+ if qpdf.qpdf_has_error(instance) ~= 0 then
+ report("error: %s",qpdf.qpdf_get_error_full_text(instance,qpdf.qpdf_get_error(qpdf)))
+ end
+ qpdf.qpdf_cleanup_p(instance)
+end
+
+-- scripts.pdf.info("e:/tmp/oeps.pdf")
+-- scripts.pdf.metadata("e:/tmp/oeps.pdf")
+-- scripts.pdf.fonts("e:/tmp/oeps.pdf")
+-- scripts.pdf.linearize("e:/tmp/oeps.pdf")
+
+local filename = environment.files[1] or ""
+
+if filename == "" then
+ application.help()
+elseif environment.argument("info") then
+ scripts.pdf.info(filename)
+elseif environment.argument("metadata") then
+ scripts.pdf.metadata(filename)
+elseif environment.argument("fonts") then
+ scripts.pdf.fonts(filename)
+elseif environment.argument("linearize") then
+ scripts.pdf.linearize(filename)
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),filename)
+else
+ application.help()
+end
+
+-- a variant on an experiment by hartmut
+
+--~ function downloadlinks(filename)
+--~ local document = lpdf.epdf.load(filename)
+--~ if document then
+--~ local pages = document.pages
+--~ for p = 1,#pages do
+--~ local annotations = pages[p].Annots
+--~ if annotations then
+--~ for a=1,#annotations do
+--~ local annotation = annotations[a]
+--~ local uri = annotation.Subtype == "Link" and annotation.A and annotation.A.URI
+--~ if uri and string.find(uri,"^http") then
+--~ os.execute("wget " .. uri)
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
+--~ end
diff --git a/scripts/context/lua/mtx-plain.lua b/scripts/context/lua/mtx-plain.lua index f43dcdeaf..975c91ee7 100644 --- a/scripts/context/lua/mtx-plain.lua +++ b/scripts/context/lua/mtx-plain.lua @@ -1,129 +1,129 @@ -if not modules then modules = { } end modules ['mtx-plain'] = { - version = 1.002, - comment = "companion to mtxrun.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- future version will use the texmf-cache/generic/formats/<engine> path --- instead because then we can use some more of the generic context --- initializers ... in that case we will also use the regular database --- instead of kpse here, just like with the font database code (as that --- one also works with kpse runtime) - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-plain</entry> - <entry name="detail">Plain TeX Runner</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="make"><short>create format file</short></flag> - <flag name="run"><short>process file</short></flag> - <flag name="format" value="string"><short>format name (default: luatex-plain)</short></flag> - <flag name="engine" value="string"><short>engine to use (default: luatex)</short></flag> - <flag name="jit"><short>use luajittex</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-plain", - banner = "Plain TeX Runner 1.00", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.plain = scripts.plain or { } - -local function execute(...) - local command = string.format(...) - report("running command %a\n",command) - os.execute(command) -end - -local function resultof(...) - local command = string.format(...) - report("running command %a",command) - return string.strip(os.resultof(command) or "") -end - -function scripts.plain.make(texengine,texformat) - report("generating kpse file database") - execute("mktexlsr") -- better play safe and use this one - local fmtpathspec = resultof("kpsewhich --var-value=TEXFORMATS --engine=%s",texengine) - if fmtpathspec ~= "" then - report("using path specification %a",fmtpathspec) - fmtpathspec = resultof('kpsewhich -expand-braces="%s"',fmtpathspec) - end - if fmtpathspec ~= "" then - report("using path expansion %a",fmtpathspec) - else - report("no valid path reported, trying alternative") - fmtpathspec = resultof("kpsewhich --show-path=fmt --engine=%s",texengine) - if fmtpathspec ~= "" then - report("using path expansion %a",fmtpathspec) - else - report("no valid path reported, falling back to current path") - fmtpathspec = "." - end - end - fmtpathspec = string.splitlines(fmtpathspec)[1] or fmtpathspec - fmtpathspec = file.splitpath(fmtpathspec) - local fmtpath = nil - for i=1,#fmtpathspec do - local path = fmtpathspec[i] - if path ~= "." then - dir.makedirs(path) - if lfs.isdir(path) and file.is_writable(path) then - fmtpath = path - break - end - end - end - if not fmtpath or fmtpath == "" then - fmtpath = "." - else - lfs.chdir(fmtpath) - end - execute('%s --ini %s \\dump',texengine,file.addsuffix(texformat,"tex")) - report("generating kpse file database") - execute("mktexlsr") - report("format %a saved on path %a",texformat,fmtpath) -end - -function scripts.plain.run(texengine,texformat,filename) - execute('%s --fmt=%s "%s"',texengine,file.removesuffix(texformat),filename) -end - -local texformat = environment.arguments.texformat or environment.arguments.format -local texengine = environment.arguments.texengine or environment.arguments.engine - -if type(texengine) ~= "string" or texengine == "" then - texengine = environment.arguments.jit and "luajittex" or"luatex" -end - -if type(texformat) ~= "string" or texformat == "" then - texformat = "luatex-plain" -end - -local filename = environment.files[1] - -if environment.arguments.exporthelp then - application.export(environment.arguments.exporthelp,filename) -elseif environment.arguments.make then - scripts.plain.make(texengine,texformat) -elseif filename then - scripts.plain.run(texengine,texformat,filename) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-plain'] = {
+ version = 1.002,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- future version will use the texmf-cache/generic/formats/<engine> path
+-- instead because then we can use some more of the generic context
+-- initializers ... in that case we will also use the regular database
+-- instead of kpse here, just like with the font database code (as that
+-- one also works with kpse runtime)
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-plain</entry>
+ <entry name="detail">Plain TeX Runner</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="make"><short>create format file</short></flag>
+ <flag name="run"><short>process file</short></flag>
+ <flag name="format" value="string"><short>format name (default: luatex-plain)</short></flag>
+ <flag name="engine" value="string"><short>engine to use (default: luatex)</short></flag>
+ <flag name="jit"><short>use luajittex</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-plain",
+ banner = "Plain TeX Runner 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.plain = scripts.plain or { }
+
+local function execute(...)
+ local command = string.format(...)
+ report("running command %a\n",command)
+ os.execute(command)
+end
+
+local function resultof(...)
+ local command = string.format(...)
+ report("running command %a",command)
+ return string.strip(os.resultof(command) or "")
+end
+
+function scripts.plain.make(texengine,texformat)
+ report("generating kpse file database")
+ execute("mktexlsr") -- better play safe and use this one
+ local fmtpathspec = resultof("kpsewhich --var-value=TEXFORMATS --engine=%s",texengine)
+ if fmtpathspec ~= "" then
+ report("using path specification %a",fmtpathspec)
+ fmtpathspec = resultof('kpsewhich -expand-braces="%s"',fmtpathspec)
+ end
+ if fmtpathspec ~= "" then
+ report("using path expansion %a",fmtpathspec)
+ else
+ report("no valid path reported, trying alternative")
+ fmtpathspec = resultof("kpsewhich --show-path=fmt --engine=%s",texengine)
+ if fmtpathspec ~= "" then
+ report("using path expansion %a",fmtpathspec)
+ else
+ report("no valid path reported, falling back to current path")
+ fmtpathspec = "."
+ end
+ end
+ fmtpathspec = string.splitlines(fmtpathspec)[1] or fmtpathspec
+ fmtpathspec = file.splitpath(fmtpathspec)
+ local fmtpath = nil
+ for i=1,#fmtpathspec do
+ local path = fmtpathspec[i]
+ if path ~= "." then
+ dir.makedirs(path)
+ if lfs.isdir(path) and file.is_writable(path) then
+ fmtpath = path
+ break
+ end
+ end
+ end
+ if not fmtpath or fmtpath == "" then
+ fmtpath = "."
+ else
+ lfs.chdir(fmtpath)
+ end
+ execute('%s --ini %s \\dump',texengine,file.addsuffix(texformat,"tex"))
+ report("generating kpse file database")
+ execute("mktexlsr")
+ report("format %a saved on path %a",texformat,fmtpath)
+end
+
+function scripts.plain.run(texengine,texformat,filename)
+ execute('%s --fmt=%s "%s"',texengine,file.removesuffix(texformat),filename)
+end
+
+local texformat = environment.arguments.texformat or environment.arguments.format
+local texengine = environment.arguments.texengine or environment.arguments.engine
+
+if type(texengine) ~= "string" or texengine == "" then
+ texengine = environment.arguments.jit and "luajittex" or"luatex"
+end
+
+if type(texformat) ~= "string" or texformat == "" then
+ texformat = "luatex-plain"
+end
+
+local filename = environment.files[1]
+
+if environment.arguments.exporthelp then
+ application.export(environment.arguments.exporthelp,filename)
+elseif environment.arguments.make then
+ scripts.plain.make(texengine,texformat)
+elseif filename then
+ scripts.plain.run(texengine,texformat,filename)
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-profile.lua b/scripts/context/lua/mtx-profile.lua index 3550474f3..15ff595d2 100644 --- a/scripts/context/lua/mtx-profile.lua +++ b/scripts/context/lua/mtx-profile.lua @@ -1,187 +1,187 @@ -if not modules then modules = { } end modules ['mtx-profile'] = { - version = 1.000, - comment = "companion to mtxrun.lua", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo: also line number --- todo: sort runtime as option - -local match, format, find = string.match, string.format, string.find - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-profile</entry> - <entry name="detail">ConTeXt MkIV LuaTeX Profiler</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="analyze"><short>analyze lua calls</short></flag> - <flag name="trace"><short>analyze tex calls</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-cache", - banner = "ConTeXt MkIV LuaTeX Profiler 1.00", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.profiler = scripts.profiler or { } - -local timethreshold = 0 -local callthreshold = 2500 -local countthreshold = 2500 - -local functiontemplate = "%12s %03.4f %9i %s" -local calltemplate = "%9i %s" -local totaltemplate = "%i internal calls, %i function calls taking %3.4f seconds" -local thresholdtemplate = "thresholds: %i internal calls, %i function calls, %i seconds" - -function scripts.profiler.analyze(filename) - local f = io.open(filename) - if f then - local times, counts, calls = { }, { }, { } - local totalruntime, totalcount, totalcalls = 0, 0, 0 - for line in f:lines() do - local stacklevel, filename, functionname, linenumber, currentline, localtime, totaltime = line:match("^(%d+)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)") - if not filename then - -- next - elseif filename == "=[C]" then - if not functionname:find("^%(") then - calls[functionname] = (calls[functionname] or 0) + 1 - end - else - local filename = filename:match("^@(.*)$") - if filename then - local fi = times[filename] - if not fi then fi = { } times[filename] = fi end - fi[functionname] = (fi[functionname] or 0) + tonumber(localtime) - counts[functionname] = (counts[functionname] or 0) + 1 - end - end - end - f:close() - print("") - local loaded = { } - local sorted = table.sortedkeys(times) - for i=1,#sorted do - local filename = sorted[i] - local functions = times[filename] - local sorted = table.sortedkeys(functions) - for i=1,#sorted do - local functionname = sorted[i] - local totaltime = functions[functionname] - local count = counts[functionname] - totalcount = totalcount + count - if totaltime > timethreshold or count > countthreshold then - totalruntime = totalruntime + totaltime - local functionfile, somenumber = functionname:match("^@(.+):(.-)$") - if functionfile then - local number = tonumber(somenumber) - if number then - if not loaded[functionfile] then - loaded[functionfile] = string.splitlines(io.loaddata(functionfile) or "") - end - functionname = loaded[functionfile][number] or functionname - functionname = functionname:gsub("^%s*","") - functionname = functionname:gsub("%s*%-%-.*$","") - functionname = number .. ": " .. functionname - end - end - filename = file.basename(filename) - print(functiontemplate:format(filename,totaltime,count,functionname)) - end - end - end - print("") - local sorted = table.sortedkeys(calls) - for i=1,#sorted do - local call = sorted[i] - local n = calls[call] - totalcalls = totalcalls + n - if n > callthreshold then - print(calltemplate:format(n,call)) - end - end - print("") - print(totaltemplate:format(totalcalls,totalcount,totalruntime)) - print("") - print(thresholdtemplate:format(callthreshold,countthreshold,timethreshold)) - end -end - -function scripts.profiler.x_analyze(filename) - local f = io.open(filename) - local calls = { } - local lines = 0 - if f then - while true do - local line = f:read() - if line then - lines = lines + 1 - local c = match(line,"\\([a-zA-Z%!%?@]+) *%->") - if c then - local cc = calls[c] - if not cc then - calls[c] = 1 - else - calls[c] = cc + 1 - end - end - else - break - end - end - f:close() - local noc = 0 -local criterium = 100 - for name, n in next, calls do - if n > criterium then - if find(name,"^@@[a-z][a-z]") then - -- parameter - elseif find(name,"^[cvserft]%!") then - -- variables and constants - elseif find(name,"^%?%?[a-z][a-z]$") then - -- prefix - elseif find(name,"^%!%!") then - -- reserved - elseif find(name,"^@.+@$") then - -- weird - else - noc = noc + n - print(format("%6i: %s",n,name)) - end - end - end - print("") - print(format("number of lines: %s",lines)) - print(format("number of calls: %s",noc)) - print(format("criterium calls: %s",criterium)) - end -end - ---~ scripts.profiler.analyze("t:/manuals/mk/mk-fonts-profile.lua") ---~ scripts.profiler.analyze("t:/manuals/mk/mk-introduction-profile.lua") - -if environment.argument("analyze") then - scripts.profiler.analyze(environment.files[1] or "luatex-profile.log") -elseif environment.argument("trace") then - scripts.profiler.analyze(environment.files[1] or "temp.log") -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-profile'] = {
+ version = 1.000,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo: also line number
+-- todo: sort runtime as option
+
+local match, format, find = string.match, string.format, string.find
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-profile</entry>
+ <entry name="detail">ConTeXt MkIV LuaTeX Profiler</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="analyze"><short>analyze lua calls</short></flag>
+ <flag name="trace"><short>analyze tex calls</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-cache",
+ banner = "ConTeXt MkIV LuaTeX Profiler 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.profiler = scripts.profiler or { }
+
+local timethreshold = 0
+local callthreshold = 2500
+local countthreshold = 2500
+
+local functiontemplate = "%12s %03.4f %9i %s"
+local calltemplate = "%9i %s"
+local totaltemplate = "%i internal calls, %i function calls taking %3.4f seconds"
+local thresholdtemplate = "thresholds: %i internal calls, %i function calls, %i seconds"
+
+function scripts.profiler.analyze(filename)
+ local f = io.open(filename)
+ if f then
+ local times, counts, calls = { }, { }, { }
+ local totalruntime, totalcount, totalcalls = 0, 0, 0
+ for line in f:lines() do
+ local stacklevel, filename, functionname, linenumber, currentline, localtime, totaltime = line:match("^(%d+)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)\t(.-)")
+ if not filename then
+ -- next
+ elseif filename == "=[C]" then
+ if not functionname:find("^%(") then
+ calls[functionname] = (calls[functionname] or 0) + 1
+ end
+ else
+ local filename = filename:match("^@(.*)$")
+ if filename then
+ local fi = times[filename]
+ if not fi then fi = { } times[filename] = fi end
+ fi[functionname] = (fi[functionname] or 0) + tonumber(localtime)
+ counts[functionname] = (counts[functionname] or 0) + 1
+ end
+ end
+ end
+ f:close()
+ print("")
+ local loaded = { }
+ local sorted = table.sortedkeys(times)
+ for i=1,#sorted do
+ local filename = sorted[i]
+ local functions = times[filename]
+ local sorted = table.sortedkeys(functions)
+ for i=1,#sorted do
+ local functionname = sorted[i]
+ local totaltime = functions[functionname]
+ local count = counts[functionname]
+ totalcount = totalcount + count
+ if totaltime > timethreshold or count > countthreshold then
+ totalruntime = totalruntime + totaltime
+ local functionfile, somenumber = functionname:match("^@(.+):(.-)$")
+ if functionfile then
+ local number = tonumber(somenumber)
+ if number then
+ if not loaded[functionfile] then
+ loaded[functionfile] = string.splitlines(io.loaddata(functionfile) or "")
+ end
+ functionname = loaded[functionfile][number] or functionname
+ functionname = functionname:gsub("^%s*","")
+ functionname = functionname:gsub("%s*%-%-.*$","")
+ functionname = number .. ": " .. functionname
+ end
+ end
+ filename = file.basename(filename)
+ print(functiontemplate:format(filename,totaltime,count,functionname))
+ end
+ end
+ end
+ print("")
+ local sorted = table.sortedkeys(calls)
+ for i=1,#sorted do
+ local call = sorted[i]
+ local n = calls[call]
+ totalcalls = totalcalls + n
+ if n > callthreshold then
+ print(calltemplate:format(n,call))
+ end
+ end
+ print("")
+ print(totaltemplate:format(totalcalls,totalcount,totalruntime))
+ print("")
+ print(thresholdtemplate:format(callthreshold,countthreshold,timethreshold))
+ end
+end
+
+function scripts.profiler.x_analyze(filename)
+ local f = io.open(filename)
+ local calls = { }
+ local lines = 0
+ if f then
+ while true do
+ local line = f:read()
+ if line then
+ lines = lines + 1
+ local c = match(line,"\\([a-zA-Z%!%?@]+) *%->")
+ if c then
+ local cc = calls[c]
+ if not cc then
+ calls[c] = 1
+ else
+ calls[c] = cc + 1
+ end
+ end
+ else
+ break
+ end
+ end
+ f:close()
+ local noc = 0
+local criterium = 100
+ for name, n in next, calls do
+ if n > criterium then
+ if find(name,"^@@[a-z][a-z]") then
+ -- parameter
+ elseif find(name,"^[cvserft]%!") then
+ -- variables and constants
+ elseif find(name,"^%?%?[a-z][a-z]$") then
+ -- prefix
+ elseif find(name,"^%!%!") then
+ -- reserved
+ elseif find(name,"^@.+@$") then
+ -- weird
+ else
+ noc = noc + n
+ print(format("%6i: %s",n,name))
+ end
+ end
+ end
+ print("")
+ print(format("number of lines: %s",lines))
+ print(format("number of calls: %s",noc))
+ print(format("criterium calls: %s",criterium))
+ end
+end
+
+--~ scripts.profiler.analyze("t:/manuals/mk/mk-fonts-profile.lua")
+--~ scripts.profiler.analyze("t:/manuals/mk/mk-introduction-profile.lua")
+
+if environment.argument("analyze") then
+ scripts.profiler.analyze(environment.files[1] or "luatex-profile.log")
+elseif environment.argument("trace") then
+ scripts.profiler.analyze(environment.files[1] or "temp.log")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-rsync.lua b/scripts/context/lua/mtx-rsync.lua index 65f795ee5..1095f2d05 100644 --- a/scripts/context/lua/mtx-rsync.lua +++ b/scripts/context/lua/mtx-rsync.lua @@ -1,189 +1,189 @@ -if not modules then modules = { } end modules ['mtx-rsync'] = { - version = 1.000, - 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 an experimental script that will be extended over time and --- is used by myself. An example or a copy spec: --- --- --- local devdir = "m:/develop/services" --- local orgdir = "m:/pod/m4all" --- --- return { --- { --- origin = { devdir, "framework/scripts/d-dispatchers.lua"}, --- target = { orgdir, "framework/scripts" }, --- }, --- { --- origin = { devdir, "framework/scripts/common/*"}, --- target = { orgdir, "framework/scripts/common" }, --- }, --- { --- origin = { devdir, "framework/scripts/d-buildtool.lua" }, --- target = { orgdir, "framework/scripts" } --- }, --- { --- origin = { devdir, "framework/scripts/buildtool/*"}, --- target = { orgdir, "framework/scripts/buildtool" }, --- }, --- { --- origin = { devdir, "framework/m4all*" }, --- target = { orgdir, "framework" }, --- }, --- { --- origin = { devdir, "framework/configurations/*m4all*"}, --- target = { orgdir, "framework/configurations" }, --- }, --- { --- recurse = true, --- origin = { devdir, "context/tex/texmf-project/tex/context/user/m4all/*" }, --- target = { orgdir, "context/tex/texmf-project/tex/context/user/m4all" }, --- }, --- } - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-rsync</entry> - <entry name="detail">Rsync Helpers</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="job"><short>use given file as specification</short></flag> - <flag name="dryrun"><short>show what would happen</short></flag> - <flag name="force"><short>force run</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-rsync", - banner = "Rsync Helpers 0.10", - helpinfo = helpinfo, -} - -local format, gsub = string.format, string.gsub -local concat = table.concat - -local report_message = logs.new("rsync message") -local report_dryrun = logs.new("rsync dryrun") -local report_normal = logs.new("rsync normal") -local report_command = logs.new("rsync command") - -local cleanup - -if os.platform == "mswin" then - os.setenv("CYGWIN","nontsec") - cleanup = function(name) - return (gsub(name,"([a-zA-Z]):/", "/cygdrive/%1/")) - end -else - cleanup = function(name) - return name - end -end - -function rsynccommand(dryrun,recurse,origin,target) - local command = "rsync -ptlva " - if dryrun then - command = command .. "-n " - end - if recurse then - command = command .. "-r " - end - return format('%s %s %s',command,origin,target) -end - -scripts = scripts or { } -scripts.rsync = scripts.rsync or { } -local rsync = scripts.rsync - -rsync.mode = "command" - -function rsync.run(origin,target,message,recurse) - if type(origin) == "table" then - origin = concat(origin,"/") - end - if type(target) == "table" then - target = concat(target,"/") - end - origin = cleanup(origin) - target = cleanup(target) - local path = gsub(target,"^/cygdrive/(.)","%1:") - if not lfs.isdir(path) then - report_message("creating target dir %s",path) - dir.makedirs(path) -- as rsync only creates them when --recursive - end - if message then - report_message(message) - end - if rsync.mode == "dryrun" then - local command = rsynccommand(true,recurse,origin,target) - report_dryrun(command.."\n") - os.execute(command) - elseif rsync.mode == "force" then - local command = rsynccommand(false,recurse,origin,target) - report_normal(command.."\n") - os.execute(command) - else - local command = rsynccommand(true,recurse,origin,target) - report_command(command) - end -end - -function rsync.job(list) - if type(list) == "string" and lfs.isfile(list) then - list = dofile(list) - end - if type(list) ~= "table" then - report_message("invalid job specification") - return - end - for i=1,#list do - local li = list[i] - local origin = li.origin - local target = li.target - local message = li.message - local recurse = li.recurse - if origin and #origin > 0 and target and #target > 0 then -- string or table - rsync.run(origin,target,message,recurse) - else - report_message("invalid job specification at index %s",i) - end - end -end - -if environment.ownscript then - -- stand alone -else - report(application.banner) - return rsync -end - -local arguments = environment.arguments -local files = environment.files - -if arguments.dryrun then - rsync.mode = "dryrun" -elseif arguments.force then - rsync.mode = "force" -end - -if arguments.exporthelp then - application.export(arguments.exporthelp,environment.files[1]) -elseif arguments.job then - rsync.job(files[1]) -elseif files[1] and files[2] then - rsync.run(files[1],files[2]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-rsync'] = {
+ version = 1.000,
+ 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 an experimental script that will be extended over time and
+-- is used by myself. An example or a copy spec:
+--
+--
+-- local devdir = "m:/develop/services"
+-- local orgdir = "m:/pod/m4all"
+--
+-- return {
+-- {
+-- origin = { devdir, "framework/scripts/d-dispatchers.lua"},
+-- target = { orgdir, "framework/scripts" },
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/common/*"},
+-- target = { orgdir, "framework/scripts/common" },
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/d-buildtool.lua" },
+-- target = { orgdir, "framework/scripts" }
+-- },
+-- {
+-- origin = { devdir, "framework/scripts/buildtool/*"},
+-- target = { orgdir, "framework/scripts/buildtool" },
+-- },
+-- {
+-- origin = { devdir, "framework/m4all*" },
+-- target = { orgdir, "framework" },
+-- },
+-- {
+-- origin = { devdir, "framework/configurations/*m4all*"},
+-- target = { orgdir, "framework/configurations" },
+-- },
+-- {
+-- recurse = true,
+-- origin = { devdir, "context/tex/texmf-project/tex/context/user/m4all/*" },
+-- target = { orgdir, "context/tex/texmf-project/tex/context/user/m4all" },
+-- },
+-- }
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-rsync</entry>
+ <entry name="detail">Rsync Helpers</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="job"><short>use given file as specification</short></flag>
+ <flag name="dryrun"><short>show what would happen</short></flag>
+ <flag name="force"><short>force run</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-rsync",
+ banner = "Rsync Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+local format, gsub = string.format, string.gsub
+local concat = table.concat
+
+local report_message = logs.new("rsync message")
+local report_dryrun = logs.new("rsync dryrun")
+local report_normal = logs.new("rsync normal")
+local report_command = logs.new("rsync command")
+
+local cleanup
+
+if os.platform == "mswin" then
+ os.setenv("CYGWIN","nontsec")
+ cleanup = function(name)
+ return (gsub(name,"([a-zA-Z]):/", "/cygdrive/%1/"))
+ end
+else
+ cleanup = function(name)
+ return name
+ end
+end
+
+function rsynccommand(dryrun,recurse,origin,target)
+ local command = "rsync -ptlva "
+ if dryrun then
+ command = command .. "-n "
+ end
+ if recurse then
+ command = command .. "-r "
+ end
+ return format('%s %s %s',command,origin,target)
+end
+
+scripts = scripts or { }
+scripts.rsync = scripts.rsync or { }
+local rsync = scripts.rsync
+
+rsync.mode = "command"
+
+function rsync.run(origin,target,message,recurse)
+ if type(origin) == "table" then
+ origin = concat(origin,"/")
+ end
+ if type(target) == "table" then
+ target = concat(target,"/")
+ end
+ origin = cleanup(origin)
+ target = cleanup(target)
+ local path = gsub(target,"^/cygdrive/(.)","%1:")
+ if not lfs.isdir(path) then
+ report_message("creating target dir %s",path)
+ dir.makedirs(path) -- as rsync only creates them when --recursive
+ end
+ if message then
+ report_message(message)
+ end
+ if rsync.mode == "dryrun" then
+ local command = rsynccommand(true,recurse,origin,target)
+ report_dryrun(command.."\n")
+ os.execute(command)
+ elseif rsync.mode == "force" then
+ local command = rsynccommand(false,recurse,origin,target)
+ report_normal(command.."\n")
+ os.execute(command)
+ else
+ local command = rsynccommand(true,recurse,origin,target)
+ report_command(command)
+ end
+end
+
+function rsync.job(list)
+ if type(list) == "string" and lfs.isfile(list) then
+ list = dofile(list)
+ end
+ if type(list) ~= "table" then
+ report_message("invalid job specification")
+ return
+ end
+ for i=1,#list do
+ local li = list[i]
+ local origin = li.origin
+ local target = li.target
+ local message = li.message
+ local recurse = li.recurse
+ if origin and #origin > 0 and target and #target > 0 then -- string or table
+ rsync.run(origin,target,message,recurse)
+ else
+ report_message("invalid job specification at index %s",i)
+ end
+ end
+end
+
+if environment.ownscript then
+ -- stand alone
+else
+ report(application.banner)
+ return rsync
+end
+
+local arguments = environment.arguments
+local files = environment.files
+
+if arguments.dryrun then
+ rsync.mode = "dryrun"
+elseif arguments.force then
+ rsync.mode = "force"
+end
+
+if arguments.exporthelp then
+ application.export(arguments.exporthelp,environment.files[1])
+elseif arguments.job then
+ rsync.job(files[1])
+elseif files[1] and files[2] then
+ rsync.run(files[1],files[2])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-scite.lua b/scripts/context/lua/mtx-scite.lua index 972edbfe6..47aa3d009 100644 --- a/scripts/context/lua/mtx-scite.lua +++ b/scripts/context/lua/mtx-scite.lua @@ -1,259 +1,259 @@ -if not modules then modules = { } end modules ['mtx-scite'] = { - 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 P, R, S, C, Ct, Cf, Cc, Cg = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.Cg -local lpegmatch = lpeg.match -local format, lower, gmatch = string.format, string.lower, string.gmatch - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-scite</entry> - <entry name="detail">Scite Helper Script</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="words"><short>convert spell-*.txt into spell-*.lua</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-scite", - banner = "Scite Helper Script 1.00", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.scite = scripts.scite or { } - --- todo: append to global properties else order of loading problem --- linux problem ... files are under root protection so we need --install --- --- local scitesignals = { "scite-context.rme", "context.properties" } --- local screenfont = "lmtypewriter10-regular.ttf" - --- function scripts.scite.start(indeed) --- local usedsignal, datapath, fullname, workname, userpath, fontpath --- if os.type == "windows" then --- workname = "scite.exe" --- userpath = os.getenv("USERPROFILE") or "" --- fontpath = os.getenv("SYSTEMROOT") --- fontpath = (fontpath and file.join(fontpath,"fonts")) or "" --- else --- workname = "scite" --- userpath = os.getenv("HOME") or "" --- fontpath = "" --- end --- local binpaths = file.split_path(os.getenv("PATH")) or file.split_path(os.getenv("path")) --- for i=1,#scitesignals do --- local scitesignal = scitesignals[i] --- local scitepath = resolvers.findfile(scitesignal,"other text files") or "" --- if scitepath ~= "" then --- scitepath = file.dirname(scitepath) -- data --- if scitepath == "" then --- scitepath = resolvers.cleanpath(lfs.currentdir()) --- else --- usedsignal, datapath = scitesignal, scitepath --- break --- end --- end --- end --- if not datapath or datapath == "" then --- report("invalid datapath, maybe you need to regenerate the file database") --- return false --- end --- if not binpaths or #binpaths == 0 then --- report("invalid binpath") --- return false --- end --- for i=1,#binpaths do --- local p = file.join(binpaths[i],workname) --- if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub --- fullname = p --- break --- end --- end --- if not fullname then --- report("unable to locate %s",workname) --- return false --- end --- local properties = dir.glob(file.join(datapath,"*.properties")) --- local luafiles = dir.glob(file.join(datapath,"*.lua")) --- local extrafont = resolvers.findfile(screenfont,"truetype font") or "" --- local pragmafound = dir.glob(file.join(datapath,"pragma.properties")) --- if userpath == "" then --- report("unable to figure out userpath") --- return false --- end --- local verbose = environment.argument("verbose") --- local tobecopied, logdata = { }, { } --- local function check_state(fullname,newpath) --- local basename = file.basename(fullname) --- local destination = file.join(newpath,basename) --- local pa, da = lfs.attributes(fullname), lfs.attributes(destination) --- if not da then --- logdata[#logdata+1] = { "new : %s", basename } --- tobecopied[#tobecopied+1] = { fullname, destination } --- elseif pa.modification > da.modification then --- logdata[#logdata+1] = { "outdated : %s", basename } --- tobecopied[#tobecopied+1] = { fullname, destination } --- else --- logdata[#logdata+1] = { "up to date : %s", basename } --- end --- end --- for i=1,#properties do --- check_state(properties[i],userpath) --- end --- for i=1,#luafiles do --- check_state(luafiles[i],userpath) --- end --- if fontpath ~= "" then --- check_state(extrafont,fontpath) --- end --- local userpropfile = "SciTEUser.properties" --- if os.name ~= "windows" then --- userpropfile = "." .. userpropfile --- end --- local fullpropfile = file.join(userpath,userpropfile) --- local userpropdata = io.loaddata(fullpropfile) or "" --- local propfiledone = false --- if pragmafound then --- if userpropdata == "" then --- logdata[#logdata+1] = { "error : no user properties found on '%s'", fullpropfile } --- elseif string.find(userpropdata,"import *pragma") then --- logdata[#logdata+1] = { "up to date : 'import pragma' in '%s'", userpropfile } --- else --- logdata[#logdata+1] = { "yet unset : 'import pragma' in '%s'", userpropfile } --- userproperties = userpropdata .. "\n\nimport pragma\n\n" --- propfiledone = true --- end --- else --- if string.find(userpropdata,"import *context") then --- logdata[#logdata+1] = { "up to date : 'import context' in '%s'", userpropfile } --- else --- logdata[#logdata+1] = { "yet unset : 'import context' in '%s'", userpropfile } --- userproperties = userpropdata .. "\n\nimport context\n\n" --- propfiledone = true --- end --- end --- if not indeed or verbose then --- report("used signal: %s", usedsignal) --- report("data path : %s", datapath) --- report("full name : %s", fullname) --- report("user path : %s", userpath) --- report("extra font : %s", extrafont) --- end --- if #logdata > 0 then --- report("") --- for k=1,#logdata do --- local v = logdata[k] --- report(v[1],v[2]) --- end --- end --- if indeed then --- if #tobecopied > 0 then --- report("warning : copying updated files") --- for i=1,#tobecopied do --- local what = tobecopied[i] --- report("copying : '%s' => '%s'",what[1],what[2]) --- file.copy(what[1],what[2]) --- end --- end --- if propfiledone then --- report("saving : '%s'",userpropfile) --- io.savedata(fullpropfile,userpropdata) --- end --- os.launch(fullname) --- end --- end - --- local splitter = (Cf(Ct("") * (Cg(C(R("az","AZ","\127\255")^1) * Cc(true)) + P(1))^1,rawset) )^0 --- --- local function splitwords(words) --- return lpegmatch(splitter,words) -- or just split and tohash --- end - -local function splitwords(words) - local w = { } - for s in string.gmatch(words,"[a-zA-Z\127-255]+") do - if #s > 2 then -- will become option - w[lower(s)] = s - end - end - return w -end - --- maybe: lowerkey = UpperWhatever - -function scripts.scite.words() - for i=1,#environment.files do - local tag = environment.files[i] - local tag = string.match(tag,"spell%-(..)%.") or tag - local txtname = format("spell-%s.txt",tag) - local luaname = format("spell-%s.lua",tag) - local lucname = format("spell-%s.luc",tag) - if lfs.isfile(txtname) then - report("loading %s",txtname) - local olddata = io.loaddata(txtname) or "" - local words = splitwords(olddata) - local min, max, n = 100, 1, 0 - for k, v in next, words do - local l = #k - if l < min then - min = l - end - if l > max then - max = l - end - n = n + 1 - end - if min > max then - min = max - end - local newdata = { - words = words, - source = oldname, - min = min, - max = max, - n = n, - } - report("saving %q, %s words, %s shortest, %s longest",luaname,n,min,max) - io.savedata(luaname,table.serialize(newdata,true)) - report("compiling %q",lucname) - os.execute(format("luac -s -o %s %s",lucname,luaname)) - else - report("no data file %s",txtname) - end - end - report("you need to move the lua files to lexers/data") -end - --- if environment.argument("start") then --- scripts.scite.start(true) --- elseif environment.argument("test") then --- scripts.scite.start() --- else --- application.help() --- end - -if environment.argument("words") then - scripts.scite.words() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end - +if not modules then modules = { } end modules ['mtx-scite'] = {
+ 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 P, R, S, C, Ct, Cf, Cc, Cg = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Ct, lpeg.Cf, lpeg.Cc, lpeg.Cg
+local lpegmatch = lpeg.match
+local format, lower, gmatch = string.format, string.lower, string.gmatch
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-scite</entry>
+ <entry name="detail">Scite Helper Script</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="words"><short>convert spell-*.txt into spell-*.lua</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-scite",
+ banner = "Scite Helper Script 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.scite = scripts.scite or { }
+
+-- todo: append to global properties else order of loading problem
+-- linux problem ... files are under root protection so we need --install
+--
+-- local scitesignals = { "scite-context.rme", "context.properties" }
+-- local screenfont = "lmtypewriter10-regular.ttf"
+
+-- function scripts.scite.start(indeed)
+-- local usedsignal, datapath, fullname, workname, userpath, fontpath
+-- if os.type == "windows" then
+-- workname = "scite.exe"
+-- userpath = os.getenv("USERPROFILE") or ""
+-- fontpath = os.getenv("SYSTEMROOT")
+-- fontpath = (fontpath and file.join(fontpath,"fonts")) or ""
+-- else
+-- workname = "scite"
+-- userpath = os.getenv("HOME") or ""
+-- fontpath = ""
+-- end
+-- local binpaths = file.split_path(os.getenv("PATH")) or file.split_path(os.getenv("path"))
+-- for i=1,#scitesignals do
+-- local scitesignal = scitesignals[i]
+-- local scitepath = resolvers.findfile(scitesignal,"other text files") or ""
+-- if scitepath ~= "" then
+-- scitepath = file.dirname(scitepath) -- data
+-- if scitepath == "" then
+-- scitepath = resolvers.cleanpath(lfs.currentdir())
+-- else
+-- usedsignal, datapath = scitesignal, scitepath
+-- break
+-- end
+-- end
+-- end
+-- if not datapath or datapath == "" then
+-- report("invalid datapath, maybe you need to regenerate the file database")
+-- return false
+-- end
+-- if not binpaths or #binpaths == 0 then
+-- report("invalid binpath")
+-- return false
+-- end
+-- for i=1,#binpaths do
+-- local p = file.join(binpaths[i],workname)
+-- if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub
+-- fullname = p
+-- break
+-- end
+-- end
+-- if not fullname then
+-- report("unable to locate %s",workname)
+-- return false
+-- end
+-- local properties = dir.glob(file.join(datapath,"*.properties"))
+-- local luafiles = dir.glob(file.join(datapath,"*.lua"))
+-- local extrafont = resolvers.findfile(screenfont,"truetype font") or ""
+-- local pragmafound = dir.glob(file.join(datapath,"pragma.properties"))
+-- if userpath == "" then
+-- report("unable to figure out userpath")
+-- return false
+-- end
+-- local verbose = environment.argument("verbose")
+-- local tobecopied, logdata = { }, { }
+-- local function check_state(fullname,newpath)
+-- local basename = file.basename(fullname)
+-- local destination = file.join(newpath,basename)
+-- local pa, da = lfs.attributes(fullname), lfs.attributes(destination)
+-- if not da then
+-- logdata[#logdata+1] = { "new : %s", basename }
+-- tobecopied[#tobecopied+1] = { fullname, destination }
+-- elseif pa.modification > da.modification then
+-- logdata[#logdata+1] = { "outdated : %s", basename }
+-- tobecopied[#tobecopied+1] = { fullname, destination }
+-- else
+-- logdata[#logdata+1] = { "up to date : %s", basename }
+-- end
+-- end
+-- for i=1,#properties do
+-- check_state(properties[i],userpath)
+-- end
+-- for i=1,#luafiles do
+-- check_state(luafiles[i],userpath)
+-- end
+-- if fontpath ~= "" then
+-- check_state(extrafont,fontpath)
+-- end
+-- local userpropfile = "SciTEUser.properties"
+-- if os.name ~= "windows" then
+-- userpropfile = "." .. userpropfile
+-- end
+-- local fullpropfile = file.join(userpath,userpropfile)
+-- local userpropdata = io.loaddata(fullpropfile) or ""
+-- local propfiledone = false
+-- if pragmafound then
+-- if userpropdata == "" then
+-- logdata[#logdata+1] = { "error : no user properties found on '%s'", fullpropfile }
+-- elseif string.find(userpropdata,"import *pragma") then
+-- logdata[#logdata+1] = { "up to date : 'import pragma' in '%s'", userpropfile }
+-- else
+-- logdata[#logdata+1] = { "yet unset : 'import pragma' in '%s'", userpropfile }
+-- userproperties = userpropdata .. "\n\nimport pragma\n\n"
+-- propfiledone = true
+-- end
+-- else
+-- if string.find(userpropdata,"import *context") then
+-- logdata[#logdata+1] = { "up to date : 'import context' in '%s'", userpropfile }
+-- else
+-- logdata[#logdata+1] = { "yet unset : 'import context' in '%s'", userpropfile }
+-- userproperties = userpropdata .. "\n\nimport context\n\n"
+-- propfiledone = true
+-- end
+-- end
+-- if not indeed or verbose then
+-- report("used signal: %s", usedsignal)
+-- report("data path : %s", datapath)
+-- report("full name : %s", fullname)
+-- report("user path : %s", userpath)
+-- report("extra font : %s", extrafont)
+-- end
+-- if #logdata > 0 then
+-- report("")
+-- for k=1,#logdata do
+-- local v = logdata[k]
+-- report(v[1],v[2])
+-- end
+-- end
+-- if indeed then
+-- if #tobecopied > 0 then
+-- report("warning : copying updated files")
+-- for i=1,#tobecopied do
+-- local what = tobecopied[i]
+-- report("copying : '%s' => '%s'",what[1],what[2])
+-- file.copy(what[1],what[2])
+-- end
+-- end
+-- if propfiledone then
+-- report("saving : '%s'",userpropfile)
+-- io.savedata(fullpropfile,userpropdata)
+-- end
+-- os.launch(fullname)
+-- end
+-- end
+
+-- local splitter = (Cf(Ct("") * (Cg(C(R("az","AZ","\127\255")^1) * Cc(true)) + P(1))^1,rawset) )^0
+--
+-- local function splitwords(words)
+-- return lpegmatch(splitter,words) -- or just split and tohash
+-- end
+
+local function splitwords(words)
+ local w = { }
+ for s in string.gmatch(words,"[a-zA-Z\127-255]+") do
+ if #s > 2 then -- will become option
+ w[lower(s)] = s
+ end
+ end
+ return w
+end
+
+-- maybe: lowerkey = UpperWhatever
+
+function scripts.scite.words()
+ for i=1,#environment.files do
+ local tag = environment.files[i]
+ local tag = string.match(tag,"spell%-(..)%.") or tag
+ local txtname = format("spell-%s.txt",tag)
+ local luaname = format("spell-%s.lua",tag)
+ local lucname = format("spell-%s.luc",tag)
+ if lfs.isfile(txtname) then
+ report("loading %s",txtname)
+ local olddata = io.loaddata(txtname) or ""
+ local words = splitwords(olddata)
+ local min, max, n = 100, 1, 0
+ for k, v in next, words do
+ local l = #k
+ if l < min then
+ min = l
+ end
+ if l > max then
+ max = l
+ end
+ n = n + 1
+ end
+ if min > max then
+ min = max
+ end
+ local newdata = {
+ words = words,
+ source = oldname,
+ min = min,
+ max = max,
+ n = n,
+ }
+ report("saving %q, %s words, %s shortest, %s longest",luaname,n,min,max)
+ io.savedata(luaname,table.serialize(newdata,true))
+ report("compiling %q",lucname)
+ os.execute(format("luac -s -o %s %s",lucname,luaname))
+ else
+ report("no data file %s",txtname)
+ end
+ end
+ report("you need to move the lua files to lexers/data")
+end
+
+-- if environment.argument("start") then
+-- scripts.scite.start(true)
+-- elseif environment.argument("test") then
+-- scripts.scite.start()
+-- else
+-- application.help()
+-- end
+
+if environment.argument("words") then
+ scripts.scite.words()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
+
diff --git a/scripts/context/lua/mtx-server-ctx-fonttest.lua b/scripts/context/lua/mtx-server-ctx-fonttest.lua index a8d7edf41..cbfc91559 100644 --- a/scripts/context/lua/mtx-server-ctx-fonttest.lua +++ b/scripts/context/lua/mtx-server-ctx-fonttest.lua @@ -1,749 +1,749 @@ -if not modules then modules = { } end modules ['mtx-server-ctx-fonttest'] = { - version = 1.001, - comment = "Font Feature Tester", - author = "Hans Hagen", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- probably too much but who cares - -dofile(resolvers.findfile("trac-lmx.lua","tex")) -dofile(resolvers.findfile("font-ini.lua","tex")) -dofile(resolvers.findfile("font-con.lua","tex")) -dofile(resolvers.findfile("font-oti.lua","tex")) -dofile(resolvers.findfile("font-otf.lua","tex")) -dofile(resolvers.findfile("font-otp.lua","tex")) -dofile(resolvers.findfile("font-ott.lua","tex")) -dofile(resolvers.findfile("font-syn.lua","tex")) -dofile(resolvers.findfile("font-mis.lua","tex")) - -local format, gsub, concat, match, find = string.format, string.gsub, table.concat, string.match, string.find - -local report = logs.reporter("ctx-fonttest") - -local sample_line = "This is a sample line!" -local tempname = "mtx-server-ctx-fonttest-temp" -local temppath = caches.setfirstwritablefile("temp","mtx-server-ctx-fonttest") -local basename = "mtx-server-ctx-fonttest-data.lua" -local basepath = temppath - -local remove_suffixes = { "tex", "pdf", "log" } -local what_options = { "trace", "basemode" } - -for i=1,#remove_suffixes do - os.remove(file.join(temppath,file.addsuffix(tempname,remove_suffixes[i]))) -end - -local process_templates = { } - -process_templates.default = [[ -\starttext - \setupdirections[bidi=global] - \definefontfeature[sample][analyze=yes,%s] - \definedfont[name:%s*sample] - \startTEXpage[offset=3pt] - \detokenize{%s} - \stopTEXpage -\stoptext -]] - -process_templates.cache = [[ -\starttext - \definedfont[name:%s] - \startTEXpage[offset=3pt] - cached: \detokenize{%s} - \stopTEXpage -\stoptext -]] - -process_templates.trace = [[ -\usemodule[fnt-20] - -\definefontfeature[sample][%s] - -\setupcolors[state=start] - -\setupdirections[bidi=global] - -\setvariables - [otftracker] - [title=Test Run, - font=name:%s, - direction=0, - features=sample, - sample={\detokenize{%s}}] -]] - -local javascripts = [[ -function selected_radio(name) { - var form = document.forms["main-form"] ; - var script = form.elements[name] ; - if (script) { - var n = script.length ; - if (n) { - for (var i=0; i<n; i++) { - if (script[i].checked) { - return script[i].value ; - } - } - } - } - return "" ; -} - -function reset_valid() { - var fields = document.getElementsByTagName("span") ; - for (var i=0; i<fields.length; i++) { - var e = fields[i] - if (e) { - if (e.className == "valid") { - e.className = "" ; - } - } - } -} - -function set_valid() { - var script = selected_radio("script") ; - var language = selected_radio("language") ; - if (script && language) { - var s = feature_hash[script] ; - if (s) { - for (l in s) { - var e = document.getElementById("t-l-" + l) ; - if (e) { - e.className = "valid" ; - } - } - var l = s[language] ; - if (l) { - for (i in l) { - var e = document.getElementById("t-f-" + i) ; - if (e) { - e.className = "valid" ; - } - } - } - var e = document.getElementById("t-s-" + script) ; - if (e) { - e.className = "valid" ; - } - } - } -} - -function check_form() { - reset_valid() ; - set_valid() ; -} - -function check_script() { - reset_valid() ; - set_valid() ; -} - -function check_language() { - reset_valid() ; - set_valid() ; -} - -function check_feature() { - // not needed -} -]] - -local cache = { } - -local function showfeatures(f) - if f then - report("processing font '%s'",f) - local features = cache[f] - if features == nil then - features = fonts.helpers.getfeatures(resolvers.findfile(f)) - if not features then - report("building cache for '%s'",f) - io.savedata(file.join(temppath,file.addsuffix(tempname,"tex")),format(process_templates.cache,f,f)) - os.execute(format("mtxrun --path=%s --script context --once --batchmode %s",temppath,tempname)) - features = fonts.helpers.getfeatures(f) - end - cache[f] = features or false - report("caching info of '%s'",f) - else - report("using cached info of '%s'",f) - end - if features then - local scr, lan, fea, rev = { }, { }, { }, { } - local function show(what) - local data = features[what] - if data and next(data) then - for f,ff in next, data do - if find(f,"<") then - -- ignore aat for the moment - else - fea[f] = true - for s, ss in next, ff do - if find(s,"%*") then - -- ignore * - else - scr[s] = true - local rs = rev[s] if not rs then rs = {} rev[s] = rs end - for k, l in next, ss do - if find(k,"%*") then - -- ignore * - else - lan[k] = true - local rsk = rs[k] if not rsk then rsk = { } rs[k] = rsk end - rsk[f] = true - end - end - end - end - end - end - end - end - for what, v in table.sortedhash(features) do - show(what) - end - local stupid = { } - stupid[#stupid+1] = "var feature_hash = new Array ;" - for s, sr in next, rev do - stupid[#stupid+1] = format("feature_hash['%s'] = new Array ;",s) - for l, lr in next, sr do - stupid[#stupid+1] = format("feature_hash['%s']['%s'] = new Array ;",s,l) - for f, fr in next, lr do - stupid[#stupid+1] = format("feature_hash['%s']['%s']['%s'] = true ;",s,l,f) - end - end - end - -- gpos feature script languages - return { - scripts = scr, - languages = lan, - features = fea, - javascript = concat(stupid,"\n") - } - end - end -end - -local template_h = [[ -<tr> - <th>safe name </th> - <th>family name </th> - <th>style-variant-weight-width </th> - <th>font name </th> - <th>weight </th> - <th>filename</th> -</tr>]] - -local template_d = [[ -<tr> - <td><a href='mtx-server-ctx-fonttest.lua?selection=%s'>%s</a> </td> - <td>%s </td> - <td>%s-%s-%s-%s </td> - <td>%s </td> - <td>%s </td> - <td>%s</td> -</tr>]] - -local function select_font() - local t = fonts.names.list(".*",false,true) - if t then - local listoffonts = { } - listoffonts[#listoffonts+1] = "<table>" - listoffonts[#listoffonts+1] = template_h - for k, v in table.sortedhash(t) do - local kind = v.format - if kind == "otf" or kind == "ttf" or kind == "ttc" then - local fontname = v.fontname - listoffonts[#listoffonts+1] = format(template_d, fontname, fontname, - v.familyname or "", - t.variant or "normal", - t.weight or "normal", - t.width or "normal", - t.style or "normal", - v.rawname or fontname, - v.fontweight or "", - v.filename or "" - ) - end - end - listoffonts[#listoffonts+1] = "</table>" - return concat(listoffonts,"\n") - end - return "<b>no fonts</b>" -end - -local edit_template = [[ - <textarea name='sampletext' rows='5' cols='100'>%s</textarea> - <br/> <br/>name: <input type='text' name='name' size='20' value=%q/> title: <input type='text' name='title' size='40' value=%q/> - <br/> <br/>scripts: %s - <br/> <br/>languages: %s - <br/> <br/>features: %s - <br/> <br/>options: %s -]] - --- <embed src="%s#toolbar=0&navpanes=0&scrollbar=0" width="100%%"/> - -local result_template = [[ - <br/> <br/> - <embed src="%s#view=Fit&toolbar=0&navpanes=0&scrollbar=0" width="100%%"/> - <br/> <br/> results: - <a href='%s' target="source">tex file</a> - <a href='%s' target="result">pdf file</a> - <br/> <br/> -]] - -scripts.webserver.registerpath(temppath) - -local function get_specification(name) - return fonts.names.resolvedspecification(name or "") -end - -local function edit_font(currentfont,detail,tempname) - report("entering edit mode for '%s'",currentfont) - local specification = get_specification(currentfont) - if specification then - local htmldata = showfeatures(specification.filename) - if htmldata then - local features, languages, scripts, options = { }, { }, { }, { } - local sorted = table.sortedkeys(htmldata.scripts) - for k=1,#sorted do - local v = sorted[k] - local s = fonts.handlers.otf.tables.scripts[v] or v - if detail and v == detail.script then - scripts[#scripts+1] = format("<input title='%s' id='s-%s' type='radio' name='script' value='%s' onclick='check_script()' checked='checked'/> <span id='t-s-%s'>%s</span>",s,v,v,v,v) - else - scripts[#scripts+1] = format("<input title='%s' id='s-%s' type='radio' name='script' value='%s' onclick='check_script()' /> <span id='t-s-%s'>%s</span>",s,v,v,v,v) - end - end - local sorted = table.sortedkeys(htmldata.languages) - for k=1,#sorted do - local v = sorted[k] - local l = fonts.handlers.otf.tables.languages[v] or v - if detail and v == detail.language then - languages[#languages+1] = format("<input title='%s' id='l-%s' type='radio' name='language' value='%s' onclick='check_language()' checked='checked'/> <span id='t-l-%s'>%s</span>",l,v,v,v,v) - else - languages[#languages+1] = format("<input title='%s' id='l-%s' type='radio' name='language' value='%s' onclick='check_language()' /> <span id='t-l-%s'>%s</span>",l,v,v,v,v) - end - end - local sorted = table.sortedkeys(htmldata.features) - for k=1,#sorted do - local v = sorted[k] - local f = fonts.handlers.otf.tables.features[v] or v - if detail and detail["f-"..v] then - features[#features+1] = format("<input title='%s' id='f-%s' type='checkbox' name='f-%s' onclick='check_feature()' checked='checked'/> <span id='t-f-%s'>%s</span>",f,v,v,v,v) - else - features[#features+1] = format("<input title='%s' id='f-%s' type='checkbox' name='f-%s' onclick='check_feature()' /> <span id='t-f-%s'>%s</span>",f,v,v,v,v) - end - end - for k=1,#what_options do - local v = what_options[k] - if detail and detail["o-"..v] then - options[#options+1] = format("<input id='o-%s' type='checkbox' name='o-%s' checked='checked'/> %s",v,v,v) - else - options[#options+1] = format("<input id='o-%s' type='checkbox' name='o-%s'/> %s",v,v,v) - end - end - local e = format(edit_template, - (detail and detail.sampletext) or sample_line,(detail and detail.name) or "no name",(detail and detail.title) or "", - concat(scripts," "),concat(languages," "),concat(features," "),concat(options," ")) - if tempname then - local pdffile, texfile = file.addsuffix(tempname,"pdf"), file.addsuffix(tempname,"tex") - local r = format(result_template,pdffile,texfile,pdffile) - return e .. r, htmldata.javascript or "" - else - return e, htmldata.javascript or "" - end - else - return "error, nothing set up yet" - end - else - return "error, no info about font" - end -end - -local function process_font(currentfont,detail) -- maybe just fontname - local features = { - "mode=node", - format("language=%s",detail.language or "dflt"), - format("script=%s",detail.script or "dflt"), - } - for k,v in next, detail do - local f = match(k,"^f%-(.*)$") - if f then - features[#features+1] = format("%s=yes",f) - end - end - local variant = process_templates.default - if detail["o-trace"] then - variant = process_templates.trace - end - local sample = string.strip(detail.sampletext or "") - if sample == "" then sample = sample_line end - report("sample text: %s",sample) - dir.mkdirs(temppath) - local fullname = file.join(temppath,file.addsuffix(tempname,"tex")) - local data = format(variant,concat(features,","),currentfont,sample) - local command = format("mtxrun --path=%q --script context --once --batchmode %q",temppath,tempname) - report("filename: %s",fullname) - report("command: %s",command) - io.savedata(fullname,data) - os.execute(command) - return edit_font(currentfont,detail,tempname) -end - -local tex_template = [[ -<pre><tt> -%s -</tt></pre> -]] - -local function show_source(currentfont,detail) - if tempname and tempname ~= "" then - local data = io.loaddata(file.join(temppath,file.addsuffix(tempname,"tex"))) or "no source yet" - return format(tex_template,data) - else - return "no source file" - end -end - -local function show_log(currentfont,detail) - if tempname and tempname ~= "" then - local data = io.loaddata(file.join(temppath,file.addsuffix(tempname,'log'))) or "no log file yet" - data = gsub(data,"[%s%%]*begin of optionfile.-end of optionfile[%s%%]*","\n") - return format(tex_template,data) - else - return "no log file" - end -end - -local function show_font(currentfont,detail) - local specification = get_specification(currentfont) - local features = fonts.helpers.getfeatures(specification.filename) - local result = { } - result[#result+1] = format("<h1>names</h1>",what) - result[#result+1] = "<table>" - result[#result+1] = format("<tr><td class='tc'>fontname: </td><td>%s</td></tr>",currentfont) - result[#result+1] = format("<tr><td class='tc'>fullname: </td><td>%s</td></tr>",specification.fontname or "-") - result[#result+1] = format("<tr><td class='tc'>filename: </td><td>%s</td></tr>",specification.fontfile or "-") - result[#result+1] = format("<tr><td class='tc'>familyname: </td><td>%s</td></tr>",specification.familyname or "-") - result[#result+1] = format("<tr><td class='tc'>fontweight: </td><td>%s</td></tr>",specification.fontweight or "-") - result[#result+1] = format("<tr><td class='tc'>format: </td><td>%s</td></tr>",specification.format or "-") - result[#result+1] = format("<tr><td class='tc'>fullname: </td><td>%s</td></tr>",specification.fullname or "-") - result[#result+1] = format("<tr><td class='tc'>subfamily: </td><td>%s</td></tr>",specification.subfamily or "-") - result[#result+1] = format("<tr><td class='tc'>rawname: </td><td>%s</td></tr>",specification.rawname or "-") - result[#result+1] = format("<tr><td class='tc'>designsize: </td><td>%s</td></tr>",specification.designsize or "-") - result[#result+1] = format("<tr><td class='tc'>minimumsize:</td><td>%s</td></tr>",specification.minsize or "-") - result[#result+1] = format("<tr><td class='tc'>maximumsize:</td><td>%s</td></tr>",specification.maxsize or "-") - result[#result+1] = format("<tr><td class='tc'>style: </td><td>%s</td></tr>",specification.style ~= "" and specification.style or "normal") - result[#result+1] = format("<tr><td class='tc'>variant: </td><td>%s</td></tr>",specification.variant ~= "" and specification.variant or "normal") - result[#result+1] = format("<tr><td class='tc'>weight: </td><td>%s</td></tr>",specification.weight ~= "" and specification.weight or "normal") - result[#result+1] = format("<tr><td class='tc'>width: </td><td>%s</td></tr>",specification.width ~= "" and specification.width or "normal") - result[#result+1] = "</table>" - if features then - for what, v in table.sortedhash(features) do - local data = features[what] - if data and next(data) then - result[#result+1] = format("<h1>%s features</h1>",what) - result[#result+1] = "<table>" - result[#result+1] = "<tr><th>feature</th><th>tag </th><th>script </th><th>languages </th></tr>" - for f,ff in table.sortedhash(data) do - local done = false - for s, ss in table.sortedhash(ff) do - if s == "*" then s = "all" end - if ss ["*"] then ss["*"] = nil ss.all = true end - if done then - f = "" - else - done = true - end - local title = fonts.handlers.otf.tables.features[f] or "" - result[#result+1] = format("<tr><td width='50%%'>%s </td><td><tt>%s </tt></td><td><tt>%s </tt></td><td><tt>%s </tt></td></tr>",title,f,s,concat(table.sortedkeys(ss)," ")) - end - end - result[#result+1] = "</table>" - end - end - else - result[#result+1] = "<br/><br/>This font has no features." - end - return concat(result,"\n") -end - - -local info_template = [[ -<pre><tt> -version : %s -comment : %s -author : %s -copyright : %s - -maillist : ntg-context at ntg.nl -webpage : www.pragma-ade.nl -wiki : contextgarden.net -</tt></pre> -]] - -local function info_about() - local m = modules ['mtx-server-ctx-fonttest'] - return format(info_template,m.version,m.comment,m.author,m.copyright) -end - -local save_template = [[ - the current setup has been saved: - <br/> <br/> - <table> - <tr><td class='tc'>name </td><td>%s</td></tr> - <tr><td class='tc'>title </td><td>%s</td></tr> - <tr><td class='tc'>font </td><td>%s</td></tr> - <tr><td class='tc'>script </td><td>%s</td></tr> - <tr><td class='tc'>language </td><td>%s</td></tr> - <tr><td class='tc'>features </td><td>%s</td></tr> - <tr><td class='tc'>options </td><td>%s</td></tr> - <tr><td class='tc'>sampletext </td><td>%s</td></tr> - </table> -]] - -local function loadbase() - local datafile = file.join(basepath,basename) - local storage = io.loaddata(datafile) or "" - if storage == "" then - storage = { } - else - report("loading '%s'",datafile) - storage = loadstring(storage) - storage = (storage and storage()) or { } - end - return storage -end - -local function loadstored(detail,currentfont,name) - local storage = loadbase() - storage = storage and storage[name] - if storage then - currentfont = storage.font - detail.script = storage.script or detail.script - detail.language = storage.language or detail.language - detail.title = storage.title or detail.title - detail.sampletext = storage.text or detail.sampletext - detail.name = name or "no name" - for k,v in next, storage.features do - detail["f-"..k] = v - end - for k,v in next, storage.options do - detail["o-"..k] = v - end - end - detail.loadname = nil - return detail, currentfont -end - -local function savebase(storage,name) - local datafile = file.join(basepath,basename) - report("saving '%s' in '%s'",name or "data",datafile) - io.savedata(datafile,table.serialize(storage,true)) -end - -local function deletestored(detail,currentfont,name) - local storage = loadbase() - if storage and name and storage[name] then - report("deleting '%s' from base",name) - storage[name] = nil - savebase(storage) - end - detail.deletename = nil - return detail, "" -end - -local function save_font(currentfont,detail) - local specification = get_specification(currentfont) - local name, title, script, language, features, options, text = currentfont, "", "dflt", "dflt", { }, { }, "" - if detail then - local htmldata = showfeatures(specification.filename) - script = detail.script or script - language = detail.language or language - text = string.strip(detail.sampletext or text) - name = string.strip(detail.name or name) - title = string.strip(detail.title or title) - for k,v in next, htmldata.features do - if detail["f-"..k] then features[k] = true end - end - for k=1,#what_options do - local v = what_options[k] - if detail["o-"..v] then options[k] = true end - end - end - if name == "" then - name = "no name" - end - local storage = loadbase() - storage[name] = { - font = currentfont, title = title, script = script, language = language, features = features, options = options, text = text, - } - savebase(storage,name) - return format(save_template,name,title,currentfont,script,language,concat(table.sortedkeys(features)," "),concat(table.sortedkeys(options)," "),text) -end - -local function load_font(currentfont) - local datafile = file.join(basepath,basename) - local storage = loadbase(datafile) - local result = {} - result[#result+1] = format("<tr><th>del </th><th>name </th><th>font </th><th>fontname </th><th>script </th><th>language </th><th>features </th><th>title </th><th>sampletext </th></tr>") - for k,v in table.sortedhash(storage) do - local fontname, fontfile = get_specification(v.font) - result[#result+1] = format("<tr><td><a href='mtx-server-ctx-fonttest.lua?deletename=%s'>x</a> </td><td><a href='mtx-server-ctx-fonttest.lua?loadname=%s'>%s</a> </td><td>%s </td<td>%s </td><td>%s </td><td>%s </td><td>%s </td><td>%s </td><td>%s </td></tr>", - k,k,k,v.font,fontname,v.script,v.language,concat(table.sortedkeys(v.features)," "),v.title or "no title",v.text or "") - end - if #result == 1 then - return "nothing saved yet" - else - return format("<table>%s</table>",concat(result,"\n")) - end -end - -local function reset_font(currentfont) - return edit_font(currentfont) -end - -local extras_template = [[ - <a href='mtx-server-ctx-fonttest.lua?extra=reload'>remake font database</a> (take some time)<br/><br/> -]] - -local function do_extras(detail,currentfont,extra) - return extras_template -end - -local extras = { } - -local function do_extra(detail,currentfont,extra) - local e = extras[extra] - if e then e(detail,currentfont,extra) end - return do_extras(detail,currentfont,extra) -end - -function extras.reload() - local command = "mtxrun --script font --reload" - report("run command: %s",command) - os.execute(command) - return do_extras() -end - - -local status_template = [[ - <input type="hidden" name="currentfont" value="%s" /> -]] - -local variables = { - ['color-background-one'] = lmx.get('color-background-green'), - ['color-background-two'] = lmx.get('color-background-blue'), - ['title'] = 'ConTeXt Font Tester', - ['formaction'] = "mtx-server-ctx-fonttest.lua", -} - -function doit(configuration,filename,hashed) - - local start = os.clock() - - local detail = url.query(hashed.query or "") - - local currentfont = detail.currentfont - local action = detail.action - local selection = detail.selection - - local loadname = detail.loadname - local deletename = detail.deletename - local extra = detail.extra - - if loadname and loadname ~= "" then - detail, currentfont = loadstored(detail,currentfont,loadname) - action = "process" - elseif deletename and deletename ~= "" then - detail, currentfont = deletestored(detail,currentfont,deletename) - action = "load" - elseif selection and selection ~= "" then - currentfont = selection - elseif extra and extra ~= "" then - do_extra(detail,currentfont,extra) - action = "extras" - end - - local fontname, fontfile = get_specification(currentfont) - - if fontfile then - variables.title = format('ConTeXt Font Tester: %s (%s)',fontname,fontfile) - else - variables.title = 'ConTeXt Font Tester' - end - - -- lua table and adapt - - local buttons = { 'process', 'select', 'save', 'load', 'edit', 'reset', 'features', 'source', 'log', 'info', 'extras'} - local menu = { } - - for i=1,#buttons do - local button = buttons[i] - menu[#menu+1] = format("<button name='action' value='%s' type='submit'>%s</button>",button,button) - end - - variables.menu = concat(menu," ") - variables.status = format(status_template,currentfont or "") - variables.maintext = "" - variables.javascriptdata = "" - variables.javascripts = "" - variables.javascriptinit = "" - - report("action: %s",action or "no action") - - local result - - if action == "select" then - variables.maintext = select_font() - elseif action == "info" then - variables.maintext = info_about() - elseif action == "extras" then - variables.maintext = do_extras() - elseif currentfont and currentfont ~= "" then - if action == "save" then - variables.maintext = save_font(currentfont,detail) - elseif action == "load" then - variables.maintext = load_font(currentfont,detail) - elseif action == "source" then - variables.maintext = show_source(currentfont,detail) - elseif action == "log" then - variables.maintext = show_log(currentfont,detail) - elseif action == "features" then - variables.maintext = show_font(currentfont,detail) - else - local e, s - if action == "process" then - e, s = process_font(currentfont,detail) - elseif action == "reset" then - e, s = reset_font(currentfont) - elseif action == "edit" then - e, s = edit_font(currentfont,detail) - else - e, s = process_font(currentfont,detail) - end - variables.maintext = e - variables.javascriptdata = s - variables.javascripts = javascripts - variables.javascriptinit = "check_form()" - end - else - variables.maintext = select_font() - end - - result = { content = lmx.convert('context-fonttest.lmx',false,variables) } - - report("time spent on page: %0.03f seconds",os.clock()-start) - - return result - -end - -return doit, true - ---~ make_lmx_page("test") +if not modules then modules = { } end modules ['mtx-server-ctx-fonttest'] = {
+ version = 1.001,
+ comment = "Font Feature Tester",
+ author = "Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- probably too much but who cares
+
+dofile(resolvers.findfile("trac-lmx.lua","tex"))
+dofile(resolvers.findfile("font-ini.lua","tex"))
+dofile(resolvers.findfile("font-con.lua","tex"))
+dofile(resolvers.findfile("font-oti.lua","tex"))
+dofile(resolvers.findfile("font-otf.lua","tex"))
+dofile(resolvers.findfile("font-otp.lua","tex"))
+dofile(resolvers.findfile("font-ott.lua","tex"))
+dofile(resolvers.findfile("font-syn.lua","tex"))
+dofile(resolvers.findfile("font-mis.lua","tex"))
+
+local format, gsub, concat, match, find = string.format, string.gsub, table.concat, string.match, string.find
+
+local report = logs.reporter("ctx-fonttest")
+
+local sample_line = "This is a sample line!"
+local tempname = "mtx-server-ctx-fonttest-temp"
+local temppath = caches.setfirstwritablefile("temp","mtx-server-ctx-fonttest")
+local basename = "mtx-server-ctx-fonttest-data.lua"
+local basepath = temppath
+
+local remove_suffixes = { "tex", "pdf", "log" }
+local what_options = { "trace", "basemode" }
+
+for i=1,#remove_suffixes do
+ os.remove(file.join(temppath,file.addsuffix(tempname,remove_suffixes[i])))
+end
+
+local process_templates = { }
+
+process_templates.default = [[
+\starttext
+ \setupdirections[bidi=global]
+ \definefontfeature[sample][analyze=yes,%s]
+ \definedfont[name:%s*sample]
+ \startTEXpage[offset=3pt]
+ \detokenize{%s}
+ \stopTEXpage
+\stoptext
+]]
+
+process_templates.cache = [[
+\starttext
+ \definedfont[name:%s]
+ \startTEXpage[offset=3pt]
+ cached: \detokenize{%s}
+ \stopTEXpage
+\stoptext
+]]
+
+process_templates.trace = [[
+\usemodule[fnt-20]
+
+\definefontfeature[sample][%s]
+
+\setupcolors[state=start]
+
+\setupdirections[bidi=global]
+
+\setvariables
+ [otftracker]
+ [title=Test Run,
+ font=name:%s,
+ direction=0,
+ features=sample,
+ sample={\detokenize{%s}}]
+]]
+
+local javascripts = [[
+function selected_radio(name) {
+ var form = document.forms["main-form"] ;
+ var script = form.elements[name] ;
+ if (script) {
+ var n = script.length ;
+ if (n) {
+ for (var i=0; i<n; i++) {
+ if (script[i].checked) {
+ return script[i].value ;
+ }
+ }
+ }
+ }
+ return "" ;
+}
+
+function reset_valid() {
+ var fields = document.getElementsByTagName("span") ;
+ for (var i=0; i<fields.length; i++) {
+ var e = fields[i]
+ if (e) {
+ if (e.className == "valid") {
+ e.className = "" ;
+ }
+ }
+ }
+}
+
+function set_valid() {
+ var script = selected_radio("script") ;
+ var language = selected_radio("language") ;
+ if (script && language) {
+ var s = feature_hash[script] ;
+ if (s) {
+ for (l in s) {
+ var e = document.getElementById("t-l-" + l) ;
+ if (e) {
+ e.className = "valid" ;
+ }
+ }
+ var l = s[language] ;
+ if (l) {
+ for (i in l) {
+ var e = document.getElementById("t-f-" + i) ;
+ if (e) {
+ e.className = "valid" ;
+ }
+ }
+ }
+ var e = document.getElementById("t-s-" + script) ;
+ if (e) {
+ e.className = "valid" ;
+ }
+ }
+ }
+}
+
+function check_form() {
+ reset_valid() ;
+ set_valid() ;
+}
+
+function check_script() {
+ reset_valid() ;
+ set_valid() ;
+}
+
+function check_language() {
+ reset_valid() ;
+ set_valid() ;
+}
+
+function check_feature() {
+ // not needed
+}
+]]
+
+local cache = { }
+
+local function showfeatures(f)
+ if f then
+ report("processing font '%s'",f)
+ local features = cache[f]
+ if features == nil then
+ features = fonts.helpers.getfeatures(resolvers.findfile(f))
+ if not features then
+ report("building cache for '%s'",f)
+ io.savedata(file.join(temppath,file.addsuffix(tempname,"tex")),format(process_templates.cache,f,f))
+ os.execute(format("mtxrun --path=%s --script context --once --batchmode %s",temppath,tempname))
+ features = fonts.helpers.getfeatures(f)
+ end
+ cache[f] = features or false
+ report("caching info of '%s'",f)
+ else
+ report("using cached info of '%s'",f)
+ end
+ if features then
+ local scr, lan, fea, rev = { }, { }, { }, { }
+ local function show(what)
+ local data = features[what]
+ if data and next(data) then
+ for f,ff in next, data do
+ if find(f,"<") then
+ -- ignore aat for the moment
+ else
+ fea[f] = true
+ for s, ss in next, ff do
+ if find(s,"%*") then
+ -- ignore *
+ else
+ scr[s] = true
+ local rs = rev[s] if not rs then rs = {} rev[s] = rs end
+ for k, l in next, ss do
+ if find(k,"%*") then
+ -- ignore *
+ else
+ lan[k] = true
+ local rsk = rs[k] if not rsk then rsk = { } rs[k] = rsk end
+ rsk[f] = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ for what, v in table.sortedhash(features) do
+ show(what)
+ end
+ local stupid = { }
+ stupid[#stupid+1] = "var feature_hash = new Array ;"
+ for s, sr in next, rev do
+ stupid[#stupid+1] = format("feature_hash['%s'] = new Array ;",s)
+ for l, lr in next, sr do
+ stupid[#stupid+1] = format("feature_hash['%s']['%s'] = new Array ;",s,l)
+ for f, fr in next, lr do
+ stupid[#stupid+1] = format("feature_hash['%s']['%s']['%s'] = true ;",s,l,f)
+ end
+ end
+ end
+ -- gpos feature script languages
+ return {
+ scripts = scr,
+ languages = lan,
+ features = fea,
+ javascript = concat(stupid,"\n")
+ }
+ end
+ end
+end
+
+local template_h = [[
+<tr>
+ <th>safe name </th>
+ <th>family name </th>
+ <th>style-variant-weight-width </th>
+ <th>font name </th>
+ <th>weight </th>
+ <th>filename</th>
+</tr>]]
+
+local template_d = [[
+<tr>
+ <td><a href='mtx-server-ctx-fonttest.lua?selection=%s'>%s</a> </td>
+ <td>%s </td>
+ <td>%s-%s-%s-%s </td>
+ <td>%s </td>
+ <td>%s </td>
+ <td>%s</td>
+</tr>]]
+
+local function select_font()
+ local t = fonts.names.list(".*",false,true)
+ if t then
+ local listoffonts = { }
+ listoffonts[#listoffonts+1] = "<table>"
+ listoffonts[#listoffonts+1] = template_h
+ for k, v in table.sortedhash(t) do
+ local kind = v.format
+ if kind == "otf" or kind == "ttf" or kind == "ttc" then
+ local fontname = v.fontname
+ listoffonts[#listoffonts+1] = format(template_d, fontname, fontname,
+ v.familyname or "",
+ t.variant or "normal",
+ t.weight or "normal",
+ t.width or "normal",
+ t.style or "normal",
+ v.rawname or fontname,
+ v.fontweight or "",
+ v.filename or ""
+ )
+ end
+ end
+ listoffonts[#listoffonts+1] = "</table>"
+ return concat(listoffonts,"\n")
+ end
+ return "<b>no fonts</b>"
+end
+
+local edit_template = [[
+ <textarea name='sampletext' rows='5' cols='100'>%s</textarea>
+ <br/> <br/>name: <input type='text' name='name' size='20' value=%q/> title: <input type='text' name='title' size='40' value=%q/>
+ <br/> <br/>scripts: %s
+ <br/> <br/>languages: %s
+ <br/> <br/>features: %s
+ <br/> <br/>options: %s
+]]
+
+-- <embed src="%s#toolbar=0&navpanes=0&scrollbar=0" width="100%%"/>
+
+local result_template = [[
+ <br/> <br/>
+ <embed src="%s#view=Fit&toolbar=0&navpanes=0&scrollbar=0" width="100%%"/>
+ <br/> <br/> results:
+ <a href='%s' target="source">tex file</a>
+ <a href='%s' target="result">pdf file</a>
+ <br/> <br/>
+]]
+
+scripts.webserver.registerpath(temppath)
+
+local function get_specification(name)
+ return fonts.names.resolvedspecification(name or "")
+end
+
+local function edit_font(currentfont,detail,tempname)
+ report("entering edit mode for '%s'",currentfont)
+ local specification = get_specification(currentfont)
+ if specification then
+ local htmldata = showfeatures(specification.filename)
+ if htmldata then
+ local features, languages, scripts, options = { }, { }, { }, { }
+ local sorted = table.sortedkeys(htmldata.scripts)
+ for k=1,#sorted do
+ local v = sorted[k]
+ local s = fonts.handlers.otf.tables.scripts[v] or v
+ if detail and v == detail.script then
+ scripts[#scripts+1] = format("<input title='%s' id='s-%s' type='radio' name='script' value='%s' onclick='check_script()' checked='checked'/> <span id='t-s-%s'>%s</span>",s,v,v,v,v)
+ else
+ scripts[#scripts+1] = format("<input title='%s' id='s-%s' type='radio' name='script' value='%s' onclick='check_script()' /> <span id='t-s-%s'>%s</span>",s,v,v,v,v)
+ end
+ end
+ local sorted = table.sortedkeys(htmldata.languages)
+ for k=1,#sorted do
+ local v = sorted[k]
+ local l = fonts.handlers.otf.tables.languages[v] or v
+ if detail and v == detail.language then
+ languages[#languages+1] = format("<input title='%s' id='l-%s' type='radio' name='language' value='%s' onclick='check_language()' checked='checked'/> <span id='t-l-%s'>%s</span>",l,v,v,v,v)
+ else
+ languages[#languages+1] = format("<input title='%s' id='l-%s' type='radio' name='language' value='%s' onclick='check_language()' /> <span id='t-l-%s'>%s</span>",l,v,v,v,v)
+ end
+ end
+ local sorted = table.sortedkeys(htmldata.features)
+ for k=1,#sorted do
+ local v = sorted[k]
+ local f = fonts.handlers.otf.tables.features[v] or v
+ if detail and detail["f-"..v] then
+ features[#features+1] = format("<input title='%s' id='f-%s' type='checkbox' name='f-%s' onclick='check_feature()' checked='checked'/> <span id='t-f-%s'>%s</span>",f,v,v,v,v)
+ else
+ features[#features+1] = format("<input title='%s' id='f-%s' type='checkbox' name='f-%s' onclick='check_feature()' /> <span id='t-f-%s'>%s</span>",f,v,v,v,v)
+ end
+ end
+ for k=1,#what_options do
+ local v = what_options[k]
+ if detail and detail["o-"..v] then
+ options[#options+1] = format("<input id='o-%s' type='checkbox' name='o-%s' checked='checked'/> %s",v,v,v)
+ else
+ options[#options+1] = format("<input id='o-%s' type='checkbox' name='o-%s'/> %s",v,v,v)
+ end
+ end
+ local e = format(edit_template,
+ (detail and detail.sampletext) or sample_line,(detail and detail.name) or "no name",(detail and detail.title) or "",
+ concat(scripts," "),concat(languages," "),concat(features," "),concat(options," "))
+ if tempname then
+ local pdffile, texfile = file.addsuffix(tempname,"pdf"), file.addsuffix(tempname,"tex")
+ local r = format(result_template,pdffile,texfile,pdffile)
+ return e .. r, htmldata.javascript or ""
+ else
+ return e, htmldata.javascript or ""
+ end
+ else
+ return "error, nothing set up yet"
+ end
+ else
+ return "error, no info about font"
+ end
+end
+
+local function process_font(currentfont,detail) -- maybe just fontname
+ local features = {
+ "mode=node",
+ format("language=%s",detail.language or "dflt"),
+ format("script=%s",detail.script or "dflt"),
+ }
+ for k,v in next, detail do
+ local f = match(k,"^f%-(.*)$")
+ if f then
+ features[#features+1] = format("%s=yes",f)
+ end
+ end
+ local variant = process_templates.default
+ if detail["o-trace"] then
+ variant = process_templates.trace
+ end
+ local sample = string.strip(detail.sampletext or "")
+ if sample == "" then sample = sample_line end
+ report("sample text: %s",sample)
+ dir.mkdirs(temppath)
+ local fullname = file.join(temppath,file.addsuffix(tempname,"tex"))
+ local data = format(variant,concat(features,","),currentfont,sample)
+ local command = format("mtxrun --path=%q --script context --once --batchmode %q",temppath,tempname)
+ report("filename: %s",fullname)
+ report("command: %s",command)
+ io.savedata(fullname,data)
+ os.execute(command)
+ return edit_font(currentfont,detail,tempname)
+end
+
+local tex_template = [[
+<pre><tt>
+%s
+</tt></pre>
+]]
+
+local function show_source(currentfont,detail)
+ if tempname and tempname ~= "" then
+ local data = io.loaddata(file.join(temppath,file.addsuffix(tempname,"tex"))) or "no source yet"
+ return format(tex_template,data)
+ else
+ return "no source file"
+ end
+end
+
+local function show_log(currentfont,detail)
+ if tempname and tempname ~= "" then
+ local data = io.loaddata(file.join(temppath,file.addsuffix(tempname,'log'))) or "no log file yet"
+ data = gsub(data,"[%s%%]*begin of optionfile.-end of optionfile[%s%%]*","\n")
+ return format(tex_template,data)
+ else
+ return "no log file"
+ end
+end
+
+local function show_font(currentfont,detail)
+ local specification = get_specification(currentfont)
+ local features = fonts.helpers.getfeatures(specification.filename)
+ local result = { }
+ result[#result+1] = format("<h1>names</h1>",what)
+ result[#result+1] = "<table>"
+ result[#result+1] = format("<tr><td class='tc'>fontname: </td><td>%s</td></tr>",currentfont)
+ result[#result+1] = format("<tr><td class='tc'>fullname: </td><td>%s</td></tr>",specification.fontname or "-")
+ result[#result+1] = format("<tr><td class='tc'>filename: </td><td>%s</td></tr>",specification.fontfile or "-")
+ result[#result+1] = format("<tr><td class='tc'>familyname: </td><td>%s</td></tr>",specification.familyname or "-")
+ result[#result+1] = format("<tr><td class='tc'>fontweight: </td><td>%s</td></tr>",specification.fontweight or "-")
+ result[#result+1] = format("<tr><td class='tc'>format: </td><td>%s</td></tr>",specification.format or "-")
+ result[#result+1] = format("<tr><td class='tc'>fullname: </td><td>%s</td></tr>",specification.fullname or "-")
+ result[#result+1] = format("<tr><td class='tc'>subfamily: </td><td>%s</td></tr>",specification.subfamily or "-")
+ result[#result+1] = format("<tr><td class='tc'>rawname: </td><td>%s</td></tr>",specification.rawname or "-")
+ result[#result+1] = format("<tr><td class='tc'>designsize: </td><td>%s</td></tr>",specification.designsize or "-")
+ result[#result+1] = format("<tr><td class='tc'>minimumsize:</td><td>%s</td></tr>",specification.minsize or "-")
+ result[#result+1] = format("<tr><td class='tc'>maximumsize:</td><td>%s</td></tr>",specification.maxsize or "-")
+ result[#result+1] = format("<tr><td class='tc'>style: </td><td>%s</td></tr>",specification.style ~= "" and specification.style or "normal")
+ result[#result+1] = format("<tr><td class='tc'>variant: </td><td>%s</td></tr>",specification.variant ~= "" and specification.variant or "normal")
+ result[#result+1] = format("<tr><td class='tc'>weight: </td><td>%s</td></tr>",specification.weight ~= "" and specification.weight or "normal")
+ result[#result+1] = format("<tr><td class='tc'>width: </td><td>%s</td></tr>",specification.width ~= "" and specification.width or "normal")
+ result[#result+1] = "</table>"
+ if features then
+ for what, v in table.sortedhash(features) do
+ local data = features[what]
+ if data and next(data) then
+ result[#result+1] = format("<h1>%s features</h1>",what)
+ result[#result+1] = "<table>"
+ result[#result+1] = "<tr><th>feature</th><th>tag </th><th>script </th><th>languages </th></tr>"
+ for f,ff in table.sortedhash(data) do
+ local done = false
+ for s, ss in table.sortedhash(ff) do
+ if s == "*" then s = "all" end
+ if ss ["*"] then ss["*"] = nil ss.all = true end
+ if done then
+ f = ""
+ else
+ done = true
+ end
+ local title = fonts.handlers.otf.tables.features[f] or ""
+ result[#result+1] = format("<tr><td width='50%%'>%s </td><td><tt>%s </tt></td><td><tt>%s </tt></td><td><tt>%s </tt></td></tr>",title,f,s,concat(table.sortedkeys(ss)," "))
+ end
+ end
+ result[#result+1] = "</table>"
+ end
+ end
+ else
+ result[#result+1] = "<br/><br/>This font has no features."
+ end
+ return concat(result,"\n")
+end
+
+
+local info_template = [[
+<pre><tt>
+version : %s
+comment : %s
+author : %s
+copyright : %s
+
+maillist : ntg-context at ntg.nl
+webpage : www.pragma-ade.nl
+wiki : contextgarden.net
+</tt></pre>
+]]
+
+local function info_about()
+ local m = modules ['mtx-server-ctx-fonttest']
+ return format(info_template,m.version,m.comment,m.author,m.copyright)
+end
+
+local save_template = [[
+ the current setup has been saved:
+ <br/> <br/>
+ <table>
+ <tr><td class='tc'>name </td><td>%s</td></tr>
+ <tr><td class='tc'>title </td><td>%s</td></tr>
+ <tr><td class='tc'>font </td><td>%s</td></tr>
+ <tr><td class='tc'>script </td><td>%s</td></tr>
+ <tr><td class='tc'>language </td><td>%s</td></tr>
+ <tr><td class='tc'>features </td><td>%s</td></tr>
+ <tr><td class='tc'>options </td><td>%s</td></tr>
+ <tr><td class='tc'>sampletext </td><td>%s</td></tr>
+ </table>
+]]
+
+local function loadbase()
+ local datafile = file.join(basepath,basename)
+ local storage = io.loaddata(datafile) or ""
+ if storage == "" then
+ storage = { }
+ else
+ report("loading '%s'",datafile)
+ storage = loadstring(storage)
+ storage = (storage and storage()) or { }
+ end
+ return storage
+end
+
+local function loadstored(detail,currentfont,name)
+ local storage = loadbase()
+ storage = storage and storage[name]
+ if storage then
+ currentfont = storage.font
+ detail.script = storage.script or detail.script
+ detail.language = storage.language or detail.language
+ detail.title = storage.title or detail.title
+ detail.sampletext = storage.text or detail.sampletext
+ detail.name = name or "no name"
+ for k,v in next, storage.features do
+ detail["f-"..k] = v
+ end
+ for k,v in next, storage.options do
+ detail["o-"..k] = v
+ end
+ end
+ detail.loadname = nil
+ return detail, currentfont
+end
+
+local function savebase(storage,name)
+ local datafile = file.join(basepath,basename)
+ report("saving '%s' in '%s'",name or "data",datafile)
+ io.savedata(datafile,table.serialize(storage,true))
+end
+
+local function deletestored(detail,currentfont,name)
+ local storage = loadbase()
+ if storage and name and storage[name] then
+ report("deleting '%s' from base",name)
+ storage[name] = nil
+ savebase(storage)
+ end
+ detail.deletename = nil
+ return detail, ""
+end
+
+local function save_font(currentfont,detail)
+ local specification = get_specification(currentfont)
+ local name, title, script, language, features, options, text = currentfont, "", "dflt", "dflt", { }, { }, ""
+ if detail then
+ local htmldata = showfeatures(specification.filename)
+ script = detail.script or script
+ language = detail.language or language
+ text = string.strip(detail.sampletext or text)
+ name = string.strip(detail.name or name)
+ title = string.strip(detail.title or title)
+ for k,v in next, htmldata.features do
+ if detail["f-"..k] then features[k] = true end
+ end
+ for k=1,#what_options do
+ local v = what_options[k]
+ if detail["o-"..v] then options[k] = true end
+ end
+ end
+ if name == "" then
+ name = "no name"
+ end
+ local storage = loadbase()
+ storage[name] = {
+ font = currentfont, title = title, script = script, language = language, features = features, options = options, text = text,
+ }
+ savebase(storage,name)
+ return format(save_template,name,title,currentfont,script,language,concat(table.sortedkeys(features)," "),concat(table.sortedkeys(options)," "),text)
+end
+
+local function load_font(currentfont)
+ local datafile = file.join(basepath,basename)
+ local storage = loadbase(datafile)
+ local result = {}
+ result[#result+1] = format("<tr><th>del </th><th>name </th><th>font </th><th>fontname </th><th>script </th><th>language </th><th>features </th><th>title </th><th>sampletext </th></tr>")
+ for k,v in table.sortedhash(storage) do
+ local fontname, fontfile = get_specification(v.font)
+ result[#result+1] = format("<tr><td><a href='mtx-server-ctx-fonttest.lua?deletename=%s'>x</a> </td><td><a href='mtx-server-ctx-fonttest.lua?loadname=%s'>%s</a> </td><td>%s </td<td>%s </td><td>%s </td><td>%s </td><td>%s </td><td>%s </td><td>%s </td></tr>",
+ k,k,k,v.font,fontname,v.script,v.language,concat(table.sortedkeys(v.features)," "),v.title or "no title",v.text or "")
+ end
+ if #result == 1 then
+ return "nothing saved yet"
+ else
+ return format("<table>%s</table>",concat(result,"\n"))
+ end
+end
+
+local function reset_font(currentfont)
+ return edit_font(currentfont)
+end
+
+local extras_template = [[
+ <a href='mtx-server-ctx-fonttest.lua?extra=reload'>remake font database</a> (take some time)<br/><br/>
+]]
+
+local function do_extras(detail,currentfont,extra)
+ return extras_template
+end
+
+local extras = { }
+
+local function do_extra(detail,currentfont,extra)
+ local e = extras[extra]
+ if e then e(detail,currentfont,extra) end
+ return do_extras(detail,currentfont,extra)
+end
+
+function extras.reload()
+ local command = "mtxrun --script font --reload"
+ report("run command: %s",command)
+ os.execute(command)
+ return do_extras()
+end
+
+
+local status_template = [[
+ <input type="hidden" name="currentfont" value="%s" />
+]]
+
+local variables = {
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ ['title'] = 'ConTeXt Font Tester',
+ ['formaction'] = "mtx-server-ctx-fonttest.lua",
+}
+
+function doit(configuration,filename,hashed)
+
+ local start = os.clock()
+
+ local detail = url.query(hashed.query or "")
+
+ local currentfont = detail.currentfont
+ local action = detail.action
+ local selection = detail.selection
+
+ local loadname = detail.loadname
+ local deletename = detail.deletename
+ local extra = detail.extra
+
+ if loadname and loadname ~= "" then
+ detail, currentfont = loadstored(detail,currentfont,loadname)
+ action = "process"
+ elseif deletename and deletename ~= "" then
+ detail, currentfont = deletestored(detail,currentfont,deletename)
+ action = "load"
+ elseif selection and selection ~= "" then
+ currentfont = selection
+ elseif extra and extra ~= "" then
+ do_extra(detail,currentfont,extra)
+ action = "extras"
+ end
+
+ local fontname, fontfile = get_specification(currentfont)
+
+ if fontfile then
+ variables.title = format('ConTeXt Font Tester: %s (%s)',fontname,fontfile)
+ else
+ variables.title = 'ConTeXt Font Tester'
+ end
+
+ -- lua table and adapt
+
+ local buttons = { 'process', 'select', 'save', 'load', 'edit', 'reset', 'features', 'source', 'log', 'info', 'extras'}
+ local menu = { }
+
+ for i=1,#buttons do
+ local button = buttons[i]
+ menu[#menu+1] = format("<button name='action' value='%s' type='submit'>%s</button>",button,button)
+ end
+
+ variables.menu = concat(menu," ")
+ variables.status = format(status_template,currentfont or "")
+ variables.maintext = ""
+ variables.javascriptdata = ""
+ variables.javascripts = ""
+ variables.javascriptinit = ""
+
+ report("action: %s",action or "no action")
+
+ local result
+
+ if action == "select" then
+ variables.maintext = select_font()
+ elseif action == "info" then
+ variables.maintext = info_about()
+ elseif action == "extras" then
+ variables.maintext = do_extras()
+ elseif currentfont and currentfont ~= "" then
+ if action == "save" then
+ variables.maintext = save_font(currentfont,detail)
+ elseif action == "load" then
+ variables.maintext = load_font(currentfont,detail)
+ elseif action == "source" then
+ variables.maintext = show_source(currentfont,detail)
+ elseif action == "log" then
+ variables.maintext = show_log(currentfont,detail)
+ elseif action == "features" then
+ variables.maintext = show_font(currentfont,detail)
+ else
+ local e, s
+ if action == "process" then
+ e, s = process_font(currentfont,detail)
+ elseif action == "reset" then
+ e, s = reset_font(currentfont)
+ elseif action == "edit" then
+ e, s = edit_font(currentfont,detail)
+ else
+ e, s = process_font(currentfont,detail)
+ end
+ variables.maintext = e
+ variables.javascriptdata = s
+ variables.javascripts = javascripts
+ variables.javascriptinit = "check_form()"
+ end
+ else
+ variables.maintext = select_font()
+ end
+
+ result = { content = lmx.convert('context-fonttest.lmx',false,variables) }
+
+ report("time spent on page: %0.03f seconds",os.clock()-start)
+
+ return result
+
+end
+
+return doit, true
+
+--~ make_lmx_page("test")
diff --git a/scripts/context/lua/mtx-server-ctx-help.lua b/scripts/context/lua/mtx-server-ctx-help.lua index b8dc0dfb2..f0901150a 100644 --- a/scripts/context/lua/mtx-server-ctx-help.lua +++ b/scripts/context/lua/mtx-server-ctx-help.lua @@ -1,705 +1,705 @@ -if not modules then modules = { } end modules ['mtx-server-ctx-help'] = { - version = 1.001, - comment = "Basic Definition Browser", - author = "Hans Hagen", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- todo in lua interface: noargument, oneargument, twoarguments, threearguments --- todo: pickup translations from mult file - -dofile(resolvers.findfile("trac-lmx.lua","tex")) - --- problem ... serialize parent stack - -local format, match, gsub, find = string.format, string.match, string.gsub, string.find -local concat = table.concat - -local report = logs.reporter("ctx-help") - --- -- -- make this a module: cont-xx.lua - -document = document or { } -document.setups = document.setups or { } - -document.setups.div = { - pe = "<div dir='rtl' lang='arabic'>%s</div>" -} - -document.setups.span = { - pe = "<span dir='rtl' lang='arabic'>%s</span>" -} - -document.setups.translations = document.setups.translations or { - - nl = { - ["title"] = "setup", - ["formula"] = "formule", - ["number"] = "getal", - ["list"] = "lijst", - ["dimension"] = "maat", - ["mark"] = "markering", - ["reference"] = "verwijzing", - ["command"] = "commando", - ["file"] = "file", - ["name"] = "naam", - ["identifier"] = "naam", - ["text"] = "tekst", - ["section"] = "sectie", - ["singular"] = "naam enkelvoud", - ["plural"] = "naam meervoud", - ["matrix"] = "n*m", - ["see"] = "zie", - ["inherits"] = "erft van", - ["optional"] = "optioneel", - ["displaymath"] = "formule", - ["index"] = "ingang", - ["math"] = "formule", - ["nothing"] = "leeg", - ["file"] = "file", - ["position"] = "positie", - ["reference"] = "verwijzing", - ["csname"] = "naam", - ["destination"] = "bestemming", - ["triplet"] = "triplet", - ["word"] = "woord", - ["content"] = "tekst", - }, - - en = { - ["title"] = "setup", - ["formula"] = "formula", - ["number"] = "number", - ["list"] = "list", - ["dimension"] = "dimension", - ["mark"] = "mark", - ["reference"] = "reference", - ["command"] = "command", - ["file"] = "file", - ["name"] = "name", - ["identifier"] = "identifier", - ["text"] = "text", - ["section"] = "section", - ["singular"] = "singular name", - ["plural"] = "plural name", - ["matrix"] = "n*m", - ["see"] = "see", - ["inherits"] = "inherits from", - ["optional"] = "optional", - ["displaymath"] = "formula", - ["index"] = "entry", - ["math"] = "formula", - ["nothing"] = "empty", - ["file"] = "file", - ["position"] = "position", - ["reference"] = "reference", - ["csname"] = "name", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "word", - ["content"] = "text", - - ["noargument"] = "\\cs", - ["oneargument"] = "\\cs#1{..}", - ["twoarguments"] = "\\cs#1#2{..}{..}", - ["threearguments"] = "\\cs#1#2#3{..}{..}{..}", - - }, - - de = { - ["title"] = "Setup", - ["formula"] = "Formel", - ["number"] = "Nummer", - ["list"] = "Liste", - ["dimension"] = "Dimension", - ["mark"] = "Beschriftung", - ["reference"] = "Referenz", - ["command"] = "Befehl", - ["file"] = "Datei", - ["name"] = "Name", - ["identifier"] = "Name", - ["text"] = "Text", - ["section"] = "Abschnitt", - ["singular"] = "singular", - ["plural"] = "plural", - ["matrix"] = "n*m", - ["see"] = "siehe", - ["inherits"] = "inherits from", - ["optional"] = "optioneel", - ["displaymath"] = "formula", - ["index"] = "entry", - ["math"] = "formula", - ["nothing"] = "empty", - ["file"] = "file", - ["position"] = "position", - ["reference"] = "reference", - ["csname"] = "name", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "word", - ["content"] = "text", - }, - - cz = { - ["title"] = "setup", - ["formula"] = "rovnice", - ["number"] = "cislo", - ["list"] = "seznam", - ["dimension"] = "dimenze", - ["mark"] = "znacka", - ["reference"] = "reference", - ["command"] = "prikaz", - ["file"] = "soubor", - ["name"] = "jmeno", - ["identifier"] = "jmeno", - ["text"] = "text", - ["section"] = "sekce", - ["singular"] = "jmeno v singularu", - ["plural"] = "jmeno v pluralu", - ["matrix"] = "n*m", - ["see"] = "viz", - ["inherits"] = "inherits from", - ["optional"] = "optioneel", - ["displaymath"] = "formula", - ["index"] = "entry", - ["math"] = "formula", - ["nothing"] = "empty", - ["file"] = "file", - ["position"] = "position", - ["reference"] = "reference", - ["csname"] = "name", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "word", - ["content"] = "text", - }, - - it = { - ["title"] = "setup", - ["formula"] = "formula", - ["number"] = "number", - ["list"] = "list", - ["dimension"] = "dimension", - ["mark"] = "mark", - ["reference"] = "reference", - ["command"] = "command", - ["file"] = "file", - ["name"] = "name", - ["identifier"] = "name", - ["text"] = "text", - ["section"] = "section", - ["singular"] = "singular name", - ["plural"] = "plural name", - ["matrix"] = "n*m", - ["see"] = "see", - ["inherits"] = "inherits from", - ["optional"] = "optioneel", - ["displaymath"] = "formula", - ["index"] = "entry", - ["math"] = "formula", - ["nothing"] = "empty", - ["file"] = "file", - ["position"] = "position", - ["reference"] = "reference", - ["csname"] = "name", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "word", - ["content"] = "text", - }, - - ro = { - ["title"] = "setari", - ["formula"] = "formula", - ["number"] = "numar", - ["list"] = "lista", - ["dimension"] = "dimensiune", - ["mark"] = "marcaj", - ["reference"] = "referinta", - ["command"] = "comanda", - ["file"] = "fisier", - ["name"] = "nume", - ["identifier"] = "nume", - ["text"] = "text", - ["section"] = "sectiune", - ["singular"] = "nume singular", - ["plural"] = "nume pluram", - ["matrix"] = "n*m", - ["see"] = "vezi", - ["inherits"] = "inherits from", - ["optional"] = "optioneel", - ["displaymath"] = "formula", - ["index"] = "entry", - ["math"] = "formula", - ["nothing"] = "empty", - ["file"] = "file", - ["position"] = "position", - ["reference"] = "reference", - ["csname"] = "name", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "word", - ["content"] = "text", - }, - - fr = { - ["title"] = "réglage", - ["formula"] = "formule", - ["number"] = "numéro", - ["list"] = "liste", - ["dimension"] = "dimension", - ["mark"] = "marquage", - ["reference"] = "reference", - ["command"] = "commande", - ["file"] = "fichier", - ["name"] = "nom", - ["identifier"] = "identificateur", - ["text"] = "texte", - ["section"] = "section", - ["singular"] = "nom singulier", - ["plural"] = "nom pluriel", - ["matrix"] = "n*m", - ["see"] = "vois", - ["inherits"] = "herite de", - ["optional"] = "optionel", - ["displaymath"] = "formule", - ["index"] = "entrée", - ["math"] = "formule", - ["nothing"] = "vide", - ["file"] = "fichier", - ["position"] = "position", - ["reference"] = "réference", - ["csname"] = "nom", - ["destination"] = "destination", - ["triplet"] = "triplet", - ["word"] = "mot", - ["content"] = "texte", - } - -} - -document.setups.formats = { - open_command = { - tex = [[\%s]], - lua = [[context.%s (]], - }, - close_command = { - tex = [[]], - lua = [[ )]], - }, - connector = { - tex = [[]], - lua = [[, ]], - }, - href_in_list = { - tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]], - lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]], - }, - href_as_command = { - tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>\%s</a>]], - lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>context.%s</a>]], - }, - modes = { - tex = [[<a href='mtx-server-ctx-help.lua?mode=lua'>lua mode</a>]], - lua = [[<a href='mtx-server-ctx-help.lua?mode=tex'>tex mode</a>]], - }, - optional_single = { - tex = "[optional string %s]", - lua = "{optional string %s}", - }, - optional_list = { - tex = "[optional list %s]", - lua = "{optional table %s}" , - } , - mandate_single = { - tex = "[mandate string %s]", - lua = "{mandate string %s}", - }, - mandate_list = { - tex = "[mandate list %s]", - lua = "{mandate list %s}", - }, - interface = [[<a href='mtx-server-ctx-help.lua?interface=%s&mode=%s'>%s</a>]], - source = [[<a href='mtx-server-ctx-help.lua?source=%s&mode=%s'>%s</a>]], - parameter = [[<tr><td width='15%%'>%s</td><td width='15%%'>%s</td><td width='70%%'>%s</td></tr>]], - parameters = [[<table width='100%%'>%s</table>]], - listing = [[<pre><t>%s</t></listing>]], - special = [[<i>%s</i>]], - default = [[<u>%s</u>]], -} - -local function translate(tag,int,noformat) - local t = document.setups.translations - local te = t["en"] - local ti = t[int] or te - if noformat then - return ti[tag] or te[tag] or tag - else - return format(document.setups.formats.special,ti[tag] or te[tag] or tag) - end -end - -local function translated(e,int) - local attributes = e.at - local s = attributes.type or "?" - local tag = match(s,"^cd:(.*)$") - if attributes.default == "yes" then - return format(document.setups.formats.default,tag or "?") - elseif tag then - return translate(tag,int) - else - return s - end -end - -document.setups.loaded = document.setups.loaded or { } - -document.setups.current = { } -document.setups.showsources = true -document.setups.mode = "tex" - -function document.setups.load(filename) - filename = resolvers.findfile(filename) or "" - if filename ~= "" then - local current = document.setups.loaded[filename] - if not current then - local loaded = xml.load(filename) - if loaded then - -- xml.inject(document.setups.root,"/",loaded) - current = { - file = filename, - root = loaded, - names = { }, - used = { }, - } - document.setups.loaded[filename] = current - end - end - document.setups.current = current or { } - end -end - -function document.setups.name(ek) - local at = ek.at - local name = at.name - if at.type == 'environment' then - name = "start" .. name - end - if at.variant then - name = name .. ":" .. at.variant - end - if at.generated == "yes" then - name = name .. "*" - end - return name:lower() -end - -function document.setups.csname(ek,int) - local cs = "" - local at = ek.at or { } - if at.type == 'environment' then - cs = translate("start",int,true) .. cs - end - for e in xml.collected(ek,'cd:sequence/(cd:string|variable)') do - if e.tg == "string" then - cs = cs .. e.at.value - else - cs = cs .. e.at.value -- to be translated - end - end - return cs -end - -function document.setups.names() - local current = document.setups.current - local names = current.names - if not names or #names == 0 then - names = { } - local name = document.setups.name - local csname = document.setups.csname - for e in xml.collected(current.root,'cd:command') do - names[#names+1] = { e.at.name, csname(e,int) } - end - table.sort(names, function(a,b) return a[2]:lower() < b[2]:lower() end) - current.names = names - end - return names -end - -function document.setups.show(name) - local current = document.setups.current - if current.root then - local name = gsub(name,"[<>]","") - local setup = xml.first(current.root,"cd:command[@name='" .. name .. "']") - current.used[#current.used+1] = setup - xml.sprint(setup) - end -end - -function document.setups.showused() - local current = document.setups.current - if current.root and next(current.used) then - local sorted = table.sortedkeys(current.used) - for i=1,#sorted do - xml.sprint(current.used[sorted[i]]) - end - end -end -function document.setups.showall() - local current = document.setups.current - if current.root then - local list = { } - for e in xml.collected(current.root,"cd:command") do - list[document.setups.name(e)] = e - end - local sorted = table.sortedkeys(list) - for i=1,#sorted do - xml.sprint(list[sorted[i]]) - end - end -end -function document.setups.resolve(name) - local current = document.setups.current - if current.root then - local e = xml.filter(current.root,format("cd:define[@name='%s']/text()",name)) - if e then - xml.sprint(e) - end - end -end - -function document.setups.collect(name,int,lastmode) - local current = document.setups.current - local formats = document.setups.formats - local command = xml.filter(current.root,format("cd:command[@name='%s']/first()",name)) - if command then - local attributes = command.at or { } - local data = { - command = command, - category = attributes.category or "", - } - if document.setups.showsources then - data.source = (attributes.file and format(formats.source,attributes.file,lastmode,attributes.file)) or "" - else - data.source = attributes.file or "" - end - local n, sequence, tags = 0, { }, { } - sequence[#sequence+1] = format(formats.open_command[lastmode],document.setups.csname(command,int)) - local arguments, tag = { }, "" - for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do - n = n + 1 - local attributes = d[k].at - if #sequence > 1 then - local c = formats.connector[lastmode] - if c ~= "" then - sequence[#sequence+1] = c - end - end - if attributes.optional == 'yes' then - if attributes.list == 'yes' then - tag = format(formats.optional_list[lastmode],n) - else - tag = format(formats.optional_single[lastmode],n) - end - else - if attributes.list == 'yes' then - tag = format(formats.mandate_list[lastmode],n) - else - tag = format(formats.mandate_single[lastmode],n) - end - end - sequence[#sequence+1] = tag - tags[#tags+1] = tag - end - sequence[#sequence+1] = formats.close_command[lastmode] - data.sequence = concat(sequence, " ") - local parameters, n = { }, 0 - for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do - n = n + 1 - if d[k].tg == "keywords" then - local left = tags[n] - local right = { } - for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do - local tag = d[k].tg - if tag == "resolve" then - local name = d[k].at.name or "" - if name ~= "" then - local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name)) - for r, d, k in xml.elements(resolved,"cd:constant") do - right[#right+1] = translated(d[k],int) - end - end - else - right[#right+1] = translated(d[k],int) - end - end - parameters[#parameters+1] = format(formats.parameter,left,"",concat(right, ", ")) - else - local what = tags[n] - for r, d, k in xml.elements(d[k],"(cd:parameter|cd:inherit)") do - local tag = d[k].tg - local left, right = d[k].at.name or "?", { } - if tag == "inherit" then - local name = d[k].at.name or "?" - local goto = format(document.setups.formats.href_as_command[lastmode],name,lastmode,name) - if #parameters > 0 and not find(parameters[#parameters],"<br/>") then - parameters[#parameters+1] = format(formats.parameter,"<br/>","","") - end - parameters[#parameters+1] = format(formats.parameter,what,format(formats.special,translate("inherits",int)),goto) - else - for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do - local tag = d[k].tg - if tag == "resolve" then - local name = d[k].at.name or "" - if name ~= "" then - local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name)) - for r, d, k in xml.elements(resolved,"cd:constant") do - right[#right+1] = translated(d[k],int) - end - end - else - right[#right+1] = translated(d[k],int) - end - end - parameters[#parameters+1] = format(formats.parameter,what,left,concat(right, ", ")) - end - what = "" - end - end - parameters[#parameters+1] = format(formats.parameter,"<br/>","","") - end - data.parameters = parameters or { } - data.mode = formats.modes[lastmode or "tex"] - return data - else - return nil - end -end - --- -- -- - -tex = tex or { } - --- -- -- - -local interfaces = { - czech = 'cz', - dutch = 'nl', - english = 'en', - french = 'fr', - german = 'de', - italian = 'it', - persian = 'pe', - romanian = 'ro', -} - -local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", "tex" - -local variables = { - ['color-background-main-left'] = '#3F3F3F', - ['color-background-main-right'] = '#5F5F5F', - ['color-background-one'] = lmx.get('color-background-green'), - ['color-background-two'] = lmx.get('color-background-blue'), - ['title'] = 'ConTeXt Help Information', -} - ---~ function lmx.loadedfile(filename) ---~ return io.loaddata(resolvers.findfile(filename)) -- return resolvers.texdatablob(filename) ---~ end - -local function doit(configuration,filename,hashed) - - local formats = document.setups.formats - - local start = os.clock() - local detail = hashed.queries or { } - - if detail then - - lastinterface = detail.interface or lastinterface - lastcommand = detail.command or lastcommand - lastsource = detail.source or lastsource - lastmode = detail.mode or lastmode or "tex" - - lastcommand = gsub(lastcommand,"%s*^\\*(.+)%s*","%1") - - if lastinterface then - report("checking interface: %s",lastinterface) - document.setups.load(format("cont-%s.xml",lastinterface)) - end - - local div = document.setups.div [lastinterface] - local span = document.setups.span[lastinterface] - - local names, refs, ints = document.setups.names(lastinterface), { }, { } - for k=1,#names do - local v = names[k] - refs[k] = format(formats.href_in_list[lastmode],v[1],lastmode,v[2]) - end - if lastmode ~= "lua" then - local sorted = table.sortedkeys(interfaces) - for k=1,#sorted do - local v = sorted[k] - ints[k] = format(formats.interface,interfaces[v],lastmode,v) - end - end - - local n = concat(refs,"<br/>") - local i = concat(ints,"<br/><br/>") - - if div then - variables.names = format(div,n) - variables.interfaces = format(div,i) - else - variables.names = n - variables.interfaces = i - end - - -- first we need to add information about mkii/mkiv - - variables.maintitle = "no definition" - variables.maintext = "" - variables.extra = "" - - if document.setups.showsources and lastsource and lastsource ~= "" then - -- todo: mkii, mkiv, tex (can be different) - local data = io.loaddata(resolvers.findfile(lastsource)) - variables.maintitle = lastsource - variables.maintext = format(formats.listing,data) - lastsource = "" - elseif lastcommand and lastcommand ~= "" then - local data = document.setups.collect(lastcommand,lastinterface,lastmode) - if data then - local what, extra = { "environment", "category", "source", "mode" }, { } - for k=1,#what do - local v = what[k] - if data[v] and data[v] ~= "" then - lmx.set(v, data[v]) - extra[#extra+1] = v .. ": " .. data[v] - end - end - variables.maintitle = data.sequence - variables.maintext = format(formats.parameters,concat(data.parameters)) - variables.extra = concat(extra," ") - else - variables.maintext = "select command" - end - end - - else - - variables.maintitle = "no definition" - variables.maintext = "some error" - variables.extra = "" - - end - - local content = lmx.convert('context-help.lmx',false,variables) - - report("time spent on page: %0.03f seconds",os.clock()-start) - - return { content = content } -end - -return doit, true +if not modules then modules = { } end modules ['mtx-server-ctx-help'] = {
+ version = 1.001,
+ comment = "Basic Definition Browser",
+ author = "Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- todo in lua interface: noargument, oneargument, twoarguments, threearguments
+-- todo: pickup translations from mult file
+
+dofile(resolvers.findfile("trac-lmx.lua","tex"))
+
+-- problem ... serialize parent stack
+
+local format, match, gsub, find = string.format, string.match, string.gsub, string.find
+local concat = table.concat
+
+local report = logs.reporter("ctx-help")
+
+-- -- -- make this a module: cont-xx.lua
+
+document = document or { }
+document.setups = document.setups or { }
+
+document.setups.div = {
+ pe = "<div dir='rtl' lang='arabic'>%s</div>"
+}
+
+document.setups.span = {
+ pe = "<span dir='rtl' lang='arabic'>%s</span>"
+}
+
+document.setups.translations = document.setups.translations or {
+
+ nl = {
+ ["title"] = "setup",
+ ["formula"] = "formule",
+ ["number"] = "getal",
+ ["list"] = "lijst",
+ ["dimension"] = "maat",
+ ["mark"] = "markering",
+ ["reference"] = "verwijzing",
+ ["command"] = "commando",
+ ["file"] = "file",
+ ["name"] = "naam",
+ ["identifier"] = "naam",
+ ["text"] = "tekst",
+ ["section"] = "sectie",
+ ["singular"] = "naam enkelvoud",
+ ["plural"] = "naam meervoud",
+ ["matrix"] = "n*m",
+ ["see"] = "zie",
+ ["inherits"] = "erft van",
+ ["optional"] = "optioneel",
+ ["displaymath"] = "formule",
+ ["index"] = "ingang",
+ ["math"] = "formule",
+ ["nothing"] = "leeg",
+ ["file"] = "file",
+ ["position"] = "positie",
+ ["reference"] = "verwijzing",
+ ["csname"] = "naam",
+ ["destination"] = "bestemming",
+ ["triplet"] = "triplet",
+ ["word"] = "woord",
+ ["content"] = "tekst",
+ },
+
+ en = {
+ ["title"] = "setup",
+ ["formula"] = "formula",
+ ["number"] = "number",
+ ["list"] = "list",
+ ["dimension"] = "dimension",
+ ["mark"] = "mark",
+ ["reference"] = "reference",
+ ["command"] = "command",
+ ["file"] = "file",
+ ["name"] = "name",
+ ["identifier"] = "identifier",
+ ["text"] = "text",
+ ["section"] = "section",
+ ["singular"] = "singular name",
+ ["plural"] = "plural name",
+ ["matrix"] = "n*m",
+ ["see"] = "see",
+ ["inherits"] = "inherits from",
+ ["optional"] = "optional",
+ ["displaymath"] = "formula",
+ ["index"] = "entry",
+ ["math"] = "formula",
+ ["nothing"] = "empty",
+ ["file"] = "file",
+ ["position"] = "position",
+ ["reference"] = "reference",
+ ["csname"] = "name",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "word",
+ ["content"] = "text",
+
+ ["noargument"] = "\\cs",
+ ["oneargument"] = "\\cs#1{..}",
+ ["twoarguments"] = "\\cs#1#2{..}{..}",
+ ["threearguments"] = "\\cs#1#2#3{..}{..}{..}",
+
+ },
+
+ de = {
+ ["title"] = "Setup",
+ ["formula"] = "Formel",
+ ["number"] = "Nummer",
+ ["list"] = "Liste",
+ ["dimension"] = "Dimension",
+ ["mark"] = "Beschriftung",
+ ["reference"] = "Referenz",
+ ["command"] = "Befehl",
+ ["file"] = "Datei",
+ ["name"] = "Name",
+ ["identifier"] = "Name",
+ ["text"] = "Text",
+ ["section"] = "Abschnitt",
+ ["singular"] = "singular",
+ ["plural"] = "plural",
+ ["matrix"] = "n*m",
+ ["see"] = "siehe",
+ ["inherits"] = "inherits from",
+ ["optional"] = "optioneel",
+ ["displaymath"] = "formula",
+ ["index"] = "entry",
+ ["math"] = "formula",
+ ["nothing"] = "empty",
+ ["file"] = "file",
+ ["position"] = "position",
+ ["reference"] = "reference",
+ ["csname"] = "name",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "word",
+ ["content"] = "text",
+ },
+
+ cz = {
+ ["title"] = "setup",
+ ["formula"] = "rovnice",
+ ["number"] = "cislo",
+ ["list"] = "seznam",
+ ["dimension"] = "dimenze",
+ ["mark"] = "znacka",
+ ["reference"] = "reference",
+ ["command"] = "prikaz",
+ ["file"] = "soubor",
+ ["name"] = "jmeno",
+ ["identifier"] = "jmeno",
+ ["text"] = "text",
+ ["section"] = "sekce",
+ ["singular"] = "jmeno v singularu",
+ ["plural"] = "jmeno v pluralu",
+ ["matrix"] = "n*m",
+ ["see"] = "viz",
+ ["inherits"] = "inherits from",
+ ["optional"] = "optioneel",
+ ["displaymath"] = "formula",
+ ["index"] = "entry",
+ ["math"] = "formula",
+ ["nothing"] = "empty",
+ ["file"] = "file",
+ ["position"] = "position",
+ ["reference"] = "reference",
+ ["csname"] = "name",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "word",
+ ["content"] = "text",
+ },
+
+ it = {
+ ["title"] = "setup",
+ ["formula"] = "formula",
+ ["number"] = "number",
+ ["list"] = "list",
+ ["dimension"] = "dimension",
+ ["mark"] = "mark",
+ ["reference"] = "reference",
+ ["command"] = "command",
+ ["file"] = "file",
+ ["name"] = "name",
+ ["identifier"] = "name",
+ ["text"] = "text",
+ ["section"] = "section",
+ ["singular"] = "singular name",
+ ["plural"] = "plural name",
+ ["matrix"] = "n*m",
+ ["see"] = "see",
+ ["inherits"] = "inherits from",
+ ["optional"] = "optioneel",
+ ["displaymath"] = "formula",
+ ["index"] = "entry",
+ ["math"] = "formula",
+ ["nothing"] = "empty",
+ ["file"] = "file",
+ ["position"] = "position",
+ ["reference"] = "reference",
+ ["csname"] = "name",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "word",
+ ["content"] = "text",
+ },
+
+ ro = {
+ ["title"] = "setari",
+ ["formula"] = "formula",
+ ["number"] = "numar",
+ ["list"] = "lista",
+ ["dimension"] = "dimensiune",
+ ["mark"] = "marcaj",
+ ["reference"] = "referinta",
+ ["command"] = "comanda",
+ ["file"] = "fisier",
+ ["name"] = "nume",
+ ["identifier"] = "nume",
+ ["text"] = "text",
+ ["section"] = "sectiune",
+ ["singular"] = "nume singular",
+ ["plural"] = "nume pluram",
+ ["matrix"] = "n*m",
+ ["see"] = "vezi",
+ ["inherits"] = "inherits from",
+ ["optional"] = "optioneel",
+ ["displaymath"] = "formula",
+ ["index"] = "entry",
+ ["math"] = "formula",
+ ["nothing"] = "empty",
+ ["file"] = "file",
+ ["position"] = "position",
+ ["reference"] = "reference",
+ ["csname"] = "name",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "word",
+ ["content"] = "text",
+ },
+
+ fr = {
+ ["title"] = "réglage",
+ ["formula"] = "formule",
+ ["number"] = "numéro",
+ ["list"] = "liste",
+ ["dimension"] = "dimension",
+ ["mark"] = "marquage",
+ ["reference"] = "reference",
+ ["command"] = "commande",
+ ["file"] = "fichier",
+ ["name"] = "nom",
+ ["identifier"] = "identificateur",
+ ["text"] = "texte",
+ ["section"] = "section",
+ ["singular"] = "nom singulier",
+ ["plural"] = "nom pluriel",
+ ["matrix"] = "n*m",
+ ["see"] = "vois",
+ ["inherits"] = "herite de",
+ ["optional"] = "optionel",
+ ["displaymath"] = "formule",
+ ["index"] = "entrée",
+ ["math"] = "formule",
+ ["nothing"] = "vide",
+ ["file"] = "fichier",
+ ["position"] = "position",
+ ["reference"] = "réference",
+ ["csname"] = "nom",
+ ["destination"] = "destination",
+ ["triplet"] = "triplet",
+ ["word"] = "mot",
+ ["content"] = "texte",
+ }
+
+}
+
+document.setups.formats = {
+ open_command = {
+ tex = [[\%s]],
+ lua = [[context.%s (]],
+ },
+ close_command = {
+ tex = [[]],
+ lua = [[ )]],
+ },
+ connector = {
+ tex = [[]],
+ lua = [[, ]],
+ },
+ href_in_list = {
+ tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>%s</a>]],
+ },
+ href_as_command = {
+ tex = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>\%s</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?command=%s&mode=%s'>context.%s</a>]],
+ },
+ modes = {
+ tex = [[<a href='mtx-server-ctx-help.lua?mode=lua'>lua mode</a>]],
+ lua = [[<a href='mtx-server-ctx-help.lua?mode=tex'>tex mode</a>]],
+ },
+ optional_single = {
+ tex = "[optional string %s]",
+ lua = "{optional string %s}",
+ },
+ optional_list = {
+ tex = "[optional list %s]",
+ lua = "{optional table %s}" ,
+ } ,
+ mandate_single = {
+ tex = "[mandate string %s]",
+ lua = "{mandate string %s}",
+ },
+ mandate_list = {
+ tex = "[mandate list %s]",
+ lua = "{mandate list %s}",
+ },
+ interface = [[<a href='mtx-server-ctx-help.lua?interface=%s&mode=%s'>%s</a>]],
+ source = [[<a href='mtx-server-ctx-help.lua?source=%s&mode=%s'>%s</a>]],
+ parameter = [[<tr><td width='15%%'>%s</td><td width='15%%'>%s</td><td width='70%%'>%s</td></tr>]],
+ parameters = [[<table width='100%%'>%s</table>]],
+ listing = [[<pre><t>%s</t></listing>]],
+ special = [[<i>%s</i>]],
+ default = [[<u>%s</u>]],
+}
+
+local function translate(tag,int,noformat)
+ local t = document.setups.translations
+ local te = t["en"]
+ local ti = t[int] or te
+ if noformat then
+ return ti[tag] or te[tag] or tag
+ else
+ return format(document.setups.formats.special,ti[tag] or te[tag] or tag)
+ end
+end
+
+local function translated(e,int)
+ local attributes = e.at
+ local s = attributes.type or "?"
+ local tag = match(s,"^cd:(.*)$")
+ if attributes.default == "yes" then
+ return format(document.setups.formats.default,tag or "?")
+ elseif tag then
+ return translate(tag,int)
+ else
+ return s
+ end
+end
+
+document.setups.loaded = document.setups.loaded or { }
+
+document.setups.current = { }
+document.setups.showsources = true
+document.setups.mode = "tex"
+
+function document.setups.load(filename)
+ filename = resolvers.findfile(filename) or ""
+ if filename ~= "" then
+ local current = document.setups.loaded[filename]
+ if not current then
+ local loaded = xml.load(filename)
+ if loaded then
+ -- xml.inject(document.setups.root,"/",loaded)
+ current = {
+ file = filename,
+ root = loaded,
+ names = { },
+ used = { },
+ }
+ document.setups.loaded[filename] = current
+ end
+ end
+ document.setups.current = current or { }
+ end
+end
+
+function document.setups.name(ek)
+ local at = ek.at
+ local name = at.name
+ if at.type == 'environment' then
+ name = "start" .. name
+ end
+ if at.variant then
+ name = name .. ":" .. at.variant
+ end
+ if at.generated == "yes" then
+ name = name .. "*"
+ end
+ return name:lower()
+end
+
+function document.setups.csname(ek,int)
+ local cs = ""
+ local at = ek.at or { }
+ if at.type == 'environment' then
+ cs = translate("start",int,true) .. cs
+ end
+ for e in xml.collected(ek,'cd:sequence/(cd:string|variable)') do
+ if e.tg == "string" then
+ cs = cs .. e.at.value
+ else
+ cs = cs .. e.at.value -- to be translated
+ end
+ end
+ return cs
+end
+
+function document.setups.names()
+ local current = document.setups.current
+ local names = current.names
+ if not names or #names == 0 then
+ names = { }
+ local name = document.setups.name
+ local csname = document.setups.csname
+ for e in xml.collected(current.root,'cd:command') do
+ names[#names+1] = { e.at.name, csname(e,int) }
+ end
+ table.sort(names, function(a,b) return a[2]:lower() < b[2]:lower() end)
+ current.names = names
+ end
+ return names
+end
+
+function document.setups.show(name)
+ local current = document.setups.current
+ if current.root then
+ local name = gsub(name,"[<>]","")
+ local setup = xml.first(current.root,"cd:command[@name='" .. name .. "']")
+ current.used[#current.used+1] = setup
+ xml.sprint(setup)
+ end
+end
+
+function document.setups.showused()
+ local current = document.setups.current
+ if current.root and next(current.used) then
+ local sorted = table.sortedkeys(current.used)
+ for i=1,#sorted do
+ xml.sprint(current.used[sorted[i]])
+ end
+ end
+end
+function document.setups.showall()
+ local current = document.setups.current
+ if current.root then
+ local list = { }
+ for e in xml.collected(current.root,"cd:command") do
+ list[document.setups.name(e)] = e
+ end
+ local sorted = table.sortedkeys(list)
+ for i=1,#sorted do
+ xml.sprint(list[sorted[i]])
+ end
+ end
+end
+function document.setups.resolve(name)
+ local current = document.setups.current
+ if current.root then
+ local e = xml.filter(current.root,format("cd:define[@name='%s']/text()",name))
+ if e then
+ xml.sprint(e)
+ end
+ end
+end
+
+function document.setups.collect(name,int,lastmode)
+ local current = document.setups.current
+ local formats = document.setups.formats
+ local command = xml.filter(current.root,format("cd:command[@name='%s']/first()",name))
+ if command then
+ local attributes = command.at or { }
+ local data = {
+ command = command,
+ category = attributes.category or "",
+ }
+ if document.setups.showsources then
+ data.source = (attributes.file and format(formats.source,attributes.file,lastmode,attributes.file)) or ""
+ else
+ data.source = attributes.file or ""
+ end
+ local n, sequence, tags = 0, { }, { }
+ sequence[#sequence+1] = format(formats.open_command[lastmode],document.setups.csname(command,int))
+ local arguments, tag = { }, ""
+ for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
+ n = n + 1
+ local attributes = d[k].at
+ if #sequence > 1 then
+ local c = formats.connector[lastmode]
+ if c ~= "" then
+ sequence[#sequence+1] = c
+ end
+ end
+ if attributes.optional == 'yes' then
+ if attributes.list == 'yes' then
+ tag = format(formats.optional_list[lastmode],n)
+ else
+ tag = format(formats.optional_single[lastmode],n)
+ end
+ else
+ if attributes.list == 'yes' then
+ tag = format(formats.mandate_list[lastmode],n)
+ else
+ tag = format(formats.mandate_single[lastmode],n)
+ end
+ end
+ sequence[#sequence+1] = tag
+ tags[#tags+1] = tag
+ end
+ sequence[#sequence+1] = formats.close_command[lastmode]
+ data.sequence = concat(sequence, " ")
+ local parameters, n = { }, 0
+ for r, d, k in xml.elements(command,"(cd:keywords|cd:assignments)") do
+ n = n + 1
+ if d[k].tg == "keywords" then
+ local left = tags[n]
+ local right = { }
+ for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do
+ local tag = d[k].tg
+ if tag == "resolve" then
+ local name = d[k].at.name or ""
+ if name ~= "" then
+ local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name))
+ for r, d, k in xml.elements(resolved,"cd:constant") do
+ right[#right+1] = translated(d[k],int)
+ end
+ end
+ else
+ right[#right+1] = translated(d[k],int)
+ end
+ end
+ parameters[#parameters+1] = format(formats.parameter,left,"",concat(right, ", "))
+ else
+ local what = tags[n]
+ for r, d, k in xml.elements(d[k],"(cd:parameter|cd:inherit)") do
+ local tag = d[k].tg
+ local left, right = d[k].at.name or "?", { }
+ if tag == "inherit" then
+ local name = d[k].at.name or "?"
+ local goto = format(document.setups.formats.href_as_command[lastmode],name,lastmode,name)
+ if #parameters > 0 and not find(parameters[#parameters],"<br/>") then
+ parameters[#parameters+1] = format(formats.parameter,"<br/>","","")
+ end
+ parameters[#parameters+1] = format(formats.parameter,what,format(formats.special,translate("inherits",int)),goto)
+ else
+ for r, d, k in xml.elements(d[k],"(cd:constant|cd:resolve)") do
+ local tag = d[k].tg
+ if tag == "resolve" then
+ local name = d[k].at.name or ""
+ if name ~= "" then
+ local resolved = xml.filter(current.root,format("cd:define[@name='%s']",name))
+ for r, d, k in xml.elements(resolved,"cd:constant") do
+ right[#right+1] = translated(d[k],int)
+ end
+ end
+ else
+ right[#right+1] = translated(d[k],int)
+ end
+ end
+ parameters[#parameters+1] = format(formats.parameter,what,left,concat(right, ", "))
+ end
+ what = ""
+ end
+ end
+ parameters[#parameters+1] = format(formats.parameter,"<br/>","","")
+ end
+ data.parameters = parameters or { }
+ data.mode = formats.modes[lastmode or "tex"]
+ return data
+ else
+ return nil
+ end
+end
+
+-- -- --
+
+tex = tex or { }
+
+-- -- --
+
+local interfaces = {
+ czech = 'cz',
+ dutch = 'nl',
+ english = 'en',
+ french = 'fr',
+ german = 'de',
+ italian = 'it',
+ persian = 'pe',
+ romanian = 'ro',
+}
+
+local lastinterface, lastcommand, lastsource, lastmode = "en", "", "", "tex"
+
+local variables = {
+ ['color-background-main-left'] = '#3F3F3F',
+ ['color-background-main-right'] = '#5F5F5F',
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ ['title'] = 'ConTeXt Help Information',
+}
+
+--~ function lmx.loadedfile(filename)
+--~ return io.loaddata(resolvers.findfile(filename)) -- return resolvers.texdatablob(filename)
+--~ end
+
+local function doit(configuration,filename,hashed)
+
+ local formats = document.setups.formats
+
+ local start = os.clock()
+ local detail = hashed.queries or { }
+
+ if detail then
+
+ lastinterface = detail.interface or lastinterface
+ lastcommand = detail.command or lastcommand
+ lastsource = detail.source or lastsource
+ lastmode = detail.mode or lastmode or "tex"
+
+ lastcommand = gsub(lastcommand,"%s*^\\*(.+)%s*","%1")
+
+ if lastinterface then
+ report("checking interface: %s",lastinterface)
+ document.setups.load(format("cont-%s.xml",lastinterface))
+ end
+
+ local div = document.setups.div [lastinterface]
+ local span = document.setups.span[lastinterface]
+
+ local names, refs, ints = document.setups.names(lastinterface), { }, { }
+ for k=1,#names do
+ local v = names[k]
+ refs[k] = format(formats.href_in_list[lastmode],v[1],lastmode,v[2])
+ end
+ if lastmode ~= "lua" then
+ local sorted = table.sortedkeys(interfaces)
+ for k=1,#sorted do
+ local v = sorted[k]
+ ints[k] = format(formats.interface,interfaces[v],lastmode,v)
+ end
+ end
+
+ local n = concat(refs,"<br/>")
+ local i = concat(ints,"<br/><br/>")
+
+ if div then
+ variables.names = format(div,n)
+ variables.interfaces = format(div,i)
+ else
+ variables.names = n
+ variables.interfaces = i
+ end
+
+ -- first we need to add information about mkii/mkiv
+
+ variables.maintitle = "no definition"
+ variables.maintext = ""
+ variables.extra = ""
+
+ if document.setups.showsources and lastsource and lastsource ~= "" then
+ -- todo: mkii, mkiv, tex (can be different)
+ local data = io.loaddata(resolvers.findfile(lastsource))
+ variables.maintitle = lastsource
+ variables.maintext = format(formats.listing,data)
+ lastsource = ""
+ elseif lastcommand and lastcommand ~= "" then
+ local data = document.setups.collect(lastcommand,lastinterface,lastmode)
+ if data then
+ local what, extra = { "environment", "category", "source", "mode" }, { }
+ for k=1,#what do
+ local v = what[k]
+ if data[v] and data[v] ~= "" then
+ lmx.set(v, data[v])
+ extra[#extra+1] = v .. ": " .. data[v]
+ end
+ end
+ variables.maintitle = data.sequence
+ variables.maintext = format(formats.parameters,concat(data.parameters))
+ variables.extra = concat(extra," ")
+ else
+ variables.maintext = "select command"
+ end
+ end
+
+ else
+
+ variables.maintitle = "no definition"
+ variables.maintext = "some error"
+ variables.extra = ""
+
+ end
+
+ local content = lmx.convert('context-help.lmx',false,variables)
+
+ report("time spent on page: %0.03f seconds",os.clock()-start)
+
+ return { content = content }
+end
+
+return doit, true
diff --git a/scripts/context/lua/mtx-server-ctx-startup.lua b/scripts/context/lua/mtx-server-ctx-startup.lua index 556805113..8e99e6371 100644 --- a/scripts/context/lua/mtx-server-ctx-startup.lua +++ b/scripts/context/lua/mtx-server-ctx-startup.lua @@ -1,39 +1,39 @@ -if not modules then modules = { } end modules ['mtx-server-ctx-startup'] = { - version = 1.001, - comment = "Overview Of Goodies", - author = "Hans Hagen", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -dofile(resolvers.findfile("trac-lmx.lua","tex")) - -function doit(configuration,filename,hashed) - - local list = { } - local root = file.dirname(resolvers.findfile("mtx-server.lua") or ".") - if root == "" then root = "." end - local pattern = root .. "/mtx-server-ctx-*.lua" - local files = dir.glob(pattern) - for i=1,#files do - local filename = file.basename(files[i]) - local name = string.match(filename,"mtx%-server%-ctx%-(.-)%.lua$") - if name and name ~= "startup" then - list[#list+1] = string.format("<a href='%s' target='ctx-%s'>%s</a><br/><br/>",filename,name,name) - end - end - - local variables = { - ['color-background-one'] = lmx.get('color-background-green'), - ['color-background-two'] = lmx.get('color-background-blue'), - ['title'] = "Overview Of Goodies", - ['color-background-one'] = lmx.get('color-background-green'), - ['color-background-two'] = lmx.get('color-background-blue'), - ['maintext'] = table.concat(list,"\n"), - } - - return { content = lmx.convert('context-base.lmx',false,variables) } - -end - -return doit, true +if not modules then modules = { } end modules ['mtx-server-ctx-startup'] = {
+ version = 1.001,
+ comment = "Overview Of Goodies",
+ author = "Hans Hagen",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+dofile(resolvers.findfile("trac-lmx.lua","tex"))
+
+function doit(configuration,filename,hashed)
+
+ local list = { }
+ local root = file.dirname(resolvers.findfile("mtx-server.lua") or ".")
+ if root == "" then root = "." end
+ local pattern = root .. "/mtx-server-ctx-*.lua"
+ local files = dir.glob(pattern)
+ for i=1,#files do
+ local filename = file.basename(files[i])
+ local name = string.match(filename,"mtx%-server%-ctx%-(.-)%.lua$")
+ if name and name ~= "startup" then
+ list[#list+1] = string.format("<a href='%s' target='ctx-%s'>%s</a><br/><br/>",filename,name,name)
+ end
+ end
+
+ local variables = {
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ ['title'] = "Overview Of Goodies",
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ ['maintext'] = table.concat(list,"\n"),
+ }
+
+ return { content = lmx.convert('context-base.lmx',false,variables) }
+
+end
+
+return doit, true
diff --git a/scripts/context/lua/mtx-server.lua b/scripts/context/lua/mtx-server.lua index 5ec15de70..675ab2c62 100644 --- a/scripts/context/lua/mtx-server.lua +++ b/scripts/context/lua/mtx-server.lua @@ -1,402 +1,402 @@ -if not modules then modules = { } end modules ['mtx-server'] = { - version = 1.001, - comment = "companion to mtxrun.lua", - author = "Hans Hagen & Taco Hoekwater", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-server</entry> - <entry name="detail">Simple Webserver For Helpers</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="start"><short>start server</short></flag> - <flag name="port"><short>port to listen to</short></flag> - <flag name="root"><short>server root</short></flag> - <flag name="scripts"><short>scripts sub path</short></flag> - <flag name="index"><short>index file</short></flag> - <flag name="auto"><short>start on own path</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-server", - banner = "Simple Webserver For Helpers 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.webserver = scripts.webserver or { } - -dofile(resolvers.findfile("luat-soc.lua","tex")) - -local socket = socket or require("socket") -local http = http or require("socket.http") -- not needed -local format = string.format - --- The following two lists are taken from webrick (ruby) and --- extended with a few extra suffixes. - -local mimetypes = { - ai = 'application/postscript', - asc = 'text/plain', - avi = 'video/x-msvideo', - bin = 'application/octet-stream', - bmp = 'image/bmp', - bz2 = 'application/x-bzip2', - cer = 'application/pkix-cert', - class = 'application/octet-stream', - crl = 'application/pkix-crl', - crt = 'application/x-x509-ca-cert', - css = 'text/css', - dms = 'application/octet-stream', - doc = 'application/msword', - dvi = 'application/x-dvi', - eps = 'application/postscript', - etx = 'text/x-setext', - exe = 'application/octet-stream', - gif = 'image/gif', - gz = 'application/x-tar', - hqx = 'application/mac-binhex40', - htm = 'text/html', - html = 'text/html', - jpe = 'image/jpeg', - jpeg = 'image/jpeg', - jpg = 'image/jpeg', - lha = 'application/octet-stream', - lzh = 'application/octet-stream', - mov = 'video/quicktime', - mpe = 'video/mpeg', - mpeg = 'video/mpeg', - mpg = 'video/mpeg', - pbm = 'image/x-portable-bitmap', - pdf = 'application/pdf', - pgm = 'image/x-portable-graymap', - png = 'image/png', - pnm = 'image/x-portable-anymap', - ppm = 'image/x-portable-pixmap', - ppt = 'application/vnd.ms-powerpoint', - ps = 'application/postscript', - qt = 'video/quicktime', - ras = 'image/x-cmu-raster', - rb = 'text/plain', - rd = 'text/plain', - rgb = 'image/x-rgb', - rtf = 'application/rtf', - sgm = 'text/sgml', - sgml = 'text/sgml', - snd = 'audio/basic', - tar = 'application/x-tar', - tgz = 'application/x-tar', - tif = 'image/tiff', - tiff = 'image/tiff', - txt = 'text/plain', - xbm = 'image/x-xbitmap', - xls = 'application/vnd.ms-excel', - xml = 'text/xml', - xpm = 'image/x-xpixmap', - xwd = 'image/x-xwindowdump', - zip = 'application/zip', -} - -local messages = { - [100] = 'Continue', - [101] = 'Switching Protocols', - [200] = 'OK', - [201] = 'Created', - [202] = 'Accepted', - [203] = 'Non-Authoritative Information', - [204] = 'No Content', - [205] = 'Reset Content', - [206] = 'Partial Content', - [300] = 'Multiple Choices', - [301] = 'Moved Permanently', - [302] = 'Found', - [303] = 'See Other', - [304] = 'Not Modified', - [305] = 'Use Proxy', - [307] = 'Temporary Redirect', - [400] = 'Bad Request', - [401] = 'Unauthorized', - [402] = 'Payment Required', - [403] = 'Forbidden', - [404] = 'Not Found', - [405] = 'Method Not Allowed', - [406] = 'Not Acceptable', - [407] = 'Proxy Authentication Required', - [408] = 'Request Timeout', - [409] = 'Conflict', - [410] = 'Gone', - [411] = 'Length Required', - [412] = 'Precondition Failed', - [413] = 'Request Entity Too Large', - [414] = 'Request-URI Too Large', - [415] = 'Unsupported Media Type', - [416] = 'Request Range Not Satisfiable', - [417] = 'Expectation Failed', - [500] = 'Internal Server Error', - [501] = 'Not Implemented', - [502] = 'Bad Gateway', - [503] = 'Service Unavailable', - [504] = 'Gateway Timeout', - [505] = 'HTTP Version Not Supported', -} - -local handlers = { } - -local function errormessage(client,configuration,n) - local data = format("<head><title>%s %s</title></head><html><h2>%s %s</h2></html>",n,messages[n],n,messages[n]) - report("handling error %s: %s",n,messages[n]) - handlers.generic(client,configuration,data,nil,true) -end - -local validpaths, registered = { }, { } - -function scripts.webserver.registerpath(name) - if not registered[name] then - local cleanname = string.gsub(name,"%.%.","deleted-parent") - report("registering path '%s'",cleanname) - validpaths[#validpaths+1] = cleanname - registered[name] = true - end -end - -function handlers.generic(client,configuration,data,suffix,iscontent) - if not iscontent then - local name = data - report("requested file '%s'",name) - local fullname = file.join(configuration.root,name) - data = io.loaddata(fullname) or "" - if data == "" then - for n=1,#validpaths do - local fullname = file.join(validpaths[n],name) - data = io.loaddata(fullname) or "" - if data ~= "" then - report("sending generic file '%s'",fullname) - break - end - end - else - report("sending generic file '%s'",fullname) - end - end - if data and data ~= "" then - client:send("HTTP/1.1 200 OK\r\n") - client:send("Connection: close\r\n") - client:send(format("Content-Length: %s\r\n",#data)) - client:send(format("Content-Type: %s\r\n",(suffix and mimetypes[suffix]) or "text/html")) - client:send("\r\n") - client:send(data) - client:send("\r\n") - else - errormessage(client,configuration,404) - end -end - --- return os.date() - --- return { content = "crap" } - --- return function(configuration,filename) --- return { content = filename } --- end - -local loaded = { } - -function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) -- filename will disappear, and become hashed.filename - local filename = file.join(configuration.scripts,filename) - if not file.is_qualified_path(filename) then - filename = file.join(configuration.root,filename) - end - -- todo: split url in components, see l-url; rather trivial - local result, keep = loaded[filename], false - if result then - report("reusing script: %s",filename) - else - report("locating script: %s",filename) - if lfs.isfile(filename) then - report("loading script: %s",filename) - result = loadfile(filename) - report("return type: %s",type(result)) - if result and type(result) == "function" then - -- result() should return a table { [type=,] [length=,] content= }, function or string - result, keep = result() - if keep then - report("saving script: %s",type(result)) - loaded[filename] = result - end - end - else - report("problematic script: %s",filename) - errormessage(client,configuration,404) - end - end - if result then - if type(result) == "function" then - report("running script: %s",filename) - result = result(configuration,filename,hashed) -- second argument will become query - end - if result and type(result) == "string" then - result = { content = result } - end - if result and type(result) == "table" then - if result.content then - local suffix = result.type or "text/html" - local action = handlers[suffix] or handlers.generic - action(client,configuration,result.content,suffix,true) -- content - elseif result.filename then - local suffix = file.suffix(result.filename) or "text/html" - local action = handlers[suffix] or handlers.generic - action(client,configuration,result.filename,suffix,false) -- filename - else - errormessage(client,configuration,404) - end - else - errormessage(client,configuration,500) - end - else - errormessage(client,configuration,404) - end -end - -handlers.luc = handlers.lua -handlers.html = handlers.htm - -local indices = { "index.htm", "index.html" } -local portnumber = 31415 -- pi suits tex - -function scripts.webserver.run(configuration) - -- check configuration - configuration.port = tonumber(configuration.port or os.getenv("MTX_SERVER_PORT") or portnumber) or portnumber - if not configuration.root or not lfs.isdir(configuration.root) then - configuration.root = os.getenv("MTX_SERVER_ROOT") or "." - end - -- locate root and index file in tex tree - if not lfs.isdir(configuration.root) then - for i=1,#indices do - local name = indices[i] - local root = resolvers.resolve("path:" .. name) or "" - if root ~= "" then - configuration.root = root - configuration.index = configuration.index or name - break - end - end - end - configuration.root = dir.expandname(configuration.root) - if not configuration.index then - for i=1,#indices do - local name = indices[i] - if lfs.isfile(file.join(configuration.root,name)) then - configuration.index = name -- we will prepend the rootpath later - break - end - end - configuration.index = configuration.index or "unknown" - end - if not configuration.scripts or configuration.scripts == "" then - configuration.scripts = dir.expandname(file.join(configuration.root or ".",configuration.scripts or ".")) - end - -- so far for checks - report("running at port: %s",configuration.port) - report("document root: %s",configuration.root or resolvers.ownpath) - report("main index file: %s",configuration.index) - report("scripts subpath: %s",configuration.scripts) - report("context services: http://localhost:%s/mtx-server-ctx-startup.lua",configuration.port) - local server = assert(socket.bind("*", configuration.port)) - local script = configuration.script - while true do -- blocking - local start = os.clock() - local client = server:accept() - client:settimeout(configuration.timeout or 60) - local request, e = client:receive() - if e then - errormessage(client,configuration,404) - else - local from = client:getpeername() - report("request from: %s",tostring(from)) - report("request data: %s",tostring(request)) - local fullurl = string.match(request,"GET (.+) HTTP/.*$") or "" -- todo: more clever / post - if fullurl == "" then - report("no url") - errormessage(client,configuration,404) - else - report("requested url: %s",fullurl) - fullurl = socket.url.unescape(fullurl) -- still needed? - local hashed = url.hashed(fullurl) - local query = url.query(hashed.query) - local filename = hashed.path -- hm, not query? - if script then - filename = script - report("forced script: %s",filename) - local suffix = file.suffix(filename) - local action = handlers[suffix] or handlers.generic - if action then - report("performing action: %s",filename) - action(client,configuration,filename,suffix,false,hashed) -- filename and no content - else - errormessage(client,configuration,404) - end - elseif filename then - filename = socket.url.unescape(filename) - report("requested action: %s",filename) - if string.find(filename,"%.%.") then - filename = nil -- invalid path - end - if filename == nil or filename == "" or filename == "/" then - filename = configuration.index - report("invalid filename, forcing: %s",filename) - end - local suffix = file.suffix(filename) - local action = handlers[suffix] or handlers.generic - if action then - report("performing action: %s",filename) - action(client,configuration,filename,suffix,false,hashed) -- filename and no content - else - errormessage(client,configuration,404) - end - else - errormessage(client,configuration,404) - end - end - end - client:close() - report("time spent with client: %0.03f seconds",os.clock()-start) - end -end - -if environment.argument("auto") then - local path = resolvers.findfile("mtx-server.lua") or "." - scripts.webserver.run { - port = environment.argument("port"), - root = environment.argument("root") or file.dirname(path) or ".", - scripts = environment.argument("scripts") or file.dirname(path) or ".", - script = environment.argument("script"), - } -elseif environment.argument("start") then - scripts.webserver.run { - port = environment.argument("port"), - root = environment.argument("root") or ".", -- "e:/websites/www.pragma-ade.com", - index = environment.argument("index"), - scripts = environment.argument("scripts"), - script = environment.argument("script"), - } -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end - --- mtxrun --script server --start => http://localhost:31415/mtx-server-ctx-startup.lua +if not modules then modules = { } end modules ['mtx-server'] = {
+ version = 1.001,
+ comment = "companion to mtxrun.lua",
+ author = "Hans Hagen & Taco Hoekwater",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-server</entry>
+ <entry name="detail">Simple Webserver For Helpers</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="start"><short>start server</short></flag>
+ <flag name="port"><short>port to listen to</short></flag>
+ <flag name="root"><short>server root</short></flag>
+ <flag name="scripts"><short>scripts sub path</short></flag>
+ <flag name="index"><short>index file</short></flag>
+ <flag name="auto"><short>start on own path</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-server",
+ banner = "Simple Webserver For Helpers 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.webserver = scripts.webserver or { }
+
+dofile(resolvers.findfile("luat-soc.lua","tex"))
+
+local socket = socket or require("socket")
+local http = http or require("socket.http") -- not needed
+local format = string.format
+
+-- The following two lists are taken from webrick (ruby) and
+-- extended with a few extra suffixes.
+
+local mimetypes = {
+ ai = 'application/postscript',
+ asc = 'text/plain',
+ avi = 'video/x-msvideo',
+ bin = 'application/octet-stream',
+ bmp = 'image/bmp',
+ bz2 = 'application/x-bzip2',
+ cer = 'application/pkix-cert',
+ class = 'application/octet-stream',
+ crl = 'application/pkix-crl',
+ crt = 'application/x-x509-ca-cert',
+ css = 'text/css',
+ dms = 'application/octet-stream',
+ doc = 'application/msword',
+ dvi = 'application/x-dvi',
+ eps = 'application/postscript',
+ etx = 'text/x-setext',
+ exe = 'application/octet-stream',
+ gif = 'image/gif',
+ gz = 'application/x-tar',
+ hqx = 'application/mac-binhex40',
+ htm = 'text/html',
+ html = 'text/html',
+ jpe = 'image/jpeg',
+ jpeg = 'image/jpeg',
+ jpg = 'image/jpeg',
+ lha = 'application/octet-stream',
+ lzh = 'application/octet-stream',
+ mov = 'video/quicktime',
+ mpe = 'video/mpeg',
+ mpeg = 'video/mpeg',
+ mpg = 'video/mpeg',
+ pbm = 'image/x-portable-bitmap',
+ pdf = 'application/pdf',
+ pgm = 'image/x-portable-graymap',
+ png = 'image/png',
+ pnm = 'image/x-portable-anymap',
+ ppm = 'image/x-portable-pixmap',
+ ppt = 'application/vnd.ms-powerpoint',
+ ps = 'application/postscript',
+ qt = 'video/quicktime',
+ ras = 'image/x-cmu-raster',
+ rb = 'text/plain',
+ rd = 'text/plain',
+ rgb = 'image/x-rgb',
+ rtf = 'application/rtf',
+ sgm = 'text/sgml',
+ sgml = 'text/sgml',
+ snd = 'audio/basic',
+ tar = 'application/x-tar',
+ tgz = 'application/x-tar',
+ tif = 'image/tiff',
+ tiff = 'image/tiff',
+ txt = 'text/plain',
+ xbm = 'image/x-xbitmap',
+ xls = 'application/vnd.ms-excel',
+ xml = 'text/xml',
+ xpm = 'image/x-xpixmap',
+ xwd = 'image/x-xwindowdump',
+ zip = 'application/zip',
+}
+
+local messages = {
+ [100] = 'Continue',
+ [101] = 'Switching Protocols',
+ [200] = 'OK',
+ [201] = 'Created',
+ [202] = 'Accepted',
+ [203] = 'Non-Authoritative Information',
+ [204] = 'No Content',
+ [205] = 'Reset Content',
+ [206] = 'Partial Content',
+ [300] = 'Multiple Choices',
+ [301] = 'Moved Permanently',
+ [302] = 'Found',
+ [303] = 'See Other',
+ [304] = 'Not Modified',
+ [305] = 'Use Proxy',
+ [307] = 'Temporary Redirect',
+ [400] = 'Bad Request',
+ [401] = 'Unauthorized',
+ [402] = 'Payment Required',
+ [403] = 'Forbidden',
+ [404] = 'Not Found',
+ [405] = 'Method Not Allowed',
+ [406] = 'Not Acceptable',
+ [407] = 'Proxy Authentication Required',
+ [408] = 'Request Timeout',
+ [409] = 'Conflict',
+ [410] = 'Gone',
+ [411] = 'Length Required',
+ [412] = 'Precondition Failed',
+ [413] = 'Request Entity Too Large',
+ [414] = 'Request-URI Too Large',
+ [415] = 'Unsupported Media Type',
+ [416] = 'Request Range Not Satisfiable',
+ [417] = 'Expectation Failed',
+ [500] = 'Internal Server Error',
+ [501] = 'Not Implemented',
+ [502] = 'Bad Gateway',
+ [503] = 'Service Unavailable',
+ [504] = 'Gateway Timeout',
+ [505] = 'HTTP Version Not Supported',
+}
+
+local handlers = { }
+
+local function errormessage(client,configuration,n)
+ local data = format("<head><title>%s %s</title></head><html><h2>%s %s</h2></html>",n,messages[n],n,messages[n])
+ report("handling error %s: %s",n,messages[n])
+ handlers.generic(client,configuration,data,nil,true)
+end
+
+local validpaths, registered = { }, { }
+
+function scripts.webserver.registerpath(name)
+ if not registered[name] then
+ local cleanname = string.gsub(name,"%.%.","deleted-parent")
+ report("registering path '%s'",cleanname)
+ validpaths[#validpaths+1] = cleanname
+ registered[name] = true
+ end
+end
+
+function handlers.generic(client,configuration,data,suffix,iscontent)
+ if not iscontent then
+ local name = data
+ report("requested file '%s'",name)
+ local fullname = file.join(configuration.root,name)
+ data = io.loaddata(fullname) or ""
+ if data == "" then
+ for n=1,#validpaths do
+ local fullname = file.join(validpaths[n],name)
+ data = io.loaddata(fullname) or ""
+ if data ~= "" then
+ report("sending generic file '%s'",fullname)
+ break
+ end
+ end
+ else
+ report("sending generic file '%s'",fullname)
+ end
+ end
+ if data and data ~= "" then
+ client:send("HTTP/1.1 200 OK\r\n")
+ client:send("Connection: close\r\n")
+ client:send(format("Content-Length: %s\r\n",#data))
+ client:send(format("Content-Type: %s\r\n",(suffix and mimetypes[suffix]) or "text/html"))
+ client:send("\r\n")
+ client:send(data)
+ client:send("\r\n")
+ else
+ errormessage(client,configuration,404)
+ end
+end
+
+-- return os.date()
+
+-- return { content = "crap" }
+
+-- return function(configuration,filename)
+-- return { content = filename }
+-- end
+
+local loaded = { }
+
+function handlers.lua(client,configuration,filename,suffix,iscontent,hashed) -- filename will disappear, and become hashed.filename
+ local filename = file.join(configuration.scripts,filename)
+ if not file.is_qualified_path(filename) then
+ filename = file.join(configuration.root,filename)
+ end
+ -- todo: split url in components, see l-url; rather trivial
+ local result, keep = loaded[filename], false
+ if result then
+ report("reusing script: %s",filename)
+ else
+ report("locating script: %s",filename)
+ if lfs.isfile(filename) then
+ report("loading script: %s",filename)
+ result = loadfile(filename)
+ report("return type: %s",type(result))
+ if result and type(result) == "function" then
+ -- result() should return a table { [type=,] [length=,] content= }, function or string
+ result, keep = result()
+ if keep then
+ report("saving script: %s",type(result))
+ loaded[filename] = result
+ end
+ end
+ else
+ report("problematic script: %s",filename)
+ errormessage(client,configuration,404)
+ end
+ end
+ if result then
+ if type(result) == "function" then
+ report("running script: %s",filename)
+ result = result(configuration,filename,hashed) -- second argument will become query
+ end
+ if result and type(result) == "string" then
+ result = { content = result }
+ end
+ if result and type(result) == "table" then
+ if result.content then
+ local suffix = result.type or "text/html"
+ local action = handlers[suffix] or handlers.generic
+ action(client,configuration,result.content,suffix,true) -- content
+ elseif result.filename then
+ local suffix = file.suffix(result.filename) or "text/html"
+ local action = handlers[suffix] or handlers.generic
+ action(client,configuration,result.filename,suffix,false) -- filename
+ else
+ errormessage(client,configuration,404)
+ end
+ else
+ errormessage(client,configuration,500)
+ end
+ else
+ errormessage(client,configuration,404)
+ end
+end
+
+handlers.luc = handlers.lua
+handlers.html = handlers.htm
+
+local indices = { "index.htm", "index.html" }
+local portnumber = 31415 -- pi suits tex
+
+function scripts.webserver.run(configuration)
+ -- check configuration
+ configuration.port = tonumber(configuration.port or os.getenv("MTX_SERVER_PORT") or portnumber) or portnumber
+ if not configuration.root or not lfs.isdir(configuration.root) then
+ configuration.root = os.getenv("MTX_SERVER_ROOT") or "."
+ end
+ -- locate root and index file in tex tree
+ if not lfs.isdir(configuration.root) then
+ for i=1,#indices do
+ local name = indices[i]
+ local root = resolvers.resolve("path:" .. name) or ""
+ if root ~= "" then
+ configuration.root = root
+ configuration.index = configuration.index or name
+ break
+ end
+ end
+ end
+ configuration.root = dir.expandname(configuration.root)
+ if not configuration.index then
+ for i=1,#indices do
+ local name = indices[i]
+ if lfs.isfile(file.join(configuration.root,name)) then
+ configuration.index = name -- we will prepend the rootpath later
+ break
+ end
+ end
+ configuration.index = configuration.index or "unknown"
+ end
+ if not configuration.scripts or configuration.scripts == "" then
+ configuration.scripts = dir.expandname(file.join(configuration.root or ".",configuration.scripts or "."))
+ end
+ -- so far for checks
+ report("running at port: %s",configuration.port)
+ report("document root: %s",configuration.root or resolvers.ownpath)
+ report("main index file: %s",configuration.index)
+ report("scripts subpath: %s",configuration.scripts)
+ report("context services: http://localhost:%s/mtx-server-ctx-startup.lua",configuration.port)
+ local server = assert(socket.bind("*", configuration.port))
+ local script = configuration.script
+ while true do -- blocking
+ local start = os.clock()
+ local client = server:accept()
+ client:settimeout(configuration.timeout or 60)
+ local request, e = client:receive()
+ if e then
+ errormessage(client,configuration,404)
+ else
+ local from = client:getpeername()
+ report("request from: %s",tostring(from))
+ report("request data: %s",tostring(request))
+ local fullurl = string.match(request,"GET (.+) HTTP/.*$") or "" -- todo: more clever / post
+ if fullurl == "" then
+ report("no url")
+ errormessage(client,configuration,404)
+ else
+ report("requested url: %s",fullurl)
+ fullurl = socket.url.unescape(fullurl) -- still needed?
+ local hashed = url.hashed(fullurl)
+ local query = url.query(hashed.query)
+ local filename = hashed.path -- hm, not query?
+ if script then
+ filename = script
+ report("forced script: %s",filename)
+ local suffix = file.suffix(filename)
+ local action = handlers[suffix] or handlers.generic
+ if action then
+ report("performing action: %s",filename)
+ action(client,configuration,filename,suffix,false,hashed) -- filename and no content
+ else
+ errormessage(client,configuration,404)
+ end
+ elseif filename then
+ filename = socket.url.unescape(filename)
+ report("requested action: %s",filename)
+ if string.find(filename,"%.%.") then
+ filename = nil -- invalid path
+ end
+ if filename == nil or filename == "" or filename == "/" then
+ filename = configuration.index
+ report("invalid filename, forcing: %s",filename)
+ end
+ local suffix = file.suffix(filename)
+ local action = handlers[suffix] or handlers.generic
+ if action then
+ report("performing action: %s",filename)
+ action(client,configuration,filename,suffix,false,hashed) -- filename and no content
+ else
+ errormessage(client,configuration,404)
+ end
+ else
+ errormessage(client,configuration,404)
+ end
+ end
+ end
+ client:close()
+ report("time spent with client: %0.03f seconds",os.clock()-start)
+ end
+end
+
+if environment.argument("auto") then
+ local path = resolvers.findfile("mtx-server.lua") or "."
+ scripts.webserver.run {
+ port = environment.argument("port"),
+ root = environment.argument("root") or file.dirname(path) or ".",
+ scripts = environment.argument("scripts") or file.dirname(path) or ".",
+ script = environment.argument("script"),
+ }
+elseif environment.argument("start") then
+ scripts.webserver.run {
+ port = environment.argument("port"),
+ root = environment.argument("root") or ".", -- "e:/websites/www.pragma-ade.com",
+ index = environment.argument("index"),
+ scripts = environment.argument("scripts"),
+ script = environment.argument("script"),
+ }
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
+
+-- mtxrun --script server --start => http://localhost:31415/mtx-server-ctx-startup.lua
diff --git a/scripts/context/lua/mtx-texworks.lua b/scripts/context/lua/mtx-texworks.lua index ae5f2afa4..8cb7736ac 100644 --- a/scripts/context/lua/mtx-texworks.lua +++ b/scripts/context/lua/mtx-texworks.lua @@ -1,121 +1,121 @@ -if not modules then modules = { } end modules ['mtx-texworks'] = { - version = 1.002, - 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 helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-texworks</entry> - <entry name="detail">TeXworks Startup Script</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="start"><short>[<ref name="verbose]"/> start texworks</short></flag> - <flag name="test"><short>report what will happen</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-texworks", - banner = "TeXworks Startup Script 1.00", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.texworks = scripts.texworks or { } - -local texworkspaths = { - "completion", - "configuration", - "dictionaries", - "translations", - "scripts", - "templates", - "TUG" -} - -local texworkssignal = "texworks-context.rme" -local texworkininame = "texworks.ini" - -function scripts.texworks.start(indeed) - local workname = (os.type == "windows" and "texworks.exe") or "texworks" - local fullname = nil - local binpaths = file.splitpath(os.getenv("PATH")) or file.splitpath(os.getenv("path")) - local usedsignal = texworkssignal - local datapath = resolvers.findfile(usedsignal,"other text files") or "" - if datapath ~= "" then - datapath = file.dirname(datapath) -- data - if datapath == "" then - datapath = resolvers.cleanpath(lfs.currentdir()) - end - else - usedsignal = texworkininame - datapath = resolvers.findfile(usedsignal,"other text files") or "" - if datapath == "" then - usedsignal = string.lower(usedsignal) - datapath = resolvers.findfile(usedsignal,"other text files") or "" - end - if datapath ~= "" and lfs.isfile(datapath) then - datapath = file.dirname(datapath) -- TUG - datapath = file.dirname(datapath) -- data - if datapath == "" then - datapath = resolvers.cleanpath(lfs.currentdir()) - end - end - end - if datapath == "" then - report("invalid datapath, maybe you need to regenerate the file database") - return false - end - if not binpaths or #binpaths == 0 then - report("invalid binpath") - return false - end - for i=1,#binpaths do - local p = file.join(binpaths[i],workname) - if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub - fullname = p - break - end - end - if not fullname then - report("unable to locate %s",workname) - return false - end - for i=1,#texworkspaths do - dir.makedirs(file.join(datapath,texworkspaths[i])) - end - os.setenv("TW_INIPATH",datapath) - os.setenv("TW_LIBPATH",datapath) - if not indeed or environment.argument("verbose") then - report("used signal: %s", usedsignal) - report("data path : %s", datapath) - report("full name : %s", fullname) - report("set paths : TW_INIPATH TW_LIBPATH") - end - if indeed then - os.launch(fullname) - end -end - -if environment.argument("start") then - scripts.texworks.start(true) -elseif environment.argument("test") then - scripts.texworks.start() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-texworks'] = {
+ version = 1.002,
+ 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 helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-texworks</entry>
+ <entry name="detail">TeXworks Startup Script</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="start"><short>[<ref name="verbose]"/> start texworks</short></flag>
+ <flag name="test"><short>report what will happen</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-texworks",
+ banner = "TeXworks Startup Script 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.texworks = scripts.texworks or { }
+
+local texworkspaths = {
+ "completion",
+ "configuration",
+ "dictionaries",
+ "translations",
+ "scripts",
+ "templates",
+ "TUG"
+}
+
+local texworkssignal = "texworks-context.rme"
+local texworkininame = "texworks.ini"
+
+function scripts.texworks.start(indeed)
+ local workname = (os.type == "windows" and "texworks.exe") or "texworks"
+ local fullname = nil
+ local binpaths = file.splitpath(os.getenv("PATH")) or file.splitpath(os.getenv("path"))
+ local usedsignal = texworkssignal
+ local datapath = resolvers.findfile(usedsignal,"other text files") or ""
+ if datapath ~= "" then
+ datapath = file.dirname(datapath) -- data
+ if datapath == "" then
+ datapath = resolvers.cleanpath(lfs.currentdir())
+ end
+ else
+ usedsignal = texworkininame
+ datapath = resolvers.findfile(usedsignal,"other text files") or ""
+ if datapath == "" then
+ usedsignal = string.lower(usedsignal)
+ datapath = resolvers.findfile(usedsignal,"other text files") or ""
+ end
+ if datapath ~= "" and lfs.isfile(datapath) then
+ datapath = file.dirname(datapath) -- TUG
+ datapath = file.dirname(datapath) -- data
+ if datapath == "" then
+ datapath = resolvers.cleanpath(lfs.currentdir())
+ end
+ end
+ end
+ if datapath == "" then
+ report("invalid datapath, maybe you need to regenerate the file database")
+ return false
+ end
+ if not binpaths or #binpaths == 0 then
+ report("invalid binpath")
+ return false
+ end
+ for i=1,#binpaths do
+ local p = file.join(binpaths[i],workname)
+ if lfs.isfile(p) and lfs.attributes(p,"size") > 10000 then -- avoind stub
+ fullname = p
+ break
+ end
+ end
+ if not fullname then
+ report("unable to locate %s",workname)
+ return false
+ end
+ for i=1,#texworkspaths do
+ dir.makedirs(file.join(datapath,texworkspaths[i]))
+ end
+ os.setenv("TW_INIPATH",datapath)
+ os.setenv("TW_LIBPATH",datapath)
+ if not indeed or environment.argument("verbose") then
+ report("used signal: %s", usedsignal)
+ report("data path : %s", datapath)
+ report("full name : %s", fullname)
+ report("set paths : TW_INIPATH TW_LIBPATH")
+ end
+ if indeed then
+ os.launch(fullname)
+ end
+end
+
+if environment.argument("start") then
+ scripts.texworks.start(true)
+elseif environment.argument("test") then
+ scripts.texworks.start()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-timing.lua b/scripts/context/lua/mtx-timing.lua index 5ba361e5f..391232b0a 100644 --- a/scripts/context/lua/mtx-timing.lua +++ b/scripts/context/lua/mtx-timing.lua @@ -1,218 +1,218 @@ -if not modules then modules = { } end modules ['mtx-timing'] = { - version = 1.002, - 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 format, gsub, concat = string.format, string.gsub, table.concat - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-timing</entry> - <entry name="detail">ConTeXt Timing Tools</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="xhtml"><short>make xhtml file</short></flag> - <flag name="launch"><short>launch after conversion</short></flag> - <flag name="remove"><short>remove after launching</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-timing", - banner = "ConTeXt Timing Tools 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -dofile(resolvers.findfile("node-snp.lua","tex")) -dofile(resolvers.findfile("trac-tim.lua","tex")) -dofile(resolvers.findfile("trac-lmx.lua","tex")) - -local meta = [[ - beginfig(%s) ; - begingroup ; - save p, q, b, h, w ; - path p, q, b ; numeric h, w ; - linecap := butt ; - h := 100 ; - w := 800pt ; - p := %s ; - q := %s ; - p := p shifted -llcorner p ; - q := q shifted -llcorner q ; - q := q xstretched w ; - p := p xstretched w ; - b := boundingbox (llcorner p -- llcorner p shifted (w,h)) ; - draw b withcolor white withpen pencircle scaled 4pt ; - draw p withcolor red withpen pencircle scaled 4pt ; - draw q withcolor blue withpen pencircle scaled 2pt ; - endgroup ; - endfig ; -]] - -local html_graphic = [[ - <h1><a name='graphic-%s'>%s (red) %s (blue)</a></h1> - <table> - <tr> - <td>%s</td> - <td valign='top'> - min: %s<br/> - max: %s<br/> - pages: %s<br/> - average: %s<br/> - </td> - </tr> - </table> - <br/> -]] - -local html_menu = [[ - <a href='#graphic-%s'>%s</a> -]] - -local directrun = true - -local what = { "parameters", "nodes" } - -plugins = plugins or { progress = { } } -- brrr, will become moduledata as well - -function plugins.progress.make_svg(filename,other) - local metadata, menudata, c = { }, { }, 0 - metadata[#metadata+1] = 'outputformat := "svg" ;' - for i=1,#what do - local kind, mdk = what[i], { } - menudata[kind] = mdk - for n, name in next, plugins.progress[kind](filename) do - local first = plugins.progress.path(filename,name) - local second = plugins.progress.path(filename,other) - c = c + 1 - metadata[#metadata+1] = format(meta,c,first,second) - mdk[#mdk+1] = { name, c } - end - end - metadata[#metadata+1] = "end ." - metadata = concat(metadata,"\n\n") - if directrun then - dofile(resolvers.findfile("mlib-run.lua","tex")) - commands = commands or { } - commands.writestatus = report - local result = metapost.directrun("metafun","timing data","svg",true,metadata) - return menudata, result - else - local mpname = file.replacesuffix(filename,"mp") - io.savedata(mpname,metadata) - os.execute(format("mpost --progname=context --mem=metafun.mem %s",mpname)) - os.remove(mpname) - os.remove(file.removesuffix(filename).."-mpgraph.mpo") -- brr - os.remove(file.removesuffix(filename)..".log") -- brr - return menudata - end -end - -function plugins.progress.makehtml(filename,other,menudata,metadata) - local graphics = { } - local result = { graphics = graphics } - for i=1,#what do - local kind, menu = what[i], { } - local md = menudata[kind] - result[kind] = menu - for k=1,#md do - local v = md[k] - local name, number = v[1], v[2] - local min = plugins.progress.bot(filename,name) - local max = plugins.progress.top(filename,name) - local pages = plugins.progress.pages(filename) - local average = math.round(max/pages) - if directrun then - local data = metadata[number] - menu[#menu+1] = format(html_menu,name,name) - graphics[#graphics+1] = format(html_graphic,name,name,other,data,min,max,pages,average) - else - local mpname = file.replacesuffix(filename,number) - local data = io.loaddata(mpname) or "" - -- data = gsub(data,"<!%-%-(.-)%-%->[\n\r]*","") - data = gsub(data,"<%?xml.->","") - menu[#menu+1] = format(html_menu,name,name) - graphics[#graphics+1] = format(html_graphic,name,name,other,data,min,max,pages,average) - os.remove(mpname) - end - end - end - return result -end - -function plugins.progress.valid_file(name) - return name and name ~= "" and lfs.isfile(name .. "-luatex-progress.lut") -end - -function plugins.progress.make_lmx_page(name,launch,remove) - - local filename = name .. "-luatex-progress" - local other = "elapsed_time" - local template = 'context-timing.lmx' - - plugins.progress.convert(filename) - - local menudata, metadata = plugins.progress.make_svg(filename,other) - local htmldata = plugins.progress.makehtml(filename,other,menudata,metadata) - - lmx.htmfile = function(name) return name .. "-timing.xhtml" end - lmx.lmxfile = function(name) return resolvers.findfile(name,'tex') end - - local variables = { - ['title-default'] = 'ConTeXt Timing Information', - ['title'] = format('ConTeXt Timing Information: %s',file.basename(name)), - ['parametersmenu'] = concat(htmldata.parameters, " "), - ['nodesmenu'] = concat(htmldata.nodes, " "), - ['graphics'] = concat(htmldata.graphics, "\n\n"), - ['color-background-one'] = lmx.get('color-background-green'), - ['color-background-two'] = lmx.get('color-background-blue'), - } - - if launch then - local htmfile = lmx.show(template,variables) - if remove then - os.sleep(1) -- give time to launch - os.remove(htmfile) - end - else - lmx.make(template,variables) - end - -end - -scripts = scripts or { } -scripts.timings = scripts.timings or { } - -function scripts.timings.xhtml(filename) - if filename == "" then - report("provide filename") - elseif not plugins.progress.valid_file(filename) then - report("first run context again with the --timing option") - else - local basename = file.removesuffix(filename) - local launch = environment.argument("launch") - local remove = environment.argument("remove") - plugins.progress.make_lmx_page(basename,launch,remove) - end -end - -if environment.argument("xhtml") then - scripts.timings.xhtml(environment.files[1] or "") -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-timing'] = {
+ version = 1.002,
+ 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 format, gsub, concat = string.format, string.gsub, table.concat
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-timing</entry>
+ <entry name="detail">ConTeXt Timing Tools</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="xhtml"><short>make xhtml file</short></flag>
+ <flag name="launch"><short>launch after conversion</short></flag>
+ <flag name="remove"><short>remove after launching</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-timing",
+ banner = "ConTeXt Timing Tools 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+dofile(resolvers.findfile("node-snp.lua","tex"))
+dofile(resolvers.findfile("trac-tim.lua","tex"))
+dofile(resolvers.findfile("trac-lmx.lua","tex"))
+
+local meta = [[
+ beginfig(%s) ;
+ begingroup ;
+ save p, q, b, h, w ;
+ path p, q, b ; numeric h, w ;
+ linecap := butt ;
+ h := 100 ;
+ w := 800pt ;
+ p := %s ;
+ q := %s ;
+ p := p shifted -llcorner p ;
+ q := q shifted -llcorner q ;
+ q := q xstretched w ;
+ p := p xstretched w ;
+ b := boundingbox (llcorner p -- llcorner p shifted (w,h)) ;
+ draw b withcolor white withpen pencircle scaled 4pt ;
+ draw p withcolor red withpen pencircle scaled 4pt ;
+ draw q withcolor blue withpen pencircle scaled 2pt ;
+ endgroup ;
+ endfig ;
+]]
+
+local html_graphic = [[
+ <h1><a name='graphic-%s'>%s (red) %s (blue)</a></h1>
+ <table>
+ <tr>
+ <td>%s</td>
+ <td valign='top'>
+ min: %s<br/>
+ max: %s<br/>
+ pages: %s<br/>
+ average: %s<br/>
+ </td>
+ </tr>
+ </table>
+ <br/>
+]]
+
+local html_menu = [[
+ <a href='#graphic-%s'>%s</a>
+]]
+
+local directrun = true
+
+local what = { "parameters", "nodes" }
+
+plugins = plugins or { progress = { } } -- brrr, will become moduledata as well
+
+function plugins.progress.make_svg(filename,other)
+ local metadata, menudata, c = { }, { }, 0
+ metadata[#metadata+1] = 'outputformat := "svg" ;'
+ for i=1,#what do
+ local kind, mdk = what[i], { }
+ menudata[kind] = mdk
+ for n, name in next, plugins.progress[kind](filename) do
+ local first = plugins.progress.path(filename,name)
+ local second = plugins.progress.path(filename,other)
+ c = c + 1
+ metadata[#metadata+1] = format(meta,c,first,second)
+ mdk[#mdk+1] = { name, c }
+ end
+ end
+ metadata[#metadata+1] = "end ."
+ metadata = concat(metadata,"\n\n")
+ if directrun then
+ dofile(resolvers.findfile("mlib-run.lua","tex"))
+ commands = commands or { }
+ commands.writestatus = report
+ local result = metapost.directrun("metafun","timing data","svg",true,metadata)
+ return menudata, result
+ else
+ local mpname = file.replacesuffix(filename,"mp")
+ io.savedata(mpname,metadata)
+ os.execute(format("mpost --progname=context --mem=metafun.mem %s",mpname))
+ os.remove(mpname)
+ os.remove(file.removesuffix(filename).."-mpgraph.mpo") -- brr
+ os.remove(file.removesuffix(filename)..".log") -- brr
+ return menudata
+ end
+end
+
+function plugins.progress.makehtml(filename,other,menudata,metadata)
+ local graphics = { }
+ local result = { graphics = graphics }
+ for i=1,#what do
+ local kind, menu = what[i], { }
+ local md = menudata[kind]
+ result[kind] = menu
+ for k=1,#md do
+ local v = md[k]
+ local name, number = v[1], v[2]
+ local min = plugins.progress.bot(filename,name)
+ local max = plugins.progress.top(filename,name)
+ local pages = plugins.progress.pages(filename)
+ local average = math.round(max/pages)
+ if directrun then
+ local data = metadata[number]
+ menu[#menu+1] = format(html_menu,name,name)
+ graphics[#graphics+1] = format(html_graphic,name,name,other,data,min,max,pages,average)
+ else
+ local mpname = file.replacesuffix(filename,number)
+ local data = io.loaddata(mpname) or ""
+ -- data = gsub(data,"<!%-%-(.-)%-%->[\n\r]*","")
+ data = gsub(data,"<%?xml.->","")
+ menu[#menu+1] = format(html_menu,name,name)
+ graphics[#graphics+1] = format(html_graphic,name,name,other,data,min,max,pages,average)
+ os.remove(mpname)
+ end
+ end
+ end
+ return result
+end
+
+function plugins.progress.valid_file(name)
+ return name and name ~= "" and lfs.isfile(name .. "-luatex-progress.lut")
+end
+
+function plugins.progress.make_lmx_page(name,launch,remove)
+
+ local filename = name .. "-luatex-progress"
+ local other = "elapsed_time"
+ local template = 'context-timing.lmx'
+
+ plugins.progress.convert(filename)
+
+ local menudata, metadata = plugins.progress.make_svg(filename,other)
+ local htmldata = plugins.progress.makehtml(filename,other,menudata,metadata)
+
+ lmx.htmfile = function(name) return name .. "-timing.xhtml" end
+ lmx.lmxfile = function(name) return resolvers.findfile(name,'tex') end
+
+ local variables = {
+ ['title-default'] = 'ConTeXt Timing Information',
+ ['title'] = format('ConTeXt Timing Information: %s',file.basename(name)),
+ ['parametersmenu'] = concat(htmldata.parameters, " "),
+ ['nodesmenu'] = concat(htmldata.nodes, " "),
+ ['graphics'] = concat(htmldata.graphics, "\n\n"),
+ ['color-background-one'] = lmx.get('color-background-green'),
+ ['color-background-two'] = lmx.get('color-background-blue'),
+ }
+
+ if launch then
+ local htmfile = lmx.show(template,variables)
+ if remove then
+ os.sleep(1) -- give time to launch
+ os.remove(htmfile)
+ end
+ else
+ lmx.make(template,variables)
+ end
+
+end
+
+scripts = scripts or { }
+scripts.timings = scripts.timings or { }
+
+function scripts.timings.xhtml(filename)
+ if filename == "" then
+ report("provide filename")
+ elseif not plugins.progress.valid_file(filename) then
+ report("first run context again with the --timing option")
+ else
+ local basename = file.removesuffix(filename)
+ local launch = environment.argument("launch")
+ local remove = environment.argument("remove")
+ plugins.progress.make_lmx_page(basename,launch,remove)
+ end
+end
+
+if environment.argument("xhtml") then
+ scripts.timings.xhtml(environment.files[1] or "")
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-tools.lua b/scripts/context/lua/mtx-tools.lua index 19b7458a1..0ef194285 100644 --- a/scripts/context/lua/mtx-tools.lua +++ b/scripts/context/lua/mtx-tools.lua @@ -1,199 +1,199 @@ -if not modules then modules = { } end modules ['mtx-tools'] = { - version = 1.002, - 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, format, sub, rep, gsub, lower = string.find, string.format, string.sub, string.rep, string.gsub, string.lower - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-tools</entry> - <entry name="detail">Some File Related Goodies</entry> - <entry name="version">1.01</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="disarmutfbomb"><short>remove utf bomb if present</short></flag> - <flag name="force"><short>remove indeed</short></flag> - </subcategory> - <subcategory> - <flag name="dirtoxml"><short>glob directory into xml</short></flag> - <flag name="pattern"><short>glob pattern (default: *)</short></flag> - <flag name="url"><short>url attribute (no processing)</short></flag> - <flag name="root"><short>the root of the globbed path (default: .)</short></flag> - <flag name="output"><short>output filename (console by default)</short></flag> - <flag name="recurse"><short>recurse into subdirecories</short></flag> - <flag name="stripname"><short>take pathpart of given pattern</short></flag> - <flag name="longname"><short>set name attributes to full path name</short></flag> - </subcategory> - <subcategory> - <flag name="pattern"><short>glob pattern (default: *)</short></flag> - <flag name="recurse"><short>recurse into subdirecories</short></flag> - <flag name="force"><short>downcase indeed</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-tools", - banner = "Some File Related Goodies 1.01", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.tools = scripts.tools or { } - -local bomb_1, bomb_2 = "^\254\255", "^\239\187\191" - -function scripts.tools.disarmutfbomb() - local force, done = environment.argument("force"), false - local files = environment.files - for i=1,#files do - local name = files[i] - if lfs.isfile(name) then - local data = io.loaddata(name) - if not data then - -- just skip - elseif find(data,bomb_1) then - report("file '%s' has a 2 character utf bomb",name) - if force then - io.savedata(name,(gsub(data,bomb_1,""))) - end - done = true - elseif find(data,bomb_2) then - report("file '%s' has a 3 character utf bomb",name) - if force then - io.savedata(name,(gsub(data,bomb_2,""))) - end - done = true - else - -- report("file '%s' has no utf bomb",name) - end - end - end - if done and not force then - report("use --force to do a real disarming") - end -end - -function scripts.tools.downcase() - local pattern = environment.argument('pattern') or "*" - local recurse = environment.argument('recurse') - local force = environment.argument('force') - local n = 0 - if recurse and not find(pattern,"^%*%*%/") then - pattern = "**/*" .. pattern - end - dir.glob(pattern,function(name) - local basename = file.basename(name) - if lower(basename) ~= basename then - n = n + 1 - if force then - os.rename(name,lower(name)) - end - end - end) - if n > 0 then - if force then - report("%s files renamed",n) - else - report("use --force to do a real rename (%s files involved)",n) - end - else - report("nothing to do") - end -end - - -function scripts.tools.dirtoxml() - - local join, removesuffix, suffixonly, date = file.join, file.removesuffix, file.suffixonly, os.date - - local xmlns = "http://www.pragma-ade.com/rlg/xmldir.rng" - local timestamp = "%Y-%m-%d %H:%M" - - local pattern = environment.argument('pattern') or ".*" - local url = environment.argument('url') or "no-url" - local root = environment.argument('root') or "." - local outputfile = environment.argument('output') - - local recurse = environment.argument('recurse') or false - local stripname = environment.argument('stripname') - local longname = environment.argument('longname') - - local function flush(list,result,n,path) - n, result = n or 1, result or { } - local d = rep(" ",n) - for name, attr in table.sortedhash(list) do - local mode = attr.mode - if mode == "file" then - result[#result+1] = format("%s<file name='%s'>",d,(longname and path and join(path,name)) or name) - result[#result+1] = format("%s <base>%s</base>",d,removesuffix(name)) - result[#result+1] = format("%s <type>%s</type>",d,suffixonly(name)) - result[#result+1] = format("%s <size>%s</size>",d,attr.size) - result[#result+1] = format("%s <permissions>%s</permissions>",d,sub(attr.permissions,7,9)) - result[#result+1] = format("%s <date>%s</date>",d,date(timestamp,attr.modification)) - result[#result+1] = format("%s</file>",d) - elseif mode == "directory" then - result[#result+1] = format("%s<directory name='%s'>",d,name) - flush(attr.list,result,n+1,(path and join(path,name)) or name) - result[#result+1] = format("%s</directory>",d) - end - end - end - - if not pattern or pattern == "" then - report('provide --pattern=') - return - end - - if stripname then - pattern = file.dirname(pattern) - end - - local luapattern = string.topattern(pattern,true) - - lfs.chdir(root) - - local list = dir.collectpattern(root,luapattern,recurse) - - if list[outputfile] then - list[outputfile] = nil - end - - local result = { "<?xml version='1.0'?>" } - result[#result+1] = format("<files url=%q root=%q pattern=%q luapattern=%q xmlns='%s' timestamp='%s'>",url,root,pattern,luapattern,xmlns,date(timestamp)) - flush(list,result) - result[#result+1] = "</files>" - - result = table.concat(result,"\n") - - if not outputfile or outputfile == "" then - texio.write_nl(result) - else - io.savedata(outputfile,result) - end - -end - -if environment.argument("disarmutfbomb") then - scripts.tools.disarmutfbomb() -elseif environment.argument("dirtoxml") then - scripts.tools.dirtoxml() -elseif environment.argument("downcase") then - scripts.tools.downcase() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-tools'] = {
+ version = 1.002,
+ 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, format, sub, rep, gsub, lower = string.find, string.format, string.sub, string.rep, string.gsub, string.lower
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-tools</entry>
+ <entry name="detail">Some File Related Goodies</entry>
+ <entry name="version">1.01</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="disarmutfbomb"><short>remove utf bomb if present</short></flag>
+ <flag name="force"><short>remove indeed</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="dirtoxml"><short>glob directory into xml</short></flag>
+ <flag name="pattern"><short>glob pattern (default: *)</short></flag>
+ <flag name="url"><short>url attribute (no processing)</short></flag>
+ <flag name="root"><short>the root of the globbed path (default: .)</short></flag>
+ <flag name="output"><short>output filename (console by default)</short></flag>
+ <flag name="recurse"><short>recurse into subdirecories</short></flag>
+ <flag name="stripname"><short>take pathpart of given pattern</short></flag>
+ <flag name="longname"><short>set name attributes to full path name</short></flag>
+ </subcategory>
+ <subcategory>
+ <flag name="pattern"><short>glob pattern (default: *)</short></flag>
+ <flag name="recurse"><short>recurse into subdirecories</short></flag>
+ <flag name="force"><short>downcase indeed</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-tools",
+ banner = "Some File Related Goodies 1.01",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.tools = scripts.tools or { }
+
+local bomb_1, bomb_2 = "^\254\255", "^\239\187\191"
+
+function scripts.tools.disarmutfbomb()
+ local force, done = environment.argument("force"), false
+ local files = environment.files
+ for i=1,#files do
+ local name = files[i]
+ if lfs.isfile(name) then
+ local data = io.loaddata(name)
+ if not data then
+ -- just skip
+ elseif find(data,bomb_1) then
+ report("file '%s' has a 2 character utf bomb",name)
+ if force then
+ io.savedata(name,(gsub(data,bomb_1,"")))
+ end
+ done = true
+ elseif find(data,bomb_2) then
+ report("file '%s' has a 3 character utf bomb",name)
+ if force then
+ io.savedata(name,(gsub(data,bomb_2,"")))
+ end
+ done = true
+ else
+ -- report("file '%s' has no utf bomb",name)
+ end
+ end
+ end
+ if done and not force then
+ report("use --force to do a real disarming")
+ end
+end
+
+function scripts.tools.downcase()
+ local pattern = environment.argument('pattern') or "*"
+ local recurse = environment.argument('recurse')
+ local force = environment.argument('force')
+ local n = 0
+ if recurse and not find(pattern,"^%*%*%/") then
+ pattern = "**/*" .. pattern
+ end
+ dir.glob(pattern,function(name)
+ local basename = file.basename(name)
+ if lower(basename) ~= basename then
+ n = n + 1
+ if force then
+ os.rename(name,lower(name))
+ end
+ end
+ end)
+ if n > 0 then
+ if force then
+ report("%s files renamed",n)
+ else
+ report("use --force to do a real rename (%s files involved)",n)
+ end
+ else
+ report("nothing to do")
+ end
+end
+
+
+function scripts.tools.dirtoxml()
+
+ local join, removesuffix, suffixonly, date = file.join, file.removesuffix, file.suffixonly, os.date
+
+ local xmlns = "http://www.pragma-ade.com/rlg/xmldir.rng"
+ local timestamp = "%Y-%m-%d %H:%M"
+
+ local pattern = environment.argument('pattern') or ".*"
+ local url = environment.argument('url') or "no-url"
+ local root = environment.argument('root') or "."
+ local outputfile = environment.argument('output')
+
+ local recurse = environment.argument('recurse') or false
+ local stripname = environment.argument('stripname')
+ local longname = environment.argument('longname')
+
+ local function flush(list,result,n,path)
+ n, result = n or 1, result or { }
+ local d = rep(" ",n)
+ for name, attr in table.sortedhash(list) do
+ local mode = attr.mode
+ if mode == "file" then
+ result[#result+1] = format("%s<file name='%s'>",d,(longname and path and join(path,name)) or name)
+ result[#result+1] = format("%s <base>%s</base>",d,removesuffix(name))
+ result[#result+1] = format("%s <type>%s</type>",d,suffixonly(name))
+ result[#result+1] = format("%s <size>%s</size>",d,attr.size)
+ result[#result+1] = format("%s <permissions>%s</permissions>",d,sub(attr.permissions,7,9))
+ result[#result+1] = format("%s <date>%s</date>",d,date(timestamp,attr.modification))
+ result[#result+1] = format("%s</file>",d)
+ elseif mode == "directory" then
+ result[#result+1] = format("%s<directory name='%s'>",d,name)
+ flush(attr.list,result,n+1,(path and join(path,name)) or name)
+ result[#result+1] = format("%s</directory>",d)
+ end
+ end
+ end
+
+ if not pattern or pattern == "" then
+ report('provide --pattern=')
+ return
+ end
+
+ if stripname then
+ pattern = file.dirname(pattern)
+ end
+
+ local luapattern = string.topattern(pattern,true)
+
+ lfs.chdir(root)
+
+ local list = dir.collectpattern(root,luapattern,recurse)
+
+ if list[outputfile] then
+ list[outputfile] = nil
+ end
+
+ local result = { "<?xml version='1.0'?>" }
+ result[#result+1] = format("<files url=%q root=%q pattern=%q luapattern=%q xmlns='%s' timestamp='%s'>",url,root,pattern,luapattern,xmlns,date(timestamp))
+ flush(list,result)
+ result[#result+1] = "</files>"
+
+ result = table.concat(result,"\n")
+
+ if not outputfile or outputfile == "" then
+ texio.write_nl(result)
+ else
+ io.savedata(outputfile,result)
+ end
+
+end
+
+if environment.argument("disarmutfbomb") then
+ scripts.tools.disarmutfbomb()
+elseif environment.argument("dirtoxml") then
+ scripts.tools.dirtoxml()
+elseif environment.argument("downcase") then
+ scripts.tools.downcase()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-unzip.lua b/scripts/context/lua/mtx-unzip.lua index 02d9676bc..6514d709a 100644 --- a/scripts/context/lua/mtx-unzip.lua +++ b/scripts/context/lua/mtx-unzip.lua @@ -1,132 +1,132 @@ -if not modules then modules = { } end modules ['mtx-unzip'] = { - 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" -} - --- maybe --pattern - -local format = string.format - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-unzip</entry> - <entry name="detail">Simple Unzipper</entry> - <entry name="version">0.10</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="list"><short>list files in archive</short></flag> - <flag name="junk"><short>flatten unzipped directory structure</short></flag> - <flag name="extract"><short>extract files</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-unzip", - banner = "Simple Unzipper 0.10", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.unzipper = scripts.unzipper or { } - -function scripts.unzipper.opened() - local filename = environment.files[1] - if filename and filename ~= "" then - filename = file.addsuffix(filename,'zip') - local zipfile = zip.open(filename) - if zipfile then - return zipfile - end - end - report("no zip file: %s",filename) - return false -end - -function scripts.unzipper.list() - local zipfile = scripts.unzipper.opened() - if zipfile then - local n = 0 - for k in zipfile:files() do - if #k.filename > n then n = #k.filename end - end - local files, paths, compressed, uncompressed = 0, 0, 0, 0 - local template_a = "%-"..n.."s" - local template_b = "%-"..n.."s % 9i % 9i" - local template_c = "\n%-"..n.."s % 9i % 9i" - for k in zipfile:files() do - if k.filename:find("/$") then - paths = paths + 1 - print(format(template_a, k.filename)) - else - files = files + 1 - local cs, us = k.compressed_size, k.uncompressed_size - if cs > compressed then - compressed = cs - end - if us > uncompressed then - uncompressed = us - end - print(format(template_b,k.filename,cs,us)) - end - end -- check following pattern, n is not enough - print(format(template_c,files .. " files, " .. paths .. " directories",compressed,uncompressed)) - end -end - -function zip.loaddata(zipfile,filename) - local f = zipfile:open(filename) - if f then - local data = f:read("*a") - f:close() - return data - end - return nil -end - -function scripts.unzipper.extract() - local zipfile = scripts.unzipper.opened() - if zipfile then - local junk = environment.arguments["j"] or environment.arguments["junk"] - for k in zipfile:files() do - local filename = k.filename - if filename:find("/$") then - if not junk then - lfs.mkdir(filename) - end - else - local data = zip.loaddata(zipfile,filename) - if data then - if junk then - filename = file.basename(filename) - end - io.savedata(filename,data) - print(filename) - end - end - end - end -end - -if environment.arguments["h"] or environment.arguments["help"] then - application.help() -elseif environment.arguments["l"] or environment.arguments["list"] then - scripts.unzipper.list(zipfile) -elseif environment.arguments["exporthelp"] then - application.export(environment.arguments["exporthelp"],environment.files[1]) -elseif environment.files[1] then -- implicit --extract - scripts.unzipper.extract(zipfile) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-unzip'] = {
+ 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"
+}
+
+-- maybe --pattern
+
+local format = string.format
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-unzip</entry>
+ <entry name="detail">Simple Unzipper</entry>
+ <entry name="version">0.10</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="list"><short>list files in archive</short></flag>
+ <flag name="junk"><short>flatten unzipped directory structure</short></flag>
+ <flag name="extract"><short>extract files</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-unzip",
+ banner = "Simple Unzipper 0.10",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.unzipper = scripts.unzipper or { }
+
+function scripts.unzipper.opened()
+ local filename = environment.files[1]
+ if filename and filename ~= "" then
+ filename = file.addsuffix(filename,'zip')
+ local zipfile = zip.open(filename)
+ if zipfile then
+ return zipfile
+ end
+ end
+ report("no zip file: %s",filename)
+ return false
+end
+
+function scripts.unzipper.list()
+ local zipfile = scripts.unzipper.opened()
+ if zipfile then
+ local n = 0
+ for k in zipfile:files() do
+ if #k.filename > n then n = #k.filename end
+ end
+ local files, paths, compressed, uncompressed = 0, 0, 0, 0
+ local template_a = "%-"..n.."s"
+ local template_b = "%-"..n.."s % 9i % 9i"
+ local template_c = "\n%-"..n.."s % 9i % 9i"
+ for k in zipfile:files() do
+ if k.filename:find("/$") then
+ paths = paths + 1
+ print(format(template_a, k.filename))
+ else
+ files = files + 1
+ local cs, us = k.compressed_size, k.uncompressed_size
+ if cs > compressed then
+ compressed = cs
+ end
+ if us > uncompressed then
+ uncompressed = us
+ end
+ print(format(template_b,k.filename,cs,us))
+ end
+ end -- check following pattern, n is not enough
+ print(format(template_c,files .. " files, " .. paths .. " directories",compressed,uncompressed))
+ end
+end
+
+function zip.loaddata(zipfile,filename)
+ local f = zipfile:open(filename)
+ if f then
+ local data = f:read("*a")
+ f:close()
+ return data
+ end
+ return nil
+end
+
+function scripts.unzipper.extract()
+ local zipfile = scripts.unzipper.opened()
+ if zipfile then
+ local junk = environment.arguments["j"] or environment.arguments["junk"]
+ for k in zipfile:files() do
+ local filename = k.filename
+ if filename:find("/$") then
+ if not junk then
+ lfs.mkdir(filename)
+ end
+ else
+ local data = zip.loaddata(zipfile,filename)
+ if data then
+ if junk then
+ filename = file.basename(filename)
+ end
+ io.savedata(filename,data)
+ print(filename)
+ end
+ end
+ end
+ end
+end
+
+if environment.arguments["h"] or environment.arguments["help"] then
+ application.help()
+elseif environment.arguments["l"] or environment.arguments["list"] then
+ scripts.unzipper.list(zipfile)
+elseif environment.arguments["exporthelp"] then
+ application.export(environment.arguments["exporthelp"],environment.files[1])
+elseif environment.files[1] then -- implicit --extract
+ scripts.unzipper.extract(zipfile)
+else
+ application.help()
+end
diff --git a/scripts/context/lua/mtx-update.lua b/scripts/context/lua/mtx-update.lua index 64203d3e3..5141bdf7a 100644 --- a/scripts/context/lua/mtx-update.lua +++ b/scripts/context/lua/mtx-update.lua @@ -1,676 +1,676 @@ -if not modules then modules = { } end modules ['mtx-update'] = { - version = 1.002, - 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 script is dedicated to Mojca Miklavec, who is the driving force behind --- moving minimal generation from our internal machines to the context garden. --- Together with Arthur Reutenauer she made sure that it worked well on all --- platforms that matter. - -local helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-update</entry> - <entry name="detail">ConTeXt Minimals Updater</entry> - <entry name="version">0.31</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="platform" value="string"><short>platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)</short></flag> - <flag name="server" value="string"><short>repository url (rsync://contextgarden.net)</short></flag> - <flag name="module" value="string"><short>repository url (minimals)</short></flag> - <flag name="repository" value="string"><short>specify version (current, experimental)</short></flag> - <flag name="context" value="string"><short>specify version (current, latest, beta, yyyy.mm.dd)</short></flag> - <flag name="rsync" value="string"><short>rsync binary (rsync)</short></flag> - <flag name="texroot" value="string"><short>installation directory (not guessed for the moment)</short></flag> - <flag name="engine" value="string"><short>tex engine (luatex, pdftex, xetex)</short></flag> - <flag name="modules" value="string"><short>extra modules (can be list or 'all')</short></flag> - <flag name="fonts" value="string"><short>additional fonts (can be list or 'all')</short></flag> - <flag name="goodies" value="string"><short>extra binaries (like scite and texworks)</short></flag> - <flag name="force"><short>instead of a dryrun, do the real thing</short></flag> - <flag name="update"><short>update minimal tree</short></flag> - <flag name="make"><short>also make formats and generate file databases</short></flag> - <flag name="keep"><short>don't delete unused or obsolete files</short></flag> - <flag name="state"><short>update tree using saved state</short></flag> - <flag name="cygwin"><short>adapt drive specs to cygwin</short></flag> - <flag name="mingw"><short>assume mingw binaries being used</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-update", - banner = "ConTeXt Minimals Updater 0.31", - helpinfo = helpinfo, -} - -local report = application.report - -local format, concat, gmatch, gsub, find = string.format, table.concat, string.gmatch, string.gsub, string.find - -scripts = scripts or { } -scripts.update = scripts.update or { } - -minimals = minimals or { } -minimals.config = minimals.config or { } - --- this is needed under windows --- else rsync fails to set the right chmod flags to files - -os.setenv("CYGWIN","nontsec") - -scripts.update.texformats = { - "cont-en", - "cont-nl", - "cont-cz", - "cont-de", - "cont-fa", - "cont-it", - "cont-ro", - "cont-uk", - "cont-pe", - -- "cont-xp", - "mptopdf", - "plain" -} - -scripts.update.mpformats = { - -- "metafun", - -- "mpost", -} - --- experimental is not functional at the moment - -scripts.update.repositories = { - "current", - "experimental" -} - --- more options than just these two are available (no idea why this is here) - -scripts.update.versions = { - "current", - "latest" -} - --- list of basic folders that are needed to make a functional distribution - -scripts.update.base = { - { "base/tex/", "texmf" }, - { "base/metapost/", "texmf" }, - { "fonts/common/", "texmf" }, - { "fonts/other/", "texmf" }, -- not *really* needed, but helpful - { "context/<version>/", "texmf-context" }, - { "misc/setuptex/", "." }, - { "misc/web2c", "texmf" }, - { "bin/common/<platform>/", "texmf-<platform>" }, - { "bin/context/<platform>/", "texmf-<platform>" }, - { "bin/metapost/<platform>/", "texmf-<platform>" }, - { "bin/man/", "texmf-<platform>" }, -} - --- binaries and font-related files --- for pdftex we don't need OpenType fonts, for LuaTeX/XeTeX we don't need TFM files - -scripts.update.engines = { - ["luatex"] = { - { "fonts/new/", "texmf" }, - { "bin/luatex/<platform>/", "texmf-<platform>" }, - { "bin/luajittex/<platform>/","texmf-<platform>" }, - }, - ["xetex"] = { - { "base/xetex/", "texmf" }, - { "fonts/new/", "texmf" }, - { "bin/luatex/<platform>/", "texmf-<platform>" }, -- tools - { "bin/xetex/<platform>/", "texmf-<platform>" }, - }, - ["pdftex"] = { - { "fonts/old/", "texmf" }, - { "bin/luatex/<platform>/", "texmf-<platform>" }, -- tools - { "bin/pdftex/<platform>/", "texmf-<platform>" }, - }, - ["all"] = { - { "fonts/new/", "texmf" }, - { "fonts/old/", "texmf" }, - { "base/xetex/", "texmf" }, - { "bin/luatex/<platform>/", "texmf-<platform>" }, - { "bin/luajittex/<platform>/","texmf-<platform>" }, - { "bin/xetex/<platform>/", "texmf-<platform>" }, - { "bin/pdftex/<platform>/", "texmf-<platform>" }, - }, -} - -scripts.update.goodies = { - ["scite"] = { - { "bin/<platform>/scite/", "texmf-<platform>" }, - }, - ["texworks"] = { - { "bin/<platform>/texworks/", "texmf-<platform>" }, - }, -} - -scripts.update.platforms = { - ["mswin"] = "mswin", - ["windows"] = "mswin", - ["win32"] = "mswin", - ["win"] = "mswin", - ["linux"] = "linux", - ["freebsd"] = "freebsd", - ["freebsd-amd64"] = "freebsd-amd64", - ["kfreebsd"] = "kfreebsd-i386", - ["kfreebsd-i386"] = "kfreebsd-i386", - ["kfreebsd-amd64"] = "kfreebsd-amd64", - ["linux-32"] = "linux", - ["linux-64"] = "linux-64", - ["linux32"] = "linux", - ["linux64"] = "linux-64", - ["linux-ppc"] = "linux-ppc", - ["ppc"] = "linux-ppc", - ["osx"] = "osx-intel", - ["macosx"] = "osx-intel", - ["osx-intel"] = "osx-intel", - ["osx-ppc"] = "osx-ppc", - ["osx-powerpc"] = "osx-ppc", - ["osx-64"] = "osx-64", - ["osxintel"] = "osx-intel", - ["osxppc"] = "osx-ppc", - ["osxpowerpc"] = "osx-ppc", - ["solaris-intel"] = "solaris-intel", - ["solaris-sparc"] = "solaris-sparc", - ["solaris"] = "solaris-sparc", -} - -scripts.update.selfscripts = { - "mtxrun", - -- "luatools", -} - --- the list is filled up later (when we know what modules to download) - -scripts.update.modules = { -} - -scripts.update.fonts = { -} - -function scripts.update.run(str) - -- important, otherwise formats fly to a weird place - -- (texlua sets luatex as the engine, we need to reset that or to fix texexec :) - os.setenv("engine",nil) - if environment.argument("force") then - report("run, %s",str) - os.execute(str) - else - report("dry run, %s",str) - end -end - -function scripts.update.fullpath(path) - if file.is_rootbased_path(path) then - return path - else - return lfs.currentdir() .. "/" .. path - end -end - -local rsync_variant = "cygwin" -- will be come mingw - -local function drive(d) - if rsync_variant == "cygwin" then - d = gsub(d,[[([a-zA-Z]):/]], "/cygdrive/%1/") - else - d = gsub(d,[[([a-zA-Z]):/]], "/%1/") - end - return d -end - -function scripts.update.synchronize() - - report("update, start") - - local texroot = scripts.update.fullpath(states.get("paths.root")) - local engines = states.get('engines') or { } - local platforms = states.get('platforms') or { } - local repositories = states.get('repositories') -- minimals - local bin = states.get("rsync.program") -- rsync - local url = states.get("rsync.server") -- contextgarden.net - local version = states.get("context.version") -- current (or beta) - local modules = states.get("modules") -- modules (third party) - local fonts = states.get("fonts") -- fonts (experimental or special) - local goodies = states.get("goodies") -- goodies (like editors) - local force = environment.argument("force") - - bin = gsub(bin,"\\","/") - - if not url:find("::$") then url = url .. "::" end - local ok = lfs.attributes(texroot,"mode") == "directory" - if not ok and force then - dir.mkdirs(texroot) - ok = lfs.attributes(texroot,"mode") == "directory" - end - - if force then - dir.mkdirs(format("%s/%s", texroot, "texmf-cache")) - dir.mkdirs(format("%s/%s", texroot, "texmf-local")) - dir.mkdirs(format("%s/%s", texroot, "texmf-project")) - dir.mkdirs(format("%s/%s", texroot, "texmf-fonts")) - dir.mkdirs(format("%s/%s", texroot, "texmf-modules")) - end - - if ok or not force then - - local fetched, individual, osplatform = { }, { }, os.platform - - -- takes a collection as argument and returns a list of folders - - local function collection_to_list_of_folders(collection, platform) - local archives = {} - for i=1,#collection do - local archive = collection[i][1] - archive = gsub(archive,"<platform>",platform) - archive = gsub(archive,"<version>",version) - archives[#archives+1] = archive - end - return archives - end - - -- takes a list of folders as argument and returns a string for rsync - -- sample input: - -- {'bin/common', 'bin/context'} - -- output: - -- 'minimals/current/bin/common minimals/current/bin/context' - - local function list_of_folders_to_rsync_string(list_of_folders) - local repository = 'current' - local prefix = format("%s/%s/", states.get('rsync.module'), repository) -- minimals/current/ - - return prefix .. concat(list_of_folders, format(" %s", prefix)) - end - - -- example of usage: print(list_of_folders_to_rsync_string(collection_to_list_of_folders(scripts.update.base, os.platform))) - - -- rename function and add some more functionality: - -- * recursive/non-recursive (default: non-recursive) - -- * filter folders or regular files only (default: no filter) - -- * grep for size of included files (with --stats switch) - - local function get_list_of_files_from_rsync(list_of_folders) - -- temporary file to store the output of rsync (could be a more random name; watch for overwrites) - local temp_file = "rsync.tmp.txt" - -- a set of folders - local folders = {} - local command = format("%s %s'%s' > %s", bin, url, list_of_folders_to_rsync_string(list_of_folders), temp_file) - os.execute(command) - -- read output of rsync - local data = io.loaddata(temp_file) or "" - -- for every line extract the filename - for chmod, s in data:gmatch("([d%-][rwx%-]+).-(%S+)[\n\r]") do - -- skip "current" folder - if s ~= '.' and chmod:len() == 10 then - folders[#folders+1] = s - end - end - -- delete the file to which we have put output of rsync - os.remove(temp_file) - return folders - end - - -- rsync://contextgarden.net/minimals/current/modules/ - - if modules and type(modules) == "table" then - -- fetch the list of available modules from rsync server - local available_modules = get_list_of_files_from_rsync({"modules/"}) - -- hash of requested modules - -- local h = table.tohash(modules:split(",")) - local asked = table.copy(modules) - asked.all = nil - for i=1,#available_modules do - local s = available_modules[i] - if modules.all or modules[s] then - scripts.update.modules[#scripts.update.modules+1] = { format("modules/%s/",s), "texmf-modules" } - end - asked[s] = nil - end - if next(asked) then - report("skipping unknown modules: %s",table.concat(table.sortedkeys(asked),", ")) - end - end - - -- rsync://contextgarden.net/minimals/current/fonts/extra/ - - if fonts and type(fonts) == "table" then - local available_fonts = get_list_of_files_from_rsync({"fonts/extra/"}) - local asked = table.copy(fonts) - asked.all = nil - for i=1,#available_fonts do - local s = available_fonts[i] - if fonts.all or fonts[s] then - scripts.update.fonts[#scripts.update.fonts+1] = { format("fonts/extra/%s/",s), "texmf" } - end - asked[s] = nil - end - if next(asked) then - report("skipping unknown fonts: %s",table.concat(table.sortedkeys(asked),", ")) - end - end - - local function add_collection(collection,platform) - if collection and platform then - platform = scripts.update.platforms[platform] - if platform then - for i=1,#collection do - local c = collection[i] - local archive = gsub(c[1],"<platform>",platform) - local destination = format("%s/%s", texroot, gsub(c[2],"<platform>", platform)) - destination = gsub(destination,"\\","/") - archive = gsub(archive,"<version>",version) - if osplatform == "windows" or osplatform == "mswin" then - destination = drive(destination) - end - individual[#individual+1] = { archive, destination } - end - end - end - end - - for platform, _ in next, platforms do - add_collection(scripts.update.base,platform) - end - for platform, _ in next, platforms do - add_collection(scripts.update.modules,platform) - end - for platform, _ in next, platforms do - add_collection(scripts.update.fonts,platform) - end - for engine, _ in next, engines do - for platform, _ in next, platforms do - add_collection(scripts.update.engines[engine],platform) - end - end - - if goodies and type(goodies) == "table" then - for goodie, _ in next, goodies do - for platform, _ in next, platforms do - add_collection(scripts.update.goodies[goodie],platform) - end - end - end - - local combined = { } - local update_repositories = scripts.update.repositories - for i=1,#update_repositories do - local repository = update_repositories[i] - if repositories[repository] then - for _, v in next, individual do - local archive, destination = v[1], v[2] - local cd = combined[destination] - if not cd then - cd = { } - combined[destination] = cd - end - cd[#cd+1] = format("%s/%s/%s",states.get('rsync.module'),repository,archive) - end - end - end - for destination, archive in next, combined do - local archives, command = concat(archive," "), "" - local normalflags, deleteflags = states.get("rsync.flags.normal"), "" - if os.name == "windows" then - normalflags = normalflags .. " -L" -- no symlinks - end - local dryrunflags = "" - if not environment.argument("force") then - dryrunflags = "--dry-run" - end - if (destination:find("texmf$") or destination:find("texmf%-context$") or destination:find("texmf%-modules$")) and (not environment.argument("keep")) then - deleteflags = states.get("rsync.flags.delete") - end - command = format("%s %s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, dryrunflags, url, archives, destination) - -- report("running command: %s",command) - if not fetched[command] then - scripts.update.run(command,true) - fetched[command] = command - end - end - - local function update_script(script, platform) - local bin = gsub(bin,"\\","/") - local texroot = gsub(texroot,"\\","/") - platform = scripts.update.platforms[platform] - if platform then - local command - if platform == 'mswin' then - bin = drive(bin) - texroot = drive(texroot) - command = format([[%s -t "%s/texmf-context/scripts/context/lua/%s.lua" "%s/texmf-mswin/bin/"]], bin, texroot, script, texroot) - else - command = format([[%s -tgo --chmod=a+x '%s/texmf-context/scripts/context/lua/%s.lua' '%s/texmf-%s/bin/%s']], bin, texroot, script, texroot, platform, script) - end - report("updating %s for %s: %s", script, platform, command) - scripts.update.run(command) - end - end - - for platform, _ in next, platforms do - for i=1, #scripts.update.selfscripts do - update_script(scripts.update.selfscripts[i],platform) - end - end - - else - report("no valid texroot: %s",texroot) - end - if not force then - report("use --force to really update files") - end - - resolvers.load_tree(texroot) -- else we operate in the wrong tree - - -- update filename database for pdftex/xetex - scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot)) - -- update filename database for luatex - scripts.update.run(format('mtxrun --tree="%s" --generate',texroot)) - - report("update, done") -end - -function table.fromhash(t) - local h = { } - for k, v in next, t do -- not indexed - if v then h[#h+1] = k end - end - return h -end - --- make the ConTeXt formats -function scripts.update.make() - - report("make, start") - - local force = environment.argument("force") - local texroot = scripts.update.fullpath(states.get("paths.root")) - local engines = states.get('engines') - local goodies = states.get('goodies') - local platforms = states.get('platforms') - local formats = states.get('formats') - - resolvers.load_tree(texroot) - - scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot)) - scripts.update.run(format('mtxrun --tree="%s" --generate',texroot)) - - local askedformats = formats - local texformats = table.tohash(scripts.update.texformats) - local mpformats = table.tohash(scripts.update.mpformats) - for k,v in next, texformats do - if not askedformats[k] then - texformats[k] = nil - end - end - for k,v in next, mpformats do - if not askedformats[k] then - mpformats[k] = nil - end - end - local formatlist = concat(table.fromhash(texformats), " ") - if formatlist ~= "" then - for engine in next, engines do - if engine == "luatex" then - scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make',texroot)) - elseif engine == "luajittex" then - scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make --engine=luajittex',texroot)) - else - scripts.update.run(format('mtxrun --tree="%s" --script texexec --make --all --%s %s',texroot,engine,formatlist)) - end - end - end - local formatlist = concat(table.fromhash(mpformats), " ") - if formatlist ~= "" then - scripts.update.run(format('mtxrun --tree="%s" --script texexec --make --all %s',texroot,formatlist)) - end - if not force then - report("make, use --force to really make formats") - end - - scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot)) -- needed for mpost - scripts.update.run(format('mtxrun --tree="%s" --generate',texroot)) - - report("make, done") -end - -scripts.savestate = true - -if scripts.savestate then - - states.load("status-of-update.lua") - - -- tag, value, default, persistent - - statistics.starttiming(states) - - states.set("info.version",0.1) -- ok - states.set("info.count",(states.get("info.count") or 0) + 1,1,false) -- ok - states.set("info.comment","this file contains the settings of the last 'mtxrun --script update' run",false) -- ok - states.set("info.date",os.date("!%Y-%m-%d %H:%M:%S")) -- ok - - states.set("rsync.program", environment.argument("rsync"), "rsync", true) -- ok - states.set("rsync.server", environment.argument("server"), "contextgarden.net::", true) -- ok - states.set("rsync.module", environment.argument("module"), "minimals", true) -- ok - states.set("rsync.flags.normal", environment.argument("flags"), "-rpztlv", true) -- ok - states.set("rsync.flags.delete", nil, "--delete", true) -- ok - - states.set("paths.root", environment.argument("texroot"), "tex", true) -- ok - - states.set("context.version", environment.argument("context"), "current", true) -- ok - - local valid = table.tohash(scripts.update.repositories) - for r in gmatch(environment.argument("repository") or "current","([^, ]+)") do - if valid[r] then states.set("repositories." .. r, true) end - end - - local valid = scripts.update.engines - local engine = environment.argument("engine") or "" - if engine == "" then - local e = states.get("engines") - if not e or not next(e) then - engine = "all" - end - end - if engine ~= "" then - for r in gmatch(engine,"([^, ]+)") do - if r == "all" then - for k, v in next, valid do - if k ~= "all" then - states.set("engines." .. k, true) - end - end - break - elseif valid[r] then - states.set("engines." .. r, true) - end - end - end - - local valid = scripts.update.platforms - for r in gmatch(environment.argument("platform") or os.platform,"([^, ]+)") do - if valid[r] then states.set("platforms." .. r, true) end - end - - local valid = table.tohash(scripts.update.texformats) - for r in gmatch(environment.argument("formats") or "","([^, ]+)") do - if valid[r] then states.set("formats." .. r, true) end - end - local valid = table.tohash(scripts.update.mpformats) - for r in gmatch(environment.argument("formats") or "","([^, ]+)") do - if valid[r] then states.set("formats." .. r, true) end - end - - states.set("formats.cont-en", true) - states.set("formats.cont-nl", true) - states.set("formats.metafun", true) - - for r in gmatch(environment.argument("extras") or "","([^, ]+)") do -- for old times sake - if r ~= "all" and not find(r,"^[a-z]%-") then - r = "t-" .. r - end - states.set("modules." .. r, true) - end - for r in gmatch(environment.argument("modules") or "","([^, ]+)") do - if r ~= "all" and not find(r,"^[a-z]%-") then - r = "t-" .. r - end - states.set("modules." .. r, true) - end - for r in gmatch(environment.argument("fonts") or "","([^, ]+)") do - states.set("fonts." .. r, true) - end - for r in gmatch(environment.argument("goodies") or "","([^, ]+)") do - states.set("goodies." .. r, true) - end - - report("state, loaded") - report() - -end - -if environment.argument("state") then - environment.setargument("update",true) - environment.setargument("force",true) - environment.setargument("make",true) -end - -if environment.argument("mingw") then - rsync_variant = "mingw" -elseif environment.argument("cygwin") then - rsync_variant = "cygwin" -end - -if environment.argument("update") then - scripts.update.synchronize() - if environment.argument("make") then - scripts.update.make() - end -elseif environment.argument("make") then - scripts.update.make() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end - -if scripts.savestate then - statistics.stoptiming(states) - states.set("info.runtime",tonumber(statistics.elapsedtime(states))) - if environment.argument("force") then - states.save() - report("state","saved") - end -end +if not modules then modules = { } end modules ['mtx-update'] = {
+ version = 1.002,
+ 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 script is dedicated to Mojca Miklavec, who is the driving force behind
+-- moving minimal generation from our internal machines to the context garden.
+-- Together with Arthur Reutenauer she made sure that it worked well on all
+-- platforms that matter.
+
+local helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-update</entry>
+ <entry name="detail">ConTeXt Minimals Updater</entry>
+ <entry name="version">0.31</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="platform" value="string"><short>platform (windows, linux, linux-64, osx-intel, osx-ppc, linux-ppc)</short></flag>
+ <flag name="server" value="string"><short>repository url (rsync://contextgarden.net)</short></flag>
+ <flag name="module" value="string"><short>repository url (minimals)</short></flag>
+ <flag name="repository" value="string"><short>specify version (current, experimental)</short></flag>
+ <flag name="context" value="string"><short>specify version (current, latest, beta, yyyy.mm.dd)</short></flag>
+ <flag name="rsync" value="string"><short>rsync binary (rsync)</short></flag>
+ <flag name="texroot" value="string"><short>installation directory (not guessed for the moment)</short></flag>
+ <flag name="engine" value="string"><short>tex engine (luatex, pdftex, xetex)</short></flag>
+ <flag name="modules" value="string"><short>extra modules (can be list or 'all')</short></flag>
+ <flag name="fonts" value="string"><short>additional fonts (can be list or 'all')</short></flag>
+ <flag name="goodies" value="string"><short>extra binaries (like scite and texworks)</short></flag>
+ <flag name="force"><short>instead of a dryrun, do the real thing</short></flag>
+ <flag name="update"><short>update minimal tree</short></flag>
+ <flag name="make"><short>also make formats and generate file databases</short></flag>
+ <flag name="keep"><short>don't delete unused or obsolete files</short></flag>
+ <flag name="state"><short>update tree using saved state</short></flag>
+ <flag name="cygwin"><short>adapt drive specs to cygwin</short></flag>
+ <flag name="mingw"><short>assume mingw binaries being used</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-update",
+ banner = "ConTeXt Minimals Updater 0.31",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+local format, concat, gmatch, gsub, find = string.format, table.concat, string.gmatch, string.gsub, string.find
+
+scripts = scripts or { }
+scripts.update = scripts.update or { }
+
+minimals = minimals or { }
+minimals.config = minimals.config or { }
+
+-- this is needed under windows
+-- else rsync fails to set the right chmod flags to files
+
+os.setenv("CYGWIN","nontsec")
+
+scripts.update.texformats = {
+ "cont-en",
+ "cont-nl",
+ "cont-cz",
+ "cont-de",
+ "cont-fa",
+ "cont-it",
+ "cont-ro",
+ "cont-uk",
+ "cont-pe",
+ -- "cont-xp",
+ "mptopdf",
+ "plain"
+}
+
+scripts.update.mpformats = {
+ -- "metafun",
+ -- "mpost",
+}
+
+-- experimental is not functional at the moment
+
+scripts.update.repositories = {
+ "current",
+ "experimental"
+}
+
+-- more options than just these two are available (no idea why this is here)
+
+scripts.update.versions = {
+ "current",
+ "latest"
+}
+
+-- list of basic folders that are needed to make a functional distribution
+
+scripts.update.base = {
+ { "base/tex/", "texmf" },
+ { "base/metapost/", "texmf" },
+ { "fonts/common/", "texmf" },
+ { "fonts/other/", "texmf" }, -- not *really* needed, but helpful
+ { "context/<version>/", "texmf-context" },
+ { "misc/setuptex/", "." },
+ { "misc/web2c", "texmf" },
+ { "bin/common/<platform>/", "texmf-<platform>" },
+ { "bin/context/<platform>/", "texmf-<platform>" },
+ { "bin/metapost/<platform>/", "texmf-<platform>" },
+ { "bin/man/", "texmf-<platform>" },
+}
+
+-- binaries and font-related files
+-- for pdftex we don't need OpenType fonts, for LuaTeX/XeTeX we don't need TFM files
+
+scripts.update.engines = {
+ ["luatex"] = {
+ { "fonts/new/", "texmf" },
+ { "bin/luatex/<platform>/", "texmf-<platform>" },
+ { "bin/luajittex/<platform>/","texmf-<platform>" },
+ },
+ ["xetex"] = {
+ { "base/xetex/", "texmf" },
+ { "fonts/new/", "texmf" },
+ { "bin/luatex/<platform>/", "texmf-<platform>" }, -- tools
+ { "bin/xetex/<platform>/", "texmf-<platform>" },
+ },
+ ["pdftex"] = {
+ { "fonts/old/", "texmf" },
+ { "bin/luatex/<platform>/", "texmf-<platform>" }, -- tools
+ { "bin/pdftex/<platform>/", "texmf-<platform>" },
+ },
+ ["all"] = {
+ { "fonts/new/", "texmf" },
+ { "fonts/old/", "texmf" },
+ { "base/xetex/", "texmf" },
+ { "bin/luatex/<platform>/", "texmf-<platform>" },
+ { "bin/luajittex/<platform>/","texmf-<platform>" },
+ { "bin/xetex/<platform>/", "texmf-<platform>" },
+ { "bin/pdftex/<platform>/", "texmf-<platform>" },
+ },
+}
+
+scripts.update.goodies = {
+ ["scite"] = {
+ { "bin/<platform>/scite/", "texmf-<platform>" },
+ },
+ ["texworks"] = {
+ { "bin/<platform>/texworks/", "texmf-<platform>" },
+ },
+}
+
+scripts.update.platforms = {
+ ["mswin"] = "mswin",
+ ["windows"] = "mswin",
+ ["win32"] = "mswin",
+ ["win"] = "mswin",
+ ["linux"] = "linux",
+ ["freebsd"] = "freebsd",
+ ["freebsd-amd64"] = "freebsd-amd64",
+ ["kfreebsd"] = "kfreebsd-i386",
+ ["kfreebsd-i386"] = "kfreebsd-i386",
+ ["kfreebsd-amd64"] = "kfreebsd-amd64",
+ ["linux-32"] = "linux",
+ ["linux-64"] = "linux-64",
+ ["linux32"] = "linux",
+ ["linux64"] = "linux-64",
+ ["linux-ppc"] = "linux-ppc",
+ ["ppc"] = "linux-ppc",
+ ["osx"] = "osx-intel",
+ ["macosx"] = "osx-intel",
+ ["osx-intel"] = "osx-intel",
+ ["osx-ppc"] = "osx-ppc",
+ ["osx-powerpc"] = "osx-ppc",
+ ["osx-64"] = "osx-64",
+ ["osxintel"] = "osx-intel",
+ ["osxppc"] = "osx-ppc",
+ ["osxpowerpc"] = "osx-ppc",
+ ["solaris-intel"] = "solaris-intel",
+ ["solaris-sparc"] = "solaris-sparc",
+ ["solaris"] = "solaris-sparc",
+}
+
+scripts.update.selfscripts = {
+ "mtxrun",
+ -- "luatools",
+}
+
+-- the list is filled up later (when we know what modules to download)
+
+scripts.update.modules = {
+}
+
+scripts.update.fonts = {
+}
+
+function scripts.update.run(str)
+ -- important, otherwise formats fly to a weird place
+ -- (texlua sets luatex as the engine, we need to reset that or to fix texexec :)
+ os.setenv("engine",nil)
+ if environment.argument("force") then
+ report("run, %s",str)
+ os.execute(str)
+ else
+ report("dry run, %s",str)
+ end
+end
+
+function scripts.update.fullpath(path)
+ if file.is_rootbased_path(path) then
+ return path
+ else
+ return lfs.currentdir() .. "/" .. path
+ end
+end
+
+local rsync_variant = "cygwin" -- will be come mingw
+
+local function drive(d)
+ if rsync_variant == "cygwin" then
+ d = gsub(d,[[([a-zA-Z]):/]], "/cygdrive/%1/")
+ else
+ d = gsub(d,[[([a-zA-Z]):/]], "/%1/")
+ end
+ return d
+end
+
+function scripts.update.synchronize()
+
+ report("update, start")
+
+ local texroot = scripts.update.fullpath(states.get("paths.root"))
+ local engines = states.get('engines') or { }
+ local platforms = states.get('platforms') or { }
+ local repositories = states.get('repositories') -- minimals
+ local bin = states.get("rsync.program") -- rsync
+ local url = states.get("rsync.server") -- contextgarden.net
+ local version = states.get("context.version") -- current (or beta)
+ local modules = states.get("modules") -- modules (third party)
+ local fonts = states.get("fonts") -- fonts (experimental or special)
+ local goodies = states.get("goodies") -- goodies (like editors)
+ local force = environment.argument("force")
+
+ bin = gsub(bin,"\\","/")
+
+ if not url:find("::$") then url = url .. "::" end
+ local ok = lfs.attributes(texroot,"mode") == "directory"
+ if not ok and force then
+ dir.mkdirs(texroot)
+ ok = lfs.attributes(texroot,"mode") == "directory"
+ end
+
+ if force then
+ dir.mkdirs(format("%s/%s", texroot, "texmf-cache"))
+ dir.mkdirs(format("%s/%s", texroot, "texmf-local"))
+ dir.mkdirs(format("%s/%s", texroot, "texmf-project"))
+ dir.mkdirs(format("%s/%s", texroot, "texmf-fonts"))
+ dir.mkdirs(format("%s/%s", texroot, "texmf-modules"))
+ end
+
+ if ok or not force then
+
+ local fetched, individual, osplatform = { }, { }, os.platform
+
+ -- takes a collection as argument and returns a list of folders
+
+ local function collection_to_list_of_folders(collection, platform)
+ local archives = {}
+ for i=1,#collection do
+ local archive = collection[i][1]
+ archive = gsub(archive,"<platform>",platform)
+ archive = gsub(archive,"<version>",version)
+ archives[#archives+1] = archive
+ end
+ return archives
+ end
+
+ -- takes a list of folders as argument and returns a string for rsync
+ -- sample input:
+ -- {'bin/common', 'bin/context'}
+ -- output:
+ -- 'minimals/current/bin/common minimals/current/bin/context'
+
+ local function list_of_folders_to_rsync_string(list_of_folders)
+ local repository = 'current'
+ local prefix = format("%s/%s/", states.get('rsync.module'), repository) -- minimals/current/
+
+ return prefix .. concat(list_of_folders, format(" %s", prefix))
+ end
+
+ -- example of usage: print(list_of_folders_to_rsync_string(collection_to_list_of_folders(scripts.update.base, os.platform)))
+
+ -- rename function and add some more functionality:
+ -- * recursive/non-recursive (default: non-recursive)
+ -- * filter folders or regular files only (default: no filter)
+ -- * grep for size of included files (with --stats switch)
+
+ local function get_list_of_files_from_rsync(list_of_folders)
+ -- temporary file to store the output of rsync (could be a more random name; watch for overwrites)
+ local temp_file = "rsync.tmp.txt"
+ -- a set of folders
+ local folders = {}
+ local command = format("%s %s'%s' > %s", bin, url, list_of_folders_to_rsync_string(list_of_folders), temp_file)
+ os.execute(command)
+ -- read output of rsync
+ local data = io.loaddata(temp_file) or ""
+ -- for every line extract the filename
+ for chmod, s in data:gmatch("([d%-][rwx%-]+).-(%S+)[\n\r]") do
+ -- skip "current" folder
+ if s ~= '.' and chmod:len() == 10 then
+ folders[#folders+1] = s
+ end
+ end
+ -- delete the file to which we have put output of rsync
+ os.remove(temp_file)
+ return folders
+ end
+
+ -- rsync://contextgarden.net/minimals/current/modules/
+
+ if modules and type(modules) == "table" then
+ -- fetch the list of available modules from rsync server
+ local available_modules = get_list_of_files_from_rsync({"modules/"})
+ -- hash of requested modules
+ -- local h = table.tohash(modules:split(","))
+ local asked = table.copy(modules)
+ asked.all = nil
+ for i=1,#available_modules do
+ local s = available_modules[i]
+ if modules.all or modules[s] then
+ scripts.update.modules[#scripts.update.modules+1] = { format("modules/%s/",s), "texmf-modules" }
+ end
+ asked[s] = nil
+ end
+ if next(asked) then
+ report("skipping unknown modules: %s",table.concat(table.sortedkeys(asked),", "))
+ end
+ end
+
+ -- rsync://contextgarden.net/minimals/current/fonts/extra/
+
+ if fonts and type(fonts) == "table" then
+ local available_fonts = get_list_of_files_from_rsync({"fonts/extra/"})
+ local asked = table.copy(fonts)
+ asked.all = nil
+ for i=1,#available_fonts do
+ local s = available_fonts[i]
+ if fonts.all or fonts[s] then
+ scripts.update.fonts[#scripts.update.fonts+1] = { format("fonts/extra/%s/",s), "texmf" }
+ end
+ asked[s] = nil
+ end
+ if next(asked) then
+ report("skipping unknown fonts: %s",table.concat(table.sortedkeys(asked),", "))
+ end
+ end
+
+ local function add_collection(collection,platform)
+ if collection and platform then
+ platform = scripts.update.platforms[platform]
+ if platform then
+ for i=1,#collection do
+ local c = collection[i]
+ local archive = gsub(c[1],"<platform>",platform)
+ local destination = format("%s/%s", texroot, gsub(c[2],"<platform>", platform))
+ destination = gsub(destination,"\\","/")
+ archive = gsub(archive,"<version>",version)
+ if osplatform == "windows" or osplatform == "mswin" then
+ destination = drive(destination)
+ end
+ individual[#individual+1] = { archive, destination }
+ end
+ end
+ end
+ end
+
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.base,platform)
+ end
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.modules,platform)
+ end
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.fonts,platform)
+ end
+ for engine, _ in next, engines do
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.engines[engine],platform)
+ end
+ end
+
+ if goodies and type(goodies) == "table" then
+ for goodie, _ in next, goodies do
+ for platform, _ in next, platforms do
+ add_collection(scripts.update.goodies[goodie],platform)
+ end
+ end
+ end
+
+ local combined = { }
+ local update_repositories = scripts.update.repositories
+ for i=1,#update_repositories do
+ local repository = update_repositories[i]
+ if repositories[repository] then
+ for _, v in next, individual do
+ local archive, destination = v[1], v[2]
+ local cd = combined[destination]
+ if not cd then
+ cd = { }
+ combined[destination] = cd
+ end
+ cd[#cd+1] = format("%s/%s/%s",states.get('rsync.module'),repository,archive)
+ end
+ end
+ end
+ for destination, archive in next, combined do
+ local archives, command = concat(archive," "), ""
+ local normalflags, deleteflags = states.get("rsync.flags.normal"), ""
+ if os.name == "windows" then
+ normalflags = normalflags .. " -L" -- no symlinks
+ end
+ local dryrunflags = ""
+ if not environment.argument("force") then
+ dryrunflags = "--dry-run"
+ end
+ if (destination:find("texmf$") or destination:find("texmf%-context$") or destination:find("texmf%-modules$")) and (not environment.argument("keep")) then
+ deleteflags = states.get("rsync.flags.delete")
+ end
+ command = format("%s %s %s %s %s'%s' '%s'", bin, normalflags, deleteflags, dryrunflags, url, archives, destination)
+ -- report("running command: %s",command)
+ if not fetched[command] then
+ scripts.update.run(command,true)
+ fetched[command] = command
+ end
+ end
+
+ local function update_script(script, platform)
+ local bin = gsub(bin,"\\","/")
+ local texroot = gsub(texroot,"\\","/")
+ platform = scripts.update.platforms[platform]
+ if platform then
+ local command
+ if platform == 'mswin' then
+ bin = drive(bin)
+ texroot = drive(texroot)
+ command = format([[%s -t "%s/texmf-context/scripts/context/lua/%s.lua" "%s/texmf-mswin/bin/"]], bin, texroot, script, texroot)
+ else
+ command = format([[%s -tgo --chmod=a+x '%s/texmf-context/scripts/context/lua/%s.lua' '%s/texmf-%s/bin/%s']], bin, texroot, script, texroot, platform, script)
+ end
+ report("updating %s for %s: %s", script, platform, command)
+ scripts.update.run(command)
+ end
+ end
+
+ for platform, _ in next, platforms do
+ for i=1, #scripts.update.selfscripts do
+ update_script(scripts.update.selfscripts[i],platform)
+ end
+ end
+
+ else
+ report("no valid texroot: %s",texroot)
+ end
+ if not force then
+ report("use --force to really update files")
+ end
+
+ resolvers.load_tree(texroot) -- else we operate in the wrong tree
+
+ -- update filename database for pdftex/xetex
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot))
+ -- update filename database for luatex
+ scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
+
+ report("update, done")
+end
+
+function table.fromhash(t)
+ local h = { }
+ for k, v in next, t do -- not indexed
+ if v then h[#h+1] = k end
+ end
+ return h
+end
+
+-- make the ConTeXt formats
+function scripts.update.make()
+
+ report("make, start")
+
+ local force = environment.argument("force")
+ local texroot = scripts.update.fullpath(states.get("paths.root"))
+ local engines = states.get('engines')
+ local goodies = states.get('goodies')
+ local platforms = states.get('platforms')
+ local formats = states.get('formats')
+
+ resolvers.load_tree(texroot)
+
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot))
+ scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
+
+ local askedformats = formats
+ local texformats = table.tohash(scripts.update.texformats)
+ local mpformats = table.tohash(scripts.update.mpformats)
+ for k,v in next, texformats do
+ if not askedformats[k] then
+ texformats[k] = nil
+ end
+ end
+ for k,v in next, mpformats do
+ if not askedformats[k] then
+ mpformats[k] = nil
+ end
+ end
+ local formatlist = concat(table.fromhash(texformats), " ")
+ if formatlist ~= "" then
+ for engine in next, engines do
+ if engine == "luatex" then
+ scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make',texroot))
+ elseif engine == "luajittex" then
+ scripts.update.run(format('mtxrun --tree="%s" --script context --autogenerate --make --engine=luajittex',texroot))
+ else
+ scripts.update.run(format('mtxrun --tree="%s" --script texexec --make --all --%s %s',texroot,engine,formatlist))
+ end
+ end
+ end
+ local formatlist = concat(table.fromhash(mpformats), " ")
+ if formatlist ~= "" then
+ scripts.update.run(format('mtxrun --tree="%s" --script texexec --make --all %s',texroot,formatlist))
+ end
+ if not force then
+ report("make, use --force to really make formats")
+ end
+
+ scripts.update.run(format('mtxrun --tree="%s" --direct --resolve mktexlsr',texroot)) -- needed for mpost
+ scripts.update.run(format('mtxrun --tree="%s" --generate',texroot))
+
+ report("make, done")
+end
+
+scripts.savestate = true
+
+if scripts.savestate then
+
+ states.load("status-of-update.lua")
+
+ -- tag, value, default, persistent
+
+ statistics.starttiming(states)
+
+ states.set("info.version",0.1) -- ok
+ states.set("info.count",(states.get("info.count") or 0) + 1,1,false) -- ok
+ states.set("info.comment","this file contains the settings of the last 'mtxrun --script update' run",false) -- ok
+ states.set("info.date",os.date("!%Y-%m-%d %H:%M:%S")) -- ok
+
+ states.set("rsync.program", environment.argument("rsync"), "rsync", true) -- ok
+ states.set("rsync.server", environment.argument("server"), "contextgarden.net::", true) -- ok
+ states.set("rsync.module", environment.argument("module"), "minimals", true) -- ok
+ states.set("rsync.flags.normal", environment.argument("flags"), "-rpztlv", true) -- ok
+ states.set("rsync.flags.delete", nil, "--delete", true) -- ok
+
+ states.set("paths.root", environment.argument("texroot"), "tex", true) -- ok
+
+ states.set("context.version", environment.argument("context"), "current", true) -- ok
+
+ local valid = table.tohash(scripts.update.repositories)
+ for r in gmatch(environment.argument("repository") or "current","([^, ]+)") do
+ if valid[r] then states.set("repositories." .. r, true) end
+ end
+
+ local valid = scripts.update.engines
+ local engine = environment.argument("engine") or ""
+ if engine == "" then
+ local e = states.get("engines")
+ if not e or not next(e) then
+ engine = "all"
+ end
+ end
+ if engine ~= "" then
+ for r in gmatch(engine,"([^, ]+)") do
+ if r == "all" then
+ for k, v in next, valid do
+ if k ~= "all" then
+ states.set("engines." .. k, true)
+ end
+ end
+ break
+ elseif valid[r] then
+ states.set("engines." .. r, true)
+ end
+ end
+ end
+
+ local valid = scripts.update.platforms
+ for r in gmatch(environment.argument("platform") or os.platform,"([^, ]+)") do
+ if valid[r] then states.set("platforms." .. r, true) end
+ end
+
+ local valid = table.tohash(scripts.update.texformats)
+ for r in gmatch(environment.argument("formats") or "","([^, ]+)") do
+ if valid[r] then states.set("formats." .. r, true) end
+ end
+ local valid = table.tohash(scripts.update.mpformats)
+ for r in gmatch(environment.argument("formats") or "","([^, ]+)") do
+ if valid[r] then states.set("formats." .. r, true) end
+ end
+
+ states.set("formats.cont-en", true)
+ states.set("formats.cont-nl", true)
+ states.set("formats.metafun", true)
+
+ for r in gmatch(environment.argument("extras") or "","([^, ]+)") do -- for old times sake
+ if r ~= "all" and not find(r,"^[a-z]%-") then
+ r = "t-" .. r
+ end
+ states.set("modules." .. r, true)
+ end
+ for r in gmatch(environment.argument("modules") or "","([^, ]+)") do
+ if r ~= "all" and not find(r,"^[a-z]%-") then
+ r = "t-" .. r
+ end
+ states.set("modules." .. r, true)
+ end
+ for r in gmatch(environment.argument("fonts") or "","([^, ]+)") do
+ states.set("fonts." .. r, true)
+ end
+ for r in gmatch(environment.argument("goodies") or "","([^, ]+)") do
+ states.set("goodies." .. r, true)
+ end
+
+ report("state, loaded")
+ report()
+
+end
+
+if environment.argument("state") then
+ environment.setargument("update",true)
+ environment.setargument("force",true)
+ environment.setargument("make",true)
+end
+
+if environment.argument("mingw") then
+ rsync_variant = "mingw"
+elseif environment.argument("cygwin") then
+ rsync_variant = "cygwin"
+end
+
+if environment.argument("update") then
+ scripts.update.synchronize()
+ if environment.argument("make") then
+ scripts.update.make()
+ end
+elseif environment.argument("make") then
+ scripts.update.make()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
+
+if scripts.savestate then
+ statistics.stoptiming(states)
+ states.set("info.runtime",tonumber(statistics.elapsedtime(states)))
+ if environment.argument("force") then
+ states.save()
+ report("state","saved")
+ end
+end
diff --git a/scripts/context/lua/mtx-watch.lua b/scripts/context/lua/mtx-watch.lua index 95323f571..aa9b9262d 100644 --- a/scripts/context/lua/mtx-watch.lua +++ b/scripts/context/lua/mtx-watch.lua @@ -1,431 +1,431 @@ -if not modules then modules = { } end modules ['mtx-watch'] = { - 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 helpinfo = [[ -<?xml version="1.0"?> -<application> - <metadata> - <entry name="name">mtx-watch</entry> - <entry name="detail">ConTeXt Request Watchdog</entry> - <entry name="version">1.00</entry> - </metadata> - <flags> - <category name="basic"> - <subcategory> - <flag name="logpath"><short>optional path for log files</short></flag> - <flag name="watch"><short>watch given path [<ref name="delay]"/></short></flag> - <flag name="pipe"><short>use pipe instead of execute</short></flag> - <flag name="delay"><short>delay between sweeps</short></flag> - <flag name="automachine"><short>replace /machine/ in path /servername/</short></flag> - <flag name="collect"><short>condense log files</short></flag> - <flag name="cleanup" value="delay"><short>remove files in given path [<ref name="force]"/></short></flag> - <flag name="showlog"><short>show log data</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtx-watch", - banner = "ConTeXt Request Watchdog 1.00", - helpinfo = helpinfo, -} - -local report = application.report - -scripts = scripts or { } -scripts.watch = scripts.watch or { } - -local format, concat, difftime, time = string.format, table.concat, os.difftime, os.time -local next, type = next, type -local basename, dirname, joinname = file.basename, file.dirname, file.join -local lfsdir, lfsattributes = lfs.dir, lfs.attributes - --- the machine/instance matches the server app we use - -local machine = socket.dns.gethostname() or "unknown-machine" -local instance = string.match(machine,"(%d+)$") or "0" - -function scripts.watch.save_exa_modes(joblog,ctmname) - local values = joblog and joblog.values - if values then - local t= { } - t[#t+1] = "<?xml version='1.0' standalone='yes'?>\n" - t[#t+1] = "<exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>" - for k, v in next, joblog.values do - t[#t+1] = format("\t<exa:variable label='%s'>%s</exa:variable>", k, tostring(v)) - end - t[#t+1] = "</exa:variables>" - io.savedata(ctmname,concat(t,"\n")) - else - os.remove(ctmname) - end -end - -local function toset(t) - if type(t) == "table" then - return concat(t,",") - else - return t - end -end - -local function noset(t) - if type(t) == "table" then - return t[1] - else - return t - end -end - --- todo: split order (o-name.luj) and combine with atime to determine sort order. - -local function glob(files,path) -- some day: sort by name (order prefix) and atime - for name in lfsdir(path) do - if name:find("^%.") then - -- skip . and .. - else - name = path .. "/" .. name - local a = lfsattributes(name) - if not a then - -- weird - elseif a.mode == "directory" then - if name:find("graphics$") or name:find("figures$") or name:find("resources$") then - -- skip these too - else - glob(files,name) - end - elseif name:find(".%luj$") then - local bname = basename(name) - local dname = dirname(name) - local order = tonumber(bname:match("^(%d+)")) or 0 - files[#files+1] = { dname, bname, order } - end - end - end -end - -local clock = os.gettimeofday or (socket and socket.gettime) or os.time -- we cannot trust os.clock on linux - --- local function filenamesort(a,b) --- local fa, da = a[1], a[2] --- local fb, db = b[1], b[2] --- if da == db then --- return fa < fb --- else --- return da < db --- end --- end - -local function filenamesort(a,b) - local fa, oa = a[2], a[3] - local fb, ob = b[2], b[3] - if fa == fb then - if oa == ob then - return a[1] < b[1] -- order file dir - else - return oa < ob -- order file - end - else - if oa == ob then - return fa < fb -- order file - else - return oa < ob -- order file - end - end -end - -function scripts.watch.watch() - local delay = tonumber(environment.argument("delay") or 5) or 5 - if delay == 0 then - delay = .25 - end - local logpath = environment.argument("logpath") or "" - local pipe = environment.argument("pipe") or false - local watcher = "mtxwatch.run" - local paths = environment.files - if #paths > 0 then - if environment.argument("automachine") then - logpath = string.gsub(logpath,"/machine/","/"..machine.."/") - for i=1,#paths do - paths[i] = string.gsub(paths[i],"/machine/","/"..machine.."/") - end - end - for i=1,#paths do - report("watching path %s",paths[i]) - end - local function process() - local done = false - for i=1,#paths do - local path = paths[i] - lfs.chdir(path) - local files = { } - glob(files,path) - table.sort(files,filenamesort) --- for name, time in next, files do - for i=1,#files do - local f = files[i] - local dirname = f[1] - local basename = f[2] -- we can use that later on - local name = joinname(dirname,basename) - --~ local ok, joblog = xpcall(function() return dofile(name) end, function() end ) - local ok, joblog = pcall(dofile,name) - if ok and joblog then - if joblog.status == "processing" then - report("aborted job, %s added to queue",name) - joblog.status = "queued" - io.savedata(name, table.serialize(joblog,true)) - elseif joblog.status == "queued" then - local command = joblog.command - if command then - local replacements = { - inputpath = toset((joblog.paths and joblog.paths.input ) or "."), - outputpath = noset((joblog.paths and joblog.paths.output) or "."), - filename = joblog.filename or "", - } - -- todo: revision path etc - command = command:gsub("%%(.-)%%", replacements) - if command ~= "" then - joblog.status = "processing" - joblog.runtime = clock() - io.savedata(name, table.serialize(joblog,true)) - report("running: %s", command) - local newpath = file.dirname(name) - io.flush() - local result = "" - local ctmname = file.basename(replacements.filename) - if ctmname == "" then ctmname = name end -- use self as fallback - ctmname = file.replacesuffix(ctmname,"ctm") - if newpath ~= "" and newpath ~= "." then - local oldpath = lfs.currentdir() - lfs.chdir(newpath) - scripts.watch.save_exa_modes(joblog,ctmname) - if pipe then result = os.resultof(command) else result = os.spawn(command) end - lfs.chdir(oldpath) - else - scripts.watch.save_exa_modes(joblog,ctmname) - if pipe then result = os.resultof(command) else result = os.spawn(command) end - end - report("return value: %s", result) - done = true - local path, base = replacements.outputpath, file.basename(replacements.filename) - joblog.runtime = clock() - joblog.runtime - if base ~= "" then - joblog.result = file.replacesuffix(file.join(path,base),"pdf") - joblog.size = lfs.attributes(joblog.result,"size") - end - joblog.status = "finished" - else - joblog.status = "invalid command" - end - else - joblog.status = "no command" - end - -- pcall, when error sleep + again - -- todo: just one log file and append - io.savedata(name, table.serialize(joblog,true)) - if logpath and logpath ~= "" then - local name = file.join(logpath,os.uuid() .. ".lua") - io.savedata(name, table.serialize(joblog,true)) - report("saving joblog in %s",name) - end - end - end - end - end - end - local n, start = 0, time() - local wtime = 0 - local function wait() - io.flush() - if not done then - n = n + 1 - if n >= 10 then - report("run time: %i seconds, memory usage: %0.3g MB", difftime(time(),start), (status.luastate_bytes/1024)/1000) - n = 0 - end - local ttime = 0 - while ttime <= delay do - local wt = lfs.attributes(watcher,"mtime") - if wt and wt ~= wtime then - -- fast signal that there is a request - wtime = wt - break - end - ttime = ttime + 0.2 - os.sleep(0.2) - end - end - end - local cleanupdelay, cleanup = environment.argument("cleanup"), false - if cleanupdelay then - local lasttime = time() - cleanup = function() - local currenttime = time() - local delta = difftime(currenttime,lasttime) - if delta > cleanupdelay then - lasttime = currenttime - for i=1,#paths do - local path = paths[i] - if string.find(path,"%.") then - -- safeguard, we want a fully qualified path - else - local files = dir.glob(file.join(path,"*")) - for i=1,#files do - local name = files[i] - local filetime = lfs.attributes(name,"modification") - local delta = difftime(currenttime,filetime) - if delta > cleanupdelay then - -- report("cleaning up '%s'",name) - os.remove(name) - end - end - end - end - end - end - else - cleanup = function() - -- nothing - end - end - while true do - if false then ---~ if true then - process() - cleanup() - wait() - else - pcall(process) - pcall(cleanup) - pcall(wait) - end - end - else - report("no paths to watch") - end -end - -function scripts.watch.collect_logs(path) -- clean 'm up too - path = path or environment.argument("logpath") or "" - path = (path == "" and ".") or path - local files = dir.globfiles(path,false,"^%d+%.lua$") - local collection = { } - local valid = table.tohash({"filename","result","runtime","size","status"}) - for i=1,#files do - local name = files[i] - local t = dofile(name) - if t and type(t) == "table" and t.status then - for k, v in next, t do - if not valid[k] then - t[k] = nil - end - end - collection[name:gsub("[^%d]","")] = t - end - end - return collection -end - -function scripts.watch.save_logs(collection,path) -- play safe - if collection and next(collection) then - path = path or environment.argument("logpath") or "" - path = (path == "" and ".") or path - local filename = format("%s/collected-%s.lua",path,tostring(time())) - io.savedata(filename,table.serialize(collection,true)) - local check = dofile(filename) - for k,v in next, check do - if not collection[k] then - report("error in saving file") - os.remove(filename) - return false - end - end - for k,v in next, check do - os.remove(format("%s.lua",k)) - end - return true - else - return false - end -end - -function scripts.watch.collect_collections(path) -- removes duplicates - path = path or environment.argument("logpath") or "" - path = (path == "" and ".") or path - local files = dir.globfiles(path,false,"^collected%-%d+%.lua$") - local collection = { } - for i=1,#files do - local name = files[i] - local t = dofile(name) - if t and type(t) == "table" then - for k, v in next, t do - collection[k] = v - end - end - end - return collection -end - -function scripts.watch.show_logs(path) -- removes duplicates - local collection = scripts.watch.collect_collections(path) or { } - local max = 0 - for k,v in next, collection do - v = v.filename or "?" - if #v > max then max = #v end - end - -- print(max) - local sorted = table.sortedkeys(collection) - for k=1,#sorted do - local v = sorted[k] - local c = collection[v] - local f, s, r, n = c.filename or "?", c.status or "?", c.runtime or 0, c.size or 0 - report("%s %s %3i %8i %s",string.padd(f,max," "),string.padd(s,10," "),r,n,v) - end -end - -function scripts.watch.cleanup_stale_files() -- removes duplicates - local path = environment.files[1] - local delay = tonumber(environment.argument("cleanup")) - local force = environment.argument("force") - if not path or path == "." then - report("provide qualified path") - elseif not delay then - report("missing --cleanup=delay") - else - report("dryrun, use --force for real cleanup") - local files = dir.glob(file.join(path,"*")) - local rtime = time() - for i=1,#files do - local name = files[i] - local mtime = lfs.attributes(name,"modification") - local delta = difftime(rtime,mtime) - if delta > delay then - report("cleaning up '%s'",name) - if force then - os.remove(name) - end - end - end - end -end - -if environment.argument("watch") then - scripts.watch.watch() -elseif environment.argument("collect") then - scripts.watch.save_logs(scripts.watch.collect_logs()) -elseif environment.argument("cleanup") then - scripts.watch.save_logs(scripts.watch.cleanup_stale_files()) -elseif environment.argument("showlog") then - scripts.watch.show_logs() -elseif environment.argument("exporthelp") then - application.export(environment.argument("exporthelp"),environment.files[1]) -else - application.help() -end +if not modules then modules = { } end modules ['mtx-watch'] = {
+ 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 helpinfo = [[
+<?xml version="1.0"?>
+<application>
+ <metadata>
+ <entry name="name">mtx-watch</entry>
+ <entry name="detail">ConTeXt Request Watchdog</entry>
+ <entry name="version">1.00</entry>
+ </metadata>
+ <flags>
+ <category name="basic">
+ <subcategory>
+ <flag name="logpath"><short>optional path for log files</short></flag>
+ <flag name="watch"><short>watch given path [<ref name="delay]"/></short></flag>
+ <flag name="pipe"><short>use pipe instead of execute</short></flag>
+ <flag name="delay"><short>delay between sweeps</short></flag>
+ <flag name="automachine"><short>replace /machine/ in path /servername/</short></flag>
+ <flag name="collect"><short>condense log files</short></flag>
+ <flag name="cleanup" value="delay"><short>remove files in given path [<ref name="force]"/></short></flag>
+ <flag name="showlog"><short>show log data</short></flag>
+ </subcategory>
+ </category>
+ </flags>
+</application>
+]]
+
+local application = logs.application {
+ name = "mtx-watch",
+ banner = "ConTeXt Request Watchdog 1.00",
+ helpinfo = helpinfo,
+}
+
+local report = application.report
+
+scripts = scripts or { }
+scripts.watch = scripts.watch or { }
+
+local format, concat, difftime, time = string.format, table.concat, os.difftime, os.time
+local next, type = next, type
+local basename, dirname, joinname = file.basename, file.dirname, file.join
+local lfsdir, lfsattributes = lfs.dir, lfs.attributes
+
+-- the machine/instance matches the server app we use
+
+local machine = socket.dns.gethostname() or "unknown-machine"
+local instance = string.match(machine,"(%d+)$") or "0"
+
+function scripts.watch.save_exa_modes(joblog,ctmname)
+ local values = joblog and joblog.values
+ if values then
+ local t= { }
+ t[#t+1] = "<?xml version='1.0' standalone='yes'?>\n"
+ t[#t+1] = "<exa:variables xmlns:exa='htpp://www.pragma-ade.com/schemas/exa-variables.rng'>"
+ for k, v in next, joblog.values do
+ t[#t+1] = format("\t<exa:variable label='%s'>%s</exa:variable>", k, tostring(v))
+ end
+ t[#t+1] = "</exa:variables>"
+ io.savedata(ctmname,concat(t,"\n"))
+ else
+ os.remove(ctmname)
+ end
+end
+
+local function toset(t)
+ if type(t) == "table" then
+ return concat(t,",")
+ else
+ return t
+ end
+end
+
+local function noset(t)
+ if type(t) == "table" then
+ return t[1]
+ else
+ return t
+ end
+end
+
+-- todo: split order (o-name.luj) and combine with atime to determine sort order.
+
+local function glob(files,path) -- some day: sort by name (order prefix) and atime
+ for name in lfsdir(path) do
+ if name:find("^%.") then
+ -- skip . and ..
+ else
+ name = path .. "/" .. name
+ local a = lfsattributes(name)
+ if not a then
+ -- weird
+ elseif a.mode == "directory" then
+ if name:find("graphics$") or name:find("figures$") or name:find("resources$") then
+ -- skip these too
+ else
+ glob(files,name)
+ end
+ elseif name:find(".%luj$") then
+ local bname = basename(name)
+ local dname = dirname(name)
+ local order = tonumber(bname:match("^(%d+)")) or 0
+ files[#files+1] = { dname, bname, order }
+ end
+ end
+ end
+end
+
+local clock = os.gettimeofday or (socket and socket.gettime) or os.time -- we cannot trust os.clock on linux
+
+-- local function filenamesort(a,b)
+-- local fa, da = a[1], a[2]
+-- local fb, db = b[1], b[2]
+-- if da == db then
+-- return fa < fb
+-- else
+-- return da < db
+-- end
+-- end
+
+local function filenamesort(a,b)
+ local fa, oa = a[2], a[3]
+ local fb, ob = b[2], b[3]
+ if fa == fb then
+ if oa == ob then
+ return a[1] < b[1] -- order file dir
+ else
+ return oa < ob -- order file
+ end
+ else
+ if oa == ob then
+ return fa < fb -- order file
+ else
+ return oa < ob -- order file
+ end
+ end
+end
+
+function scripts.watch.watch()
+ local delay = tonumber(environment.argument("delay") or 5) or 5
+ if delay == 0 then
+ delay = .25
+ end
+ local logpath = environment.argument("logpath") or ""
+ local pipe = environment.argument("pipe") or false
+ local watcher = "mtxwatch.run"
+ local paths = environment.files
+ if #paths > 0 then
+ if environment.argument("automachine") then
+ logpath = string.gsub(logpath,"/machine/","/"..machine.."/")
+ for i=1,#paths do
+ paths[i] = string.gsub(paths[i],"/machine/","/"..machine.."/")
+ end
+ end
+ for i=1,#paths do
+ report("watching path %s",paths[i])
+ end
+ local function process()
+ local done = false
+ for i=1,#paths do
+ local path = paths[i]
+ lfs.chdir(path)
+ local files = { }
+ glob(files,path)
+ table.sort(files,filenamesort)
+-- for name, time in next, files do
+ for i=1,#files do
+ local f = files[i]
+ local dirname = f[1]
+ local basename = f[2] -- we can use that later on
+ local name = joinname(dirname,basename)
+ --~ local ok, joblog = xpcall(function() return dofile(name) end, function() end )
+ local ok, joblog = pcall(dofile,name)
+ if ok and joblog then
+ if joblog.status == "processing" then
+ report("aborted job, %s added to queue",name)
+ joblog.status = "queued"
+ io.savedata(name, table.serialize(joblog,true))
+ elseif joblog.status == "queued" then
+ local command = joblog.command
+ if command then
+ local replacements = {
+ inputpath = toset((joblog.paths and joblog.paths.input ) or "."),
+ outputpath = noset((joblog.paths and joblog.paths.output) or "."),
+ filename = joblog.filename or "",
+ }
+ -- todo: revision path etc
+ command = command:gsub("%%(.-)%%", replacements)
+ if command ~= "" then
+ joblog.status = "processing"
+ joblog.runtime = clock()
+ io.savedata(name, table.serialize(joblog,true))
+ report("running: %s", command)
+ local newpath = file.dirname(name)
+ io.flush()
+ local result = ""
+ local ctmname = file.basename(replacements.filename)
+ if ctmname == "" then ctmname = name end -- use self as fallback
+ ctmname = file.replacesuffix(ctmname,"ctm")
+ if newpath ~= "" and newpath ~= "." then
+ local oldpath = lfs.currentdir()
+ lfs.chdir(newpath)
+ scripts.watch.save_exa_modes(joblog,ctmname)
+ if pipe then result = os.resultof(command) else result = os.spawn(command) end
+ lfs.chdir(oldpath)
+ else
+ scripts.watch.save_exa_modes(joblog,ctmname)
+ if pipe then result = os.resultof(command) else result = os.spawn(command) end
+ end
+ report("return value: %s", result)
+ done = true
+ local path, base = replacements.outputpath, file.basename(replacements.filename)
+ joblog.runtime = clock() - joblog.runtime
+ if base ~= "" then
+ joblog.result = file.replacesuffix(file.join(path,base),"pdf")
+ joblog.size = lfs.attributes(joblog.result,"size")
+ end
+ joblog.status = "finished"
+ else
+ joblog.status = "invalid command"
+ end
+ else
+ joblog.status = "no command"
+ end
+ -- pcall, when error sleep + again
+ -- todo: just one log file and append
+ io.savedata(name, table.serialize(joblog,true))
+ if logpath and logpath ~= "" then
+ local name = file.join(logpath,os.uuid() .. ".lua")
+ io.savedata(name, table.serialize(joblog,true))
+ report("saving joblog in %s",name)
+ end
+ end
+ end
+ end
+ end
+ end
+ local n, start = 0, time()
+ local wtime = 0
+ local function wait()
+ io.flush()
+ if not done then
+ n = n + 1
+ if n >= 10 then
+ report("run time: %i seconds, memory usage: %0.3g MB", difftime(time(),start), (status.luastate_bytes/1024)/1000)
+ n = 0
+ end
+ local ttime = 0
+ while ttime <= delay do
+ local wt = lfs.attributes(watcher,"mtime")
+ if wt and wt ~= wtime then
+ -- fast signal that there is a request
+ wtime = wt
+ break
+ end
+ ttime = ttime + 0.2
+ os.sleep(0.2)
+ end
+ end
+ end
+ local cleanupdelay, cleanup = environment.argument("cleanup"), false
+ if cleanupdelay then
+ local lasttime = time()
+ cleanup = function()
+ local currenttime = time()
+ local delta = difftime(currenttime,lasttime)
+ if delta > cleanupdelay then
+ lasttime = currenttime
+ for i=1,#paths do
+ local path = paths[i]
+ if string.find(path,"%.") then
+ -- safeguard, we want a fully qualified path
+ else
+ local files = dir.glob(file.join(path,"*"))
+ for i=1,#files do
+ local name = files[i]
+ local filetime = lfs.attributes(name,"modification")
+ local delta = difftime(currenttime,filetime)
+ if delta > cleanupdelay then
+ -- report("cleaning up '%s'",name)
+ os.remove(name)
+ end
+ end
+ end
+ end
+ end
+ end
+ else
+ cleanup = function()
+ -- nothing
+ end
+ end
+ while true do
+ if false then
+--~ if true then
+ process()
+ cleanup()
+ wait()
+ else
+ pcall(process)
+ pcall(cleanup)
+ pcall(wait)
+ end
+ end
+ else
+ report("no paths to watch")
+ end
+end
+
+function scripts.watch.collect_logs(path) -- clean 'm up too
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local files = dir.globfiles(path,false,"^%d+%.lua$")
+ local collection = { }
+ local valid = table.tohash({"filename","result","runtime","size","status"})
+ for i=1,#files do
+ local name = files[i]
+ local t = dofile(name)
+ if t and type(t) == "table" and t.status then
+ for k, v in next, t do
+ if not valid[k] then
+ t[k] = nil
+ end
+ end
+ collection[name:gsub("[^%d]","")] = t
+ end
+ end
+ return collection
+end
+
+function scripts.watch.save_logs(collection,path) -- play safe
+ if collection and next(collection) then
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local filename = format("%s/collected-%s.lua",path,tostring(time()))
+ io.savedata(filename,table.serialize(collection,true))
+ local check = dofile(filename)
+ for k,v in next, check do
+ if not collection[k] then
+ report("error in saving file")
+ os.remove(filename)
+ return false
+ end
+ end
+ for k,v in next, check do
+ os.remove(format("%s.lua",k))
+ end
+ return true
+ else
+ return false
+ end
+end
+
+function scripts.watch.collect_collections(path) -- removes duplicates
+ path = path or environment.argument("logpath") or ""
+ path = (path == "" and ".") or path
+ local files = dir.globfiles(path,false,"^collected%-%d+%.lua$")
+ local collection = { }
+ for i=1,#files do
+ local name = files[i]
+ local t = dofile(name)
+ if t and type(t) == "table" then
+ for k, v in next, t do
+ collection[k] = v
+ end
+ end
+ end
+ return collection
+end
+
+function scripts.watch.show_logs(path) -- removes duplicates
+ local collection = scripts.watch.collect_collections(path) or { }
+ local max = 0
+ for k,v in next, collection do
+ v = v.filename or "?"
+ if #v > max then max = #v end
+ end
+ -- print(max)
+ local sorted = table.sortedkeys(collection)
+ for k=1,#sorted do
+ local v = sorted[k]
+ local c = collection[v]
+ local f, s, r, n = c.filename or "?", c.status or "?", c.runtime or 0, c.size or 0
+ report("%s %s %3i %8i %s",string.padd(f,max," "),string.padd(s,10," "),r,n,v)
+ end
+end
+
+function scripts.watch.cleanup_stale_files() -- removes duplicates
+ local path = environment.files[1]
+ local delay = tonumber(environment.argument("cleanup"))
+ local force = environment.argument("force")
+ if not path or path == "." then
+ report("provide qualified path")
+ elseif not delay then
+ report("missing --cleanup=delay")
+ else
+ report("dryrun, use --force for real cleanup")
+ local files = dir.glob(file.join(path,"*"))
+ local rtime = time()
+ for i=1,#files do
+ local name = files[i]
+ local mtime = lfs.attributes(name,"modification")
+ local delta = difftime(rtime,mtime)
+ if delta > delay then
+ report("cleaning up '%s'",name)
+ if force then
+ os.remove(name)
+ end
+ end
+ end
+ end
+end
+
+if environment.argument("watch") then
+ scripts.watch.watch()
+elseif environment.argument("collect") then
+ scripts.watch.save_logs(scripts.watch.collect_logs())
+elseif environment.argument("cleanup") then
+ scripts.watch.save_logs(scripts.watch.cleanup_stale_files())
+elseif environment.argument("showlog") then
+ scripts.watch.show_logs()
+elseif environment.argument("exporthelp") then
+ application.export(environment.argument("exporthelp"),environment.files[1])
+else
+ application.help()
+end
|