From 74ed35b28606776336cd39ae3f66ba59ea66ec34 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 5 May 2023 21:25:43 +0000 Subject: texfindpkg (5may23) git-svn-id: svn://tug.org/texlive/trunk@67027 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/support/texfindpkg/tfpbuild.lua | 312 +++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 Master/texmf-dist/source/support/texfindpkg/tfpbuild.lua (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/support/texfindpkg/tfpbuild.lua b/Master/texmf-dist/source/support/texfindpkg/tfpbuild.lua new file mode 100644 index 00000000000..c0ccac47aa9 --- /dev/null +++ b/Master/texmf-dist/source/support/texfindpkg/tfpbuild.lua @@ -0,0 +1,312 @@ +#!/usr/bin/env texlua + +-- Description: Install TeX packages and their dependencies +-- Copyright: 2023 (c) Jianrui Lyu +-- Repository: https://github.com/lvjr/texfindpkg +-- License: GNU General Public License v3.0 + +tfp = { building = true } + +kpse.set_program_name("kpsewhich") +local tfp = require(kpse.lookup("texfindpkg.lua")) + +------------------------------------------------------------ +--> \section{Some variables and functions} +------------------------------------------------------------ + +local tfpMain = tfp.tfpMain +local showdbg = tfp.showdbg +local dbgPrint = tfp.dbgPrint +local fileRead = tfp.fileRead +local fileWrite = tfp.fileWrite +local getFiles = tfp.getFiles +local valueExists = tfp.valueExists +local json = tfp.json +local gzip = tfp.gzip +local tlParsePackageDB = tfp.tlParsePackageDB +local mtParsePackageDB = tfp.mtParsePackageDB + +local insert = table.insert +local remove = table.remove +local concat = table.concat +local gmatch = string.gmatch +local match = string.match + +------------------------------------------------------------ +--> \section{Compare TeX Live and MiKTeX packages} +------------------------------------------------------------ + +local tlpkgname = "download/texlive.tlpdb" +local mtpkgname = "download/package-manifests.ini" + +local function compareDistributions() + tlpkgtext = fileRead(tlpkgname) + if tlpkgtext then + tlpkgdata = tlParsePackageDB(tlpkgtext) + else + print("error in reading texlive package database!") + end + mtpkgtext = fileRead(mtpkgname) + if mtpkgtext then + mtpkgdata = mtParsePackageDB(mtpkgtext) + else + print("error in reading miktex package database!") + end + local tlmissing, mkmissing = {}, {} + for k, vt in pairs(tlpkgdata) do + local vm = mtpkgdata[k] -- or "[none]" + if vm then + mtpkgdata[k] = nil -- remove it + if vm ~= vt then + print("texlive->" .. vt, "miktex->" .. vm, k) + end + else + insert(mkmissing, {vt, k}) + end + end + for k, v in pairs(mtpkgdata) do + print("texlive doesn't include " .. v .. " -> " .. k) + end + for _, v in ipairs(mkmissing) do + print("miktex doesn't include " .. v[1] .. " -> " .. v[2]) + end +end + +------------------------------------------------------------ +--> \section{Generate json file from cwl files} +------------------------------------------------------------ + +local function insertNewValue(tbl, val) + if not valueExists(tbl, val) then + insert(tbl, val) + end +end + +local latexcwls = {"tex", "xetex", "luatex", "plaintex", "latex-document", "latex-dev"} +local islatexcwl = false + +local function cwlToRealName(base) + if valueExists(latexcwls, base) then return end + local n = match(base, "^tikzlibrary(.+)$") + if n then return base .. ".code.tex" end + local n = match(base, "^tcolorboxlibrary(.+)$") + if n then + if n == "many" or n == "most" or n == "all" then + return nil + else + return "tcb" .. n .. ".code.tex" + end + end + n = match(base, "^class%-(.+)$") + if n then return n .. ".cls" end + return base .. ".sty" +end + +local cwldata = {} + +local function extractFileData(cwl) + -- the cwl files have different eol characters + local deps = {} + for base in gmatch(cwl, "\n#include:(.-)[\r\n]") do + --dbgPrint(base) + local n = cwlToRealName(base) + if n then insertNewValue(deps, n) end + end + local envs = {} + if islatexcwl and cwldata["latex.ltx"] then + envs = cwldata["latex.ltx"].envs or {} + end + for e in gmatch(cwl, "\n\\begin{(.-)}") do + --dbgPrint("{" .. e .. "}") + insertNewValue(envs, e) + end + local cmds = {} + if islatexcwl and cwldata["latex.ltx"] then + cmds = cwldata["latex.ltx"].cmds or {} + end + for c in gmatch(cwl, "\n\\(%a+)") do + if c ~= "begin" and c ~= "end" then + --dbgPrint("\\" .. c) + if not valueExists(cmds, c) then + insert(cmds, c) + end + end + end + --return {deps, envs, cmds} + if #deps == 0 then deps = nil end + if #cmds == 0 then cmds = nil end + if #envs == 0 then envs = nil end + return {deps = deps, envs = envs, cmds = cmds} +end + +local function writeJson() + print("writing json database to file...") + local tbl1 = {} + for k, v in pairs(cwldata) do + insert(tbl1, {k, v}) + end + table.sort(tbl1, function(a, b) + -- make latex.ltx the first item in the json file + local aa, bb + if a[1] == "latex.ltx" then aa = "001" else aa = a[1] end + if b[1] == "latex.ltx" then bb = "001" else bb = b[1] end + return aa < bb + end) + local tbl2 = {} + for _, v in ipairs(tbl1) do + local item = '"' .. v[1] .. '":' .. json.tostring(v[2]) + insert(tbl2, item) + end + local text = "{\n" .. concat(tbl2, "\n,\n") .. "\n}" + fileWrite(text, "texfindpkg.json") + fileWrite(gzip.compress(text), "texfindpkg.json.gz") +end + +local cwlpath = "completion" + +local ignoredcwls = {"optex"} + +local function generateJsonData() + local list = getFiles(cwlpath, "%.cwl$") + local fname + for _, v in ipairs(list) do + local base = match(v, "^(.+)%.cwl") + if not valueExists(ignoredcwls, base) then + if valueExists(latexcwls, base) then + islatexcwl = true + fname = "latex.ltx" + else + islatexcwl = false + fname = cwlToRealName(base) + end + if fname then + --print(fname) + local cwl = fileRead(cwlpath .. "/" .. v) + --print(cwl) + if cwl then + local item = extractFileData(cwl) + dbgPrint(item) + cwldata[fname] = item + else + print("error in reading " .. v) + end + end + end + end + writeJson() +end + +------------------------------------------------------------ +--> \section{Print help or version text} +------------------------------------------------------------ + +local helptext = [[ +usage: texfindpkg [] [] + +valid actions are: + generate Generate texfindpkg.json and texfindpkg.json.gz + compare Compare packages in TeXLive and MiKTeX + check Check test files and report the results + save Check test files and save the results + help Print this message and exit + version Print version information and exit + +please report bug at https://github.com/lvjr/texfindpkg +]] + +local function help() + print(helptext) +end + +local function version() + print("TeXFindPkg Version " .. tfp.version .. " (" .. tfp.date .. ")\n") +end + +------------------------------------------------------------ +--> \section{Check or save test files} +------------------------------------------------------------ + +local function cmdLineToArgList(cmdline) + local tfparg = {} + for v in gmatch(cmdline, "([^ ]+)") do + insert(tfparg, v) + end + remove(tfparg, 1) + return tfparg +end + +local testpath = "test" + +local function readTestFiles(v) + local tests = {} + local text = fileRead(testpath .. "/" .. v) + for i, o in gmatch(text, "<<<<+\n(.-)\n%-%-%-%-+\n(.-)\n>>>>+") do + --print(i, o) + insert(tests, {i, o}) + end + return tests +end + +local function checkTestFiles() + local files = getFiles(testpath, "%.tfp$") + for _, v in ipairs(files) do + print("checking test file " .. v) + local tests = readTestFiles(v) + for _, v in ipairs(tests) do + local i, o = v[1], v[2] .. "\n" + local result = tfpMain(cmdLineToArgList(i)) + if o == result then + dbgPrint("test passed for '" .. i .. "'") + else + print("test failed for '" .. i .. "'") + end + end + end +end + +local function saveTestFiles() + local files = getFiles(testpath, "%.tfp$") + for _, v in ipairs(files) do + print("reading test file " .. v) + local tests = readTestFiles(v) + local text = "" + for _, v in ipairs(tests) do + local i = v[1] + dbgPrint("running test '" .. i .. "'") + local o = tfpMain(cmdLineToArgList(i)) + local sect = "<<<<<<<<\n" .. i .. "\n--------\n" .. o .. ">>>>>>>>\n" + text = text .. sect + end + print("saving test file " .. v) + fileWrite(text, testpath .. "/" .. v) + end +end + +------------------------------------------------------------ +--> \section{Respond to user input} +------------------------------------------------------------ + +local function main() + if arg[1] == nil then return help() end + local action = remove(arg, 1) + action = match(action, "^%-*(.*)$") -- remove leading dashes + --print(action) + if action == "help" then + help() + elseif action == "version" then + version() + elseif action == "generate" then + generateJsonData() + elseif action == "compare" then + compareDistributions() + elseif action == "check" then + checkTestFiles() + elseif action == "save" then + saveTestFiles() + else + print("unknown action '" .. action .. "'") + help() + end +end + +main() -- cgit v1.2.3