mirror of
https://github.com/folke/snacks.nvim
synced 2025-12-23 08:47:57 +00:00
fix(statuscolumn): show open folds in consecutive levels (#1534)
## Description This uses `vim.treesitter.foldexpr` to get the start of a foldlevel, because `vim.fn.foldlevel()` will return the same number in adjacent foldlevels, thus making the open fold markers inconsistent. This will however introduce a dependency on `vim.treesitter.foldexpr` and I haven't seen any other computations based on `vim.treesitter`, so maybe this is not desirable? Unfortunately, I wasn't able to come up with a better solution, so feel free to disregard. PS: I came across #1445 and this PR reverts those changes I realize. But I fail to find a good way for both to co-exist. I tried checking the value with `vim.api.nvim_get_option_value("foldexpr", {})`, but this will only work if `vim.opt.foldexpr` will be set directly into one of the 2. If it's set to another function that is required like in LazyVim, I'm not able to distinguish what value `foldexpr` is actually set to. PS2: I'm guessing the same thing happens when `foldexpr` is set to `vim.lsp.foldexpr` and the ideal would be some way to distinguish which one is currently active and then use either `vim.treesitter.foldexpr(lnum):sub(1, 1) == ">"` or `vim.lsp.foldexpr(lnum):sub(1, 1) == ">"` respectively. <!-- Describe the big picture of your changes to communicate to the maintainers why we should accept this pull request. --> ## Related Issue(s) Fixes #1533 <!-- If this PR fixes any issues, please link to the issue here. - Fixes #<issue_number> --> ## Screenshots Before  After  <!-- Add screenshots of the changes if applicable. --> --------- Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
This commit is contained in:
parent
cb0df73188
commit
7bcd3baaf8
1 changed files with 51 additions and 2 deletions
|
|
@ -13,6 +13,52 @@ M.meta = {
|
|||
needs_setup = true,
|
||||
}
|
||||
|
||||
---@class snacks.statuscolumn.FoldInfo
|
||||
---@field start number Line number where deepest fold starts
|
||||
---@field level number Fold level, when zero other fields are N/A
|
||||
---@field llevel number Lowest level that starts in v:lnum
|
||||
---@field lines number Number of lines from v:lnum to end of closed fold
|
||||
|
||||
---@type ffi.namespace*
|
||||
local C
|
||||
|
||||
local function _ffi()
|
||||
if not C then
|
||||
local ffi = require("ffi")
|
||||
ffi.cdef([[
|
||||
typedef struct {} Error;
|
||||
typedef struct {} win_T;
|
||||
typedef struct {
|
||||
int start; // line number where deepest fold starts
|
||||
int level; // fold level, when zero other fields are N/A
|
||||
int llevel; // lowest level that starts in v:lnum
|
||||
int lines; // number of lines from v:lnum to end of closed fold
|
||||
} foldinfo_T;
|
||||
foldinfo_T fold_info(win_T* wp, int lnum);
|
||||
win_T *find_window_by_handle(int Window, Error *err);
|
||||
]])
|
||||
C = ffi.C
|
||||
end
|
||||
return C
|
||||
end
|
||||
|
||||
-- Returns fold info for a given window and line number
|
||||
---@param win number
|
||||
---@param lnum number
|
||||
local function fold_info(win, lnum)
|
||||
pcall(_ffi)
|
||||
if not C then
|
||||
return
|
||||
end
|
||||
local ffi = require("ffi")
|
||||
local err = ffi.new("Error")
|
||||
local wp = C.find_window_by_handle(win, err)
|
||||
if wp == nil then
|
||||
return
|
||||
end
|
||||
return C.fold_info(wp, lnum) ---@type snacks.statuscolumn.FoldInfo
|
||||
end
|
||||
|
||||
---@alias snacks.statuscolumn.Component "mark"|"sign"|"fold"|"git"
|
||||
---@alias snacks.statuscolumn.Components snacks.statuscolumn.Component[]|fun(win:number,buf:number,lnum:number):snacks.statuscolumn.Component[]
|
||||
|
||||
|
|
@ -144,8 +190,11 @@ function M.line_signs(win, buf, lnum)
|
|||
vim.api.nvim_win_call(win, function()
|
||||
if vim.fn.foldclosed(lnum) >= 0 then
|
||||
signs[#signs + 1] = { text = vim.opt.fillchars:get().foldclose or "", texthl = "Folded", type = "fold" }
|
||||
elseif config.folds.open and vim.fn.foldlevel(lnum) > vim.fn.foldlevel(lnum - 1) then
|
||||
signs[#signs + 1] = { text = vim.opt.fillchars:get().foldopen or "", type = "fold" }
|
||||
elseif config.folds.open then
|
||||
local info = fold_info(win, lnum)
|
||||
if info and info.level > 0 and info.start == lnum then
|
||||
signs[#signs + 1] = { text = vim.opt.fillchars:get().foldopen or "", type = "fold" }
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue