diff options
Diffstat (limited to 'scripts')
32 files changed, 9556 insertions, 9556 deletions
diff --git a/scripts/context/lua/mtx-base.lua b/scripts/context/lua/mtx-base.lua index 66fd06624..bd6749717 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 7ce5e21be..bff1cb496 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 fa3b3d353..9f6852da2 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 bddb2e139..9f52509ec 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 cd7dcce62..7dd1b4ac4 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 3c2311eef..87ed3475d 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 e6de9356e..b76b3baaf 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 81e67ca2f..ba9299020 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 2e988b412..2155b24be 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 2c28f63d9..b171dd611 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 cd4856040..dbcce67f6 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 ff13d00e3..455ecbd52 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 68ad16f93..794bbca37 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 766be6b49..f4003c1db 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 e6517dd95..1239ae4c5 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 a5792ec4f..8c9e6b9fc 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 1abe90385..dca81568e 100644 --- a/scripts/context/lua/mtx-patterns.lua +++ b/scripts/context/lua/mtx-patterns.lua @@ -639,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 --compress +-- mtxrun --script pattern --convert --path=c:/data/develop/svn-hyphen/trunk/hyph-utf8/tex/generic/hyph-utf8/patterns/txt --destination=e:/tmp/patterns -- copy /Y *.hyp e:\tex-context\tex\texmf-context\tex\context\patterns -- copy /Y *.pat e:\tex-context\tex\texmf-context\tex\context\patterns diff --git a/scripts/context/lua/mtx-pdf.lua b/scripts/context/lua/mtx-pdf.lua index 2ff22e07f..551aa5b37 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 975c91ee7..f43dcdeaf 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 15ff595d2..3550474f3 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 1095f2d05..65f795ee5 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 47aa3d009..972edbfe6 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 cbfc91559..a8d7edf41 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 f0901150a..b8dc0dfb2 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 8e99e6371..556805113 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 675ab2c62..5ec15de70 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 8cb7736ac..ae5f2afa4 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 391232b0a..5ba361e5f 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 0ef194285..19b7458a1 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 6514d709a..02d9676bc 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 5141bdf7a..64203d3e3 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 aa9b9262d..95323f571 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 |