nvim-ufo icon indicating copy to clipboard operation
nvim-ufo copied to clipboard

XCode Folding Ribbon

Open kevinhwang91 opened this issue 2 years ago • 22 comments

Feature description

https://github.com/CodeEditApp/CodeEditTextView/issues/43

Describe the solution you'd like

~~Use the sign column~~ Use floating window

Additional context

No response

kevinhwang91 avatar Jun 22 '22 05:06 kevinhwang91

High priority for this feature.

kevinhwang91 avatar Jul 20 '22 16:07 kevinhwang91

🐮

xiyaowong avatar Jul 21 '22 09:07 xiyaowong

image

No idea how to handle lower and upper bar icons. The suggestion is welcome.

kevinhwang91 avatar Jul 24 '22 03:07 kevinhwang91

image

It's too hard.

  1. 19-22 and 23-43 are level1, 22 line is the lower but 23 line is the upper, it can't balance aesthetics and practicality;
  2. A line may be lower/upper of different levels, like 1-4 is level1, but 1-3 can be level2, so upper and lower are not a pair, WTF;

kevinhwang91 avatar Jul 30 '22 11:07 kevinhwang91

@kevinhwang91 I don't fully understand some of the issue you are seeing, but the result of the screenshot so far looks great. I'm guessing that the highlights are in slightly wrong places because of confusing behaviour of nvim folds maybe

akinsho avatar Jul 30 '22 11:07 akinsho

@kevinhwang91 I don't fully understand some of the issue you are seeing, but the result of the screenshot so far looks great. I'm guessing that the highlights are in slightly wrong places because of confusing behaviour of nvim folds maybe

  1. not pretty as GUI, depending on the user icon and font. image
  2. The endLnum of folds may overlap each, hard to compute with high perf. Must take a time to explore.

IMO, must highlight the current fold range with uppe/lower or the bar body, otherwise, it's useless.

kevinhwang91 avatar Jul 30 '22 12:07 kevinhwang91

maybe only use to indicator the startLnum and highlight current range is a compromise method. The upper/lower icon is hard to select and ⁀‿ in some fonts are asymmetric. This is the limitation of terminal.

image

kevinhwang91 avatar Jul 30 '22 15:07 kevinhwang91

I get sucked with the UI. There're many potential errors that need to handle. BTW, ctrl-w+o will work fine with the floating window foldcolumn. https://user-images.githubusercontent.com/17562139/181925985-66dbf19e-bd79-4659-9c3f-c66b1cbe0796.mp4

kevinhwang91 avatar Jul 30 '22 16:07 kevinhwang91

I love the appearance of the xcode folding ribbon. Thanks for sharing it!

Looks like the lower bounds do not add lot's of value, so it's ok to omit them.

Regarding the upper boundary: what if just leave the arrow as it is? That is the only change to make is to encode levels of a fold with a color instead of a number :thinking:

image

image

shofel avatar Aug 12 '22 12:08 shofel

I love the appearance of the xcode folding ribbon. Thanks for sharing it!

Looks like the lower bounds do not add lot's of value, so it's ok to omit them.

Regarding the upper boundary: what if just leave the arrow as it is? That is the only change to make is to encode levels of a fold with a color instead of a number thinking

image

image

Not bad, but must solve the perf first, I will give a try if I have time.

kevinhwang91 avatar Aug 12 '22 13:08 kevinhwang91

@kevinhwang91 whatever comes of this, your prototype looks really cool!

i-am-the-slime avatar Nov 09 '22 12:11 i-am-the-slime

Hi, Kevin, this looks great. Do you mind pushing the branch yet? Ik it's WIP, but I could be an alpha tester :laughing: I mean, even the prototype looks good for me.

Btw, does your new feature depend on the patch to nvim?

WhiteBlackGoose avatar Nov 24 '22 14:11 WhiteBlackGoose

@WhiteBlackGoose Thanks for your attention. I have tested the incomplete code and found it will make nearly a millisecond regression for redraw even if using ffi. If the code is complete, I think the regression will be worse which makes me think it's not a productive implementation. IMO, the enhanced UI shouldn't make Neovim lag, so I have stopped dev for this feature for now.

kevinhwang91 avatar Nov 24 '22 14:11 kevinhwang91

Oh, I see, sad :/

WhiteBlackGoose avatar Nov 24 '22 15:11 WhiteBlackGoose

@WhiteBlackGoose Maybe can get better perf to use statuscolumn. I will give it a try if I have spare time.

kevinhwang91 avatar Jan 11 '23 12:01 kevinhwang91

Nice, good luck with that!

WhiteBlackGoose avatar Jan 11 '23 13:01 WhiteBlackGoose

https://github.com/kevinhwang91/nvim-ufo/issues/4#issuecomment-1382702538

The ribbon is slightly more complicated than the VSCode style. The perf is not bad. Less than 1ms regression in a redraw even if a monitor in portrait orientation with hundred visible lines.

Go ahead if statuscolumn become stable.

kevinhwang91 avatar Jan 14 '23 10:01 kevinhwang91

I was trying to do the vscode style markers using the status column, could make it work with treesitter method(not ufo), couldn't figure out how to convert promise to a function that could be fed into the status column opt, can you help me with that? I was trying to use the ufo.getFolds() method

Chaitanyabsprip avatar Jan 23 '23 17:01 Chaitanyabsprip

Is there any code available showing how to achieve this affect? If anyone wants to use the unfinished feature now

ribru17 avatar Oct 01 '23 08:10 ribru17

Is there any code available showing how to achieve this affect? If anyone wants to use the unfinished feature now

No, will implement it if I have spare time.

kevinhwang91 avatar Oct 01 '23 17:10 kevinhwang91

Thank you. Also I managed to create a minimal version of this without the start and end indicators. If anyone is interested:

      {
        'luukvbaal/statuscol.nvim',
        config = function()
          local builtin = require('statuscol.builtin')
          local c = require('statuscol.ffidef').C
          local util = require('utils')
          for i = 0, 8, 1 do
            vim.api.nvim_set_hl(0, 'FoldCol' .. i, {
              bg = util.blend(
                string.format(
                  '#%06x',
                  vim.api.nvim_get_hl(0, { name = 'Normal' }).fg
                ),
                string.format(
                  '#%06x',
                  vim.api.nvim_get_hl(0, { name = 'Normal' }).bg
                ),
                0.125 * i
              ),
            })
          end
          require('statuscol').setup {
            relculright = true,
            segments = {
              { text = { '%s' }, click = 'v:lua.ScSa' },
              { text = { builtin.lnumfunc, ' ' }, click = 'v:lua.ScLa' },
              {
                -- hl = 'FoldColumn',
                text = {
                  function(args)
                    local fold_level = c.fold_info(args.wp, args.lnum).level
                    local hl = '%#FoldCol' .. fold_level .. '#'
                    if fold_level > 8 then
                      hl = '%#FoldCol8#'
                    end
                    return hl .. ' '
                  end,
                },
                click = 'v:lua.ScFa',
              },
            },
          }
        end,
      },

Util functions:

local function hexToRgb(hex_str)
  local hex = '[abcdef0-9][abcdef0-9]'
  local pat = '^#(' .. hex .. ')(' .. hex .. ')(' .. hex .. ')$'
  hex_str = string.lower(hex_str)

  assert(
    string.find(hex_str, pat) ~= nil,
    'hex_to_rgb: invalid hex_str: ' .. tostring(hex_str)
  )

  local r, g, b = string.match(hex_str, pat)
  return { tonumber(r, 16), tonumber(g, 16), tonumber(b, 16) }
end

function M.blend(fg, bg, alpha)
  bg = hexToRgb(bg)
  fg = hexToRgb(fg)

  local blendChannel = function(i)
    local ret = (alpha * fg[i] + ((1 - alpha) * bg[i]))
    return math.floor(math.min(math.max(0, ret), 255) + 0.5)
  end

  return string.format(
    '#%02X%02X%02X',
    blendChannel(1),
    blendChannel(2),
    blendChannel(3)
  )
end

ribru17 avatar Oct 01 '23 17:10 ribru17