Closed D00mch closed 1 year ago
No, you need to wrap the result return from LSP provider. https://github.com/kevinhwang91/nvim-ufo/blob/9e829d5cfa3de6a2ff561d86399772b0339ae49d/doc/example.lua#L36-L56
Keyword: provider_selector
and getFolds
Sory if it's a stupid question, but how is this
:set foldmethod=expr foldexpr=getline(v:lnum)=~'^\\s*'.&commentstring[0]
suppose to work?
As I get from the snippets you provided, we fallback to using treesitter, and next — indent. But both of them have nothing to do with the foldmethod=expr.
And as I get it, there is no way to return 'expr' from the provider_selector
.
Use a function to get the LSP result via getFolds
API and inspect the result, you also need to scan/prase the buffer content and inject the folds to the raw
result and then return.
local ftMap = {
clojure = function (bufnr)
return require('ufo').getFolds(bufnr, 'lsp'):thenCall(function (raw)
print(vim.inspect(raw))
return raw
end)
end
}
require('ufo').setup({
provider_selector = function(bufnr, filetype, buftype)
-- return ftMap[filetype] or {'treesitter', 'indent'}
return ftMap[filetype]
end
})
I am almost there. But the maestro's touch is still required. I have a function that returns ranges:
local function get_comment_folds(bufnr)
local comment_folds = {}
local line_count = vim.api.nvim_buf_line_count(bufnr)
local is_in_comment = false
local comment_start = 0
for i = 0, line_count - 1 do
local line = vim.api.nvim_buf_get_lines(bufnr, i, i + 1, false)[1]
if not is_in_comment and line:match('^%s*' .. vim.o.commentstring:sub(1, 1)) then
is_in_comment = true
comment_start = i
elseif is_in_comment and not line:match('^%s*' .. vim.o.commentstring:sub(1, 1)) then
is_in_comment = false
table.insert(comment_folds, {startLine = comment_start, endLine = i - 1})
end
end
if is_in_comment then
table.insert(comment_folds, {startLine = comment_start, endLine = line_count - 1})
end
return comment_folds
end
Here is an example of what it returns:
{{endLine = 8, startLine = 8},
{endLine = 16, startLine = 16},
{endLine = 47, startLine = 47},
{endLine = 101, startLine = 98},
{endLine = 102, startLine = 103}}
I managed to make it work with treesitter this way:
local function treesitter_and_comment_folding(bufnr)
local comment_folds = get_comment_folds(bufnr)
local lsp_folds = ufo.getFolds(bufnr, "treesitter")
for _, fold in ipairs(comment_folds) do
table.insert(lsp_folds, fold)
end
print(vim.inspect(lsp_folds))
return lsp_folds
end
So something like this should work:
local function lsp_and_comment_folding(bufnr)
local comment_folds = get_comment_folds(bufnr)
return ufo.getFolds(bufnr, 'lsp'):thenCall(function(lsp_folds)
for _, fold in ipairs(comment_folds) do
table.insert(lsp_folds, fold)
end
return lsp_folds
end)
end
But it doesn't.
I wasn't able to print anything except nil
with this code:
local ftMap = {
clojure = function (bufnr)
return require('ufo').getFolds(bufnr, 'lsp'):thenCall(function (raw)
print(vim.inspect(raw))
return raw
end)
end
}
I use fennel to config neovim, it allows me to evaluate expressions in place.
Here is an example of what
ufo.getFolds(bufnr, 'treesitter')
and ufo.getFolds(bufnr, 'lsp')
returns accordingly for a buffer with Clojure code:
(ufo.getFolds 12 :treesitter) => [{:endLine 4 :startLine 0}
{:endLine 10 :startLine 9}
{:endLine 26 :startLine 12}
{:endLine 33 :startLine 28}]
(ufo.getFolds 12 :lsp) => {:queue {} :state 1}
The last one also produces an exception:
Error executing vim.schedule lua callback: UnhandledPromiseRejection with the reason:
...pack/packer/start/nvim-ufo/lua/ufo/provider/lsp/nvim.lua:75: UfoFallbackException
LSP was attached to the buffer 12 at the moment, and all the lsp foldings work (except comments one).
I don't use fennel
and clojure
. I guess your provider is treesitter
instead of lsp
.
Run UfoInspect
in the target buffer with default provider_selector
.
I run it in Dart:
Buffer: 20
Fold Status: start
Main provider: lsp
Fallback provider: indent
Selected provider: lsp
Fold kinds: comment, imports
And in Clojure:
Buffer: 10
Fold Status: pending
Main provider: lsp
Fallback provider: indent
Selected provider: indent
Fold kinds:
For both of them (ufo.getFolds 5 :lsp)
returns {queue={}, state=1}
I guess your provider is treesitter instead of lsp.
I am sure it's LSP, because when I change provider_selector
to use treesitter
or indent
, I can see that foldings are different.
Selected provider: indent
Saying that no LSP provider and use indent as fallback.
If you wan to extend treesitter provider, you can set extra fold query directly without setuping provider_selector
.
I've successfully managed to get the desired folding functionality working. Here are a few notes for those who may encounter similar issues.
By default, LSP provides foldable comment blocks for some languages I've tested (typescript, dart). However, Clojure wasn't one of them. To address this, I implemented indent folding along with custom comment folding for Clojure (like in the treesitter_and_comment_folding
example above).
Great to hear this.
Feature description
I want to use LSP foldings and also have the ability to add custom foldings.
Example: I have a clojure file. Everything is folded with LSP except comments:
I can fold comments with:
:set foldmethod=expr foldexpr=getline(v:lnum)=~'^\\s*'.&commentstring[0]
But I then I lost LSP foldings.
Describe the solution you'd like
Maybe a config option like "additional_fold_expr"?
Additional context
I tried to achieve this with "provider_selector", but wasn't able.
But when I wrote:
:set foldmethod=expr foldexpr=getline(v:lnum)=~'^\\s*'.&commentstring[0]
And relaunch my session (using session_manager), both LSP and custom foldings worked. But it's accidental (session manager shortes almost everything).So I know it's possible to achieve, but don't know how to do it consistently.