diff --git a/lua/test-samurai/config.lua b/lua/test-samurai/config.lua index 30f3c01..e13eddd 100644 --- a/lua/test-samurai/config.lua +++ b/lua/test-samurai/config.lua @@ -1,6 +1,6 @@ local M = {} -M.defaults = { +local defaults = { runner_modules = { "test-samurai.runners.go", "test-samurai.runners.js-jest", @@ -9,18 +9,18 @@ M.defaults = { }, } -M.options = vim.deepcopy(M.defaults) +local current = vim.deepcopy(defaults) -function M.setup(opts) - if not opts or next(opts) == nil then - M.options = vim.deepcopy(M.defaults) +function M.set(opts) + if type(opts) ~= "table" then + current = vim.deepcopy(defaults) return end - M.options = vim.tbl_deep_extend("force", M.defaults, opts) + current = vim.tbl_deep_extend("force", vim.deepcopy(defaults), opts) end function M.get() - return M.options + return current or defaults end return M diff --git a/lua/test-samurai/core.lua b/lua/test-samurai/core.lua index ada304c..4d280be 100644 --- a/lua/test-samurai/core.lua +++ b/lua/test-samurai/core.lua @@ -7,6 +7,7 @@ local state = { runners = {}, last_win = nil, last_buf = nil, + autocmds_set = false, } local function load_runners() @@ -23,8 +24,32 @@ local function load_runners() end end +local function ensure_output_autocmds() + if state.autocmds_set then + return + end + + local group = vim.api.nvim_create_augroup("TestSamuraiOutput", { clear = true }) + + vim.api.nvim_create_autocmd({ "BufEnter", "WinEnter" }, { + group = group, + callback = function() + if state.last_win and vim.api.nvim_win_is_valid(state.last_win) then + local cur = vim.api.nvim_get_current_win() + if cur ~= state.last_win then + pcall(vim.api.nvim_win_close, state.last_win, true) + state.last_win = nil + end + end + end, + }) + + state.autocmds_set = true +end + function M.setup() load_runners() + ensure_output_autocmds() end function M.reload_runners() @@ -129,24 +154,32 @@ function M.get_runner_for_buf(bufnr) return nil end -local function create_output_win(initial_lines) - if state.last_win and vim.api.nvim_win_is_valid(state.last_win) then - pcall(vim.api.nvim_win_close, state.last_win, true) - end - if state.last_buf and vim.api.nvim_buf_is_valid(state.last_buf) then - pcall(vim.api.nvim_buf_delete, state.last_buf, { force = true }) - end - +local function float_geometry() local width = math.floor(vim.o.columns * 0.8) local height = math.floor(vim.o.lines * 0.8) local row = math.floor((vim.o.lines - height) / 2) local col = math.floor((vim.o.columns - width) / 2) + return width, height, row, col +end + +local function create_output_win(initial_lines) + if state.last_win and vim.api.nvim_win_is_valid(state.last_win) then + pcall(vim.api.nvim_win_close, state.last_win, true) + state.last_win = nil + end + + local buf = state.last_buf + if not (buf and vim.api.nvim_buf_is_valid(buf)) then + buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_option(buf, "bufhidden", "hide") + vim.api.nvim_buf_set_option(buf, "filetype", "test-samurai-output") + state.last_buf = buf + end - local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe") - vim.api.nvim_buf_set_option(buf, "filetype", "test-samurai-output") vim.api.nvim_buf_set_lines(buf, 0, -1, false, initial_lines or {}) + local width, height, row, col = float_geometry() + local win = vim.api.nvim_open_win(buf, true, { relative = "editor", width = width, @@ -160,6 +193,9 @@ local function create_output_win(initial_lines) vim.keymap.set("n", "", function() if vim.api.nvim_win_is_valid(win) then vim.api.nvim_win_close(win, true) + if state.last_win == win then + state.last_win = nil + end end end, { buffer = buf, nowait = true, silent = true }) @@ -169,6 +205,42 @@ local function create_output_win(initial_lines) return buf, win end +local function reopen_output_win() + if not (state.last_buf and vim.api.nvim_buf_is_valid(state.last_buf)) then + return nil, nil + end + + if state.last_win and vim.api.nvim_win_is_valid(state.last_win) then + vim.api.nvim_set_current_win(state.last_win) + return state.last_buf, state.last_win + end + + local width, height, row, col = float_geometry() + + local win = vim.api.nvim_open_win(state.last_buf, true, { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded", + }) + + vim.keymap.set("n", "", function() + if vim.api.nvim_win_is_valid(win) then + vim.api.nvim_win_close(win, true) + if state.last_win == win then + state.last_win = nil + end + end + end, { buffer = state.last_buf, nowait = true, silent = true }) + + state.last_win = win + + return state.last_buf, win +end + local function append_lines(buf, new_lines) if not (buf and vim.api.nvim_buf_is_valid(buf)) then return @@ -306,4 +378,12 @@ function M.run_nearest() }) end +function M.show_output() + if not (state.last_buf and vim.api.nvim_buf_is_valid(state.last_buf)) then + vim.notify("[test-samurai] No previous output", vim.log.levels.WARN) + return + end + reopen_output_win() +end + return M diff --git a/lua/test-samurai/init.lua b/lua/test-samurai/init.lua index 609c585..58ee7ec 100644 --- a/lua/test-samurai/init.lua +++ b/lua/test-samurai/init.lua @@ -1,10 +1,10 @@ -local config = require("test-samurai.config") local core = require("test-samurai.core") +local config = require("test-samurai.config") local M = {} function M.setup(opts) - config.setup(opts or {}) + config.set(opts or {}) core.setup() end @@ -12,4 +12,8 @@ function M.test_nearest() core.run_nearest() end +function M.show_output() + core.show_output() +end + return M diff --git a/plugin/test-samurai.lua b/plugin/test-samurai.lua index b15c3f2..b72f987 100644 --- a/plugin/test-samurai.lua +++ b/plugin/test-samurai.lua @@ -1,10 +1,16 @@ -if vim.g.loaded_test_samurai then +if vim.g.loaded_test_samurai_plugin == 1 then return end -vim.g.loaded_test_samurai = true +vim.g.loaded_test_samurai_plugin = 1 vim.api.nvim_create_user_command("TestNearest", function() require("test-samurai").test_nearest() -end, { - desc = "Run nearest test with test-samurai", -}) +end, { desc = "test-samurai: run nearest test" }) + +vim.api.nvim_create_user_command("TsShowOutput", function() + require("test-samurai").show_output() +end, { desc = "test-samurai: show last test output" }) + +vim.keymap.set("n", "to", function() + require("test-samurai").show_output() +end, { desc = "test-samurai: show last test output" }) diff --git a/tests/test_samurai_output_spec.lua b/tests/test_samurai_output_spec.lua new file mode 100644 index 0000000..a3d2272 --- /dev/null +++ b/tests/test_samurai_output_spec.lua @@ -0,0 +1,19 @@ +local test_samurai = require("test-samurai") +local core = require("test-samurai.core") + +describe("test-samurai output API", function() + it("delegates show_output to core", function() + local called = false + local orig = core.show_output + + core.show_output = function() + called = true + end + + test_samurai.show_output() + + core.show_output = orig + + assert.is_true(called) + end) +end)