neoscroll.nvim

repository·master·Indexed 24 days ago

https://github.com/karb94/neoscroll.nvim

A Neovim plugin written in Lua that provides smooth scrolling animations for window movement commands such as <C-u>, <C-d>, and zt/zz/zb. It supports customizable easing functions, duration multipliers, and pre/post hooks for custom logic during animations.

Tokens
2.3K
Snippets
5
Records
5
Agent score
35%

What's inside neoscroll.nvim

  1. Install neoscroll.nvim

    master

    Neoscroll requires Neovim 0.5 or higher. You can install it using any of the following plugin managers:

    Packer

    use 'karb94/neoscroll.nvim'

    vim-plug

    Plug 'karb94/neoscroll.nvim'

    lazy.nvim Create ~/.config/nvim/lua/plugins/neoscroll.lua:

    return {
      "karb94/neoscroll.nvim",
      opts = {},
    }
    return {
      "karb94/neoscroll.nvim",
      opts = {},
    }
  2. Use pre_hook and post_hook for custom logic

    master

    You can define pre_hook and post_hook functions in your setup() to run code before or after a scrolling animation. These functions receive an info parameter, which is the same value passed to the scroll() function (can be a string or a table). This allows you to trigger specific logic based on the type of scroll being performed.

    Example: Hiding cursorline during specific scrolls

    require('neoscroll').setup({
      pre_hook = function(info) if info == "cursorline" then vim.wo.cursorline = false end end,
      post_hook = function(info) if info == "cursorline" then vim.wo.cursorline = true end end
    })
    local keymap = {
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250; info = 'cursorline' }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250; info = 'cursorline' }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
      vim.keymap.set(modes, key, func)
    end
    require('neoscroll').setup({
      pre_hook = function(info) if info == "cursorline" then vim.wo.cursorline = false end end,
      post_hook = function(info) if info == "cursorline" then vim.wo.cursorline = true end end
    })
    local keymap = {
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250; info = 'cursorline' }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250; info = 'cursorline' }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
      vim.keymap.set(modes, key, func)
    end
  3. Configure neoscroll.nvim via setup()

    master

    Use require('neoscroll').setup(options) to configure the plugin.

    Available Options:

    • mappings: A list of keys to be mapped to default scrolling animations (e.g., '<C-u>', 'zt'). Pass an empty list {} to disable all default mappings.
    • hide_cursor: Boolean. If true, hides the cursor while scrolling.
    • stop_eof: Boolean. If true, stops scrolling downwards at the end of the file.
    • respect_scrolloff: Boolean. If true, stops scrolling when the cursor reaches the scrolloff margin.
    • cursor_scrolls_alone: Boolean. If true, the cursor continues scrolling even if the window cannot scroll further.
    • duration_multiplier: Number. Global multiplier for animation duration.
    • easing: String. The default easing function (e.g., 'linear').
    • pre_hook: Function. Runs before the animation starts. Receives an info parameter.
    • post_hook: Function. Runs after the animation ends. Receives an info parameter.
    • performance_mode: Boolean. If true, disables syntax highlighting during scrolling (Note: the option name in setup is performance_mode, but the description says Disable "Performance Mode" on all buffers which implies setting it to true enables it).
    • ignored_events: A list of events to ignore while scrolling (e.g., {'WinScrolled', 'CursorMoved'}).
    require('neoscroll').setup({
      mappings = {
        '<C-u>', '<C-d>',
        '<C-b>', '<C-f>',
        '<C-y>', '<C-e>',
        'zt', 'zz', 'zb',
      },
      hide_cursor = true,
      stop_eof = true,
      respect_scrolloff = false,
      cursor_scrolls_alone = true,
      duration_multiplier = 1.0,
      easing = 'linear',
      pre_hook = nil,
      post_hook = nil,
      performance_mode = false,
      ignored_events = {
          'WinScrolled', 'CursorMoved'
      },
    })
  4. Use easing functions for smooth animations

    master

    By default, Neoscroll uses linear easing. You can provide a different easing function to setup() or directly to a scroll()/helper call to make the start and end of animations more natural.

    Supported Easing Functions: linear, quadratic, cubic, quartic, quintic, circular, sine.

    Example usage with custom easing:

    neoscroll = require('neoscroll')
    neoscroll.setup({
      easing = "quadratic"
    })
    local keymap = {
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250; easing = 'sine' }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250; easing = 'sine' }) end;
      ["<C-b>"] = function() neoscroll.ctrl_b({ duration = 450; easing = 'circular' }) end;
      ["<C-f>"] = function() neoscroll.ctrl_f({ duration = 450; easing = 'circular' }) end;
      ["<C-y>"] = function() neoscroll.scroll(-0.1, { move_cursor=false; duration = 100 }) end;
      ["<C-e>"] = function() neoscroll.scroll(0.1, { move_cursor=false; duration = 100 }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
        vim.keymap.set(modes, key, func)
    end
    neoscroll = require('neoscroll')
    neoscroll.setup({
      -- Default easing function used in any animation where
      -- the `easing` argument has not been explicitly supplied
      easing = "quadratic"
    })
    local keymap = {
      -- Use the "sine" easing function
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250; easing = 'sine' }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250; easing = 'sine' }) end;
      -- Use the "circular" easing function
      ["<C-b>"] = function() neoscroll.ctrl_b({ duration = 450; easing = 'circular' }) end;
      ["<C-f>"] = function() neoscroll.ctrl_f({ duration = 450; easing = 'circular' }) end;
      -- When no value is passed the `easing` option supplied in `setup()` is used
      ["<C-y>"] = function() neoscroll.scroll(-0.1, { move_cursor=false; duration = 100 }) end;
      ["<C-e>"] = function() neoscroll.scroll(0.1, { move_cursor=false; duration = 100 }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
        vim.keymap.set(modes, key, func)
    end
  5. Create custom scrolling mappings

    master

    You can define custom keybindings using Neoscroll's helper functions. These functions can accept an options table to customize the animation (e.g., { duration = 250, easing = 'sine' }).

    Available Helper Functions:

    • scroll(lines, opts): Scrolls by a number of lines or a percentage (decimal) of the window.
    • ctrl_u(opts)
    • ctrl_d(opts)
    • ctrl_b(opts)
    • ctrl_f(opts)
    • zt(opts)
    • zz(opts)
    • zb(opts)

    Example Implementation:

    neoscroll = require('neoscroll')
    local keymap = {
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250 }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250 }) end;
      ["<C-b>"] = function() neoscroll.ctrl_b({ duration = 450 }) end;
      ["<C-f>"] = function() neoscroll.ctrl_f({ duration = 450 }) end;
      ["<C-y>"] = function() neoscroll.scroll(-0.1, { move_cursor=false; duration = 100 }) end;
      ["<C-e>"] = function() neoscroll.scroll(0.1, { move_cursor=false; duration = 100 }) end;
      ["zt"]    = function() neoscroll.zt({ half_win_duration = 250 }) end;
      ["zz"]    = function() neoscroll.zz({ half_win_duration = 250 }) end;
      ["zb"]    = function() neoscroll.zb({ half_win_duration = 250 }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
      vim.keymap.set(modes, key, func)
    end
    neoscroll = require('neoscroll')
    local keymap = {
      ["<C-u>"] = function() neoscroll.ctrl_u({ duration = 250 }) end;
      ["<C-d>"] = function() neoscroll.ctrl_d({ duration = 250 }) end;
      ["<C-b>"] = function() neoscroll.ctrl_b({ duration = 450 }) end;
      ["<C-f>"] = function() neoscroll.ctrl_f({ duration = 450 }) end;
      ["<C-y>"] = function() neoscroll.scroll(-0.1, { move_cursor=false; duration = 100 }) end;
      ["<C-e>"] = function() neoscroll.scroll(0.1, { move_cursor=false; duration = 100 }) end;
      ["zt"]    = function() neoscroll.zt({ half_win_duration = 250 }) end;
      ["zz"]    = function() neoscroll.zz({ half_win_duration = 250 }) end;
      ["zb"]    = function() neoscroll.zb({ half_win_duration = 250 }) end;
    }
    local modes = { 'n', 'v', 'x' }
    for key, func in pairs(keymap) do
      vim.keymap.set(modes, key, func)
    end