diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b987d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +logs.txt diff --git a/.lite_project.lua b/.lite_project.lua index e0f6d3c..3a629b2 100644 --- a/.lite_project.lua +++ b/.lite_project.lua @@ -9,7 +9,7 @@ config.plugins.jpdebug = { ["test"] = { type = "shell", cmd = {"lua", "test.lua"} - } + } }, default_target = "test" } diff --git a/init.lua b/init.lua index dde8cb6..ac5bc9e 100644 --- a/init.lua +++ b/init.lua @@ -5,6 +5,8 @@ local command = require "core.command" local View = require "core.view" local process = require "process" local config = require "core.config" +local TreeView = require "plugins.treeview" +local ToolbarView = require "plugins.toolbarview" core.jpdebug = core.jpdebug or {} @@ -13,16 +15,28 @@ core.jpdebug.runners = core.jpdebug.runners or {} local runner_shell = require("plugins.jpdebug.runners.shell") core.jpdebug.runners[runner_shell.name] = runner_shell --- A list of created views -local active_views = {} +-- Currently used view +local active_view = nil -- The selected target local selected_target = nil --- Local helper functions for debugging -------------------------- +-- The running system +local running_proc = nil +local running_runner = nil + +-- Check if required plugins are installed +local required_toolbar_plugins = true +if TreeView == nil or ToolbarView == nil then + required_toolbar_plugins = false +end + +-- Local helper functions ---------------------------------------- + ---@diagnostic disable-next-line: unused-function -local function dump(o) - if type(o) == 'table' then +local function dump(o, force) + force = force or false + if type(o) == 'table' or force then local s = '{ ' for k,v in pairs(o) do if type(k) ~= 'number' then k = '"'..k..'"' end @@ -30,10 +44,23 @@ local function dump(o) end return s .. '} ' else - return tostring(o) + return type(o)..": "..tostring(o) end end +local function get_plugin_directory() + local paths = { + USERDIR .. PATHSEP .. "plugins" .. PATHSEP .. "jpdebug", + DATADIR .. PATHSEP .. "plugins" .. PATHSEP .. "jpdebug" + } + for i, v in ipairs(paths) do + if system.get_file_info(v) then + return v + end + end + return nil +end + -- ---------- JPDebugView: a simple scrollable log view ---------- ---@class JPDebugView : core.view local JPDebugView = View:extend() @@ -94,6 +121,11 @@ function JPDebugView:draw() self:draw_scrollbar() end +function JPDebugView:try_close(do_close) + JPDebugView.super.try_close(self, do_close) + active_view = nil +end + -- ---------- helper: pick a target from project module ---------- local function get_targets() local t = (config.plugins and config.plugins.jpdebug and config.plugins.jpdebug.targets) or {} @@ -110,28 +142,29 @@ local function run_target(target, name) local title = ("JP Debug: %s"):format(name) local view = nil - if active_views[title] then + if active_view then -- If there is already a view use that one - view = active_views[title] + view = active_view else -- Otherwhise lets make one view = JPDebugView(title) core.root_view:get_active_node():add_view(view) - active_views[title] = view + active_view = view end -- 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 - local proc = runner:run(target.cmd, { + running_proc = runner:run(target.cmd, { cwd = target.cwd or ".", env = target.env or {}, stdout = process.REDIRECT_PIPE, stderr = process.REDIRECT_PIPE }, name) + running_runner = runner - if proc == nil then + if running_proc == nil then core.error("[jpdebug] Could not run the target") return end @@ -141,19 +174,24 @@ local function run_target(target, name) core.add_thread(function() while true do coroutine.yield(0.016) -- ~60fps - local out = proc:read_stdout() + if running_proc == nil then + return + end + local out = running_proc:read_stdout() if out == nil then -- stdout pipe closed: try drain stderr and break when both closed - local err = proc:read_stderr() + 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 = proc:read_stderr() + local err = runner:read_stderr(running_proc) if err ~= nil and err ~= "" then view:push("stderr", err) end end - local code = proc:wait(process.WAIT_INFINITE) + local code = runner:wait(process.WAIT_INFINITE) view:push("stdout", ("\n[exit] code=%s\n"):format(tostring(code))) + running_proc = nil + running_runner = nil end) return view @@ -163,6 +201,39 @@ local function run_target(target, name) core.error("[jpdebug] No suitable runners found for target %s", name) end +-- ---------- Add toolbar to treeview if plugins are installed ------ +if required_toolbar_plugins then + + ---@class Toolbar: core.view + local Toolbar = ToolbarView:extend() + function Toolbar:new() + Toolbar.super.new(self) + self.toolbar_font = renderer.font.load(get_plugin_directory() .. PATHSEP .. "toolbar_commands.ttf", style.icon_big_font:get_size()) + self.toolbar_commands = {} + end + + function Toolbar:_rebuild() + local t = { + {symbol = "A", command = "jpdebug:settarget"}, + } + if running_proc == nil then + table.insert(t, {symbol = "B", command = "jpdebug:run"}) + else + table.insert(t, {symbol = "D", command = "jpdebug:stop"}) + end + self.toolbar_commands = t + end + + function Toolbar:update() + Toolbar.super.update(self) + self:_rebuild() + end + + local toolbar_view = Toolbar() + local toolbar_node = TreeView.node.b:split("up", toolbar_view, {y = true}) + +end + ---@diagnostic disable-next-line: param-type-mismatch command.add(nil, { @@ -184,6 +255,18 @@ command.add(nil, { end end, + ["jpdebug:stop"] = function() + core.log(dump(running_proc)) + running_proc:kill() + running_runner:kill(running_proc) + core.log("[jpdebug] Stopped runner") + if active_view then + active_view:push("stdout", " ... Stopped") + end + running_proc = nil + running_runner = nil + end, + -- The set target command ["jpdebug:settarget"] = function() core.command_view:enter("Select target", { @@ -204,5 +287,6 @@ command.add(nil, { end }) end, + }) diff --git a/runners/shell.lua b/runners/shell.lua index 5622ed3..617282e 100644 --- a/runners/shell.lua +++ b/runners/shell.lua @@ -6,6 +6,7 @@ local M = { name = "shell" } +-- Run a shell command function M:run(cmd, opts, name) core.log("[jpdebug] Running shell command") if cmd then @@ -16,5 +17,30 @@ function M:run(cmd, opts, name) end end +-- Wait untill it ends, possibly with timeout +function M:wait(proc, time) + return proc:wait(time) +end + +-- Read the stdout, returns nil if process has stopped +function M:read_stdout(proc) + return proc:read_stdout() +end + +-- Read the stderr +function M:read_stderr(proc) + return proc:read_stderr() +end + +-- Kill the process +function M:kill(proc) + proc:kill() +end + +-- Terminate the process +function M:terminate(proc) + proc:terminate() +end + return M diff --git a/test.lua b/test.lua index 6d72ab0..677bb2a 100644 --- a/test.lua +++ b/test.lua @@ -1,5 +1,8 @@ +local socket = require 'socket' + print("Starting loop: test 123") -for i = 1, 4 do +for i = 1,100 do + socket.sleep(0.5) print("i =", i) -- we'll stop here end print("Yaaayyyy it works perfectly fine :)") diff --git a/toolbar_commands.ttf b/toolbar_commands.ttf new file mode 100644 index 0000000..9e5b30b Binary files /dev/null and b/toolbar_commands.ttf differ