local function copyObject(o) local obj = {} for k,v in pairs(o) do obj[k] = v end setmetatable(obj, getmetatable(o)) return obj end local function execDebug(env) local input = io.input() local result = { pcall(input.read, input, "*l") } if not result[1] then return false, result[2] end local func = load("return " .. result[2], "debug", "bt", env) if type(func) ~= "function" then func = load(result[2], "debug", "bt", env) if type(func) ~= "function" then return false, func end end return pcall(func) end local function debugREPL(onResult, debugArgs) local globalEnv = copyObject(_ENV) globalEnv._debug = debugArgs local shouldExit = false globalEnv.exit = function() shouldExit = true end local result, retval repeat result, retval = execDebug(globalEnv) if result and type(onResult) == "function" then onResult(retval) end until shouldExit or not result local success = result and shouldExit return success, (not success and retval) or nil end local function hookDebugger(context, Logger) Logger = Logger or require("logging").getGlobalLogger() local result, retval repeat result, retval = debugREPL(function(r) Logger:error("->", r) end, context) if not result then Logger:error("x>", retval) end until result end return { debugREPL = debugREPL, execDebug = execDebug, hookDebugger = hookDebugger }