-
Notifications
You must be signed in to change notification settings - Fork 0
/
tfpbuild.lua
339 lines (304 loc) · 9.21 KB
/
tfpbuild.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
#!/usr/bin/env texlua
-- Description: Install TeX packages and their dependencies
-- Copyright: 2023-2024 (c) Jianrui Lyu <[email protected]>
-- 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 = {}
-- Ignore lines after "# from xxx option of somepkg", see #7
local function ignoreCmdsFromOptions(cwl)
local result = ""
local isignored = false
for line in gmatch(cwl .. "\n\n", "([^\r\n]-)\r?\n") do
if not isignored then
if match(line, "# from [^ ]+ option of [^ ]+") then
isignored = true
--print("start ignoring: " .. line)
else
result = result .. line .. "\n"
end
else
if match(line, "^ -$") or match(line, "^#endif$") then
isignored = false
--print("stop ignoring: " .. line)
end
end
end
if isignored then
dbgPrint("missing stop point!")
end
--print(result)
return result
end
local function extractFileData(cwl)
cwl = ignoreCmdsFromOptions(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 <action> [<options>] [<name>]
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()