1if not modules then modules = { } end modules ['x-ldx'] = {
2 version = 1.001,
3 comment = "companion to x-ldx.mkiv",
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
25
26local banner = "version 1.0.1 - 2007+ - PRAGMA ADE / CONTEXT"
27
28local report = logs.reporter("x-ldx")
29
30
40
41
42
43
44
45
46local gsub, find, sub = string.gsub, string.find, string.sub
47local splitstring, emptystring = string.split, string.is_empty
48local concat = table.concat
49
50
55
56
61
62if not ldx then ldx = { } end
63
64
68
69function ldx.load(filename)
70 local data = file.readdata(filename)
71 local expr = "%s*%-%-%[%[ldx%-*%s*(.-)%s*%-%-ldx%]%]%-*%s*"
72 local i, j, t = 0, 0, { }
73 while true do
74 local comment, ni
75 ni, j, comment = find(data, expr, j)
76 if not ni then break end
77 t[#t+1] = { code = sub(data, i, ni-1) }
78 t[#t+1] = { comment = comment }
79 i = j + 1
80 end
81 local str = sub(data, i, #data)
82 str = gsub(str, "^%s*(.-)%s*$", "%1")
83 if str ~= "" then
84 t[#t+1] = { code = str }
85 end
86 return t
87end
88
89
93
94ldx.keywords = { }
95
96
99
100ldx.keywords.reserved = {
101 ["and"] = 1,
102 ["break"] = 1,
103 ["do"] = 1,
104 ["else"] = 1,
105 ["elseif"] = 1,
106 ["end"] = 1,
107 ["false"] = 1,
108 ["for"] = 1,
109 ["function"] = 1,
110 ["if"] = 1,
111 ["in"] = 1,
112 ["local"] = 1,
113 ["nil"] = 1,
114 ["not"] = 1,
115 ["or"] = 1,
116 ["repeat"] = 1,
117 ["return"] = 1,
118 ["then"] = 1,
119 ["true"] = 1,
120 ["until"] = 1,
121 ["while"] = 1
122}
123
124
129
130do
131 local e = { [">"] = ">", ["<"] = "<", ["&"] = "&" }
132 function ldx.escape(str)
133 return (gsub(str, "([><&])",e))
134 end
135end
136
137
144
145ldx.make_index = true
146
147function ldx.enhance(data)
148 local e = ldx.escape
149 for k=1,#data do
150 local v = data[k]
151 if v.code then
152 local dqs, sqs, com, cmt, cod = { }, { }, { }, { }, e(v.code)
153 cod = gsub(cod, '\\"', "##d##")
154 cod = gsub(cod, "\\'", "##s##")
155 cod = gsub(cod, "%-%-%[%[.-%]%]%-%-", function(s)
156 cmt[#cmt+1] = s
157 return "<l<<<".. #cmt ..">>>l>"
158 end)
159 cod = gsub(cod, "%-%-([^\n]*)", function(s)
160 com[#com+1] = s
161 return "<c<<<".. #com ..">>>c>"
162 end)
163 cod = gsub(cod, "(%b\"\")", function(s)
164 dqs[#dqs+1] = sub(s,2,-2) or ""
165 return "<d<<<".. #dqs ..">>>d>"
166 end)
167 cod = gsub(cod, "(%b\'\')", function(s)
168 sqs[#sqs+1] = sub(s,2,-2) or ""
169 return "<s<<<".. #sqs ..">>>s>"
170 end)
171 cod = gsub(cod, "(%a+)",function(key)
172 local class = ldx.keywords.reserved[key]
173 if class then
174 return "<key class='" .. class .. "'>" .. key .. "</key>"
175 else
176 return key
177 end
178 end)
179 cod = gsub(cod, "<s<<<(%d+)>>>s>", function(s)
180 return "<sqs>" .. sqs[tonumber(s)] .. "</sqs>"
181 end)
182 cod = gsub(cod, "<d<<<(%d+)>>>d>", function(s)
183 return "<dqs>" .. dqs[tonumber(s)] .. "</dqs>"
184 end)
185 cod = gsub(cod, "<c<<<(%d+)>>>c>", function(s)
186 return "<com>" .. com[tonumber(s)] .. "</com>"
187 end)
188 cod = gsub(cod, "<l<<<(%d+)>>>l>", function(s)
189 return cmt[tonumber(s)]
190 end)
191 cod = gsub(cod, "##d##", "\\\"")
192 cod = gsub(cod, "##s##", "\\\'")
193 if ldx.make_index then
194 local lines = splitstring(cod,"\n")
195 local f = "(<key class='1'>function</key>)%s+([%w%.]+)%s*%("
196 for k=1,#lines do
197 local v = lines[k]
198
199 v = gsub(v,f,function(key, str)
200 return "<function>" .. str .. "</function>("
201 end)
202
203 v = gsub(v,"^([%w][%w%,%s]-)(=[^=])",function(str, rest)
204 local t = splitstring(str,",%s*")
205 for k=1,#t do
206 t[k] = "<variable>" .. t[k] .. "</variable>"
207 end
208 return concat(t,", ") .. rest
209 end)
210
211 lines[k] = v
212 end
213 v.code = concat(lines,"\n")
214 else
215 v.code = cod
216 end
217 end
218 end
219end
220
221
228
229local newmethod = true
230
231function ldx.as_xml(data)
232 local t, cmode = { }, false
233 t[#t+1] = "<?xml version='1.0' standalone='yes'?>\n"
234 t[#t+1] = "\n<document xmlns:ldx='http://www.pragma-ade.com/schemas/ldx.rng' xmlns='http://www.pragma-ade.com/schemas/ldx.rng'>\n"
235 for k=1,#data do
236 local v = data[k]
237 if v.code and not emptystring(v.code) then
238 if newmethod then
239 t[#t+1] = "\n<luacode><![CDATA[\n"
240 t[#t+1] = v.code
241 t[#t+1] = "]]></luacode>\n"
242 else
243 t[#t+1] = "\n<code>\n"
244 local split = splitstring(v.code,"\n")
245 for k=1,#split do
246 local v = split[k]
247 local a, b = find(v,"^(%s+)")
248 if v then v = gsub(v,"[\n\r ]+$","") end
249 if a and b then
250 v = sub(v,b+1,#v)
251 if cmode then
252 t[#t+1] = "<line comment='yes' n='" .. b .. "'>" .. v .. "</line>\n"
253 else
254 t[#t+1] = "<line n='" .. b .. "'>" .. v .. "</line>\n"
255 end
256 elseif emptystring(v) then
257 if cmode then
258 t[#t+1] = "<line comment='yes'/>\n"
259 else
260 t[#t+1] = "<line/>\n"
261 end
262 elseif find(v,"^%-%-%[%[") then
263 t[#t+1] = "<line comment='yes'>" .. v .. "</line>\n"
264 cmode= true
265 elseif find(v,"^%]%]%-%-") then
266 t[#t+1] = "<line comment='yes'>" .. v .. "</line>\n"
267 cmode= false
268 elseif cmode then
269 t[#t+1] = "<line comment='yes'>" .. v .. "</line>\n"
270 else
271 t[#t+1] = "<line>" .. v .. "</line>\n"
272 end
273 end
274 t[#t+1] = "</code>\n"
275 end
276 elseif v.comment then
277 t[#t+1] = "\n<comment>\n" .. v.comment .. "\n</comment>\n"
278 else
279
280 end
281 end
282 t[#t+1] = "\n</document>\n"
283 return concat(t,"")
284end
285
286
289
290function ldx.save(filename,data)
291 file.savedata(filename,ldx.as_xml(data))
292end
293
294
297
298function ldx.convert(luaname,ldxname)
299 if not lfs.isfile(luaname) then
300 file.addsuffix(luaname,"lua")
301 end
302 if lfs.isfile(luaname) then
303 if not ldxname then
304 ldxname = file.replacesuffix(luaname,"ldx")
305 end
306 report("converting file %a to %a",luaname,ldxname)
307 local data = ldx.load(luaname)
308 if data then
309
310 if ldxname ~= luaname then
311 ldx.save(ldxname,data)
312 end
313 else
314 report("invalid file %a",luaname)
315 end
316 else
317 report("unknown file %a",luaname)
318 end
319end
320
321
347
348
349
350if environment.files and environment.files[1] then
351 ldx.convert(environment.files[1],environment.files[2])
352else
353 report("no file given")
354end
355 |