kevinhwang91 / nvim-ufo

Not UFO in the sky, but an ultra fold in Neovim.
BSD 3-Clause "New" or "Revised" License
2.18k stars 38 forks source link

An option to fold every code on startup #83

Closed snowphone closed 1 year ago

snowphone commented 1 year ago

Feature description

Is there any way to do something like set foldlevelstart = 0? I guess foldlevelstart=0 does not work maybe due to internal implementation (Actually it works but whole code is folded on almost every edit).

Describe the solution you'd like

I need something like fold_on_startup = true.

Additional context

No response

kevinhwang91 commented 1 year ago

Get and apply folds are asynchronous in ufo, you need to write down your script if you make sure what's provider you need for a buffer.

https://github.com/kevinhwang91/nvim-ufo/blob/0cd49e045553369e5e236d5ac1159ceca373b550/doc/example.lua#L105-L117

    local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
        require('async')(function()
            bufnr = bufnr or vim.api.nvim_get_current_buf()
            -- make sure buffer is attached
            require('ufo').attach(bufnr)
            -- getFolds return Promise if providerName == 'lsp'
            local ranges = await(require('ufo').getFolds(bufnr, providerName))
            local ok = require('ufo').applyFolds(bufnr, ranges)
            if ok then
                require('ufo').closeAllFolds()
            end
        end)
    end

    vim.api.nvim_create_autocmd('BufRead', {
        pattern = '*',
        callback = function(e)
            applyFoldsAndThenCloseAllFolds(e.buf, 'lsp')
        end
    })
snowphone commented 1 year ago

I put your script to my init.lua but it doesn't work. It throws 'UfoFallbackException'. Do you have any ideas why it happens?

kevinhwang91 commented 1 year ago

Your buffer doesn't support lsp, need catch error.

local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
    require('async')(function()
        bufnr = bufnr or vim.api.nvim_get_current_buf()
        -- make sure buffer is attached
        require('ufo').attach(bufnr)
        -- getFolds return Promise if providerName == 'lsp'
        local ok, ranges = pcall(await, require('ufo').getFolds(bufnr, providerName))
        if ok and ranges then
            ok = require('ufo').applyFolds(bufnr, ranges)
            if ok then
                require('ufo').closeAllFolds()
            end
        end
    end)
end
snowphone commented 1 year ago

Well, as you said the exception is caught but code is not folded still. Did I miss something? Or what should I do to support lsp in my buffer? FYI, I use neovim 0.7.2 stable, coc-nvim, and your plugin.

p.s. it works on lua files (coc-sumneko-lua) but does not work on python (coc-pyright).

kevinhwang91 commented 1 year ago

but code is not folded still.

if not ok then getFolds(bufnr, 'indent')

pyright doesn't support foldingrange, check out echo CocAction('hasProvider', 'foldingRange')

snowphone commented 1 year ago

Yeah, as you mentioned, pyright does not support foldingRange feature. So, there's no way to do it without an aid of foldingRange?

kevinhwang91 commented 1 year ago

Yes, you can bypass lsp, and use treesitter and indent instead directly for python. getFolds(bufnr, 'lsp') return a promise object that means you can feel the new buffer redraw when the lines become folded. treesitter and indent are sync.

snowphone commented 1 year ago

Thanks a lot! It clearly works :)

For future readers, I just replaced applyFoldsAndThenCloseAllFolds(e.buf, 'lsp') with applyFoldsAndThenCloseAllFolds(e.buf, 'treesitter').

Get and apply folds are asynchronous in ufo, you need to write down your script if you make sure what's provider you need for a buffer.

https://github.com/kevinhwang91/nvim-ufo/blob/0cd49e045553369e5e236d5ac1159ceca373b550/doc/example.lua#L105-L117

    local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
        require('async')(function()
            bufnr = bufnr or vim.api.nvim_get_current_buf()
            -- make sure buffer is attached
            require('ufo').attach(bufnr)
            -- getFolds return Promise if providerName == 'lsp'
            local ranges = await(require('ufo').getFolds(bufnr, providerName))
            local ok = require('ufo').applyFolds(bufnr, ranges)
            if ok then
                require('ufo').closeAllFolds()
            end
        end)
    end

    vim.api.nvim_create_autocmd('BufRead', {
        pattern = '*',
        callback = function(e)
            applyFoldsAndThenCloseAllFolds(e.buf, 'lsp')
        end
    })
kevinhwang91 commented 1 year ago

TBH, I'm not a fan of treesitter. indent for python is enough. The perf is lsp > indent > treesitter.

mBaratta96 commented 1 year ago

Hello, tried to follow this issue, but still getting:

Error executing vim.schedule lua callback: UnhandledPromiseRejection with the reason:
...ck/packer/start/nvim-ufo/lua/ufo/provider/treesitter.lua:109: UfoFallbackException

This happens each time I open a new file. Here's my config:

vim.o.foldcolumn = "0" -- '0' is not bad
vim.o.foldlevel = 99   -- Using ufo provider need a large value, feel free to decrease the value
vim.o.foldlevelstart = 99
vim.o.foldenable = true

-- Using ufo provider need remap `zR` and `zM`. If Neovim is 0.6.1, remap yourself
vim.keymap.set("n", "zO", require("ufo").openAllFolds)
vim.keymap.set("n", "zC", require("ufo").closeAllFolds)

require("ufo").setup({
    provider_selector = function(bufnr, filetype, buftype)
        return { "treesitter", "indent" }
    end,
})

local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
    require("async")(function()
        bufnr = bufnr or vim.api.nvim_get_current_buf()
        -- make sure buffer is attached
        require("ufo").attach(bufnr)
        -- getFolds return Promise if providerName == 'lsp'
        local ranges = await(require("ufo").getFolds(bufnr, providerName))
        local ok = require("ufo").applyFolds(bufnr, ranges)
        if ok then
            require("ufo").closeAllFolds()
        end
    end)
end

vim.api.nvim_create_autocmd("BufRead", {
    pattern = "*",
    callback = function(e)
        applyFoldsAndThenCloseAllFolds(e.buf, "treesitter")
    end,
})
kevinhwang91 commented 1 year ago

Read example.lua by yourself.

mBaratta96 commented 1 year ago

Managed to figure this out, I switched to lsp and added a specific if else condition with indent fallback:

local function applyFoldsAndThenCloseAllFolds(bufnr, providerName)
    require("async")(function()
        bufnr = bufnr or vim.api.nvim_get_current_buf()
        -- make sure buffer is attached
        require("ufo").attach(bufnr)
        -- getFolds return Promise if providerName == 'lsp'
        local ok, ranges = pcall(await, require("ufo").getFolds(bufnr, providerName))
        if ok and ranges then
            ok = require("ufo").applyFolds(bufnr, ranges)
            if ok then
                require("ufo").closeAllFolds()
            end
        else
            local ranges = await(require("ufo").getFolds(bufnr, "indent"))
            local ok = require("ufo").applyFolds(bufnr, ranges)
            if ok then
                require("ufo").closeAllFolds()
            end
        end
    end)
end

vim.api.nvim_create_autocmd("BufRead", {
    pattern = "*",
    callback = function(e)
        applyFoldsAndThenCloseAllFolds(e.buf, "lsp")
    end,
})