aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/pack.lua
Commit message (Collapse)AuthorAge
* fix(pack): ignore inherited GIT_INDEX_FILE #42114Jake Wang2026-09-30
| | | | | | | | | | | | Problem: An inherited Git index can leave a plugin checkout empty or prevent updates. Solution: Clear GIT_INDEX_FILE for plugin Git commands. Verify installs and updates preserve the caller environment and index. AI-assisted Signed-off-by: Jake Wang <jakezwang@users.noreply.github.com>
* ci(lua): enable annotation and style checksLewis Russell2026-09-30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: - annotation-usage-error and code-style-check are disabled. - vim.inspect relies on a dummy self-assignment for docgen, and its help omits parameter and option details. - LuaLS fallback types obscure iterator inference. - Docgen hardcodes public function names and appends separately sorted files, leaving shared helpers under the inspector heading. Solution: - Enable annotation-usage-error and code-style-check, and fix misplaced annotations. - Document vim.inspect's callable module directly, removing the dummy assignment. Describe its parameters, option defaults and process callback. - Remove LuaLS iterator fallbacks, correct iterator signatures and check values that the improved inference identifies as optional. - Parse callable modules, require bindings and parent module references. Derive public names and inherited function docs from these links, including missing help for vim.async.semaphore() and vim.version(). - Export vim.lsp.tagfunc directly with lazy loading and document its implementation instead of maintaining a wrapper. - Group files in section_order, replacing append_only and merge_files. Merge declarations before sorting each section, placing shared helpers in the main vim section and keeping vim.inspect in alphabetical order. - Add basic parser coverage for callable modules and module links. AI-assisted
* fix(lua): enable param-type-mismatch diagnosticLewis Russell2026-09-28
| | | | | | | | | Problem: Argument type mismatches are excluded from EmmyLua checks. Solution: Correct runtime annotations and calls, document local checker workarounds, and enable the diagnostic. AI-assisted
* fix(lua): enable assignment type checking in runtime codeLewis Russell2026-09-25
| | | | | | | | | | | Enable EmmyLua's assign-type-mismatch diagnostic after correcting the runtime annotations and assignments it flags. Correct option, tuple, and return types, and use separate locals when a value changes representation. Add guards and narrow casts where needed so the runtime passes the stricter check. Regenerate the affected docs. AI-assisted
* fix(lua): enable nil-safety diagnostics in runtime codeLewis Russell2026-09-25
| | | | | | | | | | | | Enable EmmyLua's need-check-nil diagnostic and resolve nullable values through more precise types, explicit invariants, and guards for missing runtime state. Keep analyzer-specific workarounds local and update the affected API documentation. Exclude the bundled re.lua from analysis so its nil-check warnings do not fail CI. AI-assisted
* 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(lua): add missing param annotations (#41911)Lewis Russell2026-09-15
|
* build: enable more EmmyLua checksLewis Russell2026-09-09
| | | | | | | | | | Enable checks for unused code, deprecated calls, return types, and annotations. Fix the warnings and replace the deprecated highlight function. Keep exceptions where old APIs are still needed or the checker gets it wrong. AI-assisted
* build: enable more EmmyLua checksLewis Russell2026-09-08
| | | | | | | | | | | | | | | | - call-non-callable - missing-fields - redefined-label - redefined-local - undefined-field - unreachable-code Promote redefined-local and unreachable-code to warnings. Fix DOS line-ending handling for multiline semantic tokens, and support intersection types in the help parser. AI-assisted
* refactor(pack): use vim.asyncLewis Russell2026-09-07
| | | | | | | | | | | Problem: vim.pack uses a private async implementation even though vim.async is now available. Solution: Remove the private implementation and run plugin operations in structured task scopes. Bound parallel work with semaphores and use protected awaits so cancellation still propagates. AI-assisted
* fix(help): :helptags regressionsJustin M. Keyes2026-08-25
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Parent commit regressed some behavior of the old C helptags-gen impl: - helpfiles in sub-directories are named by basename, so :help fails - "help-tags" always names "tags", never "tags-nl" - E150 E151 E152 E153 are never reported - existing tags file is not overwritten if no tags were found - a duplicate tag aborts the run, skipping the remaining directories - `*.TXT` and `*.FRX` (uppercase) are not recognized as helpfiles - tree-sitter-vimdoc accepts tags that the C parser rejected: `*a|b*` (breaks |links|) and unterminated `*tag` - PUC Lua "<" compares with (localized) `strcoll()`, so the tags file is not sorted by byte value (E432) - requiring `vim.treesitter` at load time breaks :help itself, not just :helptags, where the module is unavailable - `vim.pack` runs :helptags for plugins that have no "doc/" directory, so every install/update emits E150 Solution: - Fail the build if generating helptags reports any `v:errmsg`. - Restore old behavior: tags generated for runtime/doc are now identical to those from the C implementation. Errors are non-fatal messages instead of exceptions, so all directories are still processed. - Load treesitter lazily, report a plain error if parser is missing.
* 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/.
* fix(pack): do not write the lockfile when installing from it #41031Evgeni Chasnovski2026-07-28
| | | | | | | | | | | | Problem: Installing plugins during lockfile synchronization always writes the lockfile, even though its content is used during install. This might be a problem if the lockfile (itself or its parent directory) is not writeable (can only be read). Solution: Do not write the lockfile when installing directly from it. This is okay since the `src` and `rev` are used directly from the lockfile and don't change at this step. While potential change in `version` (that must be written to the lockfile) is handled in other code path.
* feat(pack): 'packlockfile' option #40562Evgeni Chasnovski2026-07-08
| | | | | Problem: No way to configure the lockfile location. Solution: Add 'packlockfile' option.
* fix(pack): do not assert non-nil `stderr` #40544Evgeni Chasnovski2026-07-02
| | | | | | | | | | | | Problem: On some systems `stderr` can be disabled. This results in not usable `vim.pack` since it asserted `stderr` to be non-nil. Solution: Stop asserting non-nil `stderr`. The downside is that potential errors are not shown, but this is intentional since `stderr` is disabled on system level. Still assert non-nil `stdout` as its output is important for `vim.pack` to actually do its job. Disabled `stdout` is not something that can work with `vim.pack`.
* 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: introduce nvim_on internally #39883Justin M. Keyes2026-05-20
| | | | | | | | | Problem: `nvim_create_autocmd` is too verbose and its `callback` requires extra "nesting". Solution: Introduce `nvim_on`. Start using it internally. Then we can get a feel for how it should look before making it public.
* fix(pack): collect "Removed plugin" into one message #39840Olivia Kinnear2026-05-20
|
* 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.
* feat(lua)!: vim.isnil, vim.nonnil, deprecate vim.F #39495Olivia Kinnear2026-05-06
|
* 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.
* fix(pack): make 'stash' call compatible with older Git #38679skewb1k2026-04-11
| | | | | | | | Problem: On Git versions 2.13..2.26 there is a bug that prevents using `stash --message`. Solution: Use the full `stash push --message` form to avoid that bug.
* feat(api): rename buffer to buf #35330Jordan2026-04-08
| | | | | | | | | | | | Problem: `:help dev-name-common` states that "buf" should be used instead of "buffer" but there are cases where buffer is mentioned in the lua API. Solution: - Rename occurrences of "buffer" to "buf" for consistency with the documentation. - Support (but deprecate) "buffer" for backwards compatibility. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* fix(pack): avoid eager vim.version call #38705Evgeni Chasnovski2026-04-05
| | | | | | | | | | | | | | | | | | Problem: Commands that rely on Git may need its version to perform more targeted actions (like decide which arguments are safe to use). For performance, computing this version is delayed up until it is needed (like to not compute on regular startup), but not done before every Git operation (as it is too much and can be done better). This requires storing the Git version in a variable which is currently initiated via `vim.version.parse()` call (most probably because it was easier to handle Lua types this way). However, the problem is that this results in sourcing `vim.version` and computing `vim.version.parse` on every startup even if no Git operation would be done. Solution: Don't call `vim.version.parse()` during `require('vim.pack')` and ensure its more precise lazy computation.
* fix(pack): use `uv.available_parallelism()` to compute number of threads #38717Evgeni Chasnovski2026-04-05
| | | | | | | | | Problem: Computing number of threads for parallel asynchronous computation using `uv.cpu_info()` can be slow. This is especially noticeable since it is pre-computed on every `require('vim.pack')` and not only when parallelism is needed. Solution: Use `uv.available_parallelism()` to compute number of threads in a helper function.
* fix(pack): set `source` in progress report #38511Evgeni Chasnovski2026-03-27
| | | | | | | | | Problem: Progress reports via `nvim_echo()` gained an ability to set `source` and `vim.pack` doesn't currently set one. Solution: Set `source` to 'vim.pack'. Ideally, the title then can be something else more informative (like "update", "download", etc.), but it is used when showing progress messages. So it has to be "vim.pack" in this case.
* fix(pack): add trailing newline to lockfile #38469Justin Mayhew2026-03-24
| | | | | | | | Problem: JSON files should end with a trailing newline so that Unix tools work as expected, Git doesn't report "No newline at end of file" and to avoid noise in diffs from editors and other tools adding the missing newline. Solution: Add trailing newline.
* refactor: integer functions, optimize asserts #34112Lewis Russell2026-03-12
| | | | | | | | | | | | refactor(lua): add integer coercion helpers Add vim._tointeger() and vim._ensure_integer(), including optional base support, and switch integer-only tonumber()/assert call sites in the Lua runtime to use them. This also cleans up related integer parsing in LSP, health, loader, URI, tohtml, and Treesitter code. supported by AI
* 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()|`.
* fix(pack): ensure `data` spec is passed in events during lockfile sync #38139Evgeni Chasnovski2026-03-03
| | | | | | | | | | | | | | | | | | | | | | | Problem: During initial "bootstrap" via lockfile synchronization, the whole plugin specification is reconstructed from the lockfile data, ignoring potential user changes added in the first `vim.pack.add()`. This is enough in most situations since it is the only data needed for actual installation. However, this affects specification passed to `PackChanged[Pre]` events. In particular, `data` field is missing which can be a problem if there is a `PackChanged kind=install` hook that uses that field (like with some kind of `build` method used during install). And there might be different `version` set in `vim.pack.add()`. Solution: Pass the `specs` input of the first `vim.pack.add()` down to lockfile synchronization and use it to reconstruct plugin specification for the to-be-installed plugin. If present among the user's `specs`, it is used but with forced `src` from the lockfile (as it is the one used during installation). Note that this still has a caveat when using separate `vim.pack.add()`, as only the specs from the first input (when the lockfile synchronization happens) is taken into account.
* fix(pack): explicitly close confirmation window #37861Evgeni Chasnovski2026-02-14
| | | | | | | | | Problem: Executing `nvim_buf_delete()` does not guarantee that the window which shows the buffer is going to close after `:write` or `:quit`. In particular, if there is no listed buffer present. Solution: Explicitly close the window that was created for confirmation buffer. Use `pcall` to catch cases when the window was already closed or when it is the last window.
* fix(pack): skip :redraw! if headless #37782Andrew Braxton2026-02-12
| | | | | Otherwise, output will be concatenated without newlines. TODO: the ":redraw!" call can be dropped entirely after ui2 becomes the default.
* fix(pack): close confirmation buffer, not tabpage #37756Evgeni Chasnovski2026-02-08
|
* docs(pack): clarify caveats about installing based on the lockfileEvgeni Chasnovski2026-01-29
|
* Merge #37309 :checkhealth vim.packJustin M. Keyes2026-01-27
|\
| * fix(pack): ensure plugin directory is created during first usage attemptEvgeni Chasnovski2026-01-08
| | | | | | | | | | | | | | Problem: Plugin directory ('.../pack/core/opt') may be missing while lockfile is present. Like after discarded attempt to install plugins. Solution: Ensure plugin directory is created on first `vim.pack` use.
* | 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.
* | fix(pack): actually checkout proper version of submodulesEvgeni Chasnovski2026-01-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Installing plugin with submodules doesn't check out their state (due to `git clone --no-checkout` to not end up with default branch code in case of invalid `version`). Updating a plugin with submodules doesn't update their state. Solution: Update `git_checkout` helper to account for submodules. Another approach would be `git checkout --recurse-submodules ...`, but that doesn't seem to allow `--filter=blob:none` for submodules, which is nice to have. Also make `git_clone` wrapper simpler since `--no-checkout` makes `--recurse-submodules` and `--also-filter-submodules` do nothing.
* | fix(pack): skip `git stash` during installEvgeni Chasnovski2026-01-12
|/ | | | | | | | | | Problem: Installing plugin is done via `git clone --no-checkout ...` (to not end up with default branch code in case of invalid `version`). This leaves cloned repo in a state that `git stash` will actually add an entry to the stash list. Although not critical, better to not have that if possible. Solution: explicitly skip `git stash` step in checkout during install.