../nuke-neovim-setup

neovim's 'setup's considered harmful

Apologies for the lazy title. This post follows up on Marc's legitimate complaint explaining why the current usage of setup to initialize neovim plugins is bad or to quote him: "setup as we know it must burn".

The painful setup of neovim plugins

As a neovim developer, as a nix maintainer for everything neovim-related, or as a user I install and try many plugins. Plugins that work out of the box have become the exception rather than the norm, which is increasingly frustrating. Neovim's mantra is to improve the out of the box experience and while core neovim sticks to it, the plugin ecosystem goes opposite to that philosophy:

  1. the useless 'setup' call
  2. the bindings exposed in a custom format, often applied by default
  3. the 100s exposed options

All of this made harder by the fact that sometimes those settings are exposed in a plugin-manager specific (for instance lazy.nvim opts autocalls setup, which certainly exacerbates the issue).

I install a plugin to use it so please have it working by default !

The problem exacerbates when you remove the software since you now have a require'plugin'.setup()` call that can't find 'plugin' anymore ! Thus you have to write defensively

local has_fzf_lua, _fzf_lua = pcall(require, 'fzf-lua')
if has_fzf_lua then 
    require'fzf-lua'.setup()
end

How to configure a plugin without setup ?

In short, like it was always done, with a global variable. The setup() paradigm is also cargo-culted: maintainers copy what other plugins do which is why we have to break the cycle ! What I witnessed across several projects to which I submitted patches to remove the setup call requirement, is that the maintainers ignored that neovim can autoload plugins just fine. Quote from :help load-plugins:

The result is that all directories in 'runtimepath' will be searched for the "plugin" sub-directory and all files ending in ".vim" or ".lua" will be sourced (in alphabetical order per directory), also in subdirectories. First ".vim" are sourced, then ".lua" files, per directory.

marc-setup-post has a more detailed answer but in short, add to your plugin a "runtime/whatever.lua" file and neovim will automatically load it !

This file can read user-configuration from a variable vim.g.PLUGIN_NAME with the same structure as the typical dictionary passed as input of setup calls. You can merge the user config with the plugin defaults to generate an exhaustive config easily accessible by the plugin, for instance in lua/my_plugin/config.lua:

local my_plugin_default_configuration = { default_option = 42; }
return vim.tbl_deep_extend("keep", vim.g.my_plugin_config or {},
my_plugin_default_configuration)

Other lua modules can just require'my_plugin.config' to get the final config.

One concern I had with setup is that sometimes I would user if the plugin had Using a global variable alleviates a worry I keep having with setup

Conclusion

If we want nice interfaces in neovim where one can just toggle a checkbox to install or uninstall a plugin, we need to get rid of the boilerplate needed for a working plugin. Provide a default sensible configuration that works out of the box, expose settings that make sense through simple types (strings, integers) and expose an API if you want to allow the users to deeply integrate with your plugin.

/plugins/ /neovim/