Skip to content

Commit

Permalink
Added smooth scrolling for mouse wheel scroll.
Browse files Browse the repository at this point in the history
  • Loading branch information
declancm committed Jul 11, 2022
1 parent f31948f commit 204a652
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 44 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ over folds.
__New Features:__
* Support for the go-to-definition and go-to-declaration builtin LSP functions 🥳🎉.
* Smooth horizontal scrolling when view has shifted left or right.
* Smooth scrolling for the scroll wheel.

__Petition for a cinnamon roll emoji:__<https://www.change.org/p/apple-cinnamon-roll-emoji>

Expand Down Expand Up @@ -97,7 +98,7 @@ Left/right movements: h, l, <Left> and <Right>
Scroll(arg1, arg2, arg3, arg4)
```

* __arg1__ = A string containing the normal mode movement commands.
* __arg1__ = A string containing the normal mode movement commands. Look at the 'Keymaps' section for examples.
* To use the go-to-definition LSP function, use 'definition' (or 'declaration'
for go-to-declaration).
* __arg2__ = Scroll the window with the cursor. (1 for on, 0 for off). Default is 0.
Expand Down Expand Up @@ -182,6 +183,11 @@ vim.keymap.set({ 'n', 'x' }, 'l', "<Cmd>lua Scroll('l', 0, 1)<CR>")
vim.keymap.set({ 'n', 'x' }, '<Left>', "<Cmd>lua Scroll('h', 0, 1)<CR>")
vim.keymap.set({ 'n', 'x' }, '<Right>', "<Cmd>lua Scroll('l', 0, 1)<CR>")

-- SCROLL_WHEEL_KEYMAPS:

vim.keymap.set({ 'n', 'x' }, '<ScrollWheelUp>', "<Cmd>lua Scroll('<ScrollWheelUp>')<CR>")
vim.keymap.set({ 'n', 'x' }, '<ScrollWheelDown>', "<Cmd>lua Scroll('<ScrollWheelDown>')<CR>")

-- LSP_KEYMAPS:

-- LSP go-to-definition:
Expand Down
115 changes: 93 additions & 22 deletions lua/cinnamon/functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ fn.check_command_errors = function(command)
return false
end

local t = function(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end

local create_delay = function(delay_length)
if delay_length == 0 then
return
Expand All @@ -65,7 +69,7 @@ local scroll_screen = function(delay_length, target_line)

-- Scroll the cursor up.
while vim.fn.winline() > target_line do
vim.cmd('silent exe "norm! \\<C-E>"')
vim.cmd('norm! ' .. t('<C-e>'))
local new_line = vim.fn.winline()
create_delay(delay_length)
if new_line == prev_line then
Expand All @@ -76,7 +80,7 @@ local scroll_screen = function(delay_length, target_line)

-- Scroll the cursor down.
while vim.fn.winline() < target_line do
vim.cmd('silent exe "norm! \\<C-Y>"')
vim.cmd('norm! ' .. t('<C-y>'))
local new_line = vim.fn.winline()
create_delay(delay_length)
if new_line == prev_line then
Expand All @@ -86,7 +90,7 @@ local scroll_screen = function(delay_length, target_line)
end
end

local scroll_down = function(curpos, scroll_win, delay_length)
local scroll_down = function(curpos, scroll_win, delay_length, scrolloff)
local lnum = curpos[2]
local win_height = vim.api.nvim_win_get_height(0)

Expand All @@ -105,24 +109,20 @@ local scroll_down = function(curpos, scroll_win, delay_length)
end

local prev_lnum = vim.fn.getcurpos()[2]

vim.cmd('norm! j')

local current_winline = vim.fn.winline()

if scroll_win then
if config.centered then
if current_winline > half_height then
vim.cmd('silent exe "norm! \\<C-E>"')
vim.cmd('norm! ' .. t('<C-e>'))
end
else
-- Scroll the window if the current line is not within 'scrolloff'.
local scrolloff
if vim.opt_local.so:get() ~= -1 then
scrolloff = vim.opt_local.so:get()
else
scrolloff = vim.opt.so:get()
end
if current_winline > scrolloff + 1 and current_winline < win_height - scrolloff then
vim.cmd('silent exe "norm! \\<C-E>"')
vim.cmd('norm! ' .. t('<C-e>'))
end
end
end
Expand All @@ -136,7 +136,7 @@ local scroll_down = function(curpos, scroll_win, delay_length)
end
end

local scroll_up = function(curpos, scroll_win, delay_length)
local scroll_up = function(curpos, scroll_win, delay_length, scrolloff)
local lnum = curpos[2]
local win_height = vim.api.nvim_win_get_height(0)

Expand All @@ -155,24 +155,20 @@ local scroll_up = function(curpos, scroll_win, delay_length)
end

local prev_lnum = vim.fn.getcurpos()[2]

vim.cmd('norm! k')

local current_winline = vim.fn.winline()

if scroll_win then
if config.centered then
if current_winline < half_height then
vim.cmd('silent exe "norm! \\<C-Y>"')
vim.cmd('norm! ' .. t('<C-y>'))
end
else
-- Scroll the window if the current line is not within 'scrolloff'.
local scrolloff
if vim.opt_local.so:get() ~= -1 then
scrolloff = vim.opt_local.so:get()
else
scrolloff = vim.opt.so:get()
end
if current_winline > scrolloff + 1 and current_winline < win_height - scrolloff then
vim.cmd('silent exe "norm! \\<C-Y>"')
vim.cmd('norm! ' .. t('<C-y>'))
end
end
end
Expand All @@ -187,11 +183,19 @@ local scroll_up = function(curpos, scroll_win, delay_length)
end

fn.scroll_vertically = function(distance, curpos, winline, scroll_win, delay_length)
-- Get the scrolloff value.
local scrolloff
if vim.opt_local.so:get() ~= -1 then
scrolloff = vim.opt_local.so:get()
else
scrolloff = vim.opt.so:get()
end

-- Scroll the cursor vertically.
if distance > 0 then
scroll_down(curpos, scroll_win, delay_length)
scroll_down(curpos, scroll_win, delay_length, scrolloff)
elseif distance < 0 then
scroll_up(curpos, scroll_win, delay_length)
scroll_up(curpos, scroll_win, delay_length, scrolloff)
end

-- Scroll the screen vertically.
Expand All @@ -200,6 +204,73 @@ fn.scroll_vertically = function(distance, curpos, winline, scroll_win, delay_len
end
end

fn.scroll_wheel_vertically = function(command, distance, curpos, winline, delay_length)
if distance == 0 and (vim.fn.winline() == winline) then
return
end

-- Get the scrolloff value.
local scrolloff
if vim.opt_local.so:get() ~= -1 then
scrolloff = vim.opt_local.so:get()
else
scrolloff = vim.opt.so:get()
end

local lnum = curpos[2]

if command == t('<ScrollWheelDown>') then
-- Scroll down.
while vim.fn.getcurpos()[2] < lnum or vim.fn.winline() > winline do
-- TODO: Find alternative method.
-- FIX: Not working with scrolloff = 999
-- Stop scrolling too far at the bottom of the file due to bug with winrestview and scrolloff.
if vim.fn.getcurpos()[2] == lnum and vim.fn.winline() <= scrolloff + 1 then
return
end

-- Check if movement ends in the current fold.
if vim.fn.foldclosedend('.') ~= -1 and vim.fn.foldclosedend('.') > lnum then
vim.fn.setpos('.', curpos)
return
end

local prev_lnum = vim.fn.getcurpos()[2]
local prev_winline = vim.fn.winline()

vim.cmd('norm! ' .. t('<C-e>'))

-- Break if line number and winline not changing.
if vim.fn.getcurpos()[2] == prev_lnum and vim.fn.winline() == prev_winline then
break
end

create_delay(delay_length)
end
elseif command == t('<ScrollWheelUp>') then
-- Scroll up.
while vim.fn.getcurpos()[2] > lnum or vim.fn.winline() < winline do
-- Check if movement ends in the current fold.
if vim.fn.foldclosedend('.') ~= -1 and vim.fn.foldclosedend('.') < lnum then
vim.fn.setpos('.', curpos)
return
end

local prev_lnum = vim.fn.getcurpos()[2]
local prev_winline = vim.fn.winline()

vim.cmd('norm! ' .. t('<C-y>'))

-- Break if line number and winline not changing.
if vim.fn.getcurpos()[2] == prev_lnum and vim.fn.winline() == prev_winline then
break
end

create_delay(delay_length)
end
end
end

fn.scroll_horizontally = function(column, wincol, delay_length)
if wincol == -1 and column == -1 then
return
Expand Down
18 changes: 13 additions & 5 deletions lua/cinnamon/motions.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
local M = {}

local utils = require('cinnamon.utils')

local function t(str)
local t = function(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end

local append_table = function(...)
local new_table = {}
for _, current_table in pairs { ... } do
for _, item in pairs(current_table) do
table.insert(new_table, item)
end
end
return new_table
end

-- Vertical:

M.vertical = { 'j', 'k' }
Expand All @@ -25,10 +33,10 @@ M.scroll_wheel = { t('<ScrollWheelUp>'), t('<ScrollWheelDown>') }
M.search_repeat = { 'n', 'N' }
M.search_cursor = { '*', '#', 'g*', 'g#' }
M.goto_declaration = { 'gd', 'gD', '1gd', '1gD' }
M.search = utils.append(M.search_repeat, M.search_cursor, M.goto_declaration)
M.search = append_table(M.search_repeat, M.search_cursor, M.goto_declaration)

-- Single line/char movements:

M.no_scroll = utils.append(M.vertical, M.horizontal, M.window_vertical, M.view_horizontal)
M.no_scroll = append_table(M.vertical, M.horizontal, M.window_vertical, M.view_horizontal)

return M
22 changes: 16 additions & 6 deletions lua/cinnamon/scroll.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ M.scroll = function(command, scroll_win, use_count, delay_length, deprecated_arg
return
end

-- Check if command is a mouse wheel scroll.
local scroll_wheel = false
if utils.contains(motions.scroll_wheel, command) then
scroll_wheel = true
end

-- Check for any errors with the command.
if fn.check_command_errors(command) then
return
Expand Down Expand Up @@ -91,13 +97,13 @@ M.scroll = function(command, scroll_win, use_count, delay_length, deprecated_arg
vim.fn.winrestview(saved_view)

-- Check if scrolled vertically and/or horizontally.
local scrolled_vertically = false
local scrolled_window_vertically = false
if winline - lnum ~= prev_winline - prev_lnum then
scrolled_vertically = true
scrolled_window_vertically = true
end
local scrolled_horizontally = false
local scrolled_view_horizontally = false
if wincol - column ~= prev_wincol - prev_column then
scrolled_horizontally = true
scrolled_view_horizontally = true
end

-- Check if values have changed.
Expand All @@ -119,14 +125,18 @@ M.scroll = function(command, scroll_win, use_count, delay_length, deprecated_arg
end

-- Scroll vertically.
if scrolled_vertically or config.always_scroll or scroll_win then
if scroll_wheel then
fn.scroll_wheel_vertically(command, distance, curpos, winline, delay_length)
elseif scrolled_window_vertically or config.always_scroll or scroll_win or scroll_wheel then
fn.scroll_vertically(distance, curpos, winline, scroll_win, delay_length)
else
fn.scroll_vertically(distance, curpos, winline, scroll_win, 0)
end

-- Scroll horizontally.
if (scrolled_horizontally and config.horizontal_scroll or config.always_scroll) and vim.fn.foldclosed('.') == -1 then
if
(scrolled_view_horizontally and config.horizontal_scroll or config.always_scroll) and vim.fn.foldclosed('.') == -1
then
fn.scroll_horizontally(column, wincol, math.ceil(delay_length / 3))
else
fn.scroll_horizontally(column, wincol, 0)
Expand Down
10 changes: 0 additions & 10 deletions lua/cinnamon/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ utils.contains = function(table, target)
return false
end

utils.append = function(...)
local new_table = {}
for _, current_table in pairs { ... } do
for _, item in pairs(current_table) do
table.insert(new_table, item)
end
end
return new_table
end

utils.merge = function(t1, t2)
for k, v in pairs(t2) do
if (type(v) == 'table') and (type(t1[k] or false) == 'table') then
Expand Down

0 comments on commit 204a652

Please sign in to comment.