- nvim with
vim.packsupport (0.12+) - [Optional]
nix-prefetch-url(and possibly more, checkout the included prefetchers here)
{
"reo101/nix-update.nvim",
-- setup() is optional; call it only when overriding defaults
opts = {
update_actions = { "apply", "flash", "notify" },
},
config = function(_, opts)
require("nix-update").setup(opts)
end,
}setup() is optional and only configures options.
Commands and <Plug> mappings are auto-registered on startup.
Recommended global config (source of truth):
vim.g.nix_update = {
update_actions = { "apply", "notify" },
extra_prefetchers = {
-- ...
},
}Lua init file (only needed when customizing options):
require("nix-update").setup(opts)setup(opts) merges your overrides into vim.g.nix_update and reapplies config.
This setup function accepts the following table:
| Action | Description |
|---|---|
apply |
Apply the update to the buffer (modifies the text) |
flash |
Briefly highlight the changed region using vim.hl.range |
notify |
Show a vim.notify message with update details |
preview |
Show the update as virtual text overlay (without applying) |
require("nix-update").setup({
-- Actions to run on each update (in order)
-- Default: { "apply", "notify" }
update_actions = { "apply", "flash", "notify" },
-- Extra prefetcher commands
-- table of tables, where each one looks like this:
extra_prefetchers = {
["myFetch"] = {
-- (array of strings) Array of required system commands
["required-cmds"] = { "cmd1", "cmd2" },
-- (array of strings) Array of required "fetch" keys
["required-keys"] = { "repo", "user" },
-- (function) Function to run to generate a command
["prefetcher"] = function(opts)
-- guaranteed to be non-nil
local repo = opts.repo
local user = opts.user
-- extra (nonrequired/optional) keys, could be nil
local submodules = opts.submodules
-- has to return a table of `cmd` and `opts`
return {
cmd = "cmd1",
args = {
"wrapped_run",
"--",
"cmd2",
repo .. "/" .. user,
},
}
end,
-- (function) Function to run to extract the new data
["extractor"] = function(stdout)
-- array of lines from funning the corresponding command
local first_line = stdout[1]
-- has to return a table with new value for the keys
return {
version = "v." .. first_line
}
end,
},
},
})NOTES:
- The table is empty by default
required-cmdsandrequired-keysare optional- You can override the builtin definitions by using the same name
extra_prefetcher_cmdsis still accepted as a backwards-compatible alias- Invalid options are validated and reported with
vim.notify(..., ERROR)
Run updates with the scoped command:
:NixUpdate prefetch " update fetch under cursor
:NixUpdate buffer " update all fetches in current buffer
:NixUpdate health " open checkhealth output
:NixUpdate help " open :h nix-updateLegacy alias (kept for compatibility):
:NixPrefetch " same as :NixUpdate bufferBind the provided <Plug> mappings:
vim.keymap.set("n", "<leader>nc", "<Plug>(NixUpdatePrefetch)")
vim.keymap.set("n", "<leader>nC", "<Plug>(NixUpdatePrefetchBuffer)")Run it in a Nix file with the cursor inside a fetch:
let
pname = "vim-fmi-cli";
version = "0.2.0";
in {
src = fetchFromGitHub {
owner = "AndrewRadev";
repo = pname;
rev = "v${version}";
sha256 = "sha256-SOMEOUTDATEDHASH";
};
}And nix-update will statically evaluate all string arguments to the fetch (string literals and interpolations), precalculate the correct hash and substitute it in the right place.
let
pname = "vim-fmi-cli";
version = "0.2.0";
in {
src = fetchFromGitHub {
owner = "AndrewRadev";
repo = pname;
rev = "v${version}";
sha256 = "sha256-RAlvDiNvDVRNtex0aD8WESc4R/mAr7FjWtgzHWa4ZSI=";
};
}This updating mechanism allows for some pretty wild stuff, like this:
let
pname = "vim-fmi-cli";
version = "0.2.0";
type = "256";
in rec {
hash = "SOMEOUTDATEDHASH";
src = fetchFromGitHub {
owner = "AndrewRadev";
repo = pname;
rev = "v${version}";
inherit sha256;
};
sha256 = "sha${type}-${hash}";
}Running prefetch_fetch on this will figure out how to construct the current value of sha256 AND skip the common prefix when updating it, i.e. the sha256- part (consisting of the string sha, the value of type, a - and finally the value of hash, which are all scattered around lets and recs) and only update the hash variable to the correct suffix of the new sha256:
let
pname = "vim-fmi-cli";
version = "0.2.0";
type = "256";
in rec {
hash = "RAlvDiNvDVRNtex0aD8WESc4R/mAr7FjWtgzHWa4ZSI=";
src = fetchFromGitHub {
owner = "AndrewRadev";
repo = pname;
rev = "v${version}";
inherit sha256;
};
sha256 = "sha${type}-${hash}";
}I'm not really sure how often would this be of help but it's cool to have it nonetheless. 😄
The lua folder is the compilation output of all files from the fnl directory.
The project uses nfnl for Fennel compilation. When you have nfnl installed in Neovim, saving any .fnl file will automatically compile it to lua/.
The repository ships a pinned flake.nix (using flake-parts) so local checks and CI run against the same Neovim build from pinned nixpkgs.
Enter the shell:
nix develop .#defaultRun checks in the CI-equivalent shell:
nix develop .#ci -c make checkThe check runner intentionally requires vim.pack.add and bootstraps nfnl + plenary.nvim through vim.pack only.
To compile all files at once:
:NfnlCompileAllFilesOr via the Makefile (requires nvim with nfnl in $PATH):
makeAlternatively, you can compile using the standalone Fennel compiler:
make fennelNote
Requires fennel (version 1.2.0) in your $PATH
Clear the compilation output (the lua folder):
make cleanRun project checks (compilation + runtime smoke checks):
make checkFor reproducible checks with pinned tooling:
nix develop .#ci -c make checkThis check script bootstraps nfnl and plenary.nvim via vim.pack.add.
Use :checkhealth nix-update to inspect runtime/config/dependency health.
- More commands
- More prefetchers
- Simpler prefetch commands (not just system ones, maybe lua functions)
- Style guidelines (with optional enforcement)
- Telescope pickers for selective updating
- Original inspiration: https://github.com/jwiegley/nix-update-el
- The Fennel language: https://fennel-lang.org