Skip to content

Commit

Permalink
fix: stop errors when opening window during scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
declancm committed Jul 1, 2024
1 parent 628ce51 commit ac7c54c
Showing 1 changed file with 19 additions and 28 deletions.
47 changes: 19 additions & 28 deletions lua/cinnamon/scroll.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ M.scroll = function(command, options)
vim.o.lazyredraw = saved_lazyredraw

if is_scrollable then
H.scroller:start(final_position, final_view, final_window, step_delay, options)
H.scroller:start(final_position, final_view, final_buffer, final_window, step_delay, options)
else
H.cleanup(options)
end
Expand Down Expand Up @@ -137,12 +137,14 @@ H.scroller = {}

---@param target_position Position
---@param target_view table
---@param buffer_id number
---@param window_id number
---@param step_delay number
---@param options ScrollOptions
function H.scroller:start(target_position, target_view, window_id, step_delay, options)
function H.scroller:start(target_position, target_view, buffer_id, window_id, step_delay, options)
self.target_position = target_position
self.target_view = target_view
self.buffer_id = buffer_id
self.window_id = window_id
self.options = options
self.scroll_cursor = (options.mode == "cursor")
Expand All @@ -154,37 +156,21 @@ function H.scroller:start(target_position, target_view, window_id, step_delay, o
vim.opt.guicursor:append({ "a:Cursor/lCursor" })
end

-- Cache values for performance
self.window_height = vim.api.nvim_win_get_height(0)
self.window_width = vim.api.nvim_win_get_width(0)
self.window_textoff = vim.fn.getwininfo(window_id)[1].textoff
self.wrap_enabled = vim.wo.wrap

self.saved_virtualedit = vim.wo.virtualedit
vim.wo.virtualedit = "all" -- Allow the cursor to move anywhere
self.saved_scrolloff = vim.wo.scrolloff
vim.wo.scrolloff = 0 -- Don't scroll the view when the cursor is near the edge

self.initial_changedtick = vim.b.changedtick
self.cancel_scroll = false

local timeout = options.max_delta.time + 1000
self.timed_out = false
self.timeout_timer = vim.uv.new_timer()
self.timeout_timer:start(timeout, 0, function()
self.cancel_scroll = true
self.timed_out = true
utils.notify("Scroll timed out", { level = "error", schedule = true })
end)

self.watcher_autocmd = vim.api.nvim_create_autocmd({
"BufLeave",
"WinLeave",
"WinResized",
}, {
callback = function()
self.cancel_scroll = true
end,
})

vim.api.nvim_exec_autocmds("User", { pattern = "CinnamonScrollPre" })

self.busy = false
Expand All @@ -202,16 +188,21 @@ end

function H.scroller:scroll()
while true do
local scroll_failed = (self.cancel_scroll or (self.initial_changedtick ~= vim.b.changedtick))
local scroll_failed = (
self.timed_out
or (self.initial_changedtick ~= vim.b.changedtick)
or (self.buffer_id ~= vim.api.nvim_get_current_buf())
or (self.window_id ~= vim.api.nvim_get_current_win())
)
local position = H.get_position()
local scroll_complete = (
not scroll_failed and H.positions_within_threshold(position, self.target_position, 0, 0)
)

if not scroll_complete and not scroll_failed then
local top_line = vim.fn.line("w0")
local topline = vim.fn.line("w0")
self:move_step()
local window_moved = (top_line ~= vim.fn.line("w0"))
local window_moved = (topline ~= vim.fn.line("w0"))
if self.scroll_cursor or window_moved then
break
end
Expand All @@ -231,7 +222,7 @@ function H.scroller:move_step()
local moved_right = false

local horizontal_error
if self.wrap_enabled then
if vim.wo.wrap then
horizontal_error = self.target_position.wincol - vim.fn.wincol()
else
horizontal_error = self.target_position.col - vim.fn.virtcol(".")
Expand Down Expand Up @@ -284,7 +275,7 @@ function H.scroller:move_step()
end

-- When text is wrapped, the view can't be horizontally scrolled
if not self.wrap_enabled then
if not vim.wo.wrap then
local wincol_error = self.target_position.wincol - vim.fn.wincol()
-- Move 2 columns per step when possible since the columns
-- are around half the size of lines.
Expand All @@ -298,16 +289,16 @@ end

---@return boolean
function H.scroller:line_is_wrapped()
if self.wrap_enabled then
return vim.fn.virtcol(".") ~= vim.fn.wincol() - self.window_textoff
if vim.wo.wrap then
local textoff = vim.fn.getwininfo(self.window_id)[1].textoff
return vim.fn.virtcol(".") ~= vim.fn.wincol() - textoff
end
return false
end

function H.scroller:stop()
self.scroll_scheduler:close()
self.timeout_timer:close()
vim.api.nvim_del_autocmd(self.watcher_autocmd)

if not self.scroll_cursor then
-- Restore the cursor
Expand Down

0 comments on commit ac7c54c

Please sign in to comment.