Added separate debugger file and fixed shell to new form
This commit is contained in:
73
debugger.lua
Normal file
73
debugger.lua
Normal file
@ -0,0 +1,73 @@
|
||||
local core = require "core"
|
||||
|
||||
---@class runner
|
||||
local runner = {
|
||||
new = function(self, o) end, ---@meta
|
||||
run = function(self, target, name) end, ---@meta
|
||||
wait = function(sefl, time) end, ---@meta
|
||||
kill = function(self) end, ---@meta
|
||||
terminate = function(self) end, ---@meta
|
||||
}
|
||||
|
||||
local debugger = {}
|
||||
local debugwindow = nil ---@type JPDebugView
|
||||
local debugrunner = nil ---@type runner|nil
|
||||
|
||||
function debugger.log(msg)
|
||||
core.log("[jpdebug][debugger] %s", msg)
|
||||
if debugwindow then debugwindow:push("meta", "debugger] "..msg) end
|
||||
end
|
||||
|
||||
function debugger.error(msg)
|
||||
core.error("[jpdebug][debugger]"..msg)
|
||||
if debugwindow then debugwindow:push("meta", "debugger] ERROR: "..msg) end
|
||||
end
|
||||
|
||||
function debugger.stdout(msg)
|
||||
if debugwindow then debugwindow:push("stdout", msg) end
|
||||
end
|
||||
|
||||
function debugger.stderr(msg)
|
||||
if debugwindow then debugwindow:push("stderr", msg) end
|
||||
end
|
||||
|
||||
function debugger.is_running()
|
||||
return debugrunner~=nil
|
||||
end
|
||||
|
||||
function debugger.run(target, name, r, view)
|
||||
debugwindow = view
|
||||
debugwindow:clear()
|
||||
debugger.log(string.format("Running %s", name))
|
||||
|
||||
-- Create new runner object
|
||||
debugrunner = r:new({
|
||||
log = debugger.log,
|
||||
error = debugger.error,
|
||||
stdout = debugger.stdout,
|
||||
stderr = debugger.stderr,
|
||||
exited = debugger.exited,
|
||||
})
|
||||
-- And run
|
||||
debugrunner:run(target, name)
|
||||
end
|
||||
|
||||
function debugger.stop()
|
||||
if debugrunner then
|
||||
debugrunner:kill()
|
||||
local exitcode = debugrunner:wait(1000)
|
||||
-- TODO terminate if needed
|
||||
debugger.log(string.format("... Stoped: %d", exitcode))
|
||||
end
|
||||
debugrunner = nil
|
||||
end
|
||||
|
||||
function debugger.exited()
|
||||
if debugrunner then
|
||||
local exitcode = debugrunner:wait(process.WAIT_INFINITE)
|
||||
debugger.log(string.format("exit: %d", exitcode))
|
||||
end
|
||||
debugrunner = nil
|
||||
end
|
||||
|
||||
return debugger
|
||||
75
init.lua
75
init.lua
@ -8,6 +8,8 @@ local config = require "core.config"
|
||||
local TreeView = require "plugins.treeview"
|
||||
local ToolbarView = require "plugins.toolbarview"
|
||||
|
||||
local debugger = require "plugins.jpdebug.debugger"
|
||||
|
||||
core.jpdebug = core.jpdebug or {}
|
||||
|
||||
-- Global list of all the runners
|
||||
@ -19,10 +21,6 @@ local active_view = nil
|
||||
-- The selected target
|
||||
local selected_target = nil
|
||||
|
||||
-- The running system
|
||||
local running_proc = nil
|
||||
local running_runner = nil
|
||||
|
||||
-- Table containing all debug information (like breakpoints)
|
||||
local debug_info = {}
|
||||
|
||||
@ -156,12 +154,7 @@ end
|
||||
|
||||
-- ---------- run target & pipe stdout/stderr into the view ----------
|
||||
local function run_target(target, name)
|
||||
-- Check if something is alredy running
|
||||
if running_proc then
|
||||
core.error("[jpdebug] Already a runner active")
|
||||
return
|
||||
end
|
||||
|
||||
-- Create/get view to push text to
|
||||
-- TODO fix this, it throws a node is locked error once in a while
|
||||
local view = nil
|
||||
if active_view then
|
||||
@ -177,53 +170,16 @@ local function run_target(target, name)
|
||||
-- Check if we have a runner
|
||||
for runner_name,runner in pairs(core.jpdebug.runners) do
|
||||
if runner_name == target.type then
|
||||
-- Found a runner
|
||||
running_proc = runner:run(target, name, debug_info)
|
||||
running_runner = runner
|
||||
|
||||
if running_proc == nil then
|
||||
core.error("[jpdebug] Could not run the target")
|
||||
view:push("stderr", "Could not run the target")
|
||||
return
|
||||
end
|
||||
|
||||
view:clear()
|
||||
|
||||
-- background pump (non-blocking I/O)
|
||||
core.add_thread(function()
|
||||
while true do
|
||||
core.redraw = true
|
||||
coroutine.yield(0.016) -- ~60fps
|
||||
if running_proc == nil then
|
||||
return
|
||||
end
|
||||
local out = runner:read_stdout(running_proc)
|
||||
if out == nil then
|
||||
-- stdout pipe closed: try drain stderr and break when both closed
|
||||
local err = runner:read_stderr(running_proc)
|
||||
if err ~= nil and err ~= "" then view:push("stderr", err) end
|
||||
break
|
||||
end
|
||||
if out ~= "" then view:push("stdout", out) end
|
||||
local err = runner:read_stderr(running_proc)
|
||||
if err ~= nil and err ~= "" then view:push("stderr", err) end
|
||||
end
|
||||
if running_proc then
|
||||
local code = runner:wait(running_proc, process.WAIT_INFINITE)
|
||||
view:push("stdout", ("\n[exit] code=%s\n"):format(tostring(code)))
|
||||
end
|
||||
running_proc = nil
|
||||
running_runner = nil
|
||||
end)
|
||||
|
||||
debugger.run(target, name, runner, view)
|
||||
return view
|
||||
end
|
||||
end
|
||||
|
||||
-- No suitable runners found
|
||||
core.error("[jpdebug] No suitable runners found for target %s", name)
|
||||
view:push("stderr", "No suitable runners found for target "..name)
|
||||
debugger.error(string.format("No suitable runners found for target %s", name))
|
||||
end
|
||||
|
||||
-- ---------- Reload a module on the go ------------------------------
|
||||
local function hot_require(name, into)
|
||||
-- blow away the cached module
|
||||
package.loaded[name] = nil
|
||||
@ -243,7 +199,11 @@ local function hot_require(name, into)
|
||||
end
|
||||
end
|
||||
|
||||
-- Load the runners table on the go
|
||||
local function load_runners()
|
||||
-- TODO Remove: reload debugger as well here
|
||||
debugger = hot_require("plugins.jpdebug.debugger", core.jpdebug.debugger)
|
||||
|
||||
local runner_shell = hot_require("plugins.jpdebug.runners.shell", core.jpdebug.runners.shell)
|
||||
local runner_luadebug = hot_require("plugins.jpdebug.runners.luadebug", core.jpdebug.runners.luadebug)
|
||||
core.jpdebug.runners[runner_shell.name] = runner_shell
|
||||
@ -268,7 +228,7 @@ if required_toolbar_plugins and ToolbarView then
|
||||
local t = {
|
||||
{symbol = "A", command = "jpdebug:set-target"},
|
||||
}
|
||||
if running_proc == nil then
|
||||
if not debugger.is_running() then
|
||||
table.insert(t, {symbol = "B", command = "jpdebug:run"})
|
||||
else
|
||||
table.insert(t, {symbol = "D", command = "jpdebug:stop"})
|
||||
@ -311,16 +271,7 @@ command.add(nil, {
|
||||
end,
|
||||
|
||||
["jpdebug:stop"] = function()
|
||||
core.log(dump(running_proc))
|
||||
if running_runner then
|
||||
running_runner:kill(running_proc)
|
||||
end
|
||||
core.log("[jpdebug] Stopped runner")
|
||||
if active_view then
|
||||
active_view:push("stdout", " ... Stopped")
|
||||
end
|
||||
running_proc = nil
|
||||
running_runner = nil
|
||||
debugger.stop()
|
||||
end,
|
||||
|
||||
-- The set target command
|
||||
|
||||
@ -18,7 +18,6 @@ end
|
||||
local function spawn_lua_process(entry, lua, cwd, env)
|
||||
local host = "localhost"
|
||||
local port = 8172
|
||||
local nowait = false
|
||||
|
||||
-- Resolve vendor/?.lua so "require('mobdebug')" finds the bundled file
|
||||
local vendor_glob = join(get_plugin_root(), "vendor/?.lua")
|
||||
@ -28,9 +27,8 @@ local function spawn_lua_process(entry, lua, cwd, env)
|
||||
local ok, m = pcall(require, "mobdebug"); if ok then
|
||||
print("Connecting to "..%q..":"..tostring(%d))
|
||||
local connected = m.start(%q, %d)
|
||||
if not connected and %s then m.off() end
|
||||
end
|
||||
]], host, port, host, port, nowait and "true" or "false")
|
||||
]], host, port, host, port)
|
||||
local launcher = string.format([[
|
||||
package.path = %q .. ";" .. package.path
|
||||
%s
|
||||
@ -74,8 +72,6 @@ function LDB:run(target, name, debuginfo)
|
||||
local cwd = target.cwd or "."
|
||||
local env = target.env or {}
|
||||
|
||||
-- TODO spawn the mobdebugger
|
||||
|
||||
-- spawn the main lua process
|
||||
local proc = spawn_lua_process(entry, lua, cwd, env)
|
||||
|
||||
@ -85,7 +81,7 @@ function LDB:run(target, name, debuginfo)
|
||||
end
|
||||
|
||||
return {
|
||||
luaproc=proc,
|
||||
luaproc=proc
|
||||
}
|
||||
end
|
||||
|
||||
@ -96,12 +92,14 @@ end
|
||||
|
||||
-- Read the stdout, returns nil if process has stopped
|
||||
function LDB:read_stdout(proc)
|
||||
return proc.luaproc:read_stdout()
|
||||
local sl = proc.luaproc:read_stdout()
|
||||
return sl
|
||||
end
|
||||
|
||||
-- Read the stderr
|
||||
function LDB:read_stderr(proc)
|
||||
return proc.luaproc:read_stderr()
|
||||
local sl = proc.luaproc:read_stderr()
|
||||
return sl
|
||||
end
|
||||
|
||||
-- Kill the process
|
||||
|
||||
@ -1,19 +1,32 @@
|
||||
local core = require "core"
|
||||
local process = require "process"
|
||||
|
||||
---@class M
|
||||
local M = {
|
||||
name = "shell"
|
||||
---@class shell: runner
|
||||
local shell = {
|
||||
name = "shell",
|
||||
proc = nil ---@type process|nil
|
||||
}
|
||||
|
||||
-- Run a shell command
|
||||
---@param target table Target table
|
||||
---@param name string Name of the target to run
|
||||
---@praam debuginfo table Debugging information
|
||||
---@return process|nil
|
||||
---@diagnostic disable-next-line: unused-local
|
||||
function M:run(target, name, debuginfo)
|
||||
core.log("[jpdebug] Running shell command")
|
||||
function shell:new(o)
|
||||
o = o or {}
|
||||
setmetatable(o, self)
|
||||
self.__index = self
|
||||
return o
|
||||
end
|
||||
|
||||
---@meta
|
||||
function shell.log(msg) end
|
||||
---@meta
|
||||
function shell.error(msg) end
|
||||
---@meta
|
||||
function shell.stdout(msg) end
|
||||
---@meta
|
||||
function shell.stderr(msg) end
|
||||
---@meta
|
||||
function shell.exited() end
|
||||
|
||||
|
||||
function shell:run(target, name)
|
||||
local opts = {
|
||||
cwd = target.cwd or ".",
|
||||
env = target.env or {},
|
||||
@ -21,43 +34,46 @@ function M:run(target, name, debuginfo)
|
||||
stderr = process.REDIRECT_PIPE
|
||||
}
|
||||
if target.cmd then
|
||||
local proc = process.start(target.cmd, opts)
|
||||
return proc
|
||||
self.proc = process.start(target.cmd, opts)
|
||||
if not self.proc then
|
||||
self.error("Could not start process...")
|
||||
return
|
||||
end
|
||||
else
|
||||
core.error("[jpdebug] command not specified for target %s", name)
|
||||
end
|
||||
self.error(string.format("command not specified for target %s", name))
|
||||
end
|
||||
|
||||
-- Wait untill it ends, possibly with timeout
|
||||
---@param proc process Process object
|
||||
---@param time any Time field, process.WAIT_INFINITE
|
||||
function M:wait(proc, time)
|
||||
return proc:wait(time)
|
||||
-- output pump
|
||||
core.add_thread(function()
|
||||
while true do
|
||||
core.redraw = true
|
||||
coroutine.yield(0.016) -- 60FPS
|
||||
local sout = self.proc:read_stdout()
|
||||
local serr = self.proc:read_stderr()
|
||||
if sout == nil and serr == nil then
|
||||
self.exited()
|
||||
break
|
||||
end
|
||||
if sout and sout~="" then self.stdout(sout) end
|
||||
if serr and serr~="" then self.stderr(serr) end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Read the stdout, returns nil if process has stopped
|
||||
---@param proc process Process object
|
||||
function M:read_stdout(proc)
|
||||
return proc:read_stdout()
|
||||
function shell:wait(time)
|
||||
if not self.proc then return end
|
||||
return self.proc:wait(time)
|
||||
end
|
||||
|
||||
-- Read the stderr
|
||||
---@param proc process Process object
|
||||
function M:read_stderr(proc)
|
||||
return proc:read_stderr()
|
||||
function shell:kill()
|
||||
if not self.proc then return end
|
||||
self.proc:kill()
|
||||
end
|
||||
|
||||
-- Kill the process
|
||||
---@param proc process Process object
|
||||
function M:kill(proc)
|
||||
proc:kill()
|
||||
function shell:terminate()
|
||||
if not self.proc then return end
|
||||
self.proc:terminate()
|
||||
end
|
||||
|
||||
-- Terminate the process
|
||||
---@param proc process Process object
|
||||
function M:terminate(proc)
|
||||
proc:terminate()
|
||||
end
|
||||
|
||||
return M
|
||||
return shell
|
||||
|
||||
|
||||
Reference in New Issue
Block a user