-- ============================================================================ -- UFO: Modern folding with LSP/treesitter support -- ============================================================================ -- Better code folding using LSP or treesitter. Shows fold preview on hover. -- zR to open all folds, zM to close all. Includes statuscol for fold icons -- in the gutter. Has OptionSet autocmd to track folding option changes. -- ============================================================================ return { "kevinhwang91/nvim-ufo", dependencies = { "kevinhwang91/promise-async", "nvim-treesitter/nvim-treesitter", { "luukvbaal/statuscol.nvim", config = function() local builtin = require("statuscol.builtin") require("statuscol").setup({ relculright = true, segments = { { text = { builtin.foldfunc }, click = "v:lua.ScFa" }, { text = { "%s" }, click = "v:lua.ScSa" }, { text = { builtin.lnumfunc, " " }, click = "v:lua.ScLa" }, }, }) end, }, }, event = { "BufReadPost", "BufNewFile" }, init = function() vim.o.foldcolumn = "1" vim.o.foldlevel = 99 vim.o.foldlevelstart = 99 vim.o.foldenable = true -- Use valid Unicode characters for foldopen and foldclose vim.o.fillchars = [[eob: ,fold: ,foldopen:▾,foldsep: ,foldclose:▸]] vim.o.foldmethod = "manual" vim.o.foldexpr = "" end, opts = { open_fold_hl_timeout = 150, close_fold_kinds_for_ft = { default = { 'imports', 'comment' }, c = { 'comment', 'region' }, }, preview = { win_config = { border = { "", "─", "", "", "", "─", "", "" }, winhighlight = "Normal:Folded", winblend = 0, }, mappings = { scrollU = "", scrollD = "", jumpTop = "[", jumpBot = "]", }, }, provider_selector = function(bufnr, filetype, buftype) return { "treesitter", "indent" } end, fold_virt_text_handler = function(virtText, lnum, endLnum, width, truncate) local newVirtText = {} local suffix = (" 󰁂 %d "):format(endLnum - lnum) local sufWidth = vim.fn.strdisplaywidth(suffix) local targetWidth = width - sufWidth local curWidth = 0 for _, chunk in ipairs(virtText) do local chunkText = chunk[1] local chunkWidth = vim.fn.strdisplaywidth(chunkText) if targetWidth > curWidth + chunkWidth then table.insert(newVirtText, chunk) else chunkText = truncate(chunkText, targetWidth - curWidth) local hlGroup = chunk[2] table.insert(newVirtText, { chunkText, hlGroup }) chunkWidth = vim.fn.strdisplaywidth(chunkText) if curWidth + chunkWidth < targetWidth then suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) end break end curWidth = curWidth + chunkWidth end table.insert(newVirtText, { suffix, "MoreMsg" }) return newVirtText end, }, config = function(_, opts) local ufo = require("ufo") ufo.setup(opts) -- Keymaps are in keymaps/ufo.lua vim.api.nvim_create_autocmd("FileType", { pattern = { "lua", "python", "javascript", "typescript", "c", "cpp", "rust", "go" }, callback = function() ufo.setFoldVirtTextHandler(nil, function(virtText, lnum, endLnum, width, truncate) local newVirtText = {} local suffix = (" 󰁂 %d "):format(endLnum - lnum) local sufWidth = vim.fn.strdisplaywidth(suffix) local targetWidth = width - sufWidth local curWidth = 0 for _, chunk in ipairs(virtText) do local chunkText = chunk[1] local chunkWidth = vim.fn.strdisplaywidth(chunkText) if targetWidth > curWidth + chunkWidth then table.insert(newVirtText, chunk) else chunkText = truncate(chunkText, targetWidth - curWidth) local hlGroup = chunk[2] table.insert(newVirtText, { chunkText, hlGroup }) chunkWidth = vim.fn.strdisplaywidth(chunkText) if curWidth + chunkWidth < targetWidth then suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) end break end curWidth = curWidth + chunkWidth end table.insert(newVirtText, { suffix, "MoreMsg" }) return newVirtText end) end, }) end, }