aboutsummaryrefslogtreecommitdiff
path: root/test/functional/plugin/pack_spec.lua
Commit message (Collapse)AuthorAge
...
* 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): use more correct URI for confirmation buffer nameEvgeni Chasnovski2025-11-06
| | | | | | | | | Problem: Confirmation buffer is named with `nvim-pack://` as scheme prefix and uses buffer id (needed for in-process LSP) as one an entry in the "hierarchical part". Solution: Use `nvim://pack-confirm#<buf>` format with a more ubiquitous `nvim://` prefix and buffer id at the end as the optional fragment.
* 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".
* fix(pack): use full hashes in lockfile and revision descriptionEvgeni Chasnovski2025-11-06
| | | | | | | | | Problem: Using abbreviated version of commit hashes might be unreliable in the long term (although highly unlikely). Solution: Use full hashes in lockfile and revision description (in confirmation buffer and log). Keep abbreviated hashes when displaying update changes (for brevity).
* fix(pack)!: do not trigger `PackChanged[Pre] kind=update` during installEvgeni Chasnovski2025-10-23
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: `PackChanged[Pre]` events with `kind=update` are triggered both during plugin's initial installation and after already installed plugin was updated. It was a deliberate decision to allow writing only a single update hook to act as a dedicated "build" entry point (like execute `make` or `cargo build —release`). This mimics how other plugin managers have a single "build" command. This was a result of 'mini.deps' experience with the different approach: "update" hooks are not run during install. This proved to be confusing as it requires to write two hooks. But also the reason might be that 'mini.deps' names it "checkout" hook instead of "update". However, the `vim.pack` event approach makes it lower cost to handle separate "update" and "install" events. Something like `if ev.data.kind == 'install' or ev.data.kind == 'update' then` instead of two autocommands. Plus this makes clearer separation of events. Solution: do not trigger `PackChanged[Pre] kind=update` event during install.
* 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.
* test(pack): refactor 'pack_spec.lua' with better codeEvgeni Chasnovski2025-10-23
| | | | | | | | | | | | | | | | | | | | | | Problem: 'pack_spec.lua' test file's code can be improved. Solution: Refactor some aspects. In particular: - Rewrite `find_in_log` for finding event data in event log into a generator function that from log list returns a finder function. This allows it to take less arguments and be more concise. - Consistently use `local function f()` instead of `local f = function()`. - Prefer to use `fn.readblob()` instead of `fn.readfile()` to assert text from a file. - Use `([[...]]):format()` approach to testing file content (instead of array of strings). Should improve readability. - Universally prefer using "assert" to mean "check if certain expectation about the process holds up" (instead of occasional "validate").
* test(plugin/pack_spec): handle pcall path truncation #36143Vlad2025-10-12
| | | | | | | | | | | | | | | Problem In `vim.pack` the source of any errors is included in the `update` buffer from lua's `pcall` method. Since the full path is known it is replaced in the unit test by the string `VIM_PACK_RUNTIME`. The issue is that `pcall` does not necessarily include the full path, it instead uses the `lua_Debug` `short_src` value which can be truncated. This means depending on where you've cloned the repo locally the test can fail. Solution Change the replacement pattern for the traceback to be more generic and handle any path prefix, not just the value of `vim.env.VIMRUNTIME`.
* fix(vim.pack): skip checkout on bad `version` #36038Mickaël RAYBAUD-ROIG2025-10-09
| | | Refs: #36037
* fix(pack): handle lockfile in case of install errors #36064Evgeni Chasnovski2025-10-07
| | | | | | | | | | | | | | Problem: If plugin was intended to install but there were errors (like if there is a typo in `src`), lockfile still includes its entry. This leads to all source of problems (like not correct `get()` output, not working `update()`, etc.). Solution: Explicitly account for plugins that were not installed. Alternative solution might be to write a safe `lock_set(plug, field, value)` wrapper (which sets field for a correct `plugins` entry in the lockfile Lua table) and use it after install to detect the change in `version`. However, this always requires an extra pass through plugins on every startup, which is suboptimal. Optimizing for the "happy path" should be a priority in `add()`.
* 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
| | | | | | | | | | | Problem: Running `update()` by default doesn't include not active plugins, because there was no way to get relevant `version` to get updates from. This might be a problem in presence of lazy loaded plugins, i.e. ones that can be "not *yet* active" but still needed to be updated. Solution: Include not active plugins by default since their `version` is tracked via lockfile.
* feat(pack)!: update `get()` to return revision regardless of `opts.info`Evgeni Chasnovski2025-10-04
| | | | | | | Problem: The revision data is returned behind `opts.info` flag because it required extra Git calls. With lockfile it is not the case. Solution: Use lockfile to always set `rev` field in output of `get()`.
* fix(pack)!: use lockfile in `get()` for data about non-active pluginsEvgeni Chasnovski2025-10-04
| | | | | | | Problem: `get()` doesn't return `spec.version` about not-yet-active plugins (because there was no way to know that without `add()`). Solution: Use lockfile data to set `spec.version` of non-active plugins.
* feat(pack): add initial lockfile trackingEvgeni Chasnovski2025-10-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Some use cases require or benefit from persistent on disk storage of plugin data (a.k.a. "lockfile"): 1. Allow `update()` to act on not-yet-active plugins. Currently if `add()` is not yet called, then plugin's version is unknown and `update()` can't decide where to look for changes. 2. Efficiently know plugin's dependencies without having to read 'pkg.json' files on every load for every plugin. This is for the future, after there is `packspec` support (or other declaration of dependencies on plugin's side). 3. Allow initial install to check out the exact latest "working" state for a reproducible setup. Currently it pulls the latest available `version.` 4. Ensure that all declared plugins are installed, even if lazy loaded. So that later `add()` does not trigger auto-install (when there might be no Internet connection, for example) and there is no issues with knowing which plugins are used in the config (so even never loaded rare plugins are still installed and can be updated). 5. Allow `add()` to detect if plugin's spec has changed between Nvim sessions and act accordingly. I.e. either set new `src` as origin or enforce `version.` This is not critical and can be done during `update()`, but it might be nice to have. Solution: Add lockfile in JSON format that tracks (adds, updtes, removes) necessary data for described use cases. Here are the required data that enables each point: 1. `name` -> `version` map. 2. `name` -> `dependencies` map. 3. `name` -> `rev` map. Probably also requires `name` -> `src` map to ensure that commit comes from correct origin. 4. `name` -> `src` map. It would be good to also track the order, but that might be too many complications and redundant together with point 2. 5. Map from `name` to all relevant spec fields. I.e. `name` -> `src` and `name` -> `version` for now. Storing data might be too much, but can be discussed, of course. This commit only adds lockfile tracking without implementing actual use cases. It is stored in user's config directory and is suggested to be tracked via version control. Example of a lockfile: ```json { # Extra nesting to more future proof. "plugins": { "plug-a": { "ref": "abcdef1" "src": "https://github.com/user/plug-a", # No `version` means it was `nil` (infer default branch later) }, "plug-b": { "dependencies": ["plugin-a", "plug-c"], "src": "https://github.com/user/plug-b", "ref": "bcdefg2", # Enclose string `version` in quotes "version": "'dev'" }, "plug-c": { "src": "https://github.com/user/plug-c", "ref": "cdefgh3", # Store `vim.version.Range` via its `tostring()` output "version": ">=0.0.0", } } } ```
* feat(pack): confirm "Always" to install all plugins #35733Evgeni Chasnovski2025-09-13
| | | | | | | | | Problem: First clean start with config containing multiple `vim.pack.add()` calls requires to explicitly confirm each one. Although usually a rare occurrence, it still might be tedious. Solution: Add a third choice during installation confirmation that approves current and all next installs within current session. It is reset after session restart.
* fix(runtime): add "Added", "Changed", "Removed" to "vim" colorscheme (#35704)zeertzjq2025-09-11
| | | These were added to syncolor.vim in Vim patch 9.1.0016.
* fix(pack): handle Git environment variables #35626Evgeni Chasnovski2025-09-07
| | | | | | Problem: Some environment variables which are useful when working inside a bare repository can affect any Git operation. Solution: Explicitly unset problematic environment variables.
* feat(pack): vim.pack.get() gets VCS info #35631Evgeni Chasnovski2025-09-07
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Force resolve `spec.version` overrides the information about whether a user supplied `version` or not. Knowing it might be useful in some use cases (like comparing to previously set `spec` to detect if it has changed). Solution: Do not resolve `spec.version`. This also improves speed when triggering events and calling `get()`. - Place default branch first when listing all branches. - Use correct terminology in `get_hash` helper. - Do not return `{ '' }` if there are no tags. Problem: There is no way to get more information about installed plugins, like current revision or default branch (necessary if resolving default `spec.version` manually). As computing Git data migth take some time, also allow `get()` to limit output to only necessary set of plugins. Solution: - introduce arguments to `get(names, opts)`, which follows other `vim.pack` functions. Plugin extra info is returned by default and should be opt-out via `opts.info = false`. - Examples: - Get current revision: `get({ 'plug-name' })[1].rev` - Get default branch: `get({ 'plug_name' })[1].branches[1]` - `update()` and `del()` act on plugins in the same order their names are supplied. This is less surprising. - default `opts.info` to `true` since this simplifies logic for the common user, while still leaving the door open for a faster `get()` if needed.
* feat(pack): use `nvim_echo{kind=progress}` to report progress #35625Evgeni Chasnovski2025-09-05
| | | | | | | | | Problem: Progress reports use plain `nvim_echo()` with manually constructed messages and populate history on every call. Solution: Use `nvim_echo()` with newly added `kind=progress` which (at least for now) is meant to be a unified interface for showing progress report. Also save in history only first and last progress report messages.
* test(pack): simplify tests for `data` fieldEvgeni Chasnovski2025-08-22
|
* feat(pack): support user-defined `data` in plugin spec #35360Birdee2025-08-21
| | | | | | | | | | | | | | | | | Problem: The load function in opts was difficult to use if you wished to customize based on the plugin being loaded. You could get the name, but without some way to mark a spec, that was of limited usefulness unless you wanted to hardcode a list of names in the function, or write a wrapper around the whole thing Solution: Allow users to provide an arbitrary data field in plugin specs so that they may receive info as to how to handle that plugin in load, get() and events, and act upon it Co-authored-by: BirdeeHub <birdee@localhost> Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com>
* feat(pack): allow skip install confirmation in `add()`Evgeni Chasnovski2025-08-09
| | | | | | | | | | | | | Problem: No way to skip install confirmation in `add()`. Having install confirmation by default is a more secure design. However, users are usually aware of the fact that plugin will be installed and there is currently no way to skip confirmation. Plus it can introduce inconvenience on the clean config initialization if it is modularized with many `vim.pack.add()` calls (leads to confirming installation many times in a row). Solution: Add `opts.confirm` option that can skip install confirmation.
* feat(pack): allow function `opts.load` in `add()`Evgeni Chasnovski2025-08-09
| | | | | | | | | | | Problem: No way to have full control over how plugin is loaded. Although `:packadd!` has small side effects (only adds plugin directory to 'runtimepath'; and maybe its 'after/' subdirectory), it still has side effects. For example, 'plugin/' directories are still loaded during startup (as part of `:h load-plugins`). Solution: Allow function `opts.load` that has full control over how plugin is loaded.
* fix(pack): update `add()` to have default `load=false` during startupEvgeni Chasnovski2025-08-09
| | | | | | | | | | | | | | Problem: the `load=true` in `vim.pack.add()` means that `:packadd` is executed even during startup. This leads to force source of 'plugin/', which breaks the intended loading order (`:h load-plugins`) and results into sourcing them twice. This also makes it ignore `--noplugin` argument. Using `:packadd!` during startup is more appropriate, while `:packadd` afterwards is still more favorable to actually force 'plugin/' source (as there is no pre-defined mechanism that will load them later). Solution: have `load=false` default during startup, `true` - afterwards.
* test(pack): add `vim.pack` testsEvgeni Chasnovski2025-08-02
|
* fix(vim.pack): add() stops unexpectedly on package load error #34787Phạm Bình An2025-07-06
| | | | | | | | | | | Problem: Error when adding a plugin will make all following plugins not `:packadd`ed Solution: - add() should handle errors from :packadd with pcall() Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* feat(pack): add built-in plugin manager `vim.pack`Evgeni Chasnovski2025-07-04
Problem: No built-in plugin manager Solution: Add built-in plugin manager Co-authored-by: Lewis Russell <lewis6991@gmail.com>