anuvyklack / pretty-fold.nvim

Foldtext customization in Neovim
Apache License 2.0
441 stars 21 forks source link

How to get rid of the `fill_char`s in the foldtext before the `content` #36

Closed tummetott closed 7 months ago

tummetott commented 11 months ago

Hello there,

Let's assume the following code snippet:

image

When i fold the function, the code looks like this image

I would like to get rid of the red circled fill_chars

As far as I can tell, the way to go about this is by configuring fill_char = ' ' within the pretty-folds setup() function and then creating a right-side section which also generates the dots in between. Something like this:

local fold_text = function()
    local lines = vim.v.foldend - vim.v.foldstart + 1
    local padding = has_scrollbar() and ' ' or ''
    local n = vim.api.nvim_win_get_width(0)
         - vim.fn.strdisplaywidth(lines)
         - vim.fn.strdisplaywidth(padding)
         - vim.fn.strdiplaywidth(content) -- How do i get content???
         + 8) -- plus 8 because I have 8 fixed characters in my final string
    local fill_chars = string.rep('⋅', n)
    return string.format('%s %d LINES %s', fill_chars, lines, padding)
end

require('pretty-fold').setup {
    sections = {
        left = { 'content' }, -- I want to have the length of this content in my custom function before
        right = { fold_text }, -- use my custom function
    },
    fill_char = ' ',
    add_close_pattern = true,
}

I'm aware I could skip using the content generated by the plugin and grab the text of the first line of the fold using vim.api.nvim_buf_get_lines(...). However, that would mean missing out on the cool substitutions like the close_pattern, etc.

Is there a way to determine the length of the content? Or perhaps a simpler approach to achieve my goal?

Thanks a lot!

runarsf commented 7 months ago

Hi there, An approach that should do what you want is to get the indentation level of the folded line, and prepend that amount of spaces to the content.

{
  keep_indentation = false,
  sections = {
    left = {
      function() return string.rep(' ', vim.fn.indent(vim.v.foldstart)) end, 'content',
    },
  },
}
tummetott commented 7 months ago

@runarsf Thank you so much for providing such a straightforward solution. I can't believe I didn't think of that earlier.

For future reference, I made some alterations to the solution. It appears that the content module adds a whitespace character as a prefix if content is not the first entry in the left dictionary and the keep_indentation flag is set to false. This can result in a misalignment issue, causing the foldtext to be off by one character. See the source code:

https://github.com/anuvyklack/pretty-fold.nvim/blob/a7d8b424abe0eedf50116c460fbe6dfd5783b1d5/lua/pretty-fold/components.lua#L343-L356

So I strip away the leading whitespace like this:

{
    keep_indentation = false,
    sections = {
        left = {
            function(config)
                local prefix = ''
                local indent = vim.fn.indent(vim.v.foldstart)
                if indent and indent > 0 then
                    prefix = string.rep(' ', indent)
                end
                local content = require('pretty-fold.components')['content'](config)
                -- Cut the leading whitespace
                content = content:gsub('^%s*', '')
                return prefix .. content
            end,
        },
    },
}