-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathF.lua
62 lines (55 loc) · 1.66 KB
/
F.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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