Migrate to vim.pack

This commit is contained in:
2026-08-02 12:00:14 -04:00
parent 1f62ddd4ac
commit 22a1fcb0b5
16 changed files with 795 additions and 663 deletions
+74
View File
@@ -0,0 +1,74 @@
# Neovim Config
Plugin management uses Neovim's native `vim.pack` (0.12+). No lazy.nvim.
## Layout
- `init.lua` — entry point: `require("config")` then `require("plugins")`
- `lua/config/*.lua` — core settings (options, keymaps, LSP, autocmds)
- `lua/plugins/init.lua` — loads every plugin module in order, hosts `PackChanged` build hooks
- `lua/plugins/<name>.lua` — one self-contained module per plugin
- `nvim-pack-lock.json` — lock file, auto-updated by `vim.pack`, commit it
## Plugin module structure
Each `lua/plugins/<name>.lua` is self-contained: it declares its own `vim.pack.add` specs (including shared deps like `nvim-lua/plenary.nvim`, `nvim-tree/nvim-web-devicons`, `MunifTanjim/nui.nvim` — repeated adds are idempotent), then runs setup/config code directly. All plugins load eagerly at startup; there is no lazy loading.
Example:
```lua
vim.pack.add({
{ src = "https://github.com/owner/repo.nvim" },
})
require("repo").setup({ ... })
```
## Adding a new plugin
1. Create `lua/plugins/<name>.lua` with a `vim.pack.add` spec and its config
2. Add `require("plugins.<name>")` to `lua/plugins/init.lua` (theme first if it affects colorscheme/highlights)
3. Restart nvim — the plugin is cloned automatically on first startup
## Spec conventions
- `version` — pin to a semver release: `version = vim.version.range("^1")`; use a branch name string (e.g. `version = "main"`) only when the plugin requires it (nvim-treesitter and its textobjects do)
- `name` — set only when the repo name is undesirable (e.g. `catppuccin/nvim` is installed as `catppuccin`)
- Shared deps listed explicitly in every module that needs them
## Build steps
There is no `build` field. Post-install/update steps run from the `PackChanged` autocmd in `lua/plugins/init.lua`, keyed by plugin name. It must stay registered before the first `vim.pack.add` call, so keep new hooks in that file:
```lua
-- in the PackChanged callback in lua/plugins/init.lua
if name == "my-plugin" and (kind == "install" or kind == "update") then
vim.system({ "make" }, { cwd = path })
end
```
Current hooks: `make` for telescope-fzf-native, parser `update` for nvim-treesitter.
## Useful commands
`vim.pack` has no `:Pack*` user commands — everything goes through `:lua`. Plugin names are the installed directory names (e.g. `telescope-fzf-native.nvim`).
- `:lua vim.pack.update()` — fetch and update all plugins to their pinned version (or latest branch), updating `nvim-pack-lock.json`
- `:lua vim.pack.update({ "gitsigns.nvim" })` — update a single plugin
- `:lua vim.pack.update(nil, { offline = true })` — update using cached refs, no network fetch
- `:lua vim.pack.update(nil, { target = "lockfile" })` — restore all plugins to the revisions in `nvim-pack-lock.json` (rollback)
- `:lua vim.pack.get()` — list all installed plugins with spec, path, revision, active status
- `:lua vim.pack.add({ { src = "https://github.com/owner/repo.nvim" } })` — install/register a plugin on the fly (restart required to persist in config)
- `:lua vim.pack.del("name")` — delete a plugin directory and its lock entry
## Updating / removing
- Update everything: `:lua vim.pack.update()` (see commands above for variants)
- Remove a plugin: delete its entry from `vim.pack.add` calls and its `lua/plugins/<name>.lua` + require in `lua/plugins/init.lua`, then run `:lua vim.pack.del("name")` to delete the directory and lock entry
## Pitfalls
- First startup installs missing plugins and asks for confirmation — expected behavior, not an error
- The first `vim.pack.add` call in a session triggers installs, so `PackChanged` hooks must be registered in `lua/plugins/init.lua` before the requires
- Only install actual Neovim plugins via `vim.pack` — CLI tools (e.g. `fd`, `ripgrep`) must not be added
- Plugins already on disk are not re-checked against their spec on startup; run `vim.pack.update()` to sync revisions