add visibility handling for the floating window

This commit is contained in:
2025-12-23 22:31:39 +01:00
parent e92c8476c2
commit 463d0ae2f7
5 changed files with 134 additions and 25 deletions

View File

@@ -1,6 +1,6 @@
local M = {} local M = {}
M.defaults = { local defaults = {
runner_modules = { runner_modules = {
"test-samurai.runners.go", "test-samurai.runners.go",
"test-samurai.runners.js-jest", "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) function M.set(opts)
if not opts or next(opts) == nil then if type(opts) ~= "table" then
M.options = vim.deepcopy(M.defaults) current = vim.deepcopy(defaults)
return return
end end
M.options = vim.tbl_deep_extend("force", M.defaults, opts) current = vim.tbl_deep_extend("force", vim.deepcopy(defaults), opts)
end end
function M.get() function M.get()
return M.options return current or defaults
end end
return M return M

View File

@@ -7,6 +7,7 @@ local state = {
runners = {}, runners = {},
last_win = nil, last_win = nil,
last_buf = nil, last_buf = nil,
autocmds_set = false,
} }
local function load_runners() local function load_runners()
@@ -23,8 +24,32 @@ local function load_runners()
end end
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() function M.setup()
load_runners() load_runners()
ensure_output_autocmds()
end end
function M.reload_runners() function M.reload_runners()
@@ -129,24 +154,32 @@ function M.get_runner_for_buf(bufnr)
return nil return nil
end end
local function create_output_win(initial_lines) local function float_geometry()
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 width = math.floor(vim.o.columns * 0.8) local width = math.floor(vim.o.columns * 0.8)
local height = math.floor(vim.o.lines * 0.8) local height = math.floor(vim.o.lines * 0.8)
local row = math.floor((vim.o.lines - height) / 2) local row = math.floor((vim.o.lines - height) / 2)
local col = math.floor((vim.o.columns - width) / 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 {}) 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, { local win = vim.api.nvim_open_win(buf, true, {
relative = "editor", relative = "editor",
width = width, width = width,
@@ -160,6 +193,9 @@ local function create_output_win(initial_lines)
vim.keymap.set("n", "<esc><esc>", function() vim.keymap.set("n", "<esc><esc>", function()
if vim.api.nvim_win_is_valid(win) then if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true) vim.api.nvim_win_close(win, true)
if state.last_win == win then
state.last_win = nil
end
end end
end, { buffer = buf, nowait = true, silent = true }) end, { buffer = buf, nowait = true, silent = true })
@@ -169,6 +205,42 @@ local function create_output_win(initial_lines)
return buf, win return buf, win
end 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", "<esc><esc>", 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) local function append_lines(buf, new_lines)
if not (buf and vim.api.nvim_buf_is_valid(buf)) then if not (buf and vim.api.nvim_buf_is_valid(buf)) then
return return
@@ -306,4 +378,12 @@ function M.run_nearest()
}) })
end 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 return M

View File

@@ -1,10 +1,10 @@
local config = require("test-samurai.config")
local core = require("test-samurai.core") local core = require("test-samurai.core")
local config = require("test-samurai.config")
local M = {} local M = {}
function M.setup(opts) function M.setup(opts)
config.setup(opts or {}) config.set(opts or {})
core.setup() core.setup()
end end
@@ -12,4 +12,8 @@ function M.test_nearest()
core.run_nearest() core.run_nearest()
end end
function M.show_output()
core.show_output()
end
return M return M

View File

@@ -1,10 +1,16 @@
if vim.g.loaded_test_samurai then if vim.g.loaded_test_samurai_plugin == 1 then
return return
end end
vim.g.loaded_test_samurai = true vim.g.loaded_test_samurai_plugin = 1
vim.api.nvim_create_user_command("TestNearest", function() vim.api.nvim_create_user_command("TestNearest", function()
require("test-samurai").test_nearest() require("test-samurai").test_nearest()
end, { end, { desc = "test-samurai: run nearest test" })
desc = "Run nearest test with test-samurai",
}) 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", "<leader>to", function()
require("test-samurai").show_output()
end, { desc = "test-samurai: show last test output" })

View File

@@ -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)