kevinhwang91 / nvim-ufo

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

Folds re-closing when text changes #167

Closed ribru17 closed 9 months ago

ribru17 commented 9 months ago

Neovim version (nvim -v | head -n1)

NVIM v0.9.2

Operating system/version

Arch Linux 6.5.5-arch1-1

How to reproduce the issue

cat mini.lua

-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify('./.repro', ':p')

-- set stdpaths to use .repro
for _, name in ipairs { 'config', 'data', 'state', 'cache' } do
  vim.env[('XDG_%s_HOME'):format(name:upper())] = root .. '/' .. name
end

-- bootstrap lazy
local lazypath = root .. '/plugins/lazy.nvim'
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system {
    'git',
    'clone',
    '--filter=blob:none',
    'https://github.com/folke/lazy.nvim.git',
    lazypath,
  }
end
vim.opt.runtimepath:prepend(lazypath)

-- Setting
vim.o.foldcolumn = '1'
vim.o.foldlevel = 99
vim.o.foldlevelstart = -1
vim.o.foldenable = true

-- install plugins
local plugins = {
  {
    'kevinhwang91/nvim-ufo',
    dependencies = { 'kevinhwang91/promise-async' },
    config = function()
      local ufo = require('ufo')
      ufo.setup {
        provider_selector = function(_, _, _)
          return { 'treesitter' }
        end,
      }
      vim.keymap.set('n', 'zR', ufo.openAllFolds)
      vim.keymap.set('n', 'zM', ufo.closeAllFolds)
    end,
  },
  {
    'akinsho/bufferline.nvim',
    dependencies = { 'kevinhwang91/nvim-ufo' },
    opts = {},
  },
  {
    'nvim-treesitter/nvim-treesitter',
    config = function()
      require('nvim-treesitter.configs').setup {
        -- A list of parser names, or "all" (the first five parsers should always be installed)
        ensure_installed = {
          'lua',
        },
        highlight = { enable = true },
      }
    end,
  },
  -- add any other plugins here
}
require('lazy').setup(plugins, {
  root = root .. '/plugins',
})

cat test.lua

---@diagnostic disable: undefined-global
---@diagnostic disable: unused-local
-- asdf
local frac = s({
  priority = 1000,
  trig = '.*%)/',
  wordTrig = true,
  regTrig = true,
  condition = in_mathzone,
}, {
  f(function(_, snip)
    local match = snip.trigger
    local stripped = match:sub(1, #match - 1)

    local k = #stripped
    local depth = 0
    while false do
      if stripped:sub(k, k) == ')' then
        depth = depth + 1
      end
      if stripped:sub(k, k) == '(' then
        depth = depth - 1
      end
      if depth == 0 then
        break
      end
      k = k - 1
    end

    -- hi

    return rv
  end, {}),
  t('{'),
  i(1),
  t('}'),
  i(0),
})

nvim --clean +'so mini.lua' test.lua

  1. Type Gzazaio<Esc>

Expected behavior

The fold should stay open after leaving insert mode.

Actual behavior

The fold unexpectedly closes. Additionally, typing u (and subsequent <C-r> and u presses) causes the fold to breifly reopen and close again immediately.

EXTRA NOTES: This bug only occurs when using the plugin akinsho/bufferline.nvim and when using the default treesitter fold provider. Using the builtin treesitter foldexpr does not suffer from this issue, and disabling the bufferline plugin also allows it to work. Additionally, this issue (from what I have seen) only occurs when folding at the bottom of a fold, I believe when the bottom line has ambiguous fold depth (e.g. in the example are we folding the entire function call or just the last table parameter?). Thanks for taking a look, this is quite a niche bug I think.

kevinhwang91 commented 9 months ago
vim.cmd([[
set rtp+=/home/kevin/.local/share/nvim/site/pack/packer/opt/nvim-treesitter
set rtp+=/home/kevin/.local/share/nvim/site/pack/packer/start/promise-async
set rtp+=/home/kevin/.local/share/nvim/site/pack/packer/opt/nvim-ufo
]])
vim.o.foldcolumn = '1'
vim.o.foldlevel = 99
vim.o.foldlevelstart = -1
vim.o.foldenable = true
local ufo = require('ufo')
ufo.setup {
    provider_selector = function(_, _, _)
        return { 'treesitter' }
    end,
}
vim.keymap.set('n', 'zR', ufo.openAllFolds)
vim.keymap.set('n', 'zM', ufo.closeAllFolds)

can't reproduce it with my mini.lua.

ribru17 commented 9 months ago

Like I said, this is only present when bufferline.nvim is present. Try the following:

vim.cmd([[
set rtp+=/home/kevin/.local/share/nvim/lazy/nvim-treesitter
set rtp+=/home/kevin/.local/share/nvim/lazy/promise-async
set rtp+=/home/kevin/.local/share/nvim/lazy/nvim-ufo
set rtp+=/home/kevin/.local/share/nvim/lazy/bufferline.nvim
]])
vim.o.foldcolumn = '1'
vim.o.foldlevel = 99
vim.o.foldlevelstart = -1
vim.o.foldenable = true
local ufo = require('ufo')
ufo.setup {
  provider_selector = function(_, _, _)
    return { 'treesitter' }
  end,
}
require('bufferline').setup {}
vim.keymap.set('n', 'zR', ufo.openAllFolds)
vim.keymap.set('n', 'zM', ufo.closeAllFolds)

There is no such issue when using default treesitter foldexpr so I suspect the issue lies in this plugin. Otherwise I would have raised the issue with bufferline.nvim.

kevinhwang91 commented 9 months ago

EXTRA NOTES: This bug only occurs when using the plugin akinsho/bufferline.nvim or when using the default treesitter fold provider.

or -> and

kevinhwang91 commented 9 months ago

still can't reproduce it with addtional akinsho/bufferline.nvim Screenshot_20231004-080241

ribru17 commented 9 months ago

EXTRA NOTES: This bug only occurs when using the plugin akinsho/bufferline.nvim or when using the default treesitter fold provider.

or -> and

My apologies. I see the confusion now. As for the reproducibility I don't know why that is. If you are able to keep your folds open after entering za twice then I suppose it must be an error from something on my machine, or maybe the error is fixed in nightly if you happen to be using that. Anyway thanks for taking a look and sorry again for the confusion.

kevinhwang91 commented 9 months ago

I tested it under v0.9.2. Maybe your ENV issue.

ribru17 commented 9 months ago

Thank you @kevinhwang91. After much head-scratching I have determined the source of the bug. It is not influenced by akinsho/bufferline.nvim at all, but rather the height of the window. That also would likely explain why the issue was not reproducible for you, perhaps your screen was a bit higher and contained all of the lines. I have noticed that when you close a fold at the bottom, and the top of the fold is above the screen (if the fold is too large to be shown on the whole screen), the odd behavior mentioned above will occur. If you reopen the fold and then scroll back up to the top, only then will the entire fold highlight as it should and the weird behavior will not occur. I hope this can be fixed (or reproduced on your end even). I will include a screencast of this behavior.

Whenever the TextChanged event fires, the folds update, causing this behavior. In the screencast I first close and open the fold with za, and each time it reopens is from me hitting za again. The fold closes are caused by the bug upon receiving TextChanged. You can see at the end that upon viewing the start of the fold, the fold gets processed, highlighted properly, and the bug goes away.

Kooha-2023-10-11-09-33-08

Thank you for taking a look.

rockyzhang24 commented 9 months ago

I can reproduce this issue.

kevinhwang91 commented 8 months ago

fixed