summaryrefslogtreecommitdiffstatshomepage
path: root/runtime/lua/vim/pack.lua
AgeCommit message (Collapse)AuthorFiles
2025-10-05feat(pack): add code actions in confirmation bufferEvgeni Chasnovski1
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()`.
2025-10-05feat(pack): add `[[` and `]]` mappings in confirmation bufferEvgeni Chasnovski1
Problem: No easy/robust way to jump between plugin sections. Solution: Add `[[` and `]]` mappings.
2025-10-04feat(pack): prefer using revision from lockfile during installEvgeni Chasnovski1
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.
2025-10-04feat(pack)!: make `update()` include not active plugins by defaultEvgeni Chasnovski1
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.
2025-10-04feat(pack)!: update `get()` to return revision regardless of `opts.info`Evgeni Chasnovski1
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()`.
2025-10-04fix(pack)!: use lockfile in `get()` for data about non-active pluginsEvgeni Chasnovski1
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.
2025-10-04feat(pack): add initial lockfile trackingEvgeni Chasnovski1
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", } } } ```
2025-09-13feat(pack): confirm "Always" to install all plugins #35733Evgeni Chasnovski1
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.
2025-09-07fix(pack): handle Git environment variables #35626Evgeni Chasnovski1
Problem: Some environment variables which are useful when working inside a bare repository can affect any Git operation. Solution: Explicitly unset problematic environment variables.
2025-09-07feat(pack): vim.pack.get() gets VCS info #35631Evgeni Chasnovski1
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.
2025-09-05feat(pack): use `nvim_echo{kind=progress}` to report progress #35625Evgeni Chasnovski1
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.
2025-08-28refactor(lua): consistent use of local aliasesChristian Clason1
2025-08-26feat(api): nvim_echo can emit Progress messages/events #34846Shadman1
Problem: Nvim does not have a core concept for indicating "progress" of long-running tasks. The LspProgress event is specific to LSP. Solution: - `nvim_echo` can emit `kind="progress"` messages. - Emits a `Progress` event. - Includes new fields (id, status, percent) in the `msg_show` ui-event. - The UI is expected to overwrite any message having the same id. - Messages have a globally unique ID. - `nvim_echo` returns the message ID. - `nvim_echo(… {id=…})` updates existing messages. Example: local grp = vim.api.nvim_create_augroup("Msg", {clear = true}) vim.api.nvim_create_autocmd('Progress', { pattern={"term"}, group = grp, callback = function(ev) print(string.format('event fired: %s', vim.inspect(ev))..'\n') end }) -- require('vim._extui').enable({enable=true, msg={target='msg', timeout=1000}}) vim.api.nvim_echo({{'searching'}}, true, {kind='progress', percent=80, status='running', title="terminal(ripgrep)"}) local id = vim.api.nvim_echo({{'searching'}}, true, {kind='progress', status='running', percent=10, title="terminal(ripgrep)"}) vim.api.nvim_echo({}, true, {id = id, kind='progress', percent=20, status = 'running', title='find tests'}) vim.api.nvim_echo({}, true, {id = id, kind='progress', status='running', percent=70}) vim.api.nvim_echo({{'complete'}}, true, {id = id, kind='progress', status='success', percent=100, title="find tests"}) Followups: - Integrate with 'statusline' by listening to the Progress autocmd event. - Integrate progress ui-event with `vim._extui`.
2025-08-22docs(pack): document `$XDG_DATA_HOME/nvim/site` presence in 'packpath'Evgeni Chasnovski1
Problem: Some use cases might lead to `vim.pack.add()` failing to `:packadd` a plugin because of missing entry in 'packpath'. Like with `nvim --clean` or manually setting `$XDG_DATA_HOME` during startup. Solution: Document it. A more proactive approach can be ensuring correct 'packpath' entry, but it is currently somewhat verbose to do (due to having to adjust for Windows using `\` in 'packpath' entries).
2025-08-22perf(pack): reduce number of 'opt/' directory computationsEvgeni Chasnovski1
2025-08-21feat(pack): support user-defined `data` in plugin spec #35360Birdee1
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>
2025-08-09feat(pack): allow skip install confirmation in `add()`Evgeni Chasnovski1
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.
2025-08-09feat(pack): allow function `opts.load` in `add()`Evgeni Chasnovski1
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.
2025-08-09fix(pack): update `add()` to have default `load=false` during startupEvgeni Chasnovski1
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.
2025-08-02fix(pack): open confirmation buffer in tabpage after the current oneEvgeni Chasnovski1
2025-08-02fix(pack): ensure consistent order of changelog during updateEvgeni Chasnovski1
Problem: Left (`<` prefix) and right (`>` prefix) parts of update changelog come in not fixed order: it can be left-right or right-left. Solution: Ensure left-right order.
2025-08-02fix(pack): make newer version suggestions more robustEvgeni Chasnovski1
Problem: New version suggestions in update confirmation buffer might include semver tags that were committed later but for versions that are not greater than current. Like if versions committed in order `v0.2.0` - `v0.3.0` - `v0.2.1` - `v0.3.1`, then when on `v0.3.0` both `v0.2.1` and `v0.3.1` are suggested, but only the latter is newer as a version. This is because those tags are computed with post-processed `git tag --list --contains HEAD`. Solution: Compute all semver tags and filter only those greater than the latest version available at HEAD.
2025-08-02refactor(pack): use `vim.cmd` methods with structured inputEvgeni Chasnovski1
2025-08-02fix(pack): ensure explicit default `version` in events (where possible)Evgeni Chasnovski1
Problem: Both `PackChangedPre` and `PackChanged` contain |event-data| with plugin's `spec`. It looks like a good idea to have all its triggers contain the same format across all kinds ("install", "update", "delete"). There are several choices: - Have it be as verbatim as supplied to `vim.pack.add()`, i.e. can be either string or table. A bit too ambiguous. - Have it be table with `src` and `name` inferred. This requires less work for "install", but more work for "update" and "delete" (since they use `vim.pack.get()` which already infers default `version`). - Have it be table with *all* defaults made explicit. This looks like the best approach, but requires extra care to only infer default `version` when needed (i.e. avoid inferring during regular load) because it is costly in terms of startup time. This might also introduce inconsistency when dealing with lockfile(s) as information there should be as close to what user supplied as possible. Address that when dealing with lockfile. Solution: Ensure explicit `version` in all events where possible.
2025-08-02fix(pack): use `vim.pack:` as message/progress prefixEvgeni Chasnovski1
2025-08-02fix(pack): validate installed plugins in `update()` and `del()`Evgeni Chasnovski1
Problem: Currently `update()` and `del()` silently ignore input plugin names that are not for already installed plugin. This might lead to confusion because they are not explicitly reported. Solution: Check that all input names are for installed plugins and error otherwise.
2025-08-02feat(pack): use colored `nvim_echo` chunks to show progress reportEvgeni Chasnovski1
Problem: using `print()` to show progress report writes to `stdout` when in `--headless` mode (interferes with the testing output) and doesn't allow coloring. Solution: use `nvim_echo` with colored chunks.
2025-08-02fix(pack): ignore 'loadplugins' when sourcing 'after/plugin' scriptsEvgeni Chasnovski1
Problem: Sourcing of 'after/plugin' scripts depends on the value of 'loadplugins' option. It is redundant, as it has effect only during startup, while it is combined with `vim.v.vim_did_enter == 1` (i.e. "it is after starting up") condition. Solution: Ignore it.
2025-08-02fix(pack): improve `vim.pack.add()` input validationEvgeni Chasnovski1
2025-08-02fix(pack): use 'coxpcall.lua' on non-LuaJITEvgeni Chasnovski1
Problem: `attempt to yield across metamethod/C-call boundary` error when trying to use `vim.pack.add()`. Solution: use `pcall()` variant from 'coxpcall' on non-LuaJIT version of Lua.
2025-07-18fix(pack): close confirmation buffer's tabpage by ID #34971György Andorka1
Problem: On canceling the update (triggering `WinClosed`), the tab page will most probably be closed too. Closing some other tab page while the confirmation buffer is open also changes tab page numbers. We are trying to close the wrong tab page in both cases. Solution: save the tab page ID, and attempt to get the tab page number from the ID when closing the buffer.
2025-07-06fix(vim.pack): add() stops unexpectedly on package load error #34787Phạm Bình An1
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>
2025-07-04feat(pack): add built-in plugin manager `vim.pack`Evgeni Chasnovski1
Problem: No built-in plugin manager Solution: Add built-in plugin manager Co-authored-by: Lewis Russell <lewis6991@gmail.com>