⚠️ WARNING: Neovim v0.7 or higher is requiredThere is a 0.6 branch which is lack of some features.
Pretty Fold is a lua plugin for Neovim which provides framework for easy foldtext customization. Filetype specific and foldmethod specific configuration is supported.
simplescreenrecorder-2022-01-05_20.24.21.mp4
Installation and setup example with packer:
use{ 'anuvyklack/pretty-fold.nvim',
config = function()
require('pretty-fold').setup()
end
}
The plugin comes with the following defaults (the description of each option is below):
config = {
sections = {
left = {
'content',
},
right = {
' ', 'number_of_folded_lines', ': ', 'percentage', ' ',
function(config) return config.fill_char:rep(3) end
}
},
fill_char = '•',
remove_fold_markers = true,
-- Keep the indentation of the content of the fold string.
keep_indentation = true,
-- Possible values:
-- "delete" : Delete all comment signs from the fold string.
-- "spaces" : Replace all comment signs with equal number of spaces.
-- false : Do nothing with comment signs.
process_comment_signs = 'spaces',
-- Comment signs additional to the value of `&commentstring` option.
comment_signs = {},
-- List of patterns that will be removed from content foldtext section.
stop_words = {
'@brief%s*', -- (for C++) Remove '@brief' and all spaces after.
},
add_close_pattern = true, -- true, 'last_line' or false
matchup_patterns = {
{ '{', '}' },
{ '%(', ')' }, -- % to escape lua pattern char
{ '%[', ']' }, -- % to escape lua pattern char
},
ft_ignore = { 'neorg' },
}
The main part. Contains two tables: config.sections.left
and
config.sections.right
which content will be left and right aligned
respectively. Each of them can contain names of the
components and functions that returns string.
The strings from the table below will be expanded according to the table.
Item | Expansion |
---|---|
'content' |
The content of the first non-blank line of the folded region, somehow modified according to other options. |
'number_of_folded_lines' |
The number of folded lines. |
'percentage' |
The percentage of the folded lines out of the whole buffer. |
All functions accept config table as an argument, so if you would like to pass
any arguments into your custom function, place them into the config table which
you pass to setup
function and then you can access them inside your function,
like this:
require('pretty-fold').setup {
custom_function_arg = 'Hello from inside custom function!',
sections = {
left = {
function(config)
return config.custom_function_arg
end
},
}
}
default: '•'
Character used to fill the space between the left and right sections.
default: true
Remove foldmarkers from the content
component.
default: true
Keep the indentation of the content of the fold string.
What to do with comment signs:
default: spaces
Option | Description |
---|---|
'delete' |
delete all comment signs from the foldstring |
'spaces' |
replace all comment signs with equal number of spaces |
false |
do nothing with comment signs |
default: {}
Table with comment signs additional to the value of &commentstring
option.
Add additional comment signs only when you really need them. Otherwise, they
give computational overhead without any benefits.
Example for Lua. Default &commentstring
value for Lua is: '--'
.
comment_signs = {
{ '--[[', '--]]' }, -- multiline comment
}
Example for C++. Default &commentstring
value for C++ is: { '/*', '*/' }
comment_signs = { '//' }
default: '@brief%s*'
(for C++) Remove '@brief' and all spaces after.
Lua patterns that will be
removed from the content
section.
default: true
If this option is set to true
for all opening patterns that will be found in
the first non-blank line of the folded region, all corresponding closing
elements will be added after ellipsis. (The synthetical string with matching
closing elements will be constructed).
If it is set to last_line
, the last line content (without comments) will be
added after the ellipsis . This behavior was the first algorithm I
implemented, but turns out it is not always relevant. For some languages (at
least for all lisps) this does not work. Since it is already written and if
someone like this behavior, I keep this option to choose.
The list with matching elements. Each item is a list itself with two items: opening lua pattern and close string which will be added if oppening pattern is found.
Examples for lua (Lua patterns are explained with railroad diagrams):
matchup_patterns = {
-- ╟─ Start of line ──╭───────╮── "do" ── End of line ─╢
-- ╰─ WSP ─╯
{ '^%s*do$', 'end' }, -- `do ... end` blocks
-- ╟─ Start of line ──╭───────╮── "if" ─╢
-- ╰─ WSP ─╯
{ '^%s*if', 'end' },
-- ╟─ Start of line ──╭───────╮── "for" ─╢
-- ╰─ WSP ─╯
{ '^%s*for', 'end' },
-- ╟─ "function" ──╭───────╮── "(" ─╢
-- ╰─ WSP ─╯
{ 'function%s*%(', 'end' }, -- 'function(' or 'function ('
{ '{', '}' },
{ '%(', ')' }, -- % to escape lua pattern char
{ '%[', ']' }, -- % to escape lua pattern char
},
The comment substring in foldtext is correctly handled on close elements adding.
If process_comment_signs = 'spaces'
is set, the output will be
This plugin provides two setup functions.
-
The first one setup configuration which will be used for all filetypes for which you doesn't set their own configuration.
require('pretty-fold').setup(config: table)
-
The second one allows to setup filetype specific configuration:
require('pretty-fold').ft_setup(filtype: string, config: table)
require('pretty-fold').ft_setup('lua', {
matchup_patterns = {
{ '^%s*do$', 'end' }, -- do ... end blocks
{ '^%s*if', 'end' }, -- if ... end
{ '^%s*for', 'end' }, -- for
{ 'function%s*%(', 'end' }, -- 'function( or 'function (''
{ '{', '}' },
{ '%(', ')' }, -- % to escape lua pattern char
{ '%[', ']' }, -- % to escape lua pattern char
},
}
default: { 'neorg' }
Filetypes to be ignored.
ft_ignore
is a unique option. It exists only in a single copy for all global
and filetype specific configurations. You can pass it in any function
(setup()
or ft_setup()
) and all this values will be collected in this one
single value.
The pretty-fold.nvim plugin supports saparate configuration for different foldmethods. For this pass the configuration table for a particular foldmethod as a value to the key named after foldmethod.
You can also pass global
configuration table for all foldmethods and tune
only desired options in foldmethod specific config table. All options that
don't have value in foldmethod config table will be taken from global
config
table.
Example:
require('pretty-fold').setup({
global = {...}, -- global config table for all foldmethods
marker = { process_comment_signs = 'spaces' },
expr = { process_comment_signs = false },
})
require('pretty-fold').setup{
keep_indentation = false,
fill_char = '•',
sections = {
left = {
'+', function() return string.rep('-', vim.v.foldlevel) end,
' ', 'number_of_folded_lines', ':', 'content',
}
}
}
require('pretty-fold').setup{
keep_indentation = false,
fill_char = '━',
sections = {
left = {
'━ ', function() return string.rep('*', vim.v.foldlevel) end, ' ━┫', 'content', '┣'
},
right = {
'┫ ', 'number_of_folded_lines', ': ', 'percentage', ' ┣━━',
}
}
}
require('pretty-fold').ft_setup('cpp', {
process_comment_signs = false,
comment_signs = {
'/**', -- C++ Doxygen comments
},
stop_words = {
-- ╟─ "*" ──╭───────╮── "@brief" ──╭───────╮──╢
-- ╰─ WSP ─╯ ╰─ WSP ─╯
'%*%s*@brief%s*',
},
})
Preview module have been moved into separate plugin.
Check 'fillchars' option. From lua it can be set the next way:
vim.opt.fillchars:append('fold:•')