aboutsummaryrefslogtreecommitdiff
path: root/runtime/doc/pack.txt
Commit message (Collapse)AuthorAge
* docs(help): specify h4 "function signature" format #42434masterJustin M. Keyes2 days
| | | | | | | | | | | | | | | | | | | | | Work towards enabling ["flow" layout](https://github.com/neovim/neovim/blob/9244da12e400ec0291450a5e9400d995e7a29b83/src/gen/gen_help_html.lua#L86-L88) in all `:help` files. Problem: The final boss of vimdoc pseudo-structure: Vim's quasi-headings on function signatures and excmd docs is visually distinctive but too inconsistent for a nice parse rule. Solution: - Define the quasi-heading format as an "h4" variant, specified at `:help help-tag-heading`. - For simplicity and predictability, it is defined as any line that ends with a help tag(s) preceded by 2 or more spaces (or 1 tab). - Update existing docs. - This one-time update has a lot of changes, but is very unlikely to conflict with ported Vim-patches because (1) Vim rarely adds new *excmds* that we want, and (2) *function* docs are auto-generated. ref https://github.com/neovim/tree-sitter-vimdoc/issues/110
* docs(pack): mention `:checkhealth vim.pack` #41955Evgeni Chasnovski2026-09-18
| | | | | | Problem: No explicit recommendations about how to check for possible issues related to `vim.pack`. Soltuion: Mention `:checkhealth vim.pack` explicitlye as a recipe.
* fix(help): resolve generic and nullable type referencesLewis Russell2026-09-07
| | | | | | | | | | Problem: K on generic and nullable type annotations can jump to the wrong help tag. Generated See references repeat the type names. Solution: Strip generic arguments and nullable suffixes when resolving help tags. Remove the redundant generated See references. AI-assisted
* feat(pack): add support for sourcing manifest scriptsEvgeni Chasnovski2026-07-31
| | | | | | | | | | | | | | | | | | | Problem: No way for plugins to define hooks that would be executed during plugin lifecycle. Like after install/update or before update/delete. Solution: Automatically source scripts defined in plugin manifest file (if any) after triggering corresponding `PackChanged{,Pre}` events. During sourcing make some termporary adjustments: - Current directory is set to plugin's root to simplify execution of CLI calls like `make build`. - Plugin's path is ensured to be inside 'runtimepath' to allow using `require('plugin-module')` inside manifest scripts. The reason to execute after triggering event is so that there is a possibility for users to execute code both before the script (exactly on event) and after the script (more-or-less via `vim.schedule` called on the event).
* feat(pack): introduce plugin manifest supportEvgeni Chasnovski2026-07-31
| | | | | | | | | Problem: There is no agreed way for plugins to provide extra information about themselves. Like required Neovim version, install/update/delete hooks, and dependencies. Solution: Introduce basic concept of plugin manifest file `pkg.json` based on https://packspec.org/.
* feat(pack): 'packlockfile' option #40562Evgeni Chasnovski2026-07-08
| | | | | Problem: No way to configure the lockfile location. Solution: Add 'packlockfile' option.
* feat(pack): ensure order of `PackChanged{Pre,}` events #40455Evgeni Chasnovski2026-06-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: due to totally async install/update/checkout there is no guaranteed order of `PackChanged{Pre,}` events across different plugins. This might lead to conflicts when callback for some "main" plugin relies on features from "dependency" plugin: i.e. callback for "main" plugin can trigger before installing/updating "dependency" plugin. The installation order can be enforced by separate vim.pack.add() calls, but update/checkout can not. Solution: Trigger events in bulk independently of async execution: - `PackChangedPre` before any action for all input plugins in order they are supplied. It will also trigger even if an action will fail. - `PackChanged` after all actions finished for all sucessfully affected plugins in order they are supplied. This also comes with a couple of side effect changes: - `PackChangedPre kind=delete` is now also triggered even if the delete won't be done. This makes it more aligned with `kind=install` and `kind=update`. - Force update (`:packupdate!`) and "udpate LSP action" now do two async steps: download/compute updates and apply them. This also results in two progress reports. This is mostly a by-product of the implementation (there has to be a pre-computation of target revision for all plugins before doing `PackChangedPre` in bulk before possibly applying an update), but I kind of like it more this way as it is more explicit of what's going on. If absolutely not acceptable, there might be some hacks to mitigate it at least in code action, but I'd keep it like this.
* refactor(docs): generate tui.txt $NVIM_TERMDEFS keys #39836Kyle2026-05-21
| | | | | | | | | Problem: Potential documentation drift in `tui.txt` if fields for `$NVIM_TERMDEFS` change. Solution: Generate docs for `tui.txt`. Add `brief_xform` to `gen_vimdoc.lua` to allow transforming briefs during generation.
* feat(pack): update `get()` to be able to fetch data from plugin sourceEvgeni Chasnovski2026-05-17
| | | | | | | | | | Problem: There is currently no convenient way to programmatically check for new updates from plugin source. Running `vim.pack.update()` is one approach, but it opens a confirmation buffer that requires a manual action to close. Solution: Add `opts.offline` to `vim.pack.get()` that will first fetch new updates from plugin source before computing the output.
* feat(pack): update `get()` to return revision of a pending updateEvgeni Chasnovski2026-05-17
| | | | | | | | | | | | Problem: No convenient way to programmatically get the revision that would be checked out after `vim.pack.update()` (with `offline=true`). Doing this manually requires resolving `spec.version` which is not trivial. This data can be useful for custom reporting of pending updates or third party confirmation step. Solution: Make `get()` include a new field for the revision that points at the state after applying pending update. This is also the same as the revision of resolved `spec.version`.
* feat(pack): update `get()` to take `rev` from actual repo if `info=true`Evgeni Chasnovski2026-05-17
| | | | | | | | | | | | Problem: `vim.pack.get()` always uses lockfile as the source for the `rev` field. This is fast, but may be misleading in case of a corrupted lockfile. Solution: Compute revision from Git repo on disk if `info=true` (default), use lockfile otherwise. This does increase execution time (as a result of one extra `git ...` call for every plugin), but `info=true` is already designed to be informative and not necessarily fast.
* feat(pack): :packupdate, :packdel commands #39693Olivia Kinnear2026-05-16
| | | | | | Define `:packupdate` and `:packdel` as separate commands instead of a unified `:pack {subcommand}` because the semantics between the two commands vary differently enough that it doesn't make sense to combine them. Additionally, `:pack! update/del` looks bad.
* fix(pack): suggest "delete" code action for active plugins #39678Evgeni Chasnovski2026-05-08
| | | | | | | | | | Problem: Trying to execute code action on an active plugin without updates leads to nothing. It is more useful if code actions "do something" on a bigger portion of the confirm buffer. Solution: Suggest "delete" code action even for active plugins. Trying to execute it will first show a confirmation buffer with relevant warning of why this might be not a good idea. Confirming will delete a plugin.
* docs: sort quasi-keysetsJustin M. Keyes2026-04-26
|
* fix(util): add and use forge link computationEvgeni Chasnovski2026-04-25
| | | | | | | | Problem: There are many Git forges each with a different way of constructing permanent links to like commits and tags. Solution: Add a private utility function that computes these special links on the best effort basis.
* feat(pack): support `textDocument/documentLink` in confirmation bufferEvgeni Chasnovski2026-04-25
| | | | | | | | | | | | | | Problem: In `vim.pack.update()` confirmation buffer it might be useful to be able to use `gx` (open link at cursor) when cursor is on something like commit or tag. Solution: Add `textDocument/documentLink` method support for the in-process LSP. This may be used by LSP clients and makes `gx` automatically work. The shortcoming is that this requires tracking how to construct a URL from source and commit/tag. Currently only GitHub hosted repositories are supported.
* fix(pack): only use tags that strictly comply with semver spec #39342Evgeni Chasnovski2026-04-23
| | | | | | | | | | | | | | | | | | Problem: Using `version=vim.version.range(...)` in plugin specification is meant to use semver-like tags. Whether a tag is semver-like was decided by a plain `vim.version.parse` which is not strict by default. This allowed treating tags like `nvim-0.6` (which is usually reserved for the latest revision compatible with Nvim<=0.6 version) like semver tags and resulted in confusing behavior (preferring `nvim-0.6` tag over `v0.2.2`, for example). Solution: Use `vim.version.range(x, { strict = true })` to decide if the tag name is semver-like or not. This allows tags like both `v1.2.3` and `1.2.3` while being consistent in what Nvim thinks is a semver string. This is technically not a breaking change since it was documented that only tags like `v<major>.<minor>.<patch>` will be recognized as semver.
* docs: misc #39045Justin M. Keyes2026-04-18
|
* docs(events): Lua types for autocmd event-data #38518Aditya Malik2026-04-18
| | | | | | | | | | Problem: No LuaLS types for event-data fields (ev.data). Types are only documented ad hoc in scattered locations. Solution: Add runtime/lua/vim/_meta/events.lua defining vim.event.<name>.data classes for events that provide ev.data. Reference the types from each event's help in autocmd.txt, lsp.txt, and pack.txt.
* docs(pack): improve "Synchronize across machines" steps #39122Evgeni Chasnovski2026-04-16
| | | | | | | | | | Problem: Sometimes automatic lockfile synchronization after `:restart` might fail, like due to bad/absent Internet connection. This would remove failed to install entries from the lockfile (since they are not on disk and lockfile is meant to lock the latest plugin version on disk). Solution: Document that this should be treated as an unwanted update and use steps similar to "Revert plugin after an update" use case.
* docs: api, messages, lsp, trustJustin M. Keyes2026-03-11
| | | | | gen_vimdoc.lua: In prepare for the upcoming release, comment-out the "Experimental" warning for prerelease features.
* docs(pack): simpify `update()` docs, fix directory path #38194Evgeni Chasnovski2026-03-09
| | | | | | | | | | | | | | Problem: Documentation of `vim.pack.update()` contains a lot of text inside nested list. This might be a bit confusing to parse for humans and definitely confusing to parse for neovim.io. The description of `vim.pack` directory is not correct for Windows. Solution: Move description of confirmation buffer in a separate "subsection". Use '"data" standard path' instead of '$XDG_DATA_HOME/nvim' when documenting directory. Also use `|standard-path|` tag to link to standard path section instead of `|stdpath()|`.
* docs(pack): clarify caveats about installing based on the lockfileEvgeni Chasnovski2026-01-29
|
* docspack): mention re-install after source's default branch change #37560Evgeni Chasnovski2026-01-26
| | | | | | | | | | | | | Problem: `vim.pack.update()` doesn't update source's default branch if it has changed on the remote. It can be done by executing `git remote set-head origin --auto` for every plugin on every update, but it feels like too much extra work (which requires Internet connection) for a very rare use case. This matters since `version = nil` will keep pointing to previous default branch even after `vim.pack.update()`. Solution: Document that in order for `version = nil` to point to the source's new default branch, perform clean re-install.
* docs: drop vim.pack WIP note, add example code #37229Evgeni Chasnovski2026-01-07
|
* Merge #37113 from echasnovski/pack-better-revertJustin M. Keyes2025-12-30
|\
| * feat(pack): allow running `update()` without Internet connectionEvgeni Chasnovski2025-12-26
| | | | | | | | | | | | | | | | | | | | Problem: There is now way to run `update()` without Internet connection while there are some workflows that do not require it. Like "switch plugin version" and "revert latest update". Solution: Add `opts.offline` to `update()`. This also allows now to treat `vim.pack.update(nil, { offline = true })` as a way to interactively explore currently installed plugins.
| * feat(pack): allow choosing update target in `update()`Evgeni Chasnovski2025-12-26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: There are two fairly common workflows that involve lockfile and can be made more straightforward in `vim.pack`: 1. Revert latest update. Like if it introduced unwanted behavior. 2. Update to a revision in the lockfile. Like if already updated on another machine, verified that everything works, `git add` + `git commit` + `git push` the config, and want to have the same plugin states on current machine. Solution: Make `update` allow `opts.target`. By default it uses `version` from a plugin specification (like a regular "get new changes from source" workflow). But it also allows `"lockfile"` value to indicate that target revision after update should be taken from the current lockfile verbatim. With this, the workflows are: 1. Revert (somehow) to the lockfile before the update, restart, and `vim.pack.update({ 'plugin' }, { target = 'lockfile' })`. If Git tracked, revert with `git checkout HEAD -- nvim-pack-lock.json`. For non-VCS tracked lockfile, the revisions can be taken from the log file. It would be nicer if `update()` would backup a lockfile before doing an update, but that might require discussions. 2. `git pull` + `:restart` + `vim.pack.update(nil, { target = 'lockfile' })`. The only caveats are for new and deleted plugins: - New plugins (not present locally but present in the lockfile) will be installed at lockfile revision during restart. - Deleted plugins (present locally but not present in the lockfile) will still be present: both locally *and* in the lockfile. They can be located by `git diff -- nvim-pack-lock.json` and require manual `vim.pack.del({ 'old-plugin1', 'old-plugin2' })`.
* | feat(pack)!: suggest "delete" code action only for not active pluginsEvgeni Chasnovski2025-12-28
| | | | | | | | | | | | | | | | Problem: Deleting active plugins can lead to a situation when it is reinstalled after restart. Solution: Suggest "delete" code action only for not active plugins. Whether a plugin is not active is visible by a hint in its header.
* | feat(pack)!: make `del()` only remove non-active plugins by defaultEvgeni Chasnovski2025-12-28
|/ | | | | | | | | | | | Problem: Using `vim.pack.del()` to delete active plugin can lead to a situation when this plugin is reinstalled after restart. Removing plugin from 'init.lua' is documented, but can be missed. Solution: Make `del()` only remove non-active plugins by default and throw an informative error if there is an active plugin. Add a way to force delete any plugin by adding `opts.force`. This also makes `del()` signature be the same as other functions, which is nice.
* docs(pack): use more tags and add "Use shorter source" exampleEvgeni Chasnovski2025-12-25
|
* feat(pack)!: change `src` of installed plugin inside `update()` in placeEvgeni Chasnovski2025-12-25
| | | | | | | | | | | | | | | | | | | Problem: Changing `src` of already installed plugin currently takes effect immediately inside `vim.pack.add()` and acts as "delete and later fresh install". Although more robust, this might lead to unintentional data loss (since plugin is deleted) if the plugin was manually modified or the new source is not valid. Also this introduces unnecessary differentiation between "change `version`" and "change `src`" of already installed plugin. Solution: Require an explicit `vim.pack.update()` to change plugin's source. It is done by conditionally changing `origin` remote of the Git repo. The effect does not require update confirmation in order to have new changes fetched from the new `src` right away. If in the future there are more types of plugins supported (i.e. not only Git repos), also do extra work (like delete + install) during `vim.pack.update()`.
* feat(pack)!: synchronize lockfile with installed plugins when reading itEvgeni Chasnovski2025-11-17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Lockfile can become out of sync with what is actually installed on disk when user performs (somewhat reasonable) manual actions like: - Delete lockfile and expect it to regenerate. - Delete plugin directory without `vim.pack.del()`. - Manually edit lock data in a bad way. Solution: Synchronize lockfile data with installed plugins on every lockfile read. In particular: 1. Install immediately all missing plugins with valid lock data. This helps with "manually delete plugin directory" case by prompting user to figure out how to properly delete a plugin. 2. Repair lock data for properly installed plugins. This helps with "manually deleted lockfile", "manually edited lockfile in an unexpected way", "installation terminated due to timeout" cases. 3. Remove unrepairable corrupted lock data and their plugins. This includes bad lock data for missing plugins and any lock data for corrupted plugins (right now this only means that plugin path is not a directory, but can be built upon). Step 1 also improves usability in case there are lazy loaded plugins that are rarely loaded (like on `FileType` event, for example): - Previously starting with config+lockfile on a new machine only installs rare `vim.pack.add()` plugin after it is called (while an entry in lockfile would still be present). This could be problematic if there is no Internet connection, for example. - Now all plugins from the lockfile are installed before actually executing the first `vim.pack.add()` call in 'init.lua'. And later they are only loaded on a rare `vim.pack.add()` call. --- Synchronizing lockfile on its every read makes it work more robustly if other `vim.pack` functions are called without any `vim.pack.add()`. --- Performance for a regular startup (good lockfile, everything is installed) is not affected and usually even increased. The bottleneck in this area is figuring out which plugins need to be installed. Previously the check was done by `vim.uv.fs_stat()` for every plugin in `vim.pack.add()`. Now it is replaced with a single `vim.fs.dir()` traversal during lockfile sync while later using lockfile data to figure out if plugin needs to be installed. The single `vim.fs.dir` approach scales better than `vim.uv.fs_stat`, but might be less performant if there are many plugins that will be not loaded via `vim.pack.add()` during startup. Rough estimate of how long the same steps (read lockfile and normalize plugin array) take with a single `vim.pack.add()` filled with 43 plugins benchmarking: - Before commit: ~700 ms - After commit: ~550 ms
* fix(pack)!: ensure plugin is fully absent if not fully installedEvgeni Chasnovski2025-11-17
| | | | | | | | | | | | | | | | | | | | | Problem: Currently it is possible to have plugin in a "partial install" state when `git clone` was successfull but `git checkout` was not. This was done to not checkout default branch by default in these situations (for security reasons). The problem is that it adds complexity when both dealing with lockfile (plugin's `rev` might be `nil`) and in how `src` and `version` are treated (wrong `src` - no plugin on disk; wrong `version` - "partial" plugin on disk). Solution: Treat plugin as "installed" if both `git clone` and `git checkout` are successful, while ensuring that not installed plugins are not on disk and in lockfile. This also means that if in 'init.lua' there is a `vim.pack.add()` with bad `version`, for first install there will be an informative error about it BUT next session will also try to install it. The solution is the same - adjust `version` beforehand.
* docs(pack): add example workflow of how to revert after a bad updateEvgeni Chasnovski2025-11-16
| | | | | | | | | | Problem: No example workflow of how to revert after a bad update. Solution: Add example workflow of how to revert after a bad update. In future this might be improved by utilizing other `vim.pack` features or via a dedicated function (like `vim.pack.restore()` that restores all installed plugins to a state from the lockfile).
* feat(pack): update `add()` to handle source change for installed pluginEvgeni Chasnovski2025-11-16
| | | | | | | | | | | | | | | Problem: Changing `src` of an existing plugin cleanly requires manual `vim.pack.del()` prior to executing `vim.pack.add()` with a new `src`. Solution: Autodetect `src` change for an existing plugin (by comparing against lockfile data). If different - properly delete immediately and treat this as new plugin installation. Alternative solution might be to update `origin` remote in the installed plugin after calling `vim.pack.update()`. Although, doable, this 1) requires more code; and 2) works only for Git plugins (which might be not the only type of plugins in the future). Automatic "delete and clean install" feels more robust.
* fix(pack)!: make default `opts.load` in `add()` to work inside 'plugin/'Evgeni Chasnovski2025-11-16
| | | | | | | | | | | | | | | Problem: Plain `vim.pack.add()` calls (with default `opts.load`) does not fully work if called inside 'plugin/' runtime directory. In particular, 'plugin/' files of newly added plugins are not sourced. This is because `opts.load` is `false` during the whole startup, which means `:packadd!` is used (modify 'runtimepath' but not force source newly added 'plugin/' files). This use case is common due to users organizing their config as separate files in '~/.config/nvim/plugin/'. Solution: Use newly added `v:vim_did_init` to decide default `opts.load` value instead of `v:vim_did_enter`.
* fix(pack): relax minimal Git version to be 2.0 #36573Evgeni Chasnovski2025-11-16
| | | | | | | | | | | Problem: Current requirement is Git>=2.36 as `--also-filter-submodules` flag for `git clone` was introduced there. This is problematic since default Git version on Ubuntu 22.04 is 2.34. Solution: Relax minimal Git version to be (at least) 2.0 by selectively applying necessary flags based on the current Git version. As 2.0.0 was released in 2014-05-28 (almost the same age as Neovim project itself), it is reasonable to drop any mention and checks on minimal version altogether.
* fix(pack): consistently use "revision" instead of "state"Evgeni Chasnovski2025-11-06
| | | | | | | | Problem: In some areas plugin's revision is named "state". This might be confusing for the users. Solution: Consistently use "revision" to indicate "plugin's state on disk".
* docs(pack): add plugin hooks exampleEvgeni Chasnovski2025-10-23
| | | | | | Problem: No examples of how to use `PackChanged[Pre]` for plugin hooks. Solution: Add examples of creating plugin hooks.
* feat(pack): add `active` field to `PackChanged` event dataEvgeni Chasnovski2025-10-23
| | | | | | | | | | Problem: Inside `PackChanged[Pre]` callbacks it might be useful to tell if the affected plugin is active or not. It is already possible via extra `vim.pack.get({ 'plug-name' })[1].active`, but it is not quite user-friendly for something that might be needed frequently in real world use cases. Solution: Supply extra `active` event data field.
* vim-patch:partial:c58f91c: runtime(doc): Whitespace updates (#36160)zeertzjq2025-10-13
| | | | | | | | | | | | | | Use double sentence spacing and wrap lines at 'textwidth'. Code examples and tables were not wrapped unless this had already been done locally. closes: vim/vim#18453 https://github.com/vim/vim/commit/c58f91c035db09358c282f2a908e2aea4287785e Fix incorrect docs in :h ModeChanged. Cherry-pick :h bufnr() changes from patch 8.1.2080. Co-authored-by: Doug Kearns <dougkearns@gmail.com>
* feat(pack): add code actions in confirmation bufferEvgeni Chasnovski2025-10-05
| | | | | | | | | | | | | Problem: No way to granularly operate on plugins when inside confirmation buffer. Solution: Implement code actions for in-process LSP that act on "plugin at cursor": - Update (if has updates). - Skip updating (if has updates). - Delete. Activate via default `gra` or `vim.lsp.buf.code_action()`.
* feat(pack): add `[[` and `]]` mappings in confirmation bufferEvgeni Chasnovski2025-10-05
| | | | | | Problem: No easy/robust way to jump between plugin sections. Solution: Add `[[` and `]]` mappings.
* feat(pack): prefer using revision from lockfile during installEvgeni Chasnovski2025-10-04
| | | | | | | | | | Problem: Installing plugin always pulls latest `version` changes (usually from the default branch or "latest version tag"). It is more robust to prefer initial installation to use the latest recorded (i.e. "working") revision. Solution: Prefer using revision from the lockfile (if present) during install. The extra `update()` will pull the latest changes.
* feat(pack)!: make `update()` include not active plugins by defaultEvgeni Chasnovski2025-10-04
| | | | | | | | |