Skip to content
Open
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
44 changes: 42 additions & 2 deletions lua/opencode/provider/snacks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
---@class opencode.provider.Snacks : opencode.Provider
---
---@field opts snacks.terminal.Opts
---@field private _job_id number|nil
---@field private _pid number|nil
local Snacks = {}
Snacks.__index = Snacks
Snacks.name = "snacks"
Expand All @@ -15,6 +17,8 @@ Snacks.name = "snacks"
function Snacks.new(opts)
local self = setmetatable({}, Snacks)
self.opts = opts or {}
self._job_id = nil
self._pid = nil
return self
end

Expand Down Expand Up @@ -44,19 +48,55 @@ end

function Snacks:toggle()
require("snacks.terminal").toggle(self.cmd, self.opts)
-- Capture the job ID and PID after terminal opens (may be a new terminal)
vim.defer_fn(function()
local win = self:get()
if win and win.buf and vim.api.nvim_buf_is_valid(win.buf) then
self._job_id = vim.b[win.buf].terminal_job_id
if self._job_id then
pcall(function()
self._pid = vim.fn.jobpid(self._job_id)
end)
end
end
end, 100)
end

function Snacks:start()
if not self:get() then
require("snacks.terminal").open(self.cmd, self.opts)
-- Capture the job ID and PID after terminal opens
vim.defer_fn(function()
local win = self:get()
if win and win.buf and vim.api.nvim_buf_is_valid(win.buf) then
self._job_id = vim.b[win.buf].terminal_job_id
if self._job_id then
pcall(function()
self._pid = vim.fn.jobpid(self._job_id)
end)
end
end
end, 100)
end
end

function Snacks:stop()
-- Kill via PID using shell kill (most reliable during VimLeavePre,
-- as vim.uv.kill and jobstop may not work when Neovim is shutting down)
if self._pid then
vim.fn.system("kill -TERM " .. self._pid .. " 2>/dev/null")
self._pid = nil
end

-- Also try jobstop as a fallback
if self._job_id then
pcall(vim.fn.jobstop, self._job_id)
self._job_id = nil
end

-- Close the window via snacks
local win = self:get()
if win then
-- TODO: Stop the job first so we don't get error exit code.
-- Not sure how to get the job ID from snacks API though.
win:close()
end
end
Expand Down
6 changes: 6 additions & 0 deletions lua/opencode/provider/terminal.lua
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ end

---Close the window, delete the buffer.
function Terminal:stop()
if self.bufnr ~= nil and vim.api.nvim_buf_is_valid(self.bufnr) then
local job_id = vim.b[self.bufnr].terminal_job_id
if job_id then
vim.fn.jobstop(job_id)
end
end
if self.winid ~= nil and vim.api.nvim_win_is_valid(self.winid) then
vim.api.nvim_win_close(self.winid, true)
self.winid = nil
Expand Down
2 changes: 1 addition & 1 deletion plugin/provider.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
vim.api.nvim_create_autocmd("VimLeave", {
vim.api.nvim_create_autocmd("VimLeavePre", {
group = vim.api.nvim_create_augroup("OpencodeProvider", { clear = true }),
pattern = "*",
callback = function()
Expand Down