You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.1 KiB
Lua

-- https://github.com/hishamhm/f-strings
local F = {}
local load = load
if _VERSION == "Lua 5.1" then
load = function(code, name, _, env)
local fn, err = loadstring(code, name)
if fn then
setfenv(fn, env)
return fn
end
return nil, err
end
end
local function scan_using(scanner, arg, searched)
local i = 1
repeat
local name, value = scanner(arg, i)
if name == searched then
return true, value
end
i = i + 1
until name == nil
return false
end
local function snd(_, b)
return b
end
local function format(_, str)
local outer_env = _ENV and
(snd(scan_using(debug.getlocal, 3, "_ENV")) or
snd(scan_using(debug.getupvalue, debug.getinfo(2, "f").func, "_ENV")) or _ENV) or
getfenv(2)
return (str:gsub("%b{}", function(block)
local code, fmt = block:match("{(.*):(%%.*)}")
code = code or block:match("{(.*)}")
local exp_env = {}
setmetatable(exp_env, {
__index = function(_, k)
local level = 6
while true do
local funcInfo = debug.getinfo(level, "f")
if not funcInfo then
break
end
local ok, value = scan_using(debug.getupvalue, funcInfo.func, k)
if ok then
return value
end
ok, value = scan_using(debug.getlocal, level + 1, k)
if ok then
return value
end
level = level + 1
end
return rawget(outer_env, k)
end,
})
local fn, err = load("return " .. code, "expression `" .. code .. "`", "t", exp_env)
if fn then
return fmt and string.format(fmt, fn()) or tostring(fn())
else
error(err, 0)
end
end))
end
setmetatable(F, {
__call = format,
})
return F