1if not modules then modules = { } end modules ['mtx-ctan'] = {
2 version = 1.00,
3 comment = "companion to mtxrun.lua",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22local lower, find, gsub = string.lower, string.find, string.gsub
23local write_nl = (logs and logs.writer) or (texio and texio.write_nl) or print
24local xmlconvert, xmltext, xmlattr, xmlcollected = xml.convert, xml.text, xml.attribute, xml.collected
25
26local helpinfo = [[
27<?xml version="1.0"?>
28<application>
29 <metadata>
30 <entry name="name">mtx-ctan</entry>
31 <entry name="detail">Dealing with CTAN</entry>
32 <entry name="version">1.00</entry>
33 </metadata>
34 <flags>
35 <category name="basic">
36 <subcategory>
37 <flag name="packages"><short>list available packages</short></flag>
38 <flag name="topics"><short>list available topics</short></flag>
39 <flag name="detail"><short>show details about package</short></flag>
40 <flag name="pattern" value="string"><short>use this pattern, otherwise first argument</short></flag>
41 </subcategory>
42 </category>
43 </flags>
44</application>
45]]
46
47local application = logs.application {
48 name = "mtx-ctan",
49 banner = "Dealing with CTAN",
50 helpinfo = helpinfo,
51}
52
53local report = application.report
54
55scripts = scripts or { }
56scripts.ctan = scripts.ctan or { }
57
58local okay, json = pcall(require,"util-jsn")
59local okay, curl = pcall(require,"libs-imp-curl")
60 pcall(require,"char-ini")
61
62local jsontolua = json and json.tolua
63local shaped = characters and characters.shaped or lower
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81local ctanurl = "https://www.ctan.org/" .. (json and "json" or "xml") .. "/2.0/"
82
83local fetched = curl and
84
85 function(str)
86 local data, message = curl.fetch {
87 url = ctanurl .. str,
88 sslverifyhost = false,
89 sslverifypeer = false,
90 }
91 if not data then
92 report("some error: %s",message)
93 end
94 return data
95 end
96
97or
98
99 function(str)
100
101
102 local data = os.resultof("curl -sS " .. ctanurl .. str)
103
104 return data
105 end
106
107
108
109
110
111
112
113local function strfound(pattern,str)
114 if not pattern then
115 return true
116 else
117 local str = lower(shaped(str))
118 if find(str,pattern) then
119 return true
120 else
121 str = gsub(str,"[^a-zA-Z0-9]","")
122 if find(str,pattern) then
123 return true
124 else
125 return false
126 end
127 end
128 end
129end
130
131local function showresult(found)
132 if #found > 2 then
133 utilities.formatters.formatcolumns(found)
134 report("")
135 for k=1,#found do
136 report(found[k])
137 end
138 report("")
139 end
140end
141
142local function checkedpattern(pattern)
143 if pattern then
144 return lower(shaped(pattern))
145 end
146end
147
148local validdata = json and
149
150 function(data)
151 if data then
152 data = jsontolua(data)
153 if type(data) == "table" then
154 return data
155 else
156 report("unable to handle this json data")
157 end
158 else
159 report("unable to fetch packages")
160 end
161 end
162
163or
164
165 function(data)
166 if data then
167 data = xmlconvert(data)
168 if data.error then
169 report("unable to handle this json data")
170 else
171 return data
172 end
173 else
174 report("unable to fetch packages")
175 end
176 end
177
178scripts.ctan.details = json and
179
180 function(name)
181 if name then
182 local data = validdata(fetched("pkg/" .. name))
183 if data then
184 report("")
185
186 report("name : %s",data.name or "-")
187 report("caption : %s",data.caption or "-")
188 report("path : %s",data.ctan.path or "-")
189 report("")
190 end
191 end
192 end
193
194or
195
196 function (name)
197 if name then
198 local data = validdata(fetched("pkg/" .. name))
199 report("")
200
201 report("name : %s",xmltext(data,"/entry/name"))
202 report("caption : %s",xmltext(data,"/entry/caption"))
203 report("path : %s",xmlattr(data,"/entry/ctan","path"))
204 report("")
205 end
206 end
207
208scripts.ctan.packages = json and
209
210 function(pattern)
211 local data = validdata(fetched("packages"))
212 if data then
213 local found = {
214 { "key", "name", "caption" },
215 { "", "", "" },
216 }
217 pattern = checkedpattern(pattern)
218 for i=1,#data do
219 local entry = data[i]
220 if strfound(pattern,entry.caption) then
221 found[#found+1] = { entry.key, entry.name, entry.caption }
222 end
223 end
224 showresult(found)
225 end
226 end
227
228or
229
230 function(pattern)
231 local data = validdata(fetched("packages"))
232 if data then
233 local found = {
234 { "key", "name", "caption" },
235 { "", "", "" },
236 }
237 pattern = checkedpattern(pattern)
238 for c in xmlcollected(data,"/packages/package") do
239 local at = c.at
240 if strfound(pattern,at.caption) then
241 found[#found+1] = { at.key, at.name, at.caption }
242 end
243 end
244 showresult(found)
245 end
246 end
247
248scripts.ctan.topics = json and
249
250 function (pattern)
251 local data = validdata(fetched("topics"))
252 if data then
253 local found = {
254 { "key", "details" },
255 { "", "" },
256 }
257 pattern = checkedpattern(pattern)
258 for i=1,#data do
259 local entry = data[i]
260 if strfound(pattern,entry.details) then
261 found[#found+1] = { entry.key or entry.name, entry.details }
262 end
263 end
264 showresult(found)
265 end
266 end
267
268or
269
270 function(pattern)
271 local data = validdata(fetched("topics"))
272 if data then
273 local found = {
274 { "name", "details" },
275 { "", "" },
276 }
277 pattern = checkedpattern(pattern)
278 for c in xmlcollected(data,"/topics/topic") do
279 local at = c.at
280 if strfound(pattern,at.caption) then
281 found[#found+1] = { at.key or at.name, at.details }
282 end
283 end
284 showresult(found)
285 end
286 end
287
288local function whatever()
289 report("")
290 report("using %s interface", json and "json" or "xml")
291 report("using curl %s", curl and "library" or "binary")
292 report("")
293end
294
295if environment.argument("packages") then
296 whatever()
297 scripts.ctan.packages(environment.argument("pattern") or environment.files[1])
298elseif environment.argument("topics") then
299 whatever()
300 scripts.ctan.topics(environment.argument("pattern") or environment.files[1])
301elseif environment.argument("details") then
302 whatever()
303 scripts.ctan.details(environment.files[1])
304elseif environment.argument("exporthelp") then
305 application.export(environment.argument("exporthelp"),environment.files[1])
306else
307 application.help()
308end
309
310
311
312
313
314
315
316
317
318
319
320 |