Set Default Fold Level
orhnk opened this issue · comments
Describe the bug
Initial setup folds all headers in an org file on startup.
You can disable this by:
vim.cmd [[setlocal nofoldenable]] -- No folds initially
With this in you config the headers don't fold anymore but folding works incorrect!
tmp-2023-09-24_08.42.30.mp4
As you can see:
- The file has no folds initially
- When I try to fold a header whole file collapses
- So I refold each header.
Steps to reproduce
- define
setlocal nofoldenable
in your config - open a org file
- try to fold any header
Expected behavior
Wanted to see the merge-lang
header folded only. (in the video)
Emacs functionality
Emacs works as it should
Minimal init.lua
vim.cmd [[setlocal nofoldenable]] -- No folds initially
Screenshots and recordings
No response
OS / Distro
archlinux
Neovim version/commit
NVIM v0.10.0-dev-bb38c06 Build type: RelWithDebInfo LuaJIT 2.1.1693350652
Additional context
No response
@UTFeight does your folds work correctly when you do not do setlocal nofoldenable
?
Here is how they look without setlocal nofoldenable
:
tmp-2023-09-24_11.44.51.mp4
They do work how they should be now.
But there is no option to set as fold_depth
which I want to see like the following:
Note
This is set foldlevel=99
And works exactly how I want it to work.
But... (look at the next video)
tmp-2023-09-24_11.47.12.mp4
Note
Using set foldlevel=99
loaded after the config,
seems to not work?
tmp-2023-09-24_11.51.15.mp4
for some nice blue switch ASMR, you can unmute videos :D
I have found a solution for this!
adding options after lazy loading the plugin didn't work well so this was happening.
Solution
-
After orgmode is (lazy) loaded (for lazy.nvim It's in
config
fn):-- vim.cmd [[setlocal foldlevel=99]] -- WARNING: DIDN'T WORK!!! vim.cmd [[setlocal nofoldenable]] -- No folds initially -- ABOVE SNIPPET IS RAN RIGHT AFTER THE PLUGIN IS LOADED
Note
Using foldlevel=99
in lazy's config
fn didn't work.
I wonder why?
- init.lua
vim.cmd [[autocmd FileType org setlocal foldlevel=99]]
Autocmd Version:
-- (Put that in init.lua if you don't have an option like mine)
vim.cmd [[autocmd FileType org setlocal nofoldenable]] -- No folds initially
vim.cmd [[autocmd FileType org setlocal foldlevel=99]]
Without UFO I can reproduce this issue, I have attached a minimal init.
Here's a minimal init that reproduces the folding behavior
local M = {}
---@class MinPlugin A plugin to download and register on the package path
---@alias PluginName string The plugin name, will be used as part of the git clone destination
---@alias PluginUrl string The git url at which a plugin is located, can be a path. See https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols for details
---@alias MinPlugins table<PluginName, PluginUrl>
local base_root_path = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h") .. "/.min"
---Gets the root directory of the minimal init and if path is specified appends the given path to the root allowing for
---subdirectories within the current cwd
---@param path string? The additional path to append to the root, not required
---@return string root The root path suffixed with the path provided or an empty suffix if none was given
function M.root(path)
return base_root_path .. "/" .. (path or "")
end
---Downloads a plugin from a given url and overwrites the 'packpath' to the new plugin package path
---@param plugin_name PluginName
---@param plugin_url PluginUrl
function M.load_plugin(plugin_name, plugin_url)
local package_root = M.root("plugins/")
local install_destination = package_root .. plugin_name
vim.opt.runtimepath:append(install_destination)
if not vim.loop.fs_stat(package_root) then
vim.fn.mkdir(package_root, "p")
end
-- If the plugin install path already exists, we don't need to clone it again.
if not vim.loop.fs_stat(install_destination) then
print(string.format("> Downloading plugin '%s' to '%s'", plugin_name, install_destination))
vim.fn.system({
"git",
"clone",
"--depth=1",
plugin_url,
install_destination,
})
if vim.v.shell_error > 0 then
error(string.format("> Failed to clone plugin: '%s' in '%s'!", plugin_name, install_destination),
vim.log.levels.ERROR)
end
end
end
---@class MinSetupConfig
---@field root? string The base path to use for all data storage, if nil the root will be set to this module's directory
---@field plugins? MinPlugins The plugins to install and register on the runtimepath
---Do the initial setup. Downloads plugins, ensures the minimal init does not pollute the filesystem by keeping
---everything self contained to the CWD of the minimal init file. Run prior to running tests, reproducing issues, etc.
---READ: It is on the user to setup the plugins, this only registers them to the runtime path, it does NOT set them up!
---@param config? MinSetupConfig
function M.setup(config)
vim.opt.packpath = {} -- Empty the package path so we use only the plugins specified
vim.opt.runtimepath:append(M.root(".min")) -- Ensure the runtime detects the root min dir
if config ~= nil then
if config.root ~= nil then
base_root_path = config.root
end
-- Install required plugins
if config.plugins ~= nil then
for plugin_name, plugin_url in pairs(config.plugins) do
M.load_plugin(plugin_name, plugin_url)
end
end
end
vim.env.XDG_CONFIG_HOME = M.root("xdg/config")
vim.env.XDG_DATA_HOME = M.root("xdg/data")
vim.env.XDG_STATE_HOME = M.root("xdg/state")
vim.env.XDG_CACHE_HOME = M.root("xdg/cache")
-- NOTE: Cleanup the xdg cache on exit so new runs of the minimal init doesn't share any previous state, e.g. shada
vim.api.nvim_create_autocmd("VimLeave", {
callback = function()
vim.fn.system({
"rm",
"-r",
"-f",
M.root("xdg")
})
end
})
end
-- NOTE: If you have additional plugins you need to install to reproduce your issue, include them in the plugins
-- table within the setup call below.
M.setup({
plugins = {
treesitter = "https://github.com/nvim-treesitter/nvim-treesitter",
orgmode = "https://github.com/nvim-orgmode/orgmode",
}
})
-- WARN: Do all plugin setup, test runs, reproductions, etc. AFTER calling setup with a list of plugins!
-- Basically, do all that stuff AFTER this line.
-- Load treesitter grammar for org
require("orgmode").setup_ts_grammar()
-- Setup treesitter
vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
require("nvim-treesitter.configs").setup({
highlight = {
enable = true,
additional_vim_regex_highlighting = { "org" },
},
ensure_installed = { "org" },
sync_install = true
})
-- Setup orgmode
vim.opt.foldlevel = 99
require("orgmode").setup({})
vim.cmd.edit("tester.org")
vim.api.nvim_buf_set_lines(0, 0, -1, false, {
"* Heading uno",
"",
"** Inner Heading One",
"",
"** Inner Heading Two",
"",
"* Another toplevel heading",
"",
})
vim.cmd.write()
-- Have to make treesitter happy so we get correct folds. So we have to write after writing the content, TS wasn't
-- ready.
local timer = vim.loop.new_timer()
timer:start(100, 0, vim.schedule_wrap(function()
vim.cmd.edit()
print("Notice that some of the content is already folded when opened... this shouldn't be the case.")
timer:close()
end))
Just copy and paste that big 'ol beast and run it with nvim -nu MINIMAL_INIT_FILE_NAME.lua
.
It'll show the issue.
Orgmode is overriding the foldlevel
to 0 and doesn't respect the foldlevel
a user may have set. It does that
here.
Ideally Orgmode wouldn't mess with the foldlevel
as it is 0 by default and if a user changed that it really should
respect the custom foldlevel
.
I think I have fixed the issues with UFO
as well by commenting out the fillchars
line as well in the ftplugin file,
link to that.
When both the foldlevel
and fillchars
lines are removed from the ftplugin/org.vim
file, UFO and my foldlevel
settings work as expected.
@kristijanhusak Is there a particular reason Orgmode ignores user configuration of fillchars
& foldlevel
? If so, I'll
see if I can find an alternative work around.
Orgmode is overriding the
foldlevel
to 0 and doesn't respect thefoldlevel
a user may have set. It does that
here.
@treatybreaker That looks like a PR!
@treatybreaker I understand why foldlevel
might be an issue, but I'm not sure why would fillchars
cause an issue?
We could introduce org-startup-folded
as described here https://orgmode.org/manual/Initial-visibility.html and have it's value as overview
by default. This value would set foldlevel
to 0
as it does now. This is just to keep everything backward compatible. Valid options would be overview
(foldlevel=0), content
(foldlevel=1), showeverything
(foldlevel=99) and nil
(no foldlevel set). Then we should read this configuration and act accordingly.
So the fillchars
may be more relevant to #599, as the fold
fillchars
interfere with nvim-ufo
's fold chars.
In terms of foldlevel
, would you accept a PR with that variable org-startup-folded
? I'd be more than happy to send it
your way.
Arguably though we don't even need options for that as Neovim has buffer options which a user could set themselves or just the filetype plugin in their after directory to set the foldlevel
. It's basically built-in. The best way to handle this may just be to just not set the foldlevel
at all and mention it in the docs.
In terms of foldlevel, would you accept a PR with that variable org-startup-folded? I'd be more than happy to send it
your way.
Yes, please send it over. I'd like to streamline it through configuration.