Neovim folding that matches JetBrains <editor-fold> comment markers, so a project folds the same way whether it is opened in Neovim or a JetBrains IDE.
// <editor-fold desc="PROPERTIES" defaultstate="collapsed">
... code ...
// </editor-fold>
defaultstate="collapsed"- fold starts closeddefaultstate="expanded"- fold starts openeddesc="..."- text shown in the closed fold marker
Minimal - just setup(), no keymaps:
{
"chewbakartik/editorfold.nvim",
opts = {
mode = "guarded" -- or "always"
},
}With the suggested keymaps plus a filetype comment-style override example included (PHP shown here - see "Filetype comment-style overrides" below for why this exists): once you supply your own config function, lazy.nvim no longer calls setup(opts) for you automatically.
{
"chewbakartik/editorfold.nvim",
opts = {
mode = "guarded" -- or "always"
commentstring_overrides = {
php = "// %s",
},
},
config = function(_, opts)
require("editorfold").setup(opts)
vim.keymap.set("n", "<leader>zc", "<cmd>EditorFoldInsertCollapsed<CR>", { desc = "Insert collapsed editor-fold" })
vim.keymap.set("n", "<leader>ze", "<cmd>EditorFoldInsertExpanded<CR>", { desc = "Insert expanded editor-fold" })
vim.keymap.set("n", "<leader>zx", "<cmd>EditorFoldInsertEnd<CR>", { desc = "Insert editor-fold end" })
vim.keymap.set("n", "<leader>zr", "<cmd>EditorFoldRefresh<CR>", { desc = "Refresh editor-fold state" })
end,
}If you'd rather manage keymaps separately from your plugin specs (e.g. in a dedicated keymaps file), use the minimal form above and set the keymaps anywhere else in your config that runs after this plugin loads - see "Suggested keymaps" below for the same bindings on their own.
This plugin does nothing until you set mode, either by setting in opts above, or calling setup() manually:
require("editorfold").setup({ mode = "guarded" })
guarded(default) - only takes over folding on buffers that actually contain aneditor-foldmarker. Won't interfere with other foldmethods on unrelated files.always- takes over folding on every buffer
-
:EditorFoldRefresh— re-scans the current buffer and reapplies fold structure anddefaultstatedefaults. Needed after adding or removing an<editor-fold>marker mid-session (fold structure doesn't update automatically for that case). Note: this resets any folds you'd manually opened/closed back to theirdefaultstate— there's no way to recompute fold structure without this side effect underfoldmethod=expr. -
:EditorFoldInsertCollapsed— inserts a new<editor-fold defaultstate="collapsed">marker below the current line, using the correct comment syntax for the buffer (see "Filetype comment-style overrides" below), and drops you into insert mode with the cursor positioned inside thedesc=""attribute. -
:EditorFoldInsertExpanded— same as above, withdefaultstate="expanded". -
:EditorFoldInsertEnd— inserts a closing</editor-fold>marker below the current line.
None of the above commands are bound to a key by default, you will need to set your own. A suggested keymap setting is:
vim.keymap.set("n", "<leader>zc", "<cmd>EditorFoldInsertCollapsed<CR>", { desc = "Insert collapsed editor-fold" })
vim.keymap.set("n", "<leader>ze", "<cmd>EditorFoldInsertExpanded<CR>", { desc = "Insert expanded editor-fold" })
vim.keymap.set("n", "<leader>zx", "<cmd>EditorFoldInsertEnd<CR>", { desc = "Insert editor-fold end" })
vim.keymap.set("n", "<leader>zr", "<cmd>EditorFoldRefresh<CR>", { desc = "Refresh editor-fold state" })Some languages support more than one comment style, but Neovim's commentstring for a given filetype only ever reports one of them. PHP is the motivating example: Neovim reports /* %s */, but // is equally valid and more common for single line comments. It is the convention that this plugin uses.
commentstring_overrides lets you tell the plugin to use a different style of commentstring than the Neovim's default for specific filetypes, both for matching and generating new markers by the insert commands.
require("editorfold").setup({
commentstring_overrides = {
php = "// %s",
-- add more as needed such as
-- c = "// %s",
},
})This is additive with the plugin's own default (php = "// %s") - your setup() options are deep-merged with the built-in defaults, so adding an override for another filetype doesn't remove the one for PHP, and overriding php replaces the default.
Regardless of commentstring_overrides, // and # are always accepted as fallback leaders when matching existing markers, though not used for generating new ones.
If there are additional languages you would like to see overrides ship by default with this plugin, please open an issue or submit a PR.
Once a buffer has folds enabled, interactions with the folds are handled by Neovim, not this plugin. The same commands work regardless of foldmethod:
| Key | Action |
|---|---|
za |
Toggle fold under cursor |
zo |
Open fold under cursor |
zc |
Close fold under cursor |
zR |
Open all folds in the buffer |
zM |
Close all folds in the buffer |
zj |
Move to start of next fold |
zk |
Move to end of previous fold |
Full reference: :help fold-commands.
The test/ directory holds an isolated Neovim config, separate from your real dotfiles. In order to see the behaviour of the plugin without any other configs or plugins interfering.
-- test/minimal.lua
vim.opt.rtp:append(vim.fn.getcwd())
require("editorfold").setup({ mode = "always" })
-- test/sample.lua
-- contains a small test lua fileLaunch it from the repo root:
nvim --clean -u test/minimal.lua test/sample.luaTested against Neovim v0.12.3. No external dependencies.