diff --git a/lua/neotest/client/strategies/overseer.lua b/lua/neotest/client/strategies/overseer.lua index 9c582acb..58a41798 100644 --- a/lua/neotest/client/strategies/overseer.lua +++ b/lua/neotest/client/strategies/overseer.lua @@ -1,6 +1,6 @@ -local async = require("neotest.async") local lib = require("neotest.lib") local log = require("overseer.log") +local nio = require("nio") local overseer = require("overseer") local util = require("overseer.util") @@ -49,8 +49,12 @@ local function get_or_create_task(spec, output_path) task.cwd = spec.cwd else -- Create a new task + local name = "Neotest" + if spec.position and spec.position.name then + name = string.format("%s %s", name, spec.position.name) + end local opts = vim.tbl_extend("keep", spec.strategy or {}, { - name = "Neotest", + name = name, components = { "default_neotest" }, }) if type(opts.components) == "function" then @@ -83,17 +87,19 @@ local function get_or_create_task(spec, output_path) return task end +---@param spec neotest.RunSpec +---@return neotest.Process local function get_strategy(spec) if not overseer.component.get_alias("default_neotest") then overseer.component.alias("default_neotest", { "default" }) end - local finish_cond = async.control.Condvar.new() + local finish_future = nio.control.future() local attach_win - local output_path = async.fn.tempname() + local output_path = nio.fn.tempname() local task = get_or_create_task(spec, output_path) task:subscribe("on_complete", function() - finish_cond:notify_all() + finish_future.set() return false end) task:start() @@ -104,31 +110,29 @@ local function get_strategy(spec) output = function() return output_path end, - stop = function() + stop = vim.schedule_wrap(function() task:stop() - end, + end), output_stream = function() - local sender, receiver = async.control.channel.mpsc() + local queue = nio.control.queue() task:subscribe("on_output", function(_, data) - sender.send(table.concat(data, "\n")) + queue.put_nowait(table.concat(data, "\n")) end) return function() - return async.lib.first(function() - finish_cond:wait() - end, receiver.recv) + return nio.first({ finish_future.wait, queue.get }) end end, attach = function() local bufnr = task:get_bufnr() - if not bufnr or not vim.api.nvim_buf_is_valid(bufnr) then + if not bufnr or not nio.api.nvim_buf_is_valid(bufnr) then return end attach_win = lib.ui.float.open({ - height = spec.strategy.height, - width = spec.strategy.width, + height = spec.strategy.height or 40, + width = spec.strategy.width or 120, buffer = bufnr, }) - async.api.nvim_buf_set_keymap(bufnr, "n", "q", "", { + nio.api.nvim_buf_set_keymap(bufnr, "n", "q", "", { noremap = true, silent = true, callback = function() @@ -139,7 +143,7 @@ local function get_strategy(spec) end, result = function() if not task:is_complete() then - finish_cond:wait() + finish_future:wait() end if attach_win then vim.schedule(function() diff --git a/lua/neotest/consumers/overseer.lua b/lua/neotest/consumers/overseer.lua index b43dff08..c1db6c68 100644 --- a/lua/neotest/consumers/overseer.lua +++ b/lua/neotest/consumers/overseer.lua @@ -1,6 +1,6 @@ -local async = require("neotest.async") local config = require("neotest.config") local lib = require("neotest.lib") +local nio = require("nio") local neotest = {} neotest.overseer = {} @@ -9,7 +9,7 @@ local client local last_group_id = 0 local task_groups = {} -function neotest.overseer.run(args) +neotest.overseer.run = nio.create(function(args) args = args or {} if type(args) == "string" then args = { args } @@ -19,50 +19,41 @@ function neotest.overseer.run(args) return neotest.run.run(args) end local strategy = require("neotest.client.strategies.overseer") - async.run(function() - local tree = neotest.run.get_tree_from_args(args, true) - if not tree then - lib.notify("No tests found") - return - end + local tree = neotest.run.get_tree_from_args(args, true) + if not tree then + lib.notify("No tests found") + return + end - if not args.strategy then - local root = tree:root():data().path - local default_strategy = config.projects[root].default_strategy - if - default_strategy - and default_strategy ~= "overseer" - and default_strategy ~= "integrated" - then - return neotest.run.run(args) - end + if not args.strategy then + local root = tree:root():data().path + local default_strategy = config.projects[root].default_strategy + if default_strategy and default_strategy ~= "overseer" and default_strategy ~= "integrated" then + return neotest.run.run(args) end + end - args.strategy = "overseer" - last_group_id = last_group_id + 1 - args.overseer_group_id = last_group_id - strategy.set_group_id(last_group_id) + args.strategy = "overseer" + last_group_id = last_group_id + 1 + strategy.set_group_id(last_group_id) - task_groups[last_group_id] = { args = args, position_id = tree:data().id } - client:run_tree(tree, args) - end) -end + task_groups[last_group_id] = { args = args, position_id = tree:data().id } + client:run_tree(tree, args) +end, 1) ---@private -function neotest.overseer.rerun_task_group(group_id) +neotest.overseer.rerun_task_group = nio.create(function(group_id) local strategy = require("neotest.client.strategies.overseer") strategy.recycle_group(group_id) strategy.set_group_id(group_id) local group = task_groups[group_id] - async.run(function() - local tree = client:get_position(group.position_id, group.args) - if not tree then - lib.notify("Prior test could not be found") - return - end - client:run_tree(tree, group.args) - end) -end + local tree = client:get_position(group.position_id, group.args) + if not tree then + lib.notify("Prior test could not be found") + return + end + client:run_tree(tree, group.args) +end, 1) function neotest.overseer.run_last(args) args = args or {} diff --git a/lua/overseer/component/unique.lua b/lua/overseer/component/unique.lua index c627bd6e..6b42a856 100644 --- a/lua/overseer/component/unique.lua +++ b/lua/overseer/component/unique.lua @@ -1,4 +1,5 @@ local task_list = require("overseer.task_list") +local util = require("overseer.util") return { desc = "Ensure that this task does not have any duplicates", -- Doesn't make sense for user to add this using a form. @@ -23,6 +24,10 @@ return { for _, t in ipairs(tasks) do if t.name == task.name and t ~= task then if params.replace then + task:subscribe("on_start", function() + util.replace_buffer_in_wins(t:get_bufnr(), task:get_bufnr()) + return false + end) t:dispose(true) else task:dispose(true) diff --git a/lua/overseer/task.lua b/lua/overseer/task.lua index db9fa58d..64adba60 100644 --- a/lua/overseer/task.lua +++ b/lua/overseer/task.lua @@ -362,7 +362,7 @@ end ---Listeners cannot be serialized, so will not be saved when saving task to disk and will not be ---copied when cloning the task. ---@param event string ----@param callback fun(task: overseer.Task) Callback can return false to unsubscribe itself +---@param callback fun(task: overseer.Task): nil|boolean Callback can return false to unsubscribe itself function Task:subscribe(event, callback) if not self._subscribers[event] then self._subscribers[event] = {} @@ -634,20 +634,7 @@ function Task:start() vim.api.nvim_buf_set_option(bufnr, "buflisted", false) end - -- If this task's previous buffer was open in any wins, replace it - if bufnr and self.prev_bufnr then - local prev_bufnr = self.prev_bufnr - for _, win in ipairs(vim.api.nvim_list_wins()) do - if vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_buf(win) == prev_bufnr then - -- If stickybuf is installed, make sure it doesn't interfere - pcall(vim.api.nvim_win_del_var, win, "sticky_original_bufnr") - pcall(vim.api.nvim_win_del_var, win, "sticky_bufnr") - pcall(vim.api.nvim_win_del_var, win, "sticky_buftype") - pcall(vim.api.nvim_win_del_var, win, "sticky_filetype") - vim.api.nvim_win_set_buf(win, bufnr) - end - end - end + util.replace_buffer_in_wins(self.prev_bufnr, bufnr) self.prev_bufnr = bufnr return true end diff --git a/lua/overseer/util.lua b/lua/overseer/util.lua index 8f4a5029..c75f7260 100644 --- a/lua/overseer/util.lua +++ b/lua/overseer/util.lua @@ -683,4 +683,23 @@ M.hack_around_termopen_autocmd = function(prev_mode) end, 10) end +---@param old_bufnr nil|integer +---@param new_bufnr nil|integer +M.replace_buffer_in_wins = function(old_bufnr, new_bufnr) + if not old_bufnr or not new_bufnr then + return + end + local has_stickybuf, stickybuf = pcall(require, "stickybuf") + -- If this task's previous buffer was open in any wins, replace it + for _, win in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_is_valid(win) and vim.api.nvim_win_get_buf(win) == old_bufnr then + -- If stickybuf is installed, make sure it doesn't interfere + if has_stickybuf then + stickybuf.unpin(win) + end + vim.api.nvim_win_set_buf(win, new_bufnr) + end + end +end + return M