perf(treesitter): better foldtext and foldexpr

This commit is contained in:
Folke Lemaitre 2024-11-13 21:11:32 +01:00
parent 0819f9396e
commit 1d7b9a1a61
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040

View file

@ -1,23 +1,23 @@
---@class lazyvim.util.ui ---@class lazyvim.util.ui
local M = {} local M = {}
-- foldtext for Neovim < 0.10.0
function M.foldtext() function M.foldtext()
local ok = pcall(vim.treesitter.get_parser, vim.api.nvim_get_current_buf()) return vim.api.nvim_buf_get_lines(0, vim.v.lnum - 1, vim.v.lnum, false)[1]
local ret = ok and vim.treesitter.foldtext and vim.treesitter.foldtext()
if not ret or type(ret) == "string" then
ret = { { vim.api.nvim_buf_get_lines(0, vim.v.lnum - 1, vim.v.lnum, false)[1], {} } }
end end
table.insert(ret, { " " .. LazyVim.config.icons.misc.dots })
if not vim.treesitter.foldtext then -- optimized treesitter foldexpr for Neovim >= 0.10.0
return table.concat( function M.foldexpr()
vim.tbl_map(function(line) local buf = vim.api.nvim_get_current_buf()
return line[1] if vim.b[buf].ts_folds == nil then
end, ret), -- as long as we don't have a filetype, don't bother
" " -- checking if treesitter is available (it won't)
) if vim.bo[buf].filetype == "" then
return "0"
end end
return ret vim.b[buf].ts_folds = pcall(vim.treesitter.get_parser, buf)
end
return vim.b[buf].ts_folds and vim.treesitter.foldexpr() or "0"
end end
---@return {fg?:string}? ---@return {fg?:string}?
@ -47,49 +47,6 @@ function M.color(name, bg)
return color and string.format("#%06x", color) or nil return color and string.format("#%06x", color) or nil
end end
M.skip_foldexpr = {} ---@type table<number,boolean>
local skip_check = assert(vim.uv.new_check())
function M.foldexpr()
local buf = vim.api.nvim_get_current_buf()
-- no highlight, no foldexpr
if not vim.b[buf].ts_highlight then
return "0"
end
-- still in the same tick and no parser
if M.skip_foldexpr[buf] then
return "0"
end
-- don't use treesitter folds for terminal
if vim.bo[buf].buftype == "terminal" then
return "0"
end
-- as long as we don't have a filetype, don't bother
-- checking if treesitter is available (it won't)
if vim.bo[buf].filetype == "" then
return "0"
end
local ok = pcall(vim.treesitter.get_parser, buf)
if ok then
return vim.treesitter.foldexpr()
end
-- no parser available, so mark it as skip
-- in the next tick, all skip marks will be reset
M.skip_foldexpr[buf] = true
skip_check:start(function()
M.skip_foldexpr = {}
skip_check:stop()
end)
return "0"
end
function M.maximize() function M.maximize()
---@type {k:string, v:any}[]? ---@type {k:string, v:any}[]?
local maximized = nil local maximized = nil