Skip to content

Commit 8d714bb

Browse files
committed
feat: add dynamic resizing for floating windows on Vim resize events
Floating windows now resize and reposition dynamically when the main viewport is resized.
1 parent a642f74 commit 8d714bb

File tree

1 file changed

+111
-90
lines changed

1 file changed

+111
-90
lines changed

lua/nvim_updater/utils.lua

Lines changed: 111 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,26 @@ function U.ConfirmPrompt(prompt, action)
6161
if type(action) == "function" then
6262
action() -- Call the function
6363
elseif type(action) == "string" then
64-
vim.cmd(action) -- Run the Vim command
64+
vim.fn.nvim_exec_lua(action, {}) -- Run the Vim command as Lua
6565
else
6666
U.notify("Action must be a function or a string", vim.log.levels.ERROR)
6767
end
6868
end
69+
6970
-- Create a new buffer
7071
local buf = vim.api.nvim_create_buf(false, true) -- Create a new empty buffer
72+
7173
-- Set the prompt text in the buffer
7274
vim.api.nvim_buf_set_lines(buf, 0, -1, false, { prompt, "y/n: " })
73-
-- Create a floating window to display the buffer
74-
local win_height = 2 -- Height of floating window
75-
local win_width = math.floor(vim.o.columns * 0.25) -- Width of floating window
75+
76+
-- Variables for the floating window
77+
local win_height = 2 -- Height of the floating window
78+
local win_width = math.floor(vim.o.columns * 0.25) -- Width of the floating window
7679
local row = math.floor((vim.o.lines - win_height) / 2) -- Position row
7780
local col = math.floor((vim.o.columns - win_width) / 2) -- Position column
7881
local win_border = "rounded"
7982
local style = "minimal"
83+
8084
-- Create a floating window
8185
local win = vim.api.nvim_open_win(buf, true, {
8286
relative = "editor",
@@ -87,49 +91,75 @@ function U.ConfirmPrompt(prompt, action)
8791
style = style,
8892
border = win_border,
8993
})
94+
9095
-- Move the cursor to the end of the buffer
9196
vim.api.nvim_win_set_cursor(win, { 2, 5 })
97+
98+
-- Function for closing the window and cleaning up
99+
local autocmd_id
100+
local function close_window()
101+
if autocmd_id then
102+
vim.api.nvim_del_autocmd(autocmd_id) -- Remove the resize autocmd
103+
autocmd_id = nil
104+
end
105+
vim.api.nvim_win_close(win, true) -- Close the window
106+
end
107+
108+
-- Update the floating window size on Vim resize events
109+
autocmd_id = vim.api.nvim_create_autocmd({ "VimResized" }, {
110+
callback = function()
111+
-- Get new dimensions of the main UI
112+
win_width = math.floor(vim.o.columns * 0.25) -- Update width
113+
col = math.floor((vim.o.columns - win_width) / 2) -- Recalculate center column
114+
row = math.floor((vim.o.lines - win_height) / 2) -- Recalculate center row
115+
116+
-- Update floating window configuration
117+
vim.api.nvim_win_set_config(win, {
118+
relative = "editor",
119+
width = win_width,
120+
height = win_height,
121+
col = col,
122+
row = row,
123+
})
124+
end,
125+
})
126+
92127
-- Define the yes function
93128
local yes = function()
94-
vim.api.nvim_win_close(win, true)
129+
close_window() -- Close window before performing action
95130
perform_action() -- Perform the action
96131
return true
97132
end
133+
98134
-- Define the no function
99135
local no = function()
100-
vim.api.nvim_win_close(win, true)
136+
close_window() -- Close window and notify
101137
U.notify("Action Canceled", vim.log.levels.INFO)
102138
end
139+
103140
-- Define buffer-specific key mappings
104141
local keymaps = {
105-
y = function()
106-
yes()
107-
end,
108-
n = function()
109-
no()
110-
end,
111-
q = function()
112-
no()
113-
end,
114-
["<Esc>"] = function()
115-
no()
116-
end,
142+
y = yes,
143+
n = no,
144+
q = no,
145+
["<Esc>"] = no,
117146
}
147+
118148
-- Set the key mappings
119149
for key, callback in pairs(keymaps) do
120150
vim.api.nvim_buf_set_keymap(buf, "n", key, "", {
121151
noremap = true,
122152
nowait = true,
123153
callback = callback,
154+
desc = key == "y" and "Confirm action" or "Cancel action",
124155
})
125156
end
126157

127158
return false
128159
end
129-
130-
--- Helper to display floating terminal in a centered, minimal Neovim window.
131-
--- This is useful for running long shell commands like building Neovim.
132-
--- You can pass arguments either as positional or as a table of options.
160+
-- Helper to display floating terminal in a centered, minimal Neovim window.
161+
-- 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.
133163
---@param command_or_opts string|table Either a shell command (string) or a table with options
134164
---@param filetype? string Custom filetype for terminal buffer (optional if using table)
135165
---@param ispreupdate? boolean Whether the terminal is for changelog before updating Neovim (optional if using table)
@@ -140,10 +170,8 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
140170

141171
-- Determine if the first argument is a table or positional arguments
142172
if type(command_or_opts) == "table" then
143-
-- Use table values directly
144173
opts = command_or_opts
145174
else
146-
-- Otherwise treat it as positional arguments
147175
opts = {
148176
command = command_or_opts or "",
149177
filetype = filetype or "floating.term", -- Default filetype
@@ -168,44 +196,66 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
168196
-- Set the filetype of the terminal buffer
169197
vim.api.nvim_set_option_value("filetype", filetype, { buf = buf })
170198

171-
-- Get UI dimensions to calculate window size
172-
local ui = vim.api.nvim_list_uis()[1]
173-
local win_width = math.floor(ui.width * 0.8)
174-
local win_height = math.floor(ui.height * 0.8)
199+
-- Create the floating window
200+
local win
201+
local autocmd_id
202+
203+
local function open_window()
204+
-- Get UI dimensions to calculate window size
205+
local ui = vim.api.nvim_list_uis()[1]
206+
local win_width = math.floor(ui.width * 0.8)
207+
local win_height = math.floor(ui.height * 0.8)
208+
209+
-- Define window options
210+
local win_opts = {
211+
style = "minimal",
212+
relative = "editor",
213+
width = win_width,
214+
height = win_height,
215+
row = math.floor((ui.height - win_height) / 2),
216+
col = math.floor((ui.width - win_width) / 2),
217+
border = "rounded",
218+
}
175219

176-
-- Define window options
177-
local win_opts = {
178-
style = "minimal",
179-
relative = "editor",
180-
width = win_width,
181-
height = win_height,
182-
row = math.floor((ui.height - win_height) / 2),
183-
col = math.floor((ui.width - win_width) / 2),
184-
border = "rounded",
185-
}
220+
-- Create or update the floating window
221+
if win and vim.api.nvim_win_is_valid(win) then
222+
vim.api.nvim_win_set_config(win, win_opts) -- Update window config
223+
else
224+
win = vim.api.nvim_open_win(buf, true, win_opts) -- Open new window
225+
if not win or win == 0 then
226+
U.notify("Failed to create floating window", vim.log.levels.ERROR)
227+
return
228+
end
229+
end
186230

187-
-- Create the floating window
188-
local win = vim.api.nvim_open_win(buf, true, win_opts)
189-
if not win or win == 0 then
190-
U.notify("Failed to create floating window", vim.log.levels.ERROR)
191-
return
231+
-- Additional settings for the window
232+
vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = buf })
233+
vim.api.nvim_set_option_value("winblend", 10, { win = win })
192234
end
193235

194-
-- Set buffer and window options
195-
vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = buf })
196-
vim.api.nvim_set_option_value("winblend", 10, { win = win })
236+
open_window() -- Initial window creation
237+
238+
-- Update window size on Vim resize events
239+
autocmd_id = vim.api.nvim_create_autocmd({ "VimResized" }, {
240+
callback = function()
241+
open_window() -- Call the function to update the window size
242+
end,
243+
})
197244

198245
-- Create the closing callback
199-
local closing = function()
200-
-- Close the terminal window
246+
local function closing()
247+
-- Remove the autocmd to prevent errors after the window is closed
248+
if autocmd_id then
249+
vim.api.nvim_del_autocmd(autocmd_id)
250+
autocmd_id = nil
251+
end
252+
201253
if vim.api.nvim_win_is_valid(win) then
202254
vim.api.nvim_win_close(win, true)
203255
end
204-
-- If NVIMUPDATER_HEADLESS is set, exit immediately
205256
if os.getenv("NVIMUPDATER_HEADLESS") then
206257
vim.cmd("qa")
207258
end
208-
-- If isupdate is true, execute NVUpdateNeovim
209259
if ispreupdate then
210260
U.ConfirmPrompt("Perform Neovim update?", function()
211261
require("nvim_updater").update_neovim()
@@ -223,46 +273,17 @@ function U.open_floating_terminal(command_or_opts, filetype, ispreupdate, autocl
223273
end
224274

225275
-- Wait for a keypress before closing the terminal window
226-
vim.api.nvim_buf_set_keymap(buf, "n", "q", "", {
227-
noremap = true,
228-
silent = true,
229-
callback = function()
230-
closing()
231-
end,
232-
desc = "Close terminal window",
233-
})
234-
vim.api.nvim_buf_set_keymap(buf, "n", "<Space>", "", {
235-
noremap = true,
236-
silent = true,
237-
callback = function()
238-
closing()
239-
end,
240-
desc = "Close terminal window",
241-
})
242-
vim.api.nvim_buf_set_keymap(buf, "n", "<CR>", "", {
243-
noremap = true,
244-
silent = true,
245-
callback = function()
246-
closing()
247-
end,
248-
desc = "Close terminal window",
249-
})
250-
vim.api.nvim_buf_set_keymap(buf, "n", "<Esc>", "", {
251-
noremap = true,
252-
silent = true,
253-
callback = function()
254-
closing()
255-
end,
256-
desc = "Close terminal window",
257-
})
258-
vim.api.nvim_buf_set_keymap(buf, "n", "y", "", {
259-
noremap = true,
260-
silent = true,
261-
callback = function()
262-
closing()
263-
end,
264-
desc = "Close terminal window",
265-
})
276+
-- Bind different keys to closing the terminal
277+
for _, key in ipairs({ "q", "<Space>", "<CR>", "<Esc>", "y" }) do
278+
vim.api.nvim_buf_set_keymap(buf, "n", key, "", {
279+
noremap = true,
280+
silent = true,
281+
callback = function()
282+
closing()
283+
end,
284+
desc = "Close terminal window",
285+
})
286+
end
266287
else
267288
U.notify("Command failed with exit code: " .. exit_code, vim.log.levels.ERROR)
268289
vim.api.nvim_buf_set_keymap(buf, "n", "q", "", {

0 commit comments

Comments
 (0)