lewis6991 / satellite.nvim

Decorate scrollbar for Neovim
MIT License
542 stars 20 forks source link

Fold API #16

Open lewis6991 opened 2 years ago

lewis6991 commented 2 years ago

In order to render a scrollbar, we need to know information about the visible (aka virtual) lines.

Currently Neovim only provides one function we can use to get this information: vim.fn.foldclosedend(). From this we can create a lazy virtual line index map so we can translate from buffer lnum to virtual lnum.

This is very inefficient as it has to be updated every time these is a change to folds. This lookup function can be made much more efficient if either:

  1. a dedicated function is added to core to translate to virtual line numbers.
  2. An API is provided to get information on the current buffer folds.

Finally we will also need information on virtual lines provided by earmarks as these should influence the rendering of a scrollbar.

clason commented 2 years ago

Is this related or can be repurposed: https://github.com/neovim/neovim/pull/15248?

lewis6991 commented 2 years ago

Kind of, but not really. That PR adds nvim_win_get_viewport() which is used to get information about the visible bounds of the buffer. For the size of the scrollbar and decorations we need to be able to translate a buffer line number to a virtual line number.

For reference this plugin currently uses these functions that an API in core would need to supplant:

-- Returns the count of virtual lines between the specified start and end lines
-- (both inclusive), in the specified window. A closed fold counts as one
-- virtual line.
function M.virtual_line_count(winid, start, vend)
  ... -- Very inefficient code
end

function M.height_to_barheight(winid, row, row2)
  local vlinecount0 = M.virtual_line_count(winid, 1) - 1
  local vheight = M.virtual_line_count(winid, row, row2)
  local winheight0 = api.nvim_win_get_height(winid) - 1
  return round(winheight0 * vheight / vlinecount0)
end

-- Calculate virtual line number from a real line number
function M.row_to_barpos(winid, row)
  return M.height_to_barheight(winid, 1, row)
end
clason commented 2 years ago

Couldn't this be an option to get_viewport, controlling how to count virtual lines?

justinmk commented 2 years ago

Related?:

lewis6991 commented 2 years ago

Couldn't this be an option to get_viewport, controlling how to count virtual lines?

To me, that doesn't seem like the best approach. get_viewport is more related to the bounds of the window.

For example say you have:

When the fold is:

This information isn't possible to calculate with only knowing the viewport bounds.

clason commented 2 years ago

OK, that does indeed sound like an orthogonal problem. Thanks for the explanation!

lewis6991 commented 1 year ago

Potential alternative solution: https://github.com/neovim/neovim/pull/24236