Created
May 4, 2020 11:38
-
-
Save Fingercomp/58388304f45bf6b2b8108e3b7a555315 to your computer and use it in GitHub Desktop.
A better debug.debug()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function insertNonNil(t, v) | |
if v then | |
v = tostring(v) | |
if #v > 0 then | |
table.insert(t, v) | |
end | |
end | |
end | |
local function backtrace(levelStart, shift) | |
c = c or coroutine.running() | |
for level = levelStart, math.huge do | |
local info = debug.getinfo(c, level, "ufnSl") | |
if not info then | |
break | |
end | |
local funcType, name, args, exec, defined = {}, nil, {}, "", {} | |
insertNonNil(funcType, info.what) | |
insertNonNil(funcType, info.namewhat) | |
table.insert(funcType, "function") | |
name = info.name or "<anon>" | |
if info.nparams then | |
for an = 1, info.nparams do | |
local argName, argValue = debug.getlocal(c, level, an) | |
if argValue ~= nil then | |
argName = argName .. "=" .. tostring(argValue) | |
end | |
table.insert(args, argName) | |
end | |
end | |
if info.isvararg then | |
table.insert(args, "...") | |
end | |
if info.currentline and info.currentline ~= -1 then | |
exec = ":" .. tostring(info.currentline) | |
end | |
insertNonNil(defined, info.short_src) | |
if info.linedefined and info.linedefined ~= -1 then | |
table.insert(defined, info.linedefined) | |
end | |
funcType = table.concat(funcType, " ") | |
args = table.concat(args, ", ") | |
defined = (defined[1] and (" in " .. defined[1] .. "") or "") .. | |
(defined[2] and (" at L" .. defined[2]) or "") | |
-- local Lua function <anon>(a, b, c, ...):33 (defined in blah.lua at 33) | |
local line = ("#%2d: %s %s%s%s%s"):format( | |
level - levelStart + shift, | |
funcType, | |
name, | |
#args > 0 and ("(" .. args .. ")") or "", | |
exec, | |
#defined > 0 and (" (defined" .. defined .. ")") or "" | |
) | |
print(line) | |
end | |
return message | |
end | |
local function getLevel(f) | |
for i = 0, math.huge, 1 do | |
local frame = debug.getinfo(i, "f") | |
if not frame then | |
break | |
end | |
if frame.func == f then | |
return i | |
end | |
end | |
end | |
local function dbg(...) | |
if select("#", ...) > 0 and not (...) then | |
return | |
end | |
if os.getenv("DEBUG") == "off" then | |
return | |
end | |
local level = 0 | |
local environment = setmetatable({}, { | |
__index = function(_, var) | |
local dbgLevel = getLevel(dbg) | |
-- locals | |
for i = 1, math.huge, 1 do | |
local name, value = debug.getlocal(level + dbgLevel, i) | |
if not name then | |
break | |
end | |
if name == var then | |
return value | |
end | |
end | |
-- arguments | |
for i = -1, -math.huge, -1 do | |
local name, value = debug.getlocal(level + dbgLevel, i) | |
if not name then | |
break | |
end | |
if name == var then | |
return value | |
end | |
end | |
-- upvalues | |
local frame = debug.getinfo(level + dbgLevel, "f") | |
if not frame then | |
return | |
end | |
local env | |
for i = 1, math.huge do | |
local name, value = debug.getupvalue(frame.func, i) | |
if not name then | |
break | |
end | |
if name == var then | |
return value | |
end | |
if name == "_ENV" then | |
env = value | |
end | |
end | |
if env then | |
return env[var] | |
end | |
end, | |
__newindex = function(_, var, value) | |
local dbgLevel = getLevel(dbg) | |
-- locals | |
for i = 1, math.huge, 1 do | |
local name = debug.getlocal(level + dbgLevel, i) | |
if not name then | |
break | |
end | |
if name == var then | |
debug.setlocal(level + dbgLevel, i, value) | |
return | |
end | |
end | |
-- arguments | |
for i = -1, -math.huge, -1 do | |
local name = debug.getlocal(level + dbgLevel, i) | |
if not name then | |
break | |
end | |
if name == var then | |
debug.setlocal(level + dbgLevel, i, value) | |
return | |
end | |
end | |
-- environment | |
local frame = debug.getinfo(level + dbgLevel, "f") | |
if not frame then | |
return | |
end | |
local env | |
for i = 1, math.huge, 1 do | |
local name, upvalue = debug.getupvalue(frame.func, i) | |
if not name then | |
break | |
end | |
if name == var then | |
debug.setupvalue(frame.func, i, value) | |
return | |
end | |
if name == "_ENV" then | |
env = upvalue | |
end | |
end | |
if env then | |
env[value] = value | |
end | |
end, | |
}) | |
while true do | |
local frameInfo = debug.getinfo(getLevel(dbg) + level, "nSl") | |
local name = frameInfo.name or "" | |
io.write(("dbg(%d: %s:%d)> "):format(level, name, frameInfo.currentline)) | |
local input = io.read("*l") | |
if not input then | |
print() | |
break | |
end | |
if input:sub(1, 1) == ":" then | |
local params = {} | |
for param in input:sub(2):gmatch("%S+") do | |
table.insert(params, param) | |
end | |
if params[1] == "up" then | |
if debug.getinfo(level + getLevel(dbg) + 1, "") then | |
level = level + 1 | |
else | |
print("Reached the top of the stack") | |
end | |
elseif params[1] == "down" then | |
if debug.getinfo(level + getLevel(dbg) - 1, "") then | |
level = level - 1 | |
else | |
print("Reached the bottom of the stack") | |
end | |
elseif params[1] == "frame" and tonumber(params[2]) then | |
if debug.getinfo(getLevel(dbg) + tonumber(params[2]), "") then | |
level = tonumber(params[2]) | |
else | |
print("No such frame") | |
end | |
elseif params[1] == "bt" then | |
backtrace(level + getLevel(dbg) + 1, level) | |
end | |
else | |
local ok, err = load("return " .. input, "=debug", "t", environment) | |
if not ok then | |
ok, err = load(input, "=debug", "t", environment) | |
end | |
local values | |
if ok then | |
values = table.pack(xpcall(ok, debug.traceback)) | |
ok = table.remove(values, 1) | |
values.n = values.n - 1 | |
err = values[1] | |
end | |
if not ok then | |
io.stderr:write(("%s\n"):format(err)) | |
else | |
for i = 1, values.n, 1 do | |
if type(values[i]) == "string" then | |
values[i] = ("%q"):format(values[i]):gsub("\\\n", "\\n") | |
else | |
values[i] = ("%s"):format(values[i]) | |
end | |
end | |
if values.n > 0 then | |
print(table.concat(values, "\t", 1, values.n)) | |
end | |
end | |
end | |
end | |
end | |
return dbg |
@Fingercomp Добрый день, я надеюсь что вы не против того что я взял этот код к себе в репозиторий и доработал его?
Не против, всё в порядке.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Fingercomp Добрый день, я надеюсь что вы не против того что я взял этот код к себе в репозиторий и доработал его?