From 456a157549f5651ec3b85cb7471a8303f0b453e8 Mon Sep 17 00:00:00 2001 From: "M.Schirmer" Date: Tue, 20 Jan 2026 09:59:21 +0100 Subject: [PATCH] mark listing entry when details are visible --- README.md | 1 + doc/test-samurai.txt | 1 + lua/test-samurai/core.lua | 36 ++++++++++++++++++++++++++++++++ tests/test_samurai_core_spec.lua | 11 ++++++++++ 4 files changed, 49 insertions(+) diff --git a/README.md b/README.md index 4acc4a3..a4822e0 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ Before running any test command, test-samurai runs `:wall` to save all buffers. - ANSI color translation is only applied in the **Detail-Float**; the **Test-Listing-Float** shows raw text without ANSI translation. - `` hides the floating window and restores the cursor position; `TSamShowOutput` reopens it. - If no output is captured for a test, the **Detail-Float** shows `No output captured`. +- The active listing entry is highlighted while the **Detail-Float** is visible. - Summary lines (`TOTAL`/`DURATION`) are appended in the listing output, including `TSamLast`. ## Runner architecture diff --git a/doc/test-samurai.txt b/doc/test-samurai.txt index b9847d4..ccf1f9b 100644 --- a/doc/test-samurai.txt +++ b/doc/test-samurai.txt @@ -73,6 +73,7 @@ Testing-Float: Close Detail-Float (when focused) Notes: + Active listing entry is highlighted while the Detail-Float is visible. Buffers are saved via :wall before every test run. diff --git a/lua/test-samurai/core.lua b/lua/test-samurai/core.lua index 7bbf738..eb1f739 100644 --- a/lua/test-samurai/core.lua +++ b/lua/test-samurai/core.lua @@ -28,6 +28,7 @@ local state = { trigger_cursor = nil, listing_unfiltered_lines = nil, listing_filtered_kind = nil, + detail_line = nil, hardtime_refcount = 0, hardtime_was_enabled = false, autocmds_set = false, @@ -37,6 +38,7 @@ local summary_ns = vim.api.nvim_create_namespace("TestSamuraiSummary") local result_ns = vim.api.nvim_create_namespace("TestSamuraiResult") local detail_ns = vim.api.nvim_create_namespace("TestSamuraiDetailAnsi") local help_ns = vim.api.nvim_create_namespace("TestSamuraiHelp") +local listing_sel_ns = vim.api.nvim_create_namespace("TestSamuraiListingSelection") local apply_border_kind local close_container local restore_listing_full @@ -100,6 +102,7 @@ local function help_lines() "", "Notes:", " No output captured -> shows placeholder text", + " Active listing entry is highlighted while Detail-Float is visible", " Buffers are saved via :wall before every test run", } end @@ -149,6 +152,7 @@ local function apply_listing_lines(buf, lines) vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) vim.api.nvim_buf_clear_namespace(buf, result_ns, 0, -1) vim.api.nvim_buf_clear_namespace(buf, summary_ns, 0, -1) + vim.api.nvim_buf_clear_namespace(buf, listing_sel_ns, 0, -1) apply_result_highlights(buf, 0, lines) apply_summary_highlights(buf, 0, lines) rebuild_result_line_map(lines) @@ -382,6 +386,30 @@ local function jump_listing_and_open(kind) end end +local function clear_listing_selection() + if state.last_buf and vim.api.nvim_buf_is_valid(state.last_buf) then + vim.api.nvim_buf_clear_namespace(state.last_buf, listing_sel_ns, 0, -1) + end + state.detail_line = nil +end + +local function apply_listing_selection(line) + if not (state.last_buf and vim.api.nvim_buf_is_valid(state.last_buf)) then + return + end + vim.api.nvim_buf_clear_namespace(state.last_buf, listing_sel_ns, 0, -1) + if not line then + state.detail_line = nil + return + end + local total = vim.api.nvim_buf_line_count(state.last_buf) + if line < 1 or line > total then + return + end + vim.api.nvim_buf_add_highlight(state.last_buf, listing_sel_ns, "TestSamuraiListingActive", line - 1, 0, -1) + state.detail_line = line +end + local function find_normal_window() for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do local cfg = vim.api.nvim_win_get_config(win) @@ -534,6 +562,7 @@ local function setup_summary_highlights() pcall(vim.api.nvim_set_hl, 0, "TestSamuraiResultSkip", { fg = skip_fg }) pcall(vim.api.nvim_set_hl, 0, "TestSamuraiBorderPass", { fg = pass_fg, bold = true }) pcall(vim.api.nvim_set_hl, 0, "TestSamuraiBorderFail", { fg = fail_fg, bold = true }) + pcall(vim.api.nvim_set_hl, 0, "TestSamuraiListingActive", { link = "Visual" }) end local function load_runners() @@ -567,6 +596,7 @@ local function ensure_output_autocmds() if state.detail_win and closed == state.detail_win then state.detail_win = nil restore_listing_full() + clear_listing_selection() hardtime_restore() return end @@ -577,6 +607,7 @@ local function ensure_output_autocmds() pcall(vim.api.nvim_win_close, state.detail_win, true) state.detail_win = nil end + clear_listing_selection() return end end, @@ -744,6 +775,7 @@ close_container = function() pcall(vim.api.nvim_win_close, state.last_win, true) state.last_win = nil end + clear_listing_selection() end local function close_container_and_restore() @@ -763,6 +795,7 @@ close_detail_float = function() if state.detail_win and vim.api.nvim_win_is_valid(state.detail_win) then pcall(vim.api.nvim_win_close, state.detail_win, true) end + clear_listing_selection() end restore_listing_full = function() @@ -1472,10 +1505,12 @@ function M.open_test_output_at_cursor() end if type(output) ~= "table" or #output == 0 then open_detail_split({ "", "No output captured" }, "default") + apply_listing_selection(line) return end local border_kind = status and status:lower() or nil open_detail_split(output, border_kind) + apply_listing_selection(line) end function M.show_help() @@ -1485,6 +1520,7 @@ function M.show_help() end local lines = help_lines() open_detail_split(lines, "default") + clear_listing_selection() apply_help_highlights(state.detail_buf, lines) end diff --git a/tests/test_samurai_core_spec.lua b/tests/test_samurai_core_spec.lua index 23c0452..a5edb02 100644 --- a/tests/test_samurai_core_spec.lua +++ b/tests/test_samurai_core_spec.lua @@ -1006,6 +1006,17 @@ describe("test-samurai core (no bundled runners)", function() local detail_buf = vim.api.nvim_get_current_buf() local detail_lines = vim.api.nvim_buf_get_lines(detail_buf, 0, -1, false) assert.same({ "", "No output captured" }, detail_lines) + local selection_ns = vim.api.nvim_create_namespace("TestSamuraiListingSelection") + local marks = vim.api.nvim_buf_get_extmarks(listing_buf, selection_ns, 0, -1, { details = true }) + assert.is_true(#marks > 0) + local highlighted = false + for _, mark in ipairs(marks) do + if mark[2] == target - 1 then + highlighted = true + break + end + end + assert.is_true(highlighted) vim.fn.jobstart = orig_jobstart end)