Skip to content

Commit 7507d78

Browse files
committed
Started adding a hide_on_text_intersect option
1 parent e8ad0e0 commit 7507d78

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

autoload/scrollview.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ if has_key(g:, 'scrollview_hide_on_intersect')
4444
endif
4545
let g:scrollview_hide_on_float_intersect =
4646
\ get(g:, 'scrollview_hide_on_float_intersect', v:false)
47+
let g:scrollview_hide_on_text_intersect =
48+
\ get(g:, 'scrollview_hide_on_text_intersect', v:false)
4749
let g:scrollview_hover = get(g:, 'scrollview_hover', v:true)
4850
let g:scrollview_include_end_region =
4951
\ get(g:, 'scrollview_include_end_region', v:false)

lua/scrollview.lua

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ local VIRTUAL_LINE_COUNT_KEY_PREFIX = 0
122122
local PROPER_LINE_COUNT_KEY_PREFIX = 1
123123
local TOPLINE_LOOKUP_KEY_PREFIX = 2
124124
local GET_WINDOW_EDGES_KEY_PREFIX = 3
125+
local ROW_LENGTH_LOOKUP_KEY_PREFIX = 4
125126

126127
-- Maps window ID and highlight group to a temporary highlight group with the
127128
-- corresponding definition. This is reset on each refresh cycle.
@@ -437,7 +438,7 @@ local with_win_workspace = function(winid, fun)
437438
-- winbar-omitted height where applicable.
438439
height = math.max(1, get_window_height(winid)),
439440
row = 0,
440-
col = 0
441+
col = 0,
441442
})
442443
end)
443444
win_workspace_lookup[winid] = workspace_winid
@@ -1379,6 +1380,52 @@ local get_scrollbar_character = function()
13791380
return character
13801381
end
13811382

1383+
-- Returns a table that maps window rows to the length of text on that row.
1384+
-- WARN: When a multi-cell character is the last character on a row, the length
1385+
-- returned by this function represents the first cell of that character.
1386+
local get_row_length_lookup = function(winid)
1387+
local memoize_key =
1388+
table.concat({ROW_LENGTH_LOOKUP_KEY_PREFIX, winid}, ':')
1389+
if memoize and cache[memoize_key] then return cache[memoize_key] end
1390+
local result = {}
1391+
with_win_workspace(winid, function()
1392+
local scrolloff = api.nvim_win_get_option(0, 'scrolloff')
1393+
local virtualedit = api.nvim_win_get_option(0, 'virtualedit')
1394+
set_window_option(0, 'scrolloff', 0)
1395+
set_window_option(0, 'virtualedit', 'none')
1396+
fn.winrestview(api.nvim_win_call(winid, fn.winsaveview))
1397+
vim.cmd('keepjumps normal! H')
1398+
local prior
1399+
-- Limit the number of steps as a precaution. The doubling of window height
1400+
-- is to be safe.
1401+
local max_steps = fn.winheight(0) * 2
1402+
local steps = 0
1403+
while fn.winline() > 1
1404+
and prior ~= fn.winline()
1405+
and steps < max_steps do
1406+
steps = steps + 1
1407+
prior = fn.winline()
1408+
vim.cmd('keepjumps normal! g0gk')
1409+
end
1410+
prior = nil
1411+
steps = 0
1412+
local winheight = get_window_height(0)
1413+
while fn.winline() <= winheight
1414+
and prior ~= fn.winline()
1415+
and steps < max_steps do
1416+
steps = steps + 1
1417+
prior = fn.winline()
1418+
vim.cmd('keepjumps normal! g$')
1419+
result[fn.winline()] = fn.wincol()
1420+
vim.cmd('keepjumps normal! g0gj')
1421+
end
1422+
set_window_option(0, 'scrolloff', scrolloff)
1423+
set_window_option(0, 'virtualedit', virtualedit)
1424+
end)
1425+
if memoize then cache[memoize_key] = result end
1426+
return result
1427+
end
1428+
13821429
-- Show a scrollbar for the specified 'winid' window ID, using the specified
13831430
-- 'bar_winid' floating window ID (a new floating window will be created if
13841431
-- this is -1). Returns -1 if the bar is not shown, and the floating window ID
@@ -1444,6 +1491,15 @@ local show_scrollbar = function(winid, bar_winid)
14441491
return -1
14451492
end
14461493
end
1494+
if to_bool(vim.g.scrollview_hide_on_text_intersect) then
1495+
local row_length_lookup = get_row_length_lookup(winid)
1496+
for row = bar_position.row, bar_position.row + bar_position.height - 1 do
1497+
if row_length_lookup[row] ~= nil
1498+
and row_length_lookup[row] >= bar_position.col then
1499+
return -1
1500+
end
1501+
end
1502+
end
14471503
if bar_bufnr == -1 or not to_bool(fn.bufloaded(bar_bufnr)) then
14481504
if bar_bufnr == -1 then
14491505
bar_bufnr = api.nvim_create_buf(false, true)
@@ -1800,6 +1856,16 @@ local show_signs = function(winid, sign_winids, bar_winid)
18001856
show = false
18011857
end
18021858
end
1859+
if to_bool(vim.g.scrollview_hide_on_text_intersect) then
1860+
local row_length_lookup = get_row_length_lookup(winid)
1861+
for c = col, col + sign_width - 1 do
1862+
if row_length_lookup[row] ~= nil
1863+
and row_length_lookup[row] >= c then
1864+
show = false
1865+
break
1866+
end
1867+
end
1868+
end
18031869
if show then
18041870
if sign_bufnr == -1 or not to_bool(fn.bufloaded(sign_bufnr)) then
18051871
if sign_bufnr == -1 then
@@ -2584,6 +2650,13 @@ local enable = function()
25842650
\ | execute "lua require('scrollview').refresh_bars_async()"
25852651
\ | endif
25862652
2653+
" Refresh scrollview when text is changed in insert mode. This way,
2654+
" scrollbars and signs will appear/hide accordingly when modifying text.
2655+
autocmd TextChangedI *
2656+
\ if g:scrollview_hide_on_text_intersect
2657+
\ | execute "lua require('scrollview').refresh_bars_async()"
2658+
\ | endif
2659+
25872660
" The following handles when :e is used to load a file. The asynchronous
25882661
" version handles a case where :e is used to reload an existing file, that
25892662
" is already scrolled. This avoids a scenario where the scrollbar is

0 commit comments

Comments
 (0)