Will automatically detect locals as well as global variables.
Usage: Macro “text ${Lua Code} more text”
local _mtg = getmetatable(_G) or {}
function _mtg.__index(self, k)
return rawget(self,k.."___macro")
end
setmetatable(_G,_mtg)
function string.escape(text)
local str = ""
for i=1, #text do
local chr = text:sub(i,i)
local escape = ""
if isIn(chr, {"(", ")"}) then escape = "%" end
str = str .. escape..chr
end
return str
end
function isIn(obj, table)
for _,v in ipairs(table) do
if obj == v then return true end
end
end
function get_locals(func)
local n = 1
local locals = {}
func = (type(func) == "number") and func + 1 or func
while true do
local lname, lvalue = debug.getlocal(func, n)
if lname == nil then break end
if lvalue == nil then lvalue = mynil end
locals[lname] = lvalue
n = n + 1
end
return locals
end
Macro = setmetatable({}, {__call=function(self, ...) return self:init(...) end})
function Macro:init(...)
--We want to retain processing capability even after declaration
local args = {...}
local __string = ""
for _,obj in ipairs(args) do
__string = __string .. tostring(obj)
end
local members = {
__string = __string,
type="Macro"
}
local methods = {
__tostring__ = function(self, n)
--Actual Processing Logic goes here
local str = self.__string
local match = "${.-[^\\]}"
--Check if str has ${statement}
local indices = {str:find(match)}
while #indices > 0 do
local sub = str:sub(indices[1]+2, indices[2]-1)
local repl = str:sub(unpack(indices))
local final = ""
local locals = get_locals(3+n)
for k,_ in pairs(locals) do
rawset(_G,k.."___macro",_)
end
--Evaluate
local _fn, e = loadstring(sub)
if not _fn then
_fn, e = loadstring("return "..sub)
end
if not _fn then
final = " "..e.." "
else
final = tostring(_fn() or " ")
end
for k,_ in pairs(locals) do
rawset(_G,k.."___macro",nil)
end
str = str:gsub(repl:escape(), final)
indices = {str:find(match)}
end
return str
end,
__tostring = function(self)
return getmetatable(self).__tostring__(self, 2)
end,
__call = function(self)
return getmetatable(self).__tostring__(self, 0)
end
}
return setmetatable(members, methods)
end
test = Macro "Hello ${jack} ${'Bauer'}"
function test1()
local jack = "Jack"
print(test)
end
test1()
function test2()
local jack = "No One"
print(test)
end
test2()
function test3()
local test = Macro "Hello ${world}"
local world = "World"
print(test())
end
test3()
function test4()
local test = Macro "Hello ${print('asdf'); return 'World'}"
local world = "World"
print(test)
end
test4()


