-- xml.lua
-- (c) Dirk Laurie 2012 Licence: zlib/pnglib
-- That means you can do anything except claim I didn't write it.
-- Some code borrowed from `strict.lua`
--[[
Usage:
interactive: lua -l "xml" -i
or filter: lua -l xml -e 'print(load("return "..io.read"*a")())'
or programming: require "xml"
After that, you can write XMLinLua, e.g. the expression
macro {name="author-short",
names{variable="author",'name form="short"'} }
represents the following string:
How it works:
When an unknown name is encountered, an immediately available
function is created that can be called in two ways:
name(body)
name{param=val,param=val...,body}
where `body` evaluates to a string. If `body` does not match
the pattern "<.*>", it will be formatted by "<%s/>".
These will respectively be rendered in XML as
body
body
Of course, the sequence of `param="val"` terms does not follow
the original, since the argument is a table.
If you have already defined the name, assign `nil` to it before
trying to use it in this way.
--]]
local getinfo, error, rawset, rawget = debug.getinfo, error, rawset, rawget
local mt = getmetatable(_G)
if mt == nil then
mt = {}
setmetatable(_G, mt)
end
local function what ()
local d = getinfo(3, "S")
return d and d.what or "C"
end
local concat=table.concat
local format, match, gsub =string.format, string.match, string.gsub
mt.__index = function (t, n)
if what() ~= "C" then
local f = function(arg)
local body, restore
if type(arg)=="table" then body=arg[1]; restore=body; arg[1]=nil
elseif type(arg)=="string" then body=arg; arg={}
else error("bad argument #1 to n: expected table or string, got "..
type(arg))
end
if type(body)=="string" then
if not match(body,"<.*>") then body=format("<%s/>",body) end
else
arg[1]=restore
error("bad argument to "..n..": expected string, got "..type(body))
end
local args={}
for k,v in pairs(arg) do args[#args+1]=format(' %s="%s"',k,v) end
return format("<%s%s>\n %s\n%s>",n,concat(args),
gsub(body,"\n","\n "),n)
end
rawset(t, n, f)
return f
end
end