Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions lua/neotest/client/strategies/overseer.lua
Original file line number Diff line number Diff line change
@@ -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")

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand Down
63 changes: 27 additions & 36 deletions lua/neotest/consumers/overseer.lua
Original file line number Diff line number Diff line change
@@ -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 = {}
Expand All @@ -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 }
Expand All @@ -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 {}
Expand Down
5 changes: 5 additions & 0 deletions lua/overseer/component/unique.lua
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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)
Expand Down
17 changes: 2 additions & 15 deletions lua/overseer/task.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {}
Expand Down Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions lua/overseer/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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