Skip to content

Commit 997c612

Browse files
committed
✨ Feat(floating_terminal): add callback function
Implements a new callback function that allows interaction with the result of commands run in the floating terminal window BREAKING CHANGE: The ispreupdate option is now deprecated and will be removed in a future release. The callback function option provides a better way to trigger subsequent functions making ispreupdate obsolete.
1 parent 07c47b2 commit 997c612

File tree

2 files changed

+150
-33
lines changed

2 files changed

+150
-33
lines changed

lua/nvim_updater/init.lua

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,23 @@ function P.update_neovim(opts)
141141

142142
local build_command = "cd " .. source_dir .. " && make CMAKE_BUILD_TYPE=" .. build_type .. " && sudo make install"
143143

144+
local update_command = git_commands .. " && " .. build_command
145+
144146
-- Use the open_floating_terminal from the 'utils' module
145-
utils.open_floating_terminal(git_commands .. " && " .. build_command, "neovim_updater_term.updating", false, true)
147+
utils.open_floating_terminal({
148+
command = update_command,
149+
filetype = "neovim_updater_term.updating",
150+
ispreupdate = false,
151+
autoclose = true,
152+
callback = function(results)
153+
if results.result_code ~= 0 then
154+
utils.notify("Neovim update failed with error code: " .. results.result_code, vim.log.levels.ERROR)
155+
else
156+
utils.notify("Neovim update complete!", vim.log.levels.INFO)
157+
utils.notify("Please restart Neovim for the changes to take effect.", vim.log.levels.INFO)
158+
end
159+
end,
160+
})
146161

147162
-- Go to insert mode
148163
vim.cmd("startinsert")
@@ -154,7 +169,10 @@ end
154169
--- Remove the Neovim source directory or a custom one.
155170
---@function P.remove_source_dir
156171
---@param opts table|nil Optional table for 'source_dir'
157-
---@return boolean success True if the directory was successfully removed, false otherwise
172+
---@return boolean|nil success True if the directory was successfully removed
173+
--- False if the directory does not exist or an error occurred
174+
--- nil if the function is delayed until the terminal is closed
175+
--- Check the U.defered_value variable for the result
158176
function P.remove_source_dir(opts)
159177
opts = opts or {}
160178
local source_dir = opts.source_dir ~= "" and opts.source_dir or P.default_config.source_dir
@@ -172,12 +190,47 @@ function P.remove_source_dir(opts)
172190
if not err then
173191
err = "Unknown error"
174192
end
175-
utils.notify(
176-
"Error removing Neovim source directory: " .. source_dir .. "\n" .. err,
177-
vim.log.levels.ERROR
178-
)
179193
utils.notify("Source directory removal failed with vim.fs.rm", vim.log.levels.DEBUG)
180-
return false
194+
195+
-- Define callback function for checking rm
196+
local function check_rm()
197+
-- Check if the source directory still exists
198+
if not utils.directory_exists(source_dir) then
199+
utils.notify(
200+
"Successfully removed Neovim source directory: " .. source_dir,
201+
vim.log.levels.INFO
202+
)
203+
return true
204+
end
205+
utils.notify("Failed to remove Neovim source directory: " .. source_dir, vim.log.levels.ERROR)
206+
return false
207+
end
208+
209+
-- Attempt to remove with elevated privileges
210+
local rm_msg = "echo Attempting to remove source directory with elevated privileges.\n"
211+
.. "echo Please authorize sudo and press enter.\n"
212+
local privileged_rm = rm_msg .. "sudo rm -rf " .. source_dir
213+
utils.open_floating_terminal({
214+
command = privileged_rm,
215+
filetype = "neovim_updater_term.privileged_rm",
216+
ispreupdate = false,
217+
autoclose = true,
218+
callback = function(results)
219+
if results.result_code == 0 then
220+
-- Double-check the results
221+
check_rm()
222+
else
223+
utils.notify(
224+
"Failed to remove Neovim source directory: " .. source_dir,
225+
vim.log.levels.ERROR
226+
)
227+
end
228+
end,
229+
})
230+
-- Go to insert mode
231+
vim.cmd("startinsert")
232+
233+
return nil
181234
end
182235
end
183236
-- Fallback to vim.fn.delete if vim.fs.rm is not available
@@ -211,23 +264,40 @@ function P.generate_source_dir(opts)
211264
local repo = "https://github.com/neovim/neovim.git"
212265
local branch = opts.branch ~= "" and opts.branch or P.default_config.branch
213266

214-
-- Build the command to fetch the latest changes from the remote repository
215-
local fetch_command = ("cd ~ && git clone %s %s"):format(repo, source_dir)
216-
217-
-- Checkout the branch
218-
local checkout_command = "cd " .. source_dir .. " && git checkout " .. branch
219-
220-
-- Combine commands
221-
local complete_command = fetch_command .. " && " .. checkout_command
222-
223-
-- Notify the user that the clone is starting
224-
utils.notify("Cloning Neovim source...", vim.log.levels.INFO)
225-
226-
-- Open a terminal window
227-
utils.open_floating_terminal(complete_command, "neovim_updater_term.cloning", false, false)
267+
if not utils.directory_exists(source_dir) then
268+
-- Build the command to fetch the latest changes from the remote repository
269+
local fetch_command = ("cd ~ && git clone %s %s"):format(repo, source_dir)
270+
271+
-- Checkout the branch
272+
local checkout_command = "cd " .. source_dir .. " && git checkout " .. branch
273+
274+
-- Combine commands
275+
local complete_command = fetch_command .. " && " .. checkout_command
276+
277+
-- Notify the user that the clone is starting
278+
utils.notify("Cloning Neovim source...", vim.log.levels.INFO)
279+
280+
-- Open a terminal window
281+
utils.open_floating_terminal({
282+
command = complete_command,
283+
filetype = "neovim_updater_term.cloning",
284+
ispreupdate = false,
285+
autoclose = true,
286+
callback = function(results)
287+
if results.result_code == 0 then
288+
utils.notify("Neovim source cloned successfully", vim.log.levels.INFO)
289+
else
290+
utils.notify("Failed to clone Neovim source: " .. results.result_code, vim.log.levels.ERROR)
291+
end
292+
end,
293+
})
228294

229-
-- Set the update count to "0"
230-
P.last_status.count = "0"
295+
-- Set the update count to "0"
296+
P.last_status.count = "0"
297+
else
298+
-- Notify the user that the source directory already exists
299+
utils.notify("Neovim source directory already exists: " .. source_dir, vim.log.levels.WARN)
300+
end
231301

232302
-- Return the source directory
233303
return source_dir
@@ -354,9 +424,10 @@ end
354424
--- @param short? boolean Optional. Whether to show a short commit list. Only used if `isupdate` is a boolean.
355425
function P.show_new_commits(isupdate, short)
356426
-- If the first argument is a table, treat it as an options table.
427+
local doupdate = false
357428
if type(isupdate) == "table" then
358429
local opts = isupdate
359-
isupdate = opts.isupdate
430+
doupdate = opts.isupdate
360431
short = opts.short
361432
end
362433
-- Define the path to the Neovim source directory
@@ -409,8 +480,15 @@ function P.show_new_commits(isupdate, short)
409480
utils.open_floating_terminal({
410481
command = term_command,
411482
filetype = "neovim_updater_term.changes",
412-
ispreupdate = isupdate,
483+
ispreupdate = false,
413484
autoclose = false,
485+
callback = function()
486+
if doupdate then
487+
utils.ConfirmPrompt("Perform Neovim update?", function()
488+
P.update_neovim()
489+
end)
490+
end
491+
end,
414492
})
415493
else
416494
utils.notify("No new Neovim commits.", vim.log.levels.INFO)

lua/nvim_updater/utils.lua

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,38 @@ function U.ConfirmPrompt(prompt, action)
157157

158158
return false
159159
end
160+
161+
--- Options table for configuring the floating terminal.
162+
---@class TerminalOptions
163+
---@field command string The shell command to run in the terminal
164+
---@field filetype? string Custom filetype for terminal buffer (optional)
165+
---@field ispreupdate? boolean @deprecated Whether the terminal is for changelog before updating Neovim (optional)
166+
--- (This is deprecated and will be removed in a future version)
167+
--- Please use the `callback` function instead.
168+
---@field autoclose? boolean Whether the terminal should be automatically closed (optional)
169+
---@field callback? fun(params?: TerminalCloseParams) Callback function to run after the terminal is closed
170+
171+
--- Callback parameter table for the floating terminal close event.
172+
---@class TerminalCloseParams
173+
---@field ev? table The close event object (optional)
174+
---@field result_code? integer The exit code of the terminal command process (optional)
175+
160176
-- Helper to display floating terminal in a centered, minimal Neovim window.
161177
-- This is useful for running long shell commands like building Neovim.
162-
-- You can pass arguments either as positional or as a table of options.
163-
---@param command_or_opts string|table Either a shell command (string) or a table with options
164-
---@param filetype? string Custom filetype for terminal buffer (optional if using table)
165-
---@param ispreupdate? boolean Whether the terminal is for changelog before updating Neovim (optional if using table)
166-
---@param autoclose? boolean Whether the terminal should be automatically closed (optional if using table)
167-
---@function open_floating_terminal
168-
function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autoclose)
178+
-- You can pass arguments either as positional values or as a table of options.
179+
---@param command_or_opts string|TerminalOptions Either a shell command (string) or a table of options
180+
---@param filetype? string Custom filetype for terminal buffer (optional if using positional arguments)
181+
---@param ispreupdate? boolean @deprecated Whether the terminal is for changelog before updating Neovim (optional if using positional arguments)
182+
--- (This is deprecated and will be removed in a future version)
183+
--- Please use the `callback` function instead.
184+
---@param autoclose? boolean Whether the terminal should be automatically closed (optional if using positional arguments)
185+
---@param callback? fun(params?: TerminalCloseParams) Callback function to run after the terminal is closed
186+
--
187+
-- This allows any function to be called after the terminal is closed,
188+
-- receiving the command result and event information in a single parameter table.
189+
function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autoclose, callback)
169190
local opts
191+
local result_code = -1 -- Indicates the command is still running
170192

171193
-- Determine if the first argument is a table or positional arguments
172194
if type(command_or_opts) == "table" then
@@ -177,6 +199,7 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
177199
filetype = filetype or "floating.term", -- Default filetype
178200
ispreupdate = ispreupdate or false,
179201
autoclose = autoclose or false,
202+
callback = callback or nil,
180203
}
181204
end
182205

@@ -185,6 +208,9 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
185208
filetype = opts.filetype or "FloatingTerm"
186209
ispreupdate = opts.ispreupdate or false
187210
autoclose = opts.autoclose or false
211+
callback = opts.callback or function()
212+
return true
213+
end
188214

189215
-- Create a new buffer for the terminal, set it as non-listed and scratch
190216
local buf = vim.api.nvim_create_buf(false, true)
@@ -266,6 +292,7 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
266292
-- Run the terminal command
267293
vim.fn.termopen(command, {
268294
on_exit = function(_, exit_code)
295+
result_code = exit_code
269296
if exit_code == 0 then
270297
if autoclose then -- If autoclose is true, close the terminal window
271298
closing()
@@ -285,7 +312,7 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
285312
})
286313
end
287314
else
288-
U.notify("Command failed with exit code: " .. exit_code, vim.log.levels.ERROR)
315+
U.notify("Command failed with exit code: " .. exit_code, vim.log.levels.DEBUG)
289316
vim.api.nvim_buf_set_keymap(buf, "n", "q", "", {
290317
noremap = true,
291318
silent = true,
@@ -299,6 +326,18 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
299326
end
300327
end,
301328
})
329+
330+
-- Create an autocmd for the window closing callback
331+
if callback then
332+
local winid = tostring(win)
333+
vim.api.nvim_create_autocmd("WinClosed", {
334+
pattern = winid, -- Use the window ID as the pattern
335+
callback = function(ev)
336+
callback({ ev = ev, result_code = result_code })
337+
return true
338+
end,
339+
})
340+
end
302341
end
303342

304343
--- Helper function to return the number of pending commits

0 commit comments

Comments
 (0)