|
6 | 6 | -- |
7 | 7 | -- copyright 2024 |
8 | 8 | -- license GNU General Public License v3.0 |
9 | | - |
10 | 9 | local M = {} |
11 | 10 |
|
| 11 | +local config = require("astroui").config.folding |
| 12 | + |
12 | 13 | local is_setup = false |
13 | 14 | local lsp_bufs = {} |
14 | 15 |
|
| 16 | +local fold_methods = { |
| 17 | + lsp = function(lnum, bufnr) |
| 18 | + if lsp_bufs[bufnr or vim.api.nvim_get_current_buf()] then return vim.lsp.foldexpr(lnum) end |
| 19 | + end, |
| 20 | + treesitter = function(lnum, bufnr) |
| 21 | + if vim.bo.filetype and vim.treesitter.get_parser(bufnr, nil, { error = false }) then |
| 22 | + return vim.treesitter.foldexpr(lnum) |
| 23 | + end |
| 24 | + end, |
| 25 | + indent = function(lnum, bufnr) |
| 26 | + if not lnum then lnum = vim.v.lnum end |
| 27 | + if not bufnr then bufnr = vim.api.nvim_get_current_buf() end |
| 28 | + return vim.api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1]:match "^%s*$" and "=" |
| 29 | + or math.floor(vim.fn.indent(lnum) / vim.bo[bufnr].shiftwidth) |
| 30 | + end, |
| 31 | +} |
| 32 | + |
15 | 33 | --- A fold expression for doing LSP and Treesitter based folding |
16 | 34 | ---@param lnum? integer the current line number |
17 | 35 | ---@return string the calculated fold level |
18 | 36 | function M.foldexpr(lnum) |
19 | 37 | if not is_setup then M.setup() end |
20 | 38 | local bufnr = vim.api.nvim_get_current_buf() |
21 | | - -- only fold real file buffers |
22 | | - if not require("astrocore.buffer").is_valid(bufnr) then return "0" end |
23 | | - -- if an LSP with folding is attached us it for folding |
24 | | - if lsp_bufs[bufnr] then return vim.lsp.foldexpr(lnum) end |
25 | | - local filetype = vim.bo[bufnr].filetype |
26 | | - -- don't fold dashboards |
27 | | - if filetype:find "dashboard" then return "0" end |
28 | | - -- if filetype and a treesitter parser exists, use treesitter for folding |
29 | | - if filetype and vim.treesitter.get_parser(bufnr, nil, { error = false }) then return vim.treesitter.foldexpr(lnum) end |
30 | | - -- fallback to indentation based folding |
31 | | - if not lnum then lnum = vim.v.lnum end |
32 | | - return vim.fn.getline(lnum):match "^%s*$" and "=" or math.floor(vim.fn.indent(lnum) / vim.bo[bufnr].shiftwidth) |
| 39 | + -- check if folding is enabled |
| 40 | + local enabled = config and config.enabled |
| 41 | + if type(enabled) == "function" then enabled = enabled(bufnr) end |
| 42 | + if enabled then |
| 43 | + for _, method in ipairs(config and config.methods or {}) do |
| 44 | + local fold_method = fold_methods[method] |
| 45 | + if fold_method then |
| 46 | + local fold = fold_method(lnum, bufnr) |
| 47 | + if fold then return fold end |
| 48 | + end |
| 49 | + end |
| 50 | + end |
| 51 | + -- fallback to no folds |
| 52 | + return "0" |
33 | 53 | end |
34 | 54 |
|
35 | 55 | function M.setup() |
36 | 56 | -- TODO: remove check when dropping support for Neovim v0.10 |
37 | | - if vim.fn.has "nvim-0.11" == 1 then |
| 57 | + if vim.lsp.foldexpr then |
38 | 58 | local augroup = vim.api.nvim_create_augroup("astroui_foldexpr", { clear = true }) |
39 | 59 | vim.api.nvim_create_autocmd("LspAttach", { |
40 | 60 | desc = "Monitor attached LSP clients with fold providers", |
|
0 commit comments