Skip to content

Commit

Permalink
fix: considers folded lines near EoF (#8)
Browse files Browse the repository at this point in the history
* fix: considers folded lines near EoF (fix #7)

* refactor: code readability

* perf: avoid calculations when far away from EoF

* Linting. Only change topline in `winrestview()`

---------

Co-authored-by: Aasim-A <23695024+Aasim-A@users.noreply.github.com>
  • Loading branch information
chrisgrieser and Aasim-A authored Aug 18, 2023
1 parent 0803498 commit 158f130
Showing 1 changed file with 35 additions and 5 deletions.
40 changes: 35 additions & 5 deletions lua/scrollEOF.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,50 @@ local M = {}
local mode_disabled = false
local filetype_disabled = false

---Counts the number of folded lines between two line numbers
---@param lnum1 number
---@param lnum2 number
---@return number
local function folded_lines_between(lnum1, lnum2)
local next_fold_end_ln = -1
local folded_lines = 0

for ln = lnum1, lnum2, 1 do
if ln > next_fold_end_ln then -- skip folded lines we already added to the count
next_fold_end_ln = vim.fn.foldclosedend(ln)
local is_folded_line = next_fold_end_ln ~= -1
if is_folded_line then
local fold_size = next_fold_end_ln - ln
folded_lines = folded_lines + fold_size
end
end
end

return folded_lines
end

local function check_eof_scrolloff()
if mode_disabled or filetype_disabled then
return
end

local win_height = vim.api.nvim_win_get_height(0)
local last_line = vim.fn.line('$')
local win_last_line = vim.fn.line('w$')

-- PERF avoid calculations when far away from the end of file
if win_last_line + win_height < last_line then return end

local win_view = vim.fn.winsaveview()
local scrolloff = math.min(vim.o.scrolloff, math.floor(win_height / 2))
local scrolloff_line_count = win_height - (vim.fn.line('w$') - win_view.topline + 1)
local distance_to_last_line = vim.fn.line('$') - win_view.lnum
local cur_line = win_view.lnum
local win_top_line = win_view.topline
local visual_distance_to_eof = last_line - cur_line - folded_lines_between(cur_line, last_line)
local visual_last_line_in_win = win_last_line - folded_lines_between(win_top_line, win_last_line)
local scrolloff_line_count = win_height - (visual_last_line_in_win - win_top_line + 1)

if distance_to_last_line < scrolloff and scrolloff_line_count + distance_to_last_line < scrolloff then
win_view.topline = win_view.topline + scrolloff - (scrolloff_line_count + distance_to_last_line)
vim.fn.winrestview(win_view)
if visual_distance_to_eof < scrolloff and scrolloff_line_count + visual_distance_to_eof < scrolloff then
vim.fn.winrestview({ topline = win_view.topline + scrolloff - (scrolloff_line_count + visual_distance_to_eof) })
end
end

Expand Down

0 comments on commit 158f130

Please sign in to comment.