Migrating to Rocks.nvim

Published Tue May 07 2024

I have recently made the jump from lazy.nvim to rocks.nvim for managing my Neovim plugins. Lazy has served me well after replacing packer.nvim, but the time is right and I am very excited about the future of rocks.nvim.

Why Rocks?

The driving cause behind rocks.nvim’s creation is dependency management. The Vim and now Neovim plugin ecosystems have used public Github repos to distribute source code for a long time. This system has been working, but as a community we stand to benefit greatly from using an actual package manager. Enter Luarocks, the package manager for Lua. By adopting Luarocks I immediately see benefits familiar to developers: dependency management, versioned plugins, and automated builds.

Installing Plugins

With lazy.nvim installing a plugin is not difficult. I create a new file in my config directory .config/nvim/lua/plugins/my-plugin.lua that follows the lazy module structure. Here is a basic config for indent-blankline:

{
  "lukas-reineke/indent-blankline.nvim",
  main = "ibl",
  opts = {}
}

This is very lightweight and easy to manage, but rocks makes life even simpler. Instead of making a new file or deciding which module to include this new plugin in I simply run :Rocks install indent-blankline.nvim. For a plugin like this where I do not need custom configuration I am all done! After running this command a new entry will be added to my rocks.toml file in the root of my Neovim config:

"indent-blankline.nvim" = "3.5.4"

Now should this plugin push new versions or breaking changes my configuration will not be affected until I decide to upgrade. Version 3.5.4 is now pinned in my configuration.

There is a catch here, not all plugins are available through Luarocks and therefore will not be installed automagically like the plugin above. To address this rocks-git.nvim extends rocks.nvim to allow for installing from git sources. I am using this for a handful of plugins such as nvim-cmp.

"nvim-cmp" = { git = "hrsh7th/nvim-cmp" }

Configuring Plugins

Many plugins require some custom configuration and cannot simply be installed. For these plugins you can use rocks-config. This extension handles calling setup automatically for plugins like the above indent-blankline.nvim as well as providing a place for your plugin configuration files to live. I am using the following settings:

[config]
plugins_dir = "plugins/"
auto_setup = true

The auto_setup option enables the simple no configuration setup shown above by calling the setup function on plugins that do not have a configuration file. For plugins that have a file under the specified plugins_dir you will take care of setup. These files are simply lua files though and do not have a standardized format like lazy.nvim modules do. Here is an abbreviated comparison of my oil.nvim configuration using lazy.nvim and then using rocks.nvim.

; lazy configuration
{
  1 :stevearc/oil.nvim
  :dependencies [:nvim-tree/nvim-web-devicons]
  :config (fn []
    (let [oil (require :oil)]
      (oil.setup {
        :float {
          :padding 17
        }
      })
    )
  )
  :keys [
    {
      :mode "n"
      1 "<C-n>"
      2 (fn []
          (let [oil (require :oil)]
            (oil.toggle_float)
          )
        )
      :desc "Oil - parent directory"
    }
  ]
}
; rocks configuration
(let [oil (require :oil)]
  (oil.setup {
    :float {
      :padding 17
    }
  })

  (vim.keymap.set
    :n
    "<C-n>"
    (fn []
      (let [oil (require :oil)]
        (oil.toggle_float)))
    { :desc "Oil - parent directory" })

The code here is very similar, but there are some important differences. First off, the lazy.nvim configuration makes me specify a plugin’s dependencies as we see here for nvim-web-devicons. With rocks the user is no longer responsible for dependency management, when I run :Rocks install oil.nvim the dependencies are installed for me as specified by the plugin’s maintainers. For some this may not seem like a big deal, but this is very important because it removes a communication burden from maintainers. Plugin authors can include dependencies without worrying about making setup too complicated for their users.

One part of lazy.nvim I missed while migrating is the keys table. While calling vim.keymap.set directly is not much more verbose I did appreciate the table syntax. This can be addressed easily, but is a nice touch in lazy.nvim.

Since rocks-config uses the installed plugin’s name to look for a file under /plugins, configuration files must be named after the plugin. This is not required by Lazy since the plugin source is specified within the file.

Conclusion

I am very happy with rocks.nvim. It is still in early development, but you can tell a lot of thought has been put into the plugin manager and I am excited to see it continue to grow. In it’s current early state it is already a very capable lazy.nvim replacement. I highly recommend giving it a shot, you will not regret it!