karb94 / neoscroll.nvim

Smooth scrolling neovim plugin written in lua
MIT License
1.46k stars 36 forks source link

[Feature Request] Define speed rather than time, or have user defined function to determine time #63

Open jrwrigh opened 2 years ago

jrwrigh commented 2 years ago

I work between a very large monitor at work where I have 120+ lines of code and my laptop screen where sometimes I might only have 20-30 lines visible. I've noticed that scrolling up and down feels significantly different between the two situations, mainly because while the time to complete the scroll is the same, the number of lines it moves to do that is different.

It'd be nice to have the option of setting the scroll speed instead of time, as the number of lines needed to do a specific operation changes depending on the window size.

Additionally/alternatively, it'd be really nice to allow for setting a user defined function to determine how long a scrolling operation should take. I'd imagine neoscroll would pass the number of lines for the operation and the function would return the time (in milliseconds) that should be take for the operation.

jrwrigh commented 1 year ago

Not sure why it was taken down, but this is the reply from "Tonico" (username in the email notification):

I came up with the following function to compute the relative image runtime:

local function rel_time(n)
    local win_height = vim.fn.winheight(0)
    n = n or win_height
    if n % 1 ~= 0 then
        n = n * win_height
    end
    -- n is the numof lines we want to scroll
    local lines_ratio = n / win_height
    local threshold = 46 -- windows smaller thant this scroll faster
    local win_ratio = win_height / threshold
    local factor = win_ratio * lines_ratio
    local log_factor = 1 / math.log(1 / factor + 1, 2)
    local time = 300 * log_factor
    print(time)
    return time
end

The function takes as input the number (or fraction) of lines we want to scroll. It has hard coded in the number (46) of lines where the scrolling speed is "normal" and the "normal" scrolling time (300). It returns the normal scroll time scaled by a logarithmic factor that depends on the ratio between lines and win_height, and the ratio between win_height and normal height. Of course, this is very specific to my setup.

Examples: n = 46 and win_height = 46 -> time = 300 n = 23 and win_height = 46 -> time = 189 n = 0.33 and win_height = 46 -> time = 149 n = 23 and win_height = 23 -> time = 189 n = 11 and win_height = 23 -> time = 126 n = 0.33 and win_height = 23 -> time = 106

The function is used in my config like this:

local neoscroll = require("neoscroll")
neoscroll.setup({
    mappings = {}, -- no default mappings
})

local function map_key(lhs, rhs)
    vim.keymap.set({ "x", "n" }, lhs, rhs)
end

map_key("<C-u>", function()
    neoscroll.scroll(-vim.wo.scroll, true, rel_time(vim.wo.scroll))
end)

map_key("<C-d>", function()
    neoscroll.scroll(vim.wo.scroll, true, rel_time(vim.wo.scroll))
end)

-- other mappings ...

map_key("zz", function()
    neoscroll.zz(rel_time(0.33))
end)

@Tonico if you'd like this to be taken down again, let me know. I haven't tried this to verify whether this works.