Skip to content

Instantly share code, notes, and snippets.

@kirjavascript
Last active October 29, 2025 22:56
Show Gist options
  • Select an option

  • Save kirjavascript/f6864a30de873c978a993a6c11fa05b3 to your computer and use it in GitHub Desktop.

Select an option

Save kirjavascript/f6864a30de873c978a993a6c11fa05b3 to your computer and use it in GitHub Desktop.
local LEFT_PLACEHOLDER = '__LEFT_BRACE__'
local RIGHT_PLACEHOLDER = '__RIGHT_BRACE__'
local function template(str)
local parts = {}
local last = 1
str = str:gsub('{{', LEFT_PLACEHOLDER)
str = str:gsub('}}', RIGHT_PLACEHOLDER)
for start, _, expr, finish in str:gmatch('()({(.-)})()') do
local code = str:sub(last, start - 1)
:gsub(LEFT_PLACEHOLDER, '{')
:gsub(RIGHT_PLACEHOLDER, '}')
table.insert(parts, string.format('%q', code))
table.insert(parts, '(' .. expr .. ')')
last = finish
end
local remaining = str:sub(last)
:gsub(LEFT_PLACEHOLDER, '{')
:gsub(RIGHT_PLACEHOLDER, '}')
table.insert(parts, string.format('%q', remaining))
local source =
'return function() return table.concat({'
.. table.concat(parts, ',')
.. '}) end'
local env = setmetatable({}, {
__index = function(t, k)
if _G[k] then
return _G[k]
else
local level = 1
while true do
local info = debug.getinfo(level, "f")
if not info then break end -- no more stack frames
local i = 1
while true do
local name, value = debug.getlocal(level, i)
if not name then break end
if name == k then
-- cache value
rawset(t, k, value)
return value
end
i = i + 1
end
level = level + 1
end
rawset(t, k, '???')
return '???'
end
end
})
local fn, err = load(source, 'template', 't', env)
if not fn then error('template compile error: ' .. err) end
local tpl = fn()
return function(vars)
for k, v in next, vars do env[k] = v end
return tpl()
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment