Skip to content

Commit 85241fc

Browse files
committed
feat(folding): add configuration for folding
1 parent 6863bce commit 85241fc

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ require("astroui").setup({
5151
{
5252
-- Colorscheme set on startup, a string that is used with `:colorscheme astrodark`
5353
colorscheme = "astrodark",
54+
-- Configure how folding works
55+
folding = {
56+
-- whether a buffer should have folding can be true/false for global enable/disable or fun(bufnr:integer):boolean
57+
enabled = function(bufnr) return require("astrocore.buffer").is_valid(bufnr) end,
58+
-- a priority list of fold methods to try using, available methods are "lsp", "treesitter", and "indent"
59+
methods = { "lsp", "treesitter", "indent" },
60+
},
5461
-- Override highlights in any colorscheme
5562
-- Keys can be:
5663
-- `init`: table of highlights to apply to all colorschemes

lua/astroui/config.lua

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@
2929
---```
3030
---@field file_icon AstroUIFileIconHighlights?
3131

32+
---@alias AstroUIFoldingMethod
33+
---| "indent" # indentation based folding (`:h fold-indent`)
34+
---| "lsp" # LSP based folding (`:h vim.lsp.foldexpr`)
35+
---| "treesitter" # Treesitter based folding (`:h vim.treesitter.foldexpr`)
36+
37+
---@class AstroUIFoldingOpts
38+
---@field enabled (boolean|fun(bufnr:integer):boolean)? whether folding should be enabled in a buffer or not
39+
---@field methods AstroUIFoldingMethod[]? a table of folding methods in priority order
40+
3241
---@class AstroUILazygitOpts
3342
---@field theme_path string? the path to the storage location for the lazygit theme configuration
3443
---@field theme table<string|number,{fg:string?,bg:string?,bold:boolean?,reverse:boolean?,underline:boolean?,strikethrough:boolean?}>? table of highlight groups to use for the lazygit theme
@@ -131,6 +140,16 @@
131140
---colorscheme = "astrodark"
132141
---```
133142
---@field colorscheme string?
143+
---Configure how folding works
144+
---Example:
145+
---
146+
---```lua
147+
---folding = {
148+
--- enabled = function(bufnr) return require("astrocore.buffer").is_valid(bufnr) end,
149+
--- methods = { "lsp", "treesitter", "indent" },
150+
---}
151+
---```
152+
---@field folding AstroUIFoldingOpts|false?
134153
---Override highlights in any colorscheme
135154
---Keys can be:
136155
--- `init`: table of highlights to apply to all colorschemes
@@ -218,6 +237,7 @@
218237
---@type AstroUIOpts
219238
local M = {
220239
colorscheme = nil,
240+
folding = {},
221241
highlights = {},
222242
icons = {},
223243
text_icons = {},

lua/astroui/folding.lua

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,55 @@
66
--
77
-- copyright 2024
88
-- license GNU General Public License v3.0
9-
109
local M = {}
1110

11+
local config = require("astroui").config.folding
12+
1213
local is_setup = false
1314
local lsp_bufs = {}
1415

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+
1533
--- A fold expression for doing LSP and Treesitter based folding
1634
---@param lnum? integer the current line number
1735
---@return string the calculated fold level
1836
function M.foldexpr(lnum)
1937
if not is_setup then M.setup() end
2038
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"
3353
end
3454

3555
function M.setup()
3656
-- 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
3858
local augroup = vim.api.nvim_create_augroup("astroui_foldexpr", { clear = true })
3959
vim.api.nvim_create_autocmd("LspAttach", {
4060
desc = "Monitor attached LSP clients with fold providers",

0 commit comments

Comments
 (0)