How to use private NeoVim plugins on NixOS by Marcos Benevides

Over time my config changed a lot since the early days, as of now I’m using a combination of Flakes and home-manager to manage my workstations. I try not to overthink too much when it comes to Nix, my current Neovim setup is pretty simple, lua-based, yet, fully nixified.

  dotfiles
  ├── (...)
  ├── nvim
  │   ├── files.lua
  │   ├── line.lua
  │   ├── lsp.lua
  │   ├── settings.lua
  │   ├── tabs.lua
  │   └── treesitter.lua
  ├── (...)
  └── zsh
  └── zshrc

I do it by having a simple directory where all my Neovim derivations stand.

  home
  ├── (...)
  ├── development
  │   ├── cloud.nix
  │   ├── default.nix
  │   ├── git.nix
  │   ├── iac.nix
  │   ├── kubernetes.nix
  │   └── programming.nix
  ├── editors.nix
  ├── (...)
  ├── neovim
  │   ├── default.nix
  │   ├── packages.nix
  │   └── private.nix
  ├── (...)
  └── zshell.nix

here’s an example of what a private.nix file would look like, this is useful when you want to use some package that’s not available yet into nixpkgs.

  { pkgs, config }:

  let
    plugin = pkgs.vimUtils.buildVimPlugin;
  in
  {
    vim-taskjuggler = plugin {
      name = "vim-taskjuggler";
      src = pkgs.fetchFromGitHub {
        owner = "kalafut";
        repo = "vim-taskjuggler";
        rev = "e94c9a0b06022d11a34310ad5f82c1c2bcd86fb7";
        sha256 = "0f8smjl6wi52p8n1hhl5zhk8i3lpsfndxxdammyybw2vz17s0j8q";
      };
    };
  }

then you can just import it from other files:

  { pkgs, config, lib, ... }:

  let
    plugins = pkgs.vimPlugins;
    private = import ./private.nix { inherit pkgs config; };
  in
  {
    base = with plugins; [
      nvim-surround
      vim-which-key
      vim-visual-multi
      hologram-nvim
    ];
    eyecandy = with plugins // private; [
      kanagawa-nvim
      nvim-colorizer-lua
      nvim-cursorline
      nvim-web-devicons
      tokyonight-nvim
    ];
    ui = with plugins; [
      # File Tree
      nvim-tree-lua
      # Find/Filter
      plenary-nvim
      telescope-nvim
      # Status Line
      lualine-nvim
      # Tabs
      barbar-nvim
    ];
    lsp = with plugins // private; [
      nvim-cmp
      nvim-lspconfig
      (nvim-treesitter.withPlugins (p:
        [
          p.c
          p.bash
          p.dockerfile
          p.gitignore
          p.lua
          p.markdown
          p.nix
          p.proto
          p.scheme
          p.sql
          p.terraform
          p.yaml
        ]
      ))
      # Snippets
      luasnip
      cmp-git
      # CMP Plugins
      cmp-cmdline
      cmp_luasnip
      cmp-nvim-lsp
      cmp-path
      cmp-treesitter
    ];
    tooling = with plugins; [
      direnv-vim
      Ionide-vim
      vim-nix
      vim-terraform
    ];
  }

and since Neovim has an awesome module in home-manager, make sure to use it:

  programs.neovim = {
    enable = true;

    # (...)
    plugins = vimPlugins.base ++ vimPlugins.eyecandy ++ vimPlugins.ui ++ vimPlugins.lsp ++ vimPlugins.tooling;
  };

If you want to see an up-to-date version of these dotfiles, feel free to steal take a look here.