do
_ = termcolours.getstyle;
styles = {
- boundary_padding = _("bright", "white");
+ boundary_padding = _("bright");
filename = _("bright", "blue");
level_num = _("green");
funcname = _("yellow");
end
module("debugx", package.seeall);
-function get_locals_table(level)
- level = level + 1; -- Skip this function itself
+function get_locals_table(thread, level)
local locals = {};
for local_num = 1, math.huge do
- local name, value = debug.getlocal(level, local_num);
+ local name, value;
+ if thread then
+ name, value = debug.getlocal(thread, level, local_num);
+ else
+ name, value = debug.getlocal(level+1, local_num);
+ end
if not name then break; end
table.insert(locals, { name = name, value = value });
end
if thread then
info = debug.getinfo(thread, level);
else
- info = debug.getinfo(level);
+ info = debug.getinfo(level+1);
end
if not info then break; end
-
+
levels[(level-start_level)+1] = {
level = level;
info = info;
- locals = get_locals_table(level);
+ locals = get_locals_table(thread, level+(thread and 0 or 1));
upvalues = get_upvalues_table(info.func);
};
- end
+ end
return levels;
end
function _traceback(thread, message, level)
- if type(thread) ~= "thread" then
+ -- Lua manual says: debug.traceback ([thread,] [message [, level]])
+ -- I fathom this to mean one of:
+ -- ()
+ -- (thread)
+ -- (message, level)
+ -- (thread, message, level)
+
+ if thread == nil then -- Defaults
+ thread, message, level = coroutine.running(), message, level;
+ elseif type(thread) == "string" then
thread, message, level = coroutine.running(), thread, message;
+ elseif type(thread) ~= "thread" then
+ return nil; -- debug.traceback() does this
end
- if level and type(message) ~= "string" then
- return nil, "invalid message";
- elseif not level then
- if type(message) == "number" then
- level, message = message, nil;
- else
- level = 2;
- end
- end
-
+
+ level = level or 0;
+
message = message and (message.."\n") or "";
-
- local levels = get_traceback_table(thread, level+2);
-
+
+ -- +3 counts for this function, and the pcall() and wrapper above us, the +1... I don't know.
+ local levels = get_traceback_table(thread, level+(thread == nil and 4 or 0));
+
local last_source_desc;
-
+
local lines = {};
for nlevel, level in ipairs(levels) do
local info = level.info;
nlevel = nlevel-1;
table.insert(lines, "\t"..(nlevel==0 and ">" or " ")..getstring(styles.level_num, "("..nlevel..") ")..line);
local npadding = (" "):rep(#tostring(nlevel));
- local locals_str = string_from_var_table(level.locals, optimal_line_length, "\t "..npadding);
- if locals_str then
- table.insert(lines, "\t "..npadding.."Locals: "..locals_str);
+ if level.locals then
+ local locals_str = string_from_var_table(level.locals, optimal_line_length, "\t "..npadding);
+ if locals_str then
+ table.insert(lines, "\t "..npadding.."Locals: "..locals_str);
+ end
end
local upvalues_str = string_from_var_table(level.upvalues, optimal_line_length, "\t "..npadding);
if upvalues_str then