Overview
This chapter will explore the different architectural designs implemented within nixCats-nvim
and will provide a concise understanding of the concepts involved. Later, we will explore a few ways to get started with nixCats-nvim
.
Investigation
There are many ways you could approach the way to handle neovim using nix. Lets go through them briefly, which will give you a clear idea of the reason why nixcats is superior to its alternatives. In order to have neovim in our NixOS system. We can add the nixpkgs
option or the package itself. It would look something like this (use only one of these, setting both would most probably give you an infinite recursion):
programs.neovim.enable = true;
# OR
environment.systemPackages = with pkgs; [
neovim
];
The nixpkgs derivations do already a great job in wrapping neovim itself and build from source. The next step obviously would be to add a few plugins to get our workflow going smoothly as we want to.
Home Manager
When using home-manager
, you are able to link files into place.
home.".config/nvim/".source = ./mynvimconfig;
Whats the problem with this! Its great! I can download stuff with a neovim package manager and mason... right?
Well, you can try. But if you want treesitter grammers, you're also going to want this.
home.packages = with pkgs; [
stdenv.cc.cc
];
And mason just isn't going to work on nixos, so youre going to want to swap that for just lspconfig and add those too.
home.packages = with pkgs; [
stdenv.cc.cc
nixd
lua-language-server
rust-analyzer
];
Uh oh!!!
How do we pass in info from nix into our configuration? I'm using agenix!
Well, now we have to probably write some stuff in nix. Lets change our approach and use the home manager module.
programs.neovim = {
enable = true;
plugins = with pkgs.vimPlugins [
lze;
{
plugin = telescope-nvim;
config = ''
require("lze").load {
"telescope.nvim",
cmd = "Telescope",
}
'';
type = "lua";
optional = true;
}
{
plugin = sweetie-nvim;
config = ''
require("lze").load {
"sweetie.nvim",
colorscheme = "sweetie",
}
'';
type = "lua";
optional = true;
}
];
};
Oh no... This is all wrong... Where is our auto complete! Where did our directory go?
You think I'm going to write all my lua in nix strings just so that I can "${interpolate}"
if I need to?
Also, this is tied to home manager! What if you don't want home manager on a machine?
What if you want to run it on another person's machine without putting your whole home-manager configuration on their computer?
A naieve standalone approach
Lets try pkgs.wrapNeovim
in a flake
.
{
inputs = {
nixpkgs = {
url = "github:nixos/nixpkgs/nixpkgs-unstable";
};
};
outputs = { nixpkgs, neovim-nightly, ...}@inputs: let
forAllSys = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all;
in {
packages = forAllSys (system: let
pkgs = import nixpkgs { inherit system; };
myNeovim = let
luaRC = final.writeText "init.lua" ''
local configdir = "${./mynvimconfig}";
vim.opt.packpath:prepend(configdir)
vim.opt.runtimepath:prepend(configdir)
vim.opt.runtimepath:append(configdir .. "/after")
if vim.fn.filereadable(configdir .. "/init.lua") == 1 then
dofile(configdir .. "/init.lua")
end
'';
in
pkgs.wrapNeovim pkgs.neovim-unwrapped {
configure = {
customRC = ''lua dofile("${luaRC}")'';
packages.all.start = with pkgs.vimPlugins; [
nvim-treesitter.withAllGrammars
lze
telescope-nvim
];
packages.all.opt = with pkgs.vimPlugins; [
];
};
extraMakeWrapperArgs = builtins.concatStringsSep " " [
''--prefix PATH : "${pkgs.lib.makeBinPath (with pkgs; [
stdenv.cc.cc
nixd
lua-language-server
rust-analyzer
])}"''
];
extraLuaPackages = (_: []);
extraPythonPackages = (_: []);
withPython3 = true;
extraPython3Packages = (_: []);
withNodeJs = false;
withRuby = true;
vimAlias = false;
viAlias = false;
extraName = "";
};
in
{
default = myNeovim;
});
};
}
Well, this is kinda cool. We can run this from the command line, it pulls in our directory... It's pretty close to what we want.
But still... It could be better.
How do we pass info from nix into our directory?
The answer? Usually people just add a bunch of global variables.
Obviously that's not super ideal.
Also, every time we want to change it, we have to reload!
What do we want?
The ideal neovim configuration would necessarily need a few feature to be maintainable:
- A way to write
lua
separately in alua
file andnix
in its own file. - A way to seamlessly pass extra arbitrary info from
nix
to our configuration, without creating a long list ofvim.g.global_variables
. - Run our configuration outside of our system that have access to
nix
(CLI). - Have utilities for easily installing plugins that aren't on
nixpkgs
. - Have multiple configuration profiles within a same configuration base.
- Have a mode that allows editing
lua
and seeing the results without rebuilding via nix, assuming the required things are already installed. - Our configuration should be exported* as
nixosModule
,homeManagerModule
,overlay
andpackage
.
This would enable users to integrate with any necessary system with ease.
Now lets enter the nixCats
world. The next pages will talk about the options and specific architectural pattern within nixCats
.
*
: The exports could differ from template to template. Thus, make sure you choose a template that fits your need.