Compare commits

...

1610 commits

Author SHA1 Message Date
github-actions[bot]
6c3bda4aca
chore(main): release 11.17.1 (#1927)
🤖 I have created a release *beep* *boop*
---


##
[11.17.1](https://github.com/folke/lazy.nvim/compare/v11.17.0...v11.17.1)
(2025-02-25)


### Bug Fixes

* **bootstrap:** support for older Neovim versions
([1c9ba37](1c9ba37045))
* **meta:** rebuild dirty right after disable. See
[#1889](https://github.com/folke/lazy.nvim/issues/1889)
([d51cf69](d51cf69783))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-25 20:19:57 +01:00
Folke Lemaitre
d51cf69783
fix(meta): rebuild dirty right after disable. See #1889 2025-02-25 20:18:25 +01:00
Folke Lemaitre
1c9ba37045
fix(bootstrap): support for older Neovim versions 2025-02-25 20:02:32 +01:00
github-actions[bot]
96a205c8ce
chore(main): release 11.17.0 (#1877)
🤖 I have created a release *beep* *boop*
---


##
[11.17.0](https://github.com/folke/lazy.nvim/compare/v11.16.2...v11.17.0)
(2025-02-24)


### Features

* **config,render:** allow customizing the debug icon
([#1863](https://github.com/folke/lazy.nvim/issues/1863))
([a9c660d](a9c660d6ef))
* **util:** pass lang to `vim.notify` so that snacks notifier can render
the ft. Closes [#1919](https://github.com/folke/lazy.nvim/issues/1919)
([c6a57a3](c6a57a3534))


### Bug Fixes

* **config:** add missing space on the default debug icon
([#1879](https://github.com/folke/lazy.nvim/issues/1879))
([4df5c4d](4df5c4d65a))
* **meta:** disable top-level specs before the rest. Closes
[#1889](https://github.com/folke/lazy.nvim/issues/1889)
([f81a3fb](f81a3fb7fe))
* **ui:** do not show virt_lines for messages
([#1904](https://github.com/folke/lazy.nvim/issues/1904))
([f15a939](f15a93907d))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-25 19:14:41 +01:00
Salomon Popp
a8c6db5da7
style(types): add optional return value for LazyKeysSpec rhs (#1924)
## Description

<!-- Describe the big picture of your changes to communicate to the
maintainers
  why we should accept this pull request. -->

when `expr=true` the rhs function should return a string.

example

```lua
{
    keys = {
        {
            '<leader>j',
            function()
                return require('dial.map').inc_normal()
            end,
            expr = true,
            desc = 'Increment value',
        }
    }
}
```

## Related Issue(s)

<!--
  If this PR fixes any issues, please link to the issue here.
  - Fixes #<issue_number>
-->

## Screenshots

<!-- Add screenshots of the changes if applicable. -->
2025-02-24 07:20:35 +01:00
Folke Lemaitre
e5e9bf4821
test: fix tests 2025-02-15 23:09:58 +01:00
Folke Lemaitre
f81a3fb7fe
fix(meta): disable top-level specs before the rest. Closes #1889 2025-02-15 23:06:09 +01:00
github-actions[bot]
ac21a639c7 chore(build): auto-generate rockspec mappings 2025-02-15 07:25:07 +00:00
Folke Lemaitre
c6a57a3534
feat(util): pass lang to vim.notify so that snacks notifier can render the ft. Closes #1919 2025-02-15 08:19:49 +01:00
JINNOUCHI Yasushi
f15a93907d
fix(ui): do not show virt_lines for messages (#1904)
## Description

<!-- Describe the big picture of your changes to communicate to the
maintainers
  why we should accept this pull request. -->

https://github.com/neovim/neovim/pull/31959 has introduced virtual lines
for showing diagnostics. If this is enabled (default value), messages
from lazy.nvim, such as `update available` are shown as virtual lines in
addition to virtual texts.

## Related Issue(s)

<!--
  If this PR fixes any issues, please link to the issue here.
  - Fixes #<issue_number>
-->

## Screenshots

<!-- Add screenshots of the changes if applicable. -->

* ***before***
- <img width="592" alt="スクリーンショット 2025-01-27 16 42 27"
src="https://github.com/user-attachments/assets/6994ac84-4862-4532-81ee-80f4015181e5"
/>
* ***after***
- <img width="585" alt="スクリーンショット 2025-01-27 16 42 58"
src="https://github.com/user-attachments/assets/d19f63dc-fb6d-434f-89cf-a0bc49d31c5f"
/>
2025-02-06 07:53:12 +01:00
github-actions[bot]
7527af40dd chore(build): auto-generate rockspec mappings 2025-01-30 19:19:03 +00:00
Folke Lemaitre
5586fda88d
ci: remove debug 2025-01-30 20:14:57 +01:00
Folke Lemaitre
4f30c61b64
ci: check 2025-01-30 20:13:53 +01:00
github-actions[bot]
d8f26efd45 chore(build): auto-generate docs 2025-01-06 20:14:50 +00:00
Eduardo Bray
4df5c4d65a
fix(config): add missing space on the default debug icon (#1879)
## Description

Adds the missing space from a9c660d

## Screenshots

Current:


![imagen](https://github.com/user-attachments/assets/9a3a1a0c-43ad-49f3-8b39-b3250f53ec40)

After:


![imagen](https://github.com/user-attachments/assets/3b3d4dfd-3c03-4db9-8f61-d2bd4f9ed22d)
2025-01-06 21:14:06 +01:00
github-actions[bot]
72aa3a2624 chore(build): auto-generate docs 2025-01-05 05:41:31 +00:00
Shihua Zeng
a9c660d6ef
feat(config,render): allow customizing the debug icon (#1863)
## Description

lazy.nvim allows users to configure all icons except for the debug icon.
This PR enables user to configure the debug icon with `ui.icons.debug`

## Screenshots

Before:


![image](https://github.com/user-attachments/assets/42b02fd9-58e6-4ebc-a1a7-c5e91f07a11a)

After (with config `{ ui = { icons = { debug = ' ' } } }`):


![image](https://github.com/user-attachments/assets/3ade5392-a988-4a10-86fc-f52b41a690c5)
2025-01-05 06:40:44 +01:00
github-actions[bot]
7e6c863bc7
chore(main): release 11.16.2 (#1854)
🤖 I have created a release *beep* *boop*
---


##
[11.16.2](https://github.com/folke/lazy.nvim/compare/v11.16.1...v11.16.2)
(2024-12-13)


### Bug Fixes

* **meta:** when a plugin is both optional and disabled, then just
delete it from the list
([805b85c](805b85c2ea))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-13 19:58:17 +01:00
Folke Lemaitre
805b85c2ea
fix(meta): when a plugin is both optional and disabled, then just delete it from the list 2024-12-13 19:56:52 +01:00
github-actions[bot]
7c493713bc
chore(main): release 11.16.1 (#1844)
🤖 I have created a release *beep* *boop*
---


##
[11.16.1](https://github.com/folke/lazy.nvim/compare/v11.16.0...v11.16.1)
(2024-12-09)


### Bug Fixes

* **types:** ensure all fields for `LazyPluginSpec` are optional
([#1843](https://github.com/folke/lazy.nvim/issues/1843))
([703be1d](703be1dda3)),
closes [#1842](https://github.com/folke/lazy.nvim/issues/1842)

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-10 20:12:21 +01:00
github-actions[bot]
b97ee167f5 chore(build): auto-generate docs 2024-12-10 05:18:15 +00:00
Daemon
703be1dda3
fix(types): ensure all fields for LazyPluginSpec are optional (#1843)
> After updating lua_ls to
[v3.13.3](https://github.com/LuaLS/lua-language-server/releases/tag/3.13.3)
noticed my plugin scripts using `@type LazyPluginSpec` now have
`missing-fields` warnings.
It seems they have changed how `missing-fields` diagnostics work with
inherited types:
7b2d58537f.

Duplicate offending fields as optional in type `LazyPluginSpec`

Closes: #1842
2024-12-09 22:40:21 +01:00
github-actions[bot]
014d1d6d78
chore(main): release 11.16.0 (#1838)
🤖 I have created a release *beep* *boop*
---


##
[11.16.0](https://github.com/folke/lazy.nvim/compare/v11.15.0...v11.16.0)
(2024-12-07)


### Features

* **plugin:** added support for virtual plugins. Closes
[#1836](https://github.com/folke/lazy.nvim/issues/1836)
([ee64abc](ee64abc76b))


### Bug Fixes

* **plugin:** don't check if dir exists for virtual plugins
([656cf43](656cf43093))
* **render:** show correct key for home. Fixes
[#1796](https://github.com/folke/lazy.nvim/issues/1796)
([b08dba8](b08dba8107))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-07 21:44:18 +01:00
Folke Lemaitre
656cf43093
fix(plugin): don't check if dir exists for virtual plugins 2024-12-07 11:52:43 +01:00
Folke Lemaitre
b08dba8107
fix(render): show correct key for home. Fixes #1796 2024-12-07 07:57:03 +01:00
Folke Lemaitre
ee64abc76b
feat(plugin): added support for virtual plugins. Closes #1836 2024-12-06 20:28:53 +01:00
github-actions[bot]
3388a26417 chore(build): auto-generate rockspec mappings 2024-12-05 08:11:36 +00:00
github-actions[bot]
a44e9cd165
chore(main): release 11.15.0 (#1835)
🤖 I have created a release *beep* *boop*
---


##
[11.15.0](https://github.com/folke/lazy.nvim/compare/v11.14.2...v11.15.0)
(2024-12-05)


### Features

* **plugin:** show error for local plugins that don't exist. Fixes
[#1773](https://github.com/folke/lazy.nvim/issues/1773)
([9570a5a](9570a5ae7b))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-05 09:10:16 +01:00
Folke Lemaitre
9570a5ae7b
feat(plugin): show error for local plugins that don't exist. Fixes #1773 2024-12-05 09:06:28 +01:00
github-actions[bot]
56ead98e05 chore(build): auto-generate rockspec mappings 2024-11-20 08:28:09 +00:00
Folke Lemaitre
7d0fe7615a
ci: docgen fixes 2024-11-20 09:24:28 +01:00
github-actions[bot]
8e11d208d6 chore(build): auto-generate docs 2024-11-20 08:13:59 +00:00
Folke Lemaitre
25749704e4
docs: docgen 2024-11-20 09:11:45 +01:00
Folke Lemaitre
e41dffcbaf
docs: fix hl_group docgen 2024-11-20 09:08:44 +01:00
github-actions[bot]
7967abe557
chore(main): release 11.14.2 (#1730)
🤖 I have created a release *beep* *boop*
---


##
[11.14.2](https://github.com/folke/lazy.nvim/compare/v11.14.1...v11.14.2)
(2024-11-10)


### Bug Fixes

* **bootstrap:** single forward slash. Fixes
[#1747](https://github.com/folke/lazy.nvim/issues/1747)
([aca30f6](aca30f6361))
* **completion:** check if command string is a prefix of Lazy
([#1760](https://github.com/folke/lazy.nvim/issues/1760))
([e9fd76e](e9fd76e239)),
closes [#1758](https://github.com/folke/lazy.nvim/issues/1758)
* **docs:** always update helptags for local plugins
([60cf258](60cf258a9a))
* **luarocks:** try to install from root manifest
([#1687](https://github.com/folke/lazy.nvim/issues/1687))
([591ef40](591ef40f2d))
* **rocks:** add lib64 plugin directory to package.cpath
([#1717](https://github.com/folke/lazy.nvim/issues/1717))
([80da254](80da254e64))
* **rockspec:** allow binary lua files. Fixes
[#1800](https://github.com/folke/lazy.nvim/issues/1800)
([408449a](408449a59a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-11 11:07:59 +01:00
Folke Lemaitre
60cf258a9a
fix(docs): always update helptags for local plugins 2024-11-10 07:28:51 +01:00
github-actions[bot]
b1134ab82e chore(build): auto-generate rockspec mappings 2024-11-04 10:49:21 +00:00
Folke Lemaitre
408449a59a
fix(rockspec): allow binary lua files. Fixes #1800 2024-11-04 11:46:48 +01:00
github-actions[bot]
cf8ecc2c5e chore(build): auto-generate rockspec mappings 2024-10-22 10:47:57 +00:00
Lorenzo Zabot
40dab7450e
style(typos): correct a few typos (#1776)
## Description

<!-- Describe the big picture of your changes to communicate to the
maintainers
  why we should accept this pull request. -->
This PR just fixes a few typos :)

`dont => don't`
## Related Issue(s)

<!--
  If this PR fixes any issues, please link to the issue here.
  - Fixes #<issue_number>
-->

## Screenshots

<!-- Add screenshots of the changes if applicable. -->
2024-10-22 12:43:33 +02:00
github-actions[bot]
1159bdccd8 chore(build): auto-generate rockspec mappings 2024-10-02 07:54:44 +00:00
Luna Saphie Mittelbach
e9fd76e239
fix(completion): check if command string is a prefix of Lazy (#1760)
Problem: Command completion doesn't work if the command name isn't
written in full

Solution: Use vim.startswith to check if the command is a prefix of
'Lazy'

Fixes #1758
2024-10-02 09:52:51 +02:00
github-actions[bot]
460e1cd8f2 chore(build): auto-generate rockspec mappings 2024-09-16 08:17:41 +00:00
Folke Lemaitre
aca30f6361
fix(bootstrap): single forward slash. Fixes #1747 2024-09-16 10:13:11 +02:00
github-actions[bot]
48b52b5cfc chore(build): auto-generate rockspec mappings 2024-08-31 07:03:18 +00:00
Marc Jakobi
591ef40f2d
fix(luarocks): try to install from root manifest (#1687)
## Description

When passing the `--dev` flag to `luarocks`, it will prioritise `dev`
versions when resolving dependencies (treating `dev` or `scm` as greater
than a SemVer version) if the rockspec doesn't specify an upper version
constraint (which is often the case).

Dev packages are often unstable and may cause more problems, especially
for Windows users (an example I've seen is git for windows trying and
failing to checkout submodules).

For now , a good compromise between too many retries and not retrying at
all could be to try `luarocks install` from the root manifest first, but
to keep the `--dev` flag in `luarocks make`.

If that still causes problems, it might be better to fall back to
`luarocks make` without `--dev` first, and then to try `luarocks ---dev
make` as a last resort.
In rocks.nvim, we only fall back to adding the `--dev` flag if the
install error message contains the string `"No results matching query
were found"`; assuming that stable non-dev packages shouldn't depend on
dev packages.
2024-08-31 08:59:45 +02:00
Roger Kim
80da254e64
fix(rocks): add lib64 plugin directory to package.cpath (#1717)
## Description
`package.cpath` is missing the `lib64` directory for plugins that have
luarocks dependencies.

## Context
I found this issue when I was working on my new Neovim plugin on my
Fedora 39 machine. I added the `luasockets` dependency to rockspec file
in my plugin like so:

```
rockspec_format = "3.0"
package = "typeracer.nvim"
version = "scm-1"
source = {
	url = "git+https://github.com/carbon-steel/typeracer.nvim",
}
dependencies = {
	"luasocket",
}
test_dependencies = {
	"nlua",
}
build = {
	type = "builtin",
	copy_directories = {},
}

```

I found that the dynamic libraries from the `luasockets` dependency were
installed like so:
`/home/username/.local/share/nvim/lazy-rocks/typeracer.nvim/lib64/lua/5.1/socket/core.so`.
However, the only entry related to my plugin `typeracer.nvim` was:
`/home/glyph/.local/share/nvim/lazy-rocks/typeracer.nvim/lib/lua/5.1/?.so`.
The issue is that we only have the plugin's `lib` directory in
`package.cpath` and not `lib64`.

I looked through `lazy.nvim`'s code and I think adding the `lib64`
directory should fix the issue. I don't know if we also want to worry
about `lib32` as well, but so far, this change works for me.
2024-08-31 08:58:43 +02:00
Christoph Zirkelbach
014a72b7a8
docs: update dev.path description (#1711)
## Description

In the issue (#1707) I was confused by the description of `dev.path`. I
thought functions must also return the general directory for local
plugins, but it must be the plugin directory.

## Related Issue(s)

#1707
2024-08-31 08:57:58 +02:00
github-actions[bot]
077102c5bf
chore(main): release 11.14.1 (#1680)
🤖 I have created a release *beep* *boop*
---


##
[11.14.1](https://github.com/folke/lazy.nvim/compare/v11.14.0...v11.14.1)
(2024-07-25)


### Bug Fixes

* **plugins:** "Vim:E150: Not a directory" on plugin update
([#1679](https://github.com/folke/lazy.nvim/issues/1679))
([7108809](7108809ab1))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-25 13:38:23 +02:00
Alexander Grebennik
7108809ab1
fix(plugins): "Vim:E150: Not a directory" on plugin update (#1679)
## Description

On plugins update it fails with following error for any plugin.

```
~/.local/share/nvim/lazy/lazy.nvim/manage/task/plugin.lua:95: Vim:E150: Not a directory: ~/.local/share/nvim/lazy/gitsigns.nvim/doc/
```
2024-07-25 12:53:01 +02:00
github-actions[bot]
4496b4cad6
chore(main): release 11.14.0 (#1673)
🤖 I have created a release *beep* *boop*
---


##
[11.14.0](https://github.com/folke/lazy.nvim/compare/v11.13.5...v11.14.0)
(2024-07-24)


### Features

* added `opts.git.cooldown` to allow updating plugins on slow
connections. Fixes
[#1656](https://github.com/folke/lazy.nvim/issues/1656)
([d5686ef](d5686efbd0))
* **plugin:** improve error handling and show better error message
([c02268a](c02268ac6e))


### Bug Fixes

* **plugin:** make .lazy.lua work again
([b4a5a12](b4a5a1209e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-24 07:38:49 +02:00
Folke Lemaitre
b4a5a1209e
fix(plugin): make .lazy.lua work again 2024-07-24 07:23:36 +02:00
Folke Lemaitre
c02268ac6e
feat(plugin): improve error handling and show better error message 2024-07-23 17:24:33 +02:00
Folke Lemaitre
d5686efbd0
feat: added opts.git.cooldown to allow updating plugins on slow connections. Fixes #1656 2024-07-23 13:31:25 +02:00
github-actions[bot]
839f9e78e7
chore(main): release 11.13.5 (#1672)
🤖 I have created a release *beep* *boop*
---


##
[11.13.5](https://github.com/folke/lazy.nvim/compare/v11.13.4...v11.13.5)
(2024-07-22)


### Bug Fixes

* **health:** dont use vim.fn.system to get cmd versions
([7d29719](7d29719ade))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-22 14:41:58 +02:00
Folke Lemaitre
7d29719ade
fix(health): dont use vim.fn.system to get cmd versions 2024-07-22 14:38:00 +02:00
Folke Lemaitre
cc028e77eb
ci: update 2024-07-22 14:24:40 +02:00
github-actions[bot]
16a5c46aa3
chore(main): release 11.13.4 (#1670)
🤖 I have created a release *beep* *boop*
---


##
[11.13.4](https://github.com/folke/lazy.nvim/compare/v11.13.3...v11.13.4)
(2024-07-22)


### Bug Fixes

* **loader:** add plugins whose rtp got loaded early to start plugins
([34b0126](34b0126e5b))
* **loader:** explicitely set package.loaded.modname to nil to prevent
recursive loading errors
([12f2c74](12f2c74244))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-22 09:47:04 +02:00
Folke Lemaitre
12f2c74244
fix(loader): explicitely set package.loaded.modname to nil to prevent recursive loading errors 2024-07-22 09:45:03 +02:00
Folke Lemaitre
34b0126e5b
fix(loader): add plugins whose rtp got loaded early to start plugins 2024-07-22 09:45:03 +02:00
github-actions[bot]
a09c876f6e
chore(main): release 11.13.3 (#1669)
🤖 I have created a release *beep* *boop*
---


##
[11.13.3](https://github.com/folke/lazy.nvim/compare/v11.13.2...v11.13.3)
(2024-07-21)


### Reverts

* fix(loader): add auto loaded module to package.loaded early to prevent
require loops
([a692bf8](a692bf8688))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-21 17:34:22 +02:00
Folke Lemaitre
a692bf8688
revert: fix(loader): add auto loaded module to package.loaded early to prevent require loops
This reverts commit 18d1c1b47e.
2024-07-21 17:32:50 +02:00
github-actions[bot]
8bef0742a2
chore(main): release 11.13.2 (#1668)
🤖 I have created a release *beep* *boop*
---


##
[11.13.2](https://github.com/folke/lazy.nvim/compare/v11.13.1...v11.13.2)
(2024-07-21)


### Bug Fixes

* **loader:** add auto loaded module to package.loaded early to prevent
require loops
([18d1c1b](18d1c1b47e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-21 15:53:27 +02:00
Folke Lemaitre
18d1c1b47e
fix(loader): add auto loaded module to package.loaded early to prevent require loops 2024-07-21 12:41:54 +02:00
github-actions[bot]
9a374a0fb4
chore(main): release 11.13.1 (#1664)
🤖 I have created a release *beep* *boop*
---


##
[11.13.1](https://github.com/folke/lazy.nvim/compare/v11.13.0...v11.13.1)
(2024-07-19)


### Bug Fixes

* **build:** only load the plugin before build for `:` build commands
([5bdb12a](5bdb12a038))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-19 11:50:14 +02:00
Folke Lemaitre
5bdb12a038
fix(build): only load the plugin before build for : build commands 2024-07-19 08:57:37 +02:00
github-actions[bot]
c92c6b5fd2 chore(build): auto-generate docs 2024-07-18 13:57:58 +00:00
Gert Burger
124b864233
docs(commands): fix command ordering for sync (#1661)
## Description

After a discussion on Slack we noticed that the description of the sync
command is a bit vague. Some people, including myself, assumed
`clean`/`install`/`update` referred to build steps being performed per
plugin.

Another person mentioned they thought it referred to the Lazy commands,
which does make more sense.
They also noticed that the order of the commands do not match the source
code.

So this PR corrects the order, assuming it was meant to be ordered, and
mentions that those are commands for clarity.
2024-07-18 15:57:12 +02:00
github-actions[bot]
8f62257511
chore(main): release 11.13.0 (#1660)
🤖 I have created a release *beep* *boop*
---


##
[11.13.0](https://github.com/folke/lazy.nvim/compare/v11.12.0...v11.13.0)
(2024-07-17)


### Features

* **ui:** added mapping descriptions
([6ca90a2](6ca90a2120))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-18 10:47:30 +02:00
Folke Lemaitre
6ca90a2120
feat(ui): added mapping descriptions 2024-07-18 00:40:42 +02:00
github-actions[bot]
5473e3d77c
chore(main): release 11.12.0 (#1655)
🤖 I have created a release *beep* *boop*
---


##
[11.12.0](https://github.com/folke/lazy.nvim/compare/v11.11.1...v11.12.0)
(2024-07-16)


### Features

* **git:** added git network throttle to limit network related git ops
per interval. Closes
[#1635](https://github.com/folke/lazy.nvim/issues/1635)
([d731a6b](d731a6b005))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-17 12:54:53 +02:00
Folke Lemaitre
d731a6b005
feat(git): added git network throttle to limit network related git ops per interval. Closes #1635 2024-07-16 16:50:31 +02:00
github-actions[bot]
9d445ebbd8
chore(update): update repository (#1653)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-15 17:09:32 +02:00
github-actions[bot]
315191aa9e
chore(update): update repository (#1651)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-15 11:19:51 +02:00
github-actions[bot]
b02c9eae6a
chore(main): release 11.11.1 (#1643)
🤖 I have created a release *beep* *boop*
---


##
[11.11.1](https://github.com/folke/lazy.nvim/compare/v11.11.0...v11.11.1)
(2024-07-13)


### Bug Fixes

* **config:** check for lib64. Fixes
[#1343](https://github.com/folke/lazy.nvim/issues/1343)
([93499c5](93499c5deb))
* **lockfile:** ensure newline at EOF for lockfile
([#1639](https://github.com/folke/lazy.nvim/issues/1639))
([7ed9f71](7ed9f7173c))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-13 22:50:19 +02:00
github-actions[bot]
6e66f8e655
chore(update): update repository (#1648)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-13 19:29:13 +02:00
Folke Lemaitre
93499c5deb
fix(config): check for lib64. Fixes #1343 2024-07-13 18:07:56 +02:00
github-actions[bot]
788feaf10e
chore(update): update repository (#1644)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-13 16:16:17 +02:00
github-actions[bot]
58c6bc4ab2
chore(update): update repository (#1638)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-13 10:07:17 +02:00
Ethan Wu
7ed9f7173c
fix(lockfile): ensure newline at EOF for lockfile (#1639)
## Description

The lockfile currently does not end with a newline at EOF. Text files
should [end with a newline](https://unix.stackexchange.com/a/18789).
This also lets you manually edit the lockfile in vim without 'fixeol'
creating a spurious change for the added newline.

This change however will create a change in users' lockfiles adding a
newline upon updating, but since the lockfile would be changing anyways
to update lazy.nvim itself, this is likely acceptable.

## Related Issue(s)

*none*

## Screenshots

*N/A*
2024-07-13 09:51:44 +02:00
Folke Lemaitre
54f70c757c
ci: add luassert to minitest for now 2024-07-13 09:45:01 +02:00
github-actions[bot]
070418dca1
chore(main): release 11.11.0 (#1634)
🤖 I have created a release *beep* *boop*
---


##
[11.11.0](https://github.com/folke/lazy.nvim/compare/v11.10.4...v11.11.0)
(2024-07-11)


### Features

* add plugin name to handlers.managed
([17473db](17473db1d7))


### Bug Fixes

* **minit:** add tests to package.path when running busted (helpers.lua
etc)
([fadebdc](fadebdc76b))
* **util:** strip `-lua` in normname
([54b003c](54b003c650))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-13 09:25:55 +02:00
Folke Lemaitre
1d451b4c2c
ci: use mini.test instead of busted 2024-07-11 22:32:11 +02:00
Folke Lemaitre
17473db1d7
feat: add plugin name to handlers.managed 2024-07-11 22:04:06 +02:00
Folke Lemaitre
54b003c650
fix(util): strip -lua in normname 2024-07-11 22:03:53 +02:00
github-actions[bot]
d1de92dffa chore(build): auto-generate docs 2024-07-09 15:26:28 +00:00
Folke Lemaitre
2cb8af1eb1
ci: skip docs on main 2024-07-09 17:25:41 +02:00
folke
159036c576 chore(build): auto-generate docs 2024-07-09 13:03:11 +00:00
Folke Lemaitre
fadebdc76b
fix(minit): add tests to package.path when running busted (helpers.lua etc) 2024-07-09 15:02:18 +02:00
github-actions[bot]
1870238cf9 chore(build): auto-generate docs 2024-07-08 05:53:40 +00:00
github-actions[bot]
f918318d21
chore(main): release 11.10.4 (#1628)
🤖 I have created a release *beep* *boop*
---


##
[11.10.4](https://github.com/folke/lazy.nvim/compare/v11.10.3...v11.10.4)
(2024-07-08)


### Bug Fixes

* **rocks:** try building anyway even when prerequisits have not been
met. (will likely fail)
([f0324de](f0324defdd))
* **ui:** don't treat suspended as headless. Closes
[#1626](https://github.com/folke/lazy.nvim/issues/1626)
([2dfccd7](2dfccd7b94))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-08 07:52:50 +02:00
folke
a4c473cc2d chore(build): auto-generate docs 2024-07-08 05:46:33 +00:00
Folke Lemaitre
f0324defdd
fix(rocks): try building anyway even when prerequisits have not been met. (will likely fail) 2024-07-08 07:45:45 +02:00
github-actions[bot]
0002bfbd9f chore(build): auto-generate docs 2024-07-08 05:28:57 +00:00
Folke Lemaitre
2dfccd7b94
fix(ui): don't treat suspended as headless. Closes #1626 2024-07-08 07:28:02 +02:00
folke
44cd12fa27 chore(build): auto-generate docs 2024-07-07 19:26:10 +00:00
github-actions[bot]
a6daaf68a2
chore(main): release 11.10.3 (#1625)
🤖 I have created a release *beep* *boop*
---


##
[11.10.3](https://github.com/folke/lazy.nvim/compare/v11.10.2...v11.10.3)
(2024-07-07)


### Bug Fixes

* **git:** local plugin fixes
([#1624](https://github.com/folke/lazy.nvim/issues/1624))
([72c0dc9](72c0dc9462))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-07 21:25:12 +02:00
github-actions[bot]
436d09af7d chore(build): auto-generate docs 2024-07-07 15:15:37 +00:00
github-actions[bot]
93c9a3f872 chore(build): auto-generate docs 2024-07-07 15:14:44 +00:00
Andre Toerien
72c0dc9462
fix(git): local plugin fixes (#1624)
## Description

As I described in
https://github.com/folke/lazy.nvim/pull/1512#issuecomment-2212474372,
this makes it so that local plugins will only show as needing updates if
the local branch is behind the upstream branch. This is done by checking
the output of the `git log` command, and only setting `plugin._.updates`
if the output is not empty.

This seems to solve my issue where local plugins with unpushed changes
always show as needing updates, but if there's a easier/better way of
doing it then please feel free to edit/close this. Or if you don't agree
that the current behaviour is a bug, then that's also fine - it's not a
big deal and I can easily just ignore the "updates available" notice.

I also came across a minor issue where the plugin diff view (press `d`)
compares the wrong commits for local plugins, because
[lua/lazy/view/init.lua](c771cf4928/lua/lazy/view/init.lua (L268))
always uses `get_target`. I fixed this by moving `get_local_target` into
`get_target` - I think this is simpler and more straightforward than the
alternative of adding a ternary everywhere `get_target` is called.

This second bugfix is a very small change, so I've just included it
here, but I'm happy to make a second PR if you'd like.

## Related Issue(s)

Related PR: #1512
2024-07-07 17:13:49 +02:00
folke
c771cf4928 chore(build): auto-generate docs 2024-07-07 06:46:59 +00:00
github-actions[bot]
25026d2382 chore(build): auto-generate docs 2024-07-07 06:45:25 +00:00
folke
083f3dfb5e chore(build): auto-generate docs 2024-07-07 06:45:23 +00:00
github-actions[bot]
89b264ac1d
chore(main): release 11.10.2 (#1621)
🤖 I have created a release *beep* *boop*
---


##
[11.10.2](https://github.com/folke/lazy.nvim/compare/v11.10.1...v11.10.2)
(2024-07-07)


### Bug Fixes

* **git:** only check for new commits for local plugins. Closes
[#1512](https://github.com/folke/lazy.nvim/issues/1512)
([81d2bff](81d2bfffdc))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-07 08:44:37 +02:00
github-actions[bot]
23aeb224ed chore(build): auto-generate docs 2024-07-07 06:43:02 +00:00
Folke Lemaitre
81d2bfffdc
fix(git): only check for new commits for local plugins. Closes #1512 2024-07-07 08:42:21 +02:00
folke
933f0b596c chore(build): auto-generate docs 2024-07-06 21:46:26 +00:00
Folke Lemaitre
55b46b3993
ci: update 2024-07-06 23:45:30 +02:00
Folke Lemaitre
23ea80b6a3
ci: update 2024-07-06 23:19:48 +02:00
Folke Lemaitre
e6035dc59b
ci: update 2024-07-06 23:18:28 +02:00
github-actions[bot]
0ff7e83c17 chore(build): auto-generate docs 2024-07-06 16:05:52 +00:00
folke
1e7745a4a0 chore(build): auto-generate docs 2024-07-06 16:05:47 +00:00
github-actions[bot]
49a35d3c8c
chore(update): update repository (#1618)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-06 18:05:10 +02:00
github-actions[bot]
16ccd54360 chore(build): auto-generate docs 2024-07-06 13:01:02 +00:00
github-actions[bot]
c060de160a
chore(update): update repository (#1616)
Automated changes by
[create-pull-request](https://github.com/peter-evans/create-pull-request)
GitHub action

Co-authored-by: folke <292349+folke@users.noreply.github.com>
2024-07-06 15:00:16 +02:00
folke
e3154ff0b7 chore(build): auto-generate docs 2024-07-06 09:48:26 +00:00
Folke Lemaitre
c3a9cec06b
ci: update 2024-07-06 11:45:24 +02:00
github-actions[bot]
d901d2166f chore(build): auto-generate docs 2024-07-05 17:03:38 +00:00
folke
94b6b67031 chore(build): auto-generate docs 2024-07-05 17:03:29 +00:00
Folke Lemaitre
538f060e42
ci: update 2024-07-05 19:02:48 +02:00
github-actions[bot]
894cd193e9 chore(build): auto-generate docs 2024-07-05 14:13:57 +00:00
folke
11e802dbaa chore(build): auto-generate docs 2024-07-05 14:13:53 +00:00
github-actions[bot]
6ca23c15f6
chore(main): release 11.10.1 (#1612)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-05 16:13:11 +02:00
github-actions[bot]
40e08f2b8a chore(build): auto-generate docs 2024-07-05 14:05:18 +00:00
Folke Lemaitre
d0c00e697a
ci: remove tests dep 2024-07-05 16:04:29 +02:00
folke
61c7156b57 chore(build): auto-generate docs 2024-07-05 14:04:23 +00:00
Folke Lemaitre
6186b3de3e
ci: add generated files to .styluaignore 2024-07-05 16:03:09 +02:00
Folke Lemaitre
53661bb38c
ci: update 2024-07-05 16:03:09 +02:00
github-actions[bot]
a1d23e80ba chore(build): auto-generate docs 2024-07-05 07:31:34 +00:00
Folke Lemaitre
baac551777
fix(lockfile): keep cond=false and enabed=false in lockfile. Fixes #1535. Fixes #1606 2024-07-05 09:01:04 +02:00
github-actions[bot]
407e65c792
chore(main): release 11.10.0 (#1609)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-04 21:01:57 +02:00
Folke Lemaitre
851b12034d
ci: use main for bootstrap 2024-07-04 18:05:36 +02:00
Folke Lemaitre
1225f1dc60
ci: dont enable local specs for minit 2024-07-04 18:00:59 +02:00
Folke Lemaitre
a17ad27435
build: better minit 2024-07-04 17:53:45 +02:00
Folke Lemaitre
923e1aa7a4
fix(plugin): local spec name 2024-07-04 16:16:39 +02:00
Folke Lemaitre
6fdd904ee4
fix(config): determine headless only during startup. Fixes #1608 2024-07-04 15:19:41 +02:00
Folke Lemaitre
0f2786bcc9
feat(profiling): merge VeryLazy stats and show startuptime in profile view 2024-07-04 15:17:10 +02:00
github-actions[bot]
cea5920abb
chore(main): release 11.9.2 (#1595)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-03 12:11:21 +02:00
github-actions[bot]
36c85945ee chore(build): auto-generate docs 2024-07-03 08:20:37 +00:00
Folke Lemaitre
d0921f5b9b
fix(health): check for errors when executing commands. Closes #1599 2024-07-02 13:43:03 +02:00
Folke Lemaitre
a9d7ade203
perf(plugin): minor optim to resolve imports a bit faster 2024-07-01 07:07:49 +02:00
Folke Lemaitre
1fad61712b
fix(async): make asyncs abortable 2024-06-30 13:35:14 +02:00
github-actions[bot]
c882227f1f
chore(main): release 11.9.1 (#1592)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-30 12:47:41 +02:00
Folke Lemaitre
2f4ac035bc
perf: suspend when tasks are active 2024-06-30 09:13:04 +02:00
Folke Lemaitre
c7ed87f9ca
perf: automatically suspend the scheduler when all threads are waiting (#1591)
* perf: automatically suspend the scheduler when all threads are waiting

* ci: fix ci

* test: cleanup
2024-06-30 08:48:03 +02:00
github-actions[bot]
0507e19289
chore(main): release 11.9.0 (#1587)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 17:01:41 +02:00
Folke Lemaitre
5e3c112cb3
feat(ui): use [[ & ]] to navigate between plugins. Fixes #1463 2024-06-29 14:23:31 +02:00
Folke Lemaitre
3772914075
fix(ui): when closing details, jump to plugin header. Closes #1338 2024-06-29 14:23:31 +02:00
github-actions[bot]
5bddef2415
chore(main): release 11.8.2 (#1586)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 13:59:37 +02:00
Folke Lemaitre
5d334b9f57
fix(ui): save/restore view right before/after rendering 2024-06-29 13:58:13 +02:00
Folke Lemaitre
a75d950b8f
fix(process): deal with process errors 2024-06-29 13:52:50 +02:00
Folke Lemaitre
332a7ff9b3
ci: auto-commit-action v5 2024-06-29 12:06:54 +02:00
Folke Lemaitre
440999fc5a
ci: fix 2024-06-29 12:03:42 +02:00
Folke Lemaitre
07ccb49ace
ci: set env for docs 2024-06-29 12:01:52 +02:00
Folke Lemaitre
09f69bae4b
ci: dispatch docs gen from main 2024-06-29 12:00:15 +02:00
Folke Lemaitre
9ab3061690
perf(rocks): vim.fn.executable is slow on WSL2, so only check for luarocks when needed. Closes #1585 2024-06-29 11:44:31 +02:00
github-actions[bot]
8dd947fccd
chore(main): release 11.8.1 (#1584)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 10:37:55 +02:00
Folke Lemaitre
3513227a9a
fix(async): remove debug assert 2024-06-29 10:36:37 +02:00
github-actions[bot]
00c23e72a3
chore(main): release 11.8.0 (#1583)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 10:20:23 +02:00
Folke Lemaitre
695a05872a
feat(plugin): allow loading specs without pkg 2024-06-29 10:18:33 +02:00
github-actions[bot]
7af8a317e2 chore(build): auto-generate docs 2024-06-29 06:29:46 +00:00
github-actions[bot]
cece2a9b4a
chore(main): release 11.7.0 (#1582)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 08:13:24 +02:00
Folke Lemaitre
88f4d13e5f
feat(minit): fallback to habamax when no colorscheme set 2024-06-29 08:11:42 +02:00
Folke Lemaitre
3078688263
ci(minit): LAZY_STDPATH 2024-06-29 08:03:37 +02:00
Folke Lemaitre
cdfea60506
build(bootstrap): added support for custom lazypath 2024-06-29 08:03:06 +02:00
Folke Lemaitre
0e106c085c
ci(minit): added repro 2024-06-29 07:46:41 +02:00
Folke Lemaitre
b1821ca2fa
ci: tests using minit 2024-06-29 07:26:55 +02:00
Folke Lemaitre
f47ab692f1
ci: allow to run busted script with nvim -u to inspect env 2024-06-29 07:26:55 +02:00
github-actions[bot]
cfdfb786b1
chore(main): release 11.6.0 (#1579)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-29 07:17:01 +02:00
Folke Lemaitre
c93eb359a3
ci: minit (minimal init) 2024-06-29 07:15:22 +02:00
Folke Lemaitre
ba1a9c5392
ci: bootstrap script 2024-06-29 07:13:37 +02:00
github-actions[bot]
a1fffe18f9 chore(build): auto-generate docs 2024-06-28 18:22:55 +00:00
Folke Lemaitre
9cf745939d
feat(task): build procs can now yield a LazyMsg for more control 2024-06-28 20:17:35 +02:00
github-actions[bot]
ec95702ae6
chore(main): release 11.5.2 (#1577)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-28 18:33:22 +02:00
Folke Lemaitre
2a6a2dce1b
fix(git): tagrefs 2024-06-28 18:31:12 +02:00
github-actions[bot]
a617d9f47b
chore(main): release 11.5.1 (#1573)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-28 17:47:04 +02:00
Folke Lemaitre
f85575ab23
perf: use timer instead of check for async executor 2024-06-28 17:44:43 +02:00
Folke Lemaitre
ab46edbd47
perf: async render 2024-06-28 17:44:21 +02:00
Folke Lemaitre
a36ebd2a75
refactor: async processes 2024-06-28 16:08:26 +02:00
Folke Lemaitre
4319846b8c
fix(rocks): lua-5.1. Closes #1575 2024-06-28 16:07:49 +02:00
Folke Lemaitre
60fe75c88d
fix(task): run on_exit async. See #1569 2024-06-28 00:35:41 +02:00
Folke Lemaitre
461552474c
refactor: cleanup 2024-06-28 00:35:40 +02:00
github-actions[bot]
37c7163f8d
chore(main): release 11.5.0 (#1565)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-27 17:34:05 +02:00
Folke Lemaitre
68cee30cdb
perf: prevent active waiting in coroutines. suspend/resume instead 2024-06-27 13:06:39 +02:00
Folke Lemaitre
79bcc02d17
ci: make simple test script 2024-06-27 12:48:50 +02:00
Folke Lemaitre
e3e431480d
feat(ui): remap gx -> K. Fixes #1561 2024-06-27 12:38:47 +02:00
Folke Lemaitre
c0fd59b020
feat(health): show steps to get luarocks working. See #1570 2024-06-27 12:31:58 +02:00
Folke Lemaitre
82276321f5
fix(rocks): if installing with luarocks (binaries) fails, then build from source. Fixes #1563 2024-06-27 11:33:11 +02:00
Folke Lemaitre
e02c5b1b57
fix(runner): only check for errors when a task is no longer running 2024-06-27 11:32:30 +02:00
Folke Lemaitre
a0391c3e21
fix(manage): dont skip install for plugins that need a build, but dont have an url (like local plugins). Fixes #1563 2024-06-27 11:32:00 +02:00
Folke Lemaitre
53f314d9e6
feat(ui): show indication of plugins that need build. See #1563 2024-06-27 11:31:20 +02:00
Folke Lemaitre
2e1167df4a
feat: added localleader-i to inspect a plugin 2024-06-27 11:30:29 +02:00
Folke Lemaitre
9c8e7a4840
feat(health): show user's lazy.nvim version in checkhealth 2024-06-27 10:44:35 +02:00
Folke Lemaitre
6a423278a1
fix(meta): resolve deps from meta instead of fragments. Fixes #1566 2024-06-27 10:21:54 +02:00
Folke Lemaitre
24a86d5ca4
fix(pkg): only show pkg changed when effectively changing a pkg file. Fixes #1567 2024-06-27 09:48:37 +02:00
Folke Lemaitre
591ded8309
feat(ui): keep cursor position when rendering view 2024-06-26 22:45:21 +02:00
Folke Lemaitre
249902ab31
fix(ui): diagnostics without status 2024-06-26 22:44:57 +02:00
Folke Lemaitre
a0a51c06c2
feat: added opts.headless to control ansi output when running headless 2024-06-26 21:38:28 +02:00
Folke Lemaitre
93b3a77286
fix(runner): wait_step 2024-06-26 20:17:32 +02:00
Folke Lemaitre
66a4170f0e
fix(runner): properly do concurrency 2024-06-26 19:58:45 +02:00
Folke Lemaitre
97f4df0824
fix(runner): only use Config.plugins when updated. Fixes #1560 2024-06-26 19:39:28 +02:00
Folke Lemaitre
804cae0a65
refactor: hererocks check 2024-06-26 19:39:28 +02:00
github-actions[bot]
20af3fcc4e
chore(main): release 11.4.2 (#1558)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-26 18:47:38 +02:00
Folke Lemaitre
56075b57c4
fix(runner): bring concurrency back 2024-06-26 18:45:40 +02:00
Folke Lemaitre
206d208018
test: fix tests 2024-06-26 18:42:52 +02:00
Folke Lemaitre
6c7ef7e27a
refactor: logging 2024-06-26 18:31:31 +02:00
Folke Lemaitre
765773a176
refactor: use new async code for runner and simplify task class 2024-06-26 17:06:56 +02:00
Folke Lemaitre
768de1ebf6
refactor: move scheduler to async 2024-06-26 15:11:31 +02:00
Folke Lemaitre
0eb46e7816
ci: use utfTerminal output for busted 2024-06-26 14:35:29 +02:00
Folke Lemaitre
9c1dd5a090
test: buse busted for running tasks 2024-06-26 14:30:55 +02:00
Folke Lemaitre
bbe136bda6
test: fix tests 2024-06-26 14:30:38 +02:00
Folke Lemaitre
0614ca6ca6
perf: tasks are now fully async 2024-06-26 14:28:53 +02:00
Folke Lemaitre
36952153ec
perf(util): improve impl of throttle 2024-06-26 14:28:22 +02:00
Folke Lemaitre
64fd346728
test: cleanup 2024-06-26 11:25:04 +02:00
Folke Lemaitre
707e2e923b
test: fix init test 2024-06-26 11:11:11 +02:00
Folke Lemaitre
90e14d1585
refactor(rocks): is_simple_build 2024-06-26 11:11:00 +02:00
Folke Lemaitre
2aa8e061f2
fix(config): dont start checker/change_detection when running headless 2024-06-26 11:10:43 +02:00
Folke Lemaitre
aa1c9572aa
fix(rocks): build.type instead of build.build_type 2024-06-26 08:50:06 +02:00
Folke Lemaitre
473361139c
fix(rockspec): dont lazy-load rock deps 2024-06-26 08:49:42 +02:00
Folke Lemaitre
d63e80bae9
test: remove debug output 2024-06-26 07:18:07 +02:00
Folke Lemaitre
e79805d706
fix(ui): don't show output when it's the same as error 2024-06-26 07:15:12 +02:00
Folke Lemaitre
28e435b7f3
fix(git): fetch commit from origin or local to check if branch was changed. See #1549 2024-06-26 07:15:12 +02:00
github-actions[bot]
6d60dc3c05 chore(build): auto-generate rockspec mappings 2024-06-26 04:22:43 +00:00
Folke Lemaitre
67e1e8e6a3
ci: added neo to rockspec patterns 2024-06-26 06:22:23 +02:00
github-actions[bot]
69041bccb7
chore(main): release 11.4.1 (#1555)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-25 22:09:17 +02:00
Folke Lemaitre
3f7368c3ac
ci: use 5.1 manifest 2024-06-25 21:53:56 +02:00
Folke Lemaitre
0d9fd636be
fix(health): show what plugins need luarocks and if none, use warnings instead of errors. See #1551 2024-06-25 21:15:51 +02:00
github-actions[bot]
9ac375653b
chore(main): release 11.4.0 (#1554)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-25 21:05:40 +02:00
Folke Lemaitre
6b8bf58ebf
feat(rocks): simple rockspecs are now fully resolved by lazy without luarocks. See #1548 2024-06-25 20:53:42 +02:00
Folke Lemaitre
be74a8a535
feat(pkg): utils to get rock to url mappings 2024-06-25 20:39:12 +02:00
Folke Lemaitre
25981e1f39
fix(meta): only tag new top-level pkg fragment as optional 2024-06-25 20:39:12 +02:00
github-actions[bot]
aff7ee8e89 chore(build): auto-generate rockspec mappings 2024-06-25 18:35:51 +00:00
Folke Lemaitre
aff65371fc
ci: add cmp to generated luarock mappings 2024-06-25 20:35:27 +02:00
github-actions[bot]
33be7ac317 chore(build): auto-generate rockspec mappings 2024-06-25 16:13:21 +00:00
Folke Lemaitre
7cda552c1c
ci: more rockspec patterns 2024-06-25 18:12:39 +02:00
Folke Lemaitre
49c0b86a6f
ci: move to _generated.lua 2024-06-25 18:07:28 +02:00
github-actions[bot]
786a3febc0 chore(build): auto-generate rockspec mappings 2024-06-25 15:48:19 +00:00
Folke Lemaitre
88911547e7
ci: fix some github urls 2024-06-25 17:48:04 +02:00
Folke Lemaitre
8abfed457c
test: fix tests 2024-06-25 17:42:48 +02:00
github-actions[bot]
bc7bfb5d36 chore(build): auto-generate rockspec mappings 2024-06-25 15:42:29 +00:00
Folke Lemaitre
b6eba0d026
ci: auto-get rockspec mappings for rock name => github short url or url 2024-06-25 17:41:16 +02:00
github-actions[bot]
2ca68f9979
chore(main): release 11.3.0 (#1543)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-25 16:21:15 +02:00
Folke Lemaitre
24c832213c
fix(meta): no need to check for old_dir when frags were not built yet. Fixes #1550 2024-06-25 15:51:40 +02:00
Folke Lemaitre
4ca3e9aa51
fix(rocks): windows 2024-06-25 15:44:13 +02:00
Folke Lemaitre
7d3f69104f
fix(rocks): better errors / warnings when something goes wrong with luarocks 2024-06-25 13:23:25 +02:00
github-actions[bot]
9005e8ede7 chore(build): auto-generate docs 2024-06-25 06:48:06 +00:00
Folke Lemaitre
45cd8d3f0f
fix(rocks): hererocks paths on windows 2024-06-25 06:40:50 +02:00
github-actions[bot]
0a5839ceea chore(build): auto-generate docs 2024-06-25 05:58:24 +00:00
Folke Lemaitre
d87da76679
feat(rocks): use hererocks to install luarocks when luarocks is not found 2024-06-25 07:55:30 +02:00
Folke Lemaitre
dea1f687fe
fix(fragments): check for empty plugin names 2024-06-25 00:31:34 +02:00
github-actions[bot]
378bfb4656
chore(main): release 11.2.1 (#1542)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-24 23:44:20 +02:00
Folke Lemaitre
62a47b921f
fix(loader): no need to check plugin.dir in auto_load 2024-06-24 23:42:53 +02:00
github-actions[bot]
9bcbbc17a7
chore(main): release 11.2.0 (#1541)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-24 21:59:16 +02:00
Folke Lemaitre
a089d43dba
feat: rewrite some known plugins to lazy specs instead of luarocks (plenary.nvim). Closes #1540 2024-06-24 21:57:34 +02:00
Folke Lemaitre
1446f6cfbb
perf: minimize meta rebuild when loading specs 2024-06-24 21:56:43 +02:00
github-actions[bot]
972baa615b chore(build): auto-generate docs 2024-06-24 18:23:56 +00:00
Folke Lemaitre
0081c95aee
style: allow false for build 2024-06-24 20:23:03 +02:00
github-actions[bot]
b6b0c4c15c
chore(main): release 11.1.0 (#1539)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-24 20:06:31 +02:00
Folke Lemaitre
ae4881d36e
fix(health): only check for luarocks when luarocks is enabled. 2024-06-24 20:03:00 +02:00
Folke Lemaitre
77edda11bf
test: fixes 2024-06-24 19:55:11 +02:00
github-actions[bot]
bd397ff1e3 chore(build): auto-generate docs 2024-06-24 17:45:13 +00:00
Folke Lemaitre
e3ee51b668
fix(health): show missing luarocks as warning 2024-06-24 19:44:22 +02:00
Folke Lemaitre
07c067a1a8
feat: make it easier to disable luarocks 2024-06-24 19:44:07 +02:00
Folke Lemaitre
105d4805ad
fix(runner): sync package specs after installing and before building 2024-06-24 19:38:33 +02:00
Folke Lemaitre
656d3d1f5b
feat: show rockspec deps in plugin details 2024-06-24 18:02:54 +02:00
Folke Lemaitre
0f45c0d062
fix(health): added luarocks check to health 2024-06-24 17:50:29 +02:00
github-actions[bot]
79c2efc8d8 chore(build): auto-generate docs 2024-06-24 15:49:09 +00:00
Folke Lemaitre
79afa96b90
style: remove pkg.versions 2024-06-24 17:47:01 +02:00
github-actions[bot]
cd3581efd1 chore(build): auto-generate docs 2024-06-24 15:42:27 +00:00
github-actions[bot]
7f52977c1d
chore(main): release 11.0.1 (#1538)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-24 17:39:01 +02:00
Folke Lemaitre
146de4e801
fix(rocks): dont trigger rebuild for luarocks when build is overriden 2024-06-24 17:36:59 +02:00
github-actions[bot]
c33b9fbf8d
chore(main): release 11.0.0 (#1537)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-24 17:16:50 +02:00
github-actions[bot]
eb26e95deb chore(build): auto-generate docs 2024-06-24 17:15:10 +02:00
Folke Lemaitre
9a6c219826 fix(rocks): only build rockspec when it has deps or an advanced build step 2024-06-24 17:15:10 +02:00
Folke Lemaitre
dbffad6f44 fix(fragments): prevent adding the same spec instance more than once 2024-06-24 17:15:10 +02:00
github-actions[bot]
fd04bc62f9 chore(build): auto-generate docs 2024-06-24 17:15:10 +02:00
Folke Lemaitre
b73c57ed9e fix(luarocks): cleanup luarocks when deleting a plugin 2024-06-24 17:15:10 +02:00
Folke Lemaitre
368747bc9a feat(build): build files and functions are now async. use coroutine.yield to interrupt and report progress 2024-06-24 17:15:10 +02:00
Folke Lemaitre
fcfd54835d feat: spec.rocks is no longer needed & added support for installing any luarock 2024-06-24 17:15:10 +02:00
github-actions[bot]
b3ee5b96f2 chore(build): auto-generate docs 2024-06-24 17:15:10 +02:00
github-actions[bot]
d4c07d062d chore(build): auto-generate docs 2024-06-24 17:15:10 +02:00
Folke Lemaitre
d498f81b8c style: wording 2024-06-24 17:15:10 +02:00
github-actions[bot]
23c2851265 chore(build): auto-generate docs 2024-06-24 17:15:10 +02:00
Folke Lemaitre
502600d3e6 docs: fix default lazy-loading comment 2024-06-24 17:15:10 +02:00
Folke Lemaitre
7b6ddbfc13 fix(pkg): automatically update pkgs when editing a pkg file 2024-06-24 17:15:10 +02:00
Folke Lemaitre
3515cb518f fix(pkg): make sure state dir exists 2024-06-24 17:15:10 +02:00
Folke Lemaitre
fd8229d6e3 fix(pkg): versioning and reload specs when pkg-cache is dirty 2024-06-24 17:15:10 +02:00
Folke Lemaitre
183f59e2e8 feat!: new docs for v11.0 2024-06-24 17:15:10 +02:00
Folke Lemaitre
4326d4b487 fix(pkg): correctly pre-load package specs and remove them when needed during resolve 2024-06-24 17:15:10 +02:00
Folke Lemaitre
ee2ca39f67 feat(meta): check for dir changes for plugins already added to the rtp 2024-06-24 17:15:10 +02:00
Folke Lemaitre
05e31ad059 docs: added comment on package source order 2024-06-24 17:15:10 +02:00
Folke Lemaitre
d2bea9eefd docs: added doc comments 2024-06-24 17:15:10 +02:00
Folke Lemaitre
c1912e2348 feat(pkg): import package specs in the scope of the plugin 2024-06-24 17:15:10 +02:00
Folke Lemaitre
75ffe56f70 feat: rewrite of spec resolving 2024-06-24 17:15:10 +02:00
Folke Lemaitre
8d35e60eeb test: fix spec tests 2024-06-24 17:15:10 +02:00
Folke Lemaitre
3be55a4615 feat: added support for plugin packages by lazy, rockspec and packspec 2024-06-24 17:15:10 +02:00
Folke Lemaitre
f1ba2e3d05 feat: luarocks support 2024-06-24 17:15:10 +02:00
Folke Lemaitre
8eba74c3fc feat: packspec 2024-06-24 17:15:10 +02:00
github-actions[bot]
4ea9fe0600
chore(main): release 10.24.3 (#1529)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-23 07:38:56 +02:00
github-actions[bot]
849890c2c4 chore(build): auto-generate vimdoc 2024-06-23 05:00:24 +00:00
Ben Elan
6994ee3751
ci(release): fix version bumping in extra-file (#1534)
* ci(release): fix version bumping in extra-file

Release Please's doc is either incorrect or they have a bug, but this
resolves the issue.

* ci(release): use manifest file
2024-06-23 06:59:54 +02:00
Folke Lemaitre
bc62078366
ci: remove deploy 2024-06-18 23:48:55 +02:00
Folke Lemaitre
acc0449d83
ci: docs deploy 2024-06-18 23:37:01 +02:00
github-actions[bot]
07269d494e chore(build): auto-generate vimdoc 2024-06-18 21:22:17 +00:00
Folke Lemaitre
1325119e85
ci: docs 2024-06-18 23:21:42 +02:00
github-actions[bot]
cd6a829343 chore(build): auto-generate vimdoc 2024-06-17 22:36:50 +00:00
Folke Lemaitre
f4d57485b0
refactor: reloader 2024-06-18 00:36:11 +02:00
Folke Lemaitre
025520d083
fix(util): dump 2024-06-18 00:35:56 +02:00
github-actions[bot]
c501b429cf
chore(main): release 10.24.2 (#1526)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-16 16:25:23 +02:00
Folke Lemaitre
b4316da731
fix(plugin): rebuild optional when needed and remove frags from parent deps. Fixes #1402 2024-06-16 15:52:33 +02:00
github-actions[bot]
38d6b74b63
chore(main): release 10.24.1 (#1525)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-16 07:15:01 +02:00
github-actions[bot]
5da0245f05 chore(build): auto-generate vimdoc 2024-06-16 05:10:11 +00:00
Folke Lemaitre
be5dfba542
fix(plugin): better way of dealing with local specs. Fixes #1524 2024-06-16 07:09:33 +02:00
github-actions[bot]
4c6479e98a
chore(main): release 10.24.0 (#1522)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-15 09:54:45 +02:00
Folke Lemaitre
e2e10d9cbe
feat: find local_spec in parent directories as well. Closes #1519 2024-06-15 09:28:58 +02:00
github-actions[bot]
6944b105cb chore(build): auto-generate vimdoc 2024-06-15 07:12:11 +00:00
Folke Lemaitre
067fd41933
fix(plugin): check optional plugins again after resolving enabled. Fixes #1402 2024-06-15 09:11:36 +02:00
Folke Lemaitre
eb4957442e
ci: update release please. Fixes #1504 2024-06-07 16:31:18 +02:00
dependabot[bot]
db5c465509
build(deps): bump actions/checkout from 3 to 4 (#1508)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:28:52 +02:00
dependabot[bot]
0aac19ccc7
build(deps): bump stefanzweifel/git-auto-commit-action from 4 to 5 (#1506)
Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 4 to 5.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-07 16:28:42 +02:00
Folke Lemaitre
938e195108
ci: Update dependabot.yml 2024-06-07 16:26:38 +02:00
Folke Lemaitre
034b03c803
ci: Create dependabot.yml 2024-06-07 16:23:47 +02:00
github-actions[bot]
fafe1f7c64
chore(main): release 10.23.0 (#1502)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-07 10:54:20 +02:00
github-actions[bot]
e0bc9a07e4 chore(build): auto-generate vimdoc 2024-06-07 07:03:28 +00:00
Folke Lemaitre
1f7b720cff
feat(plugin): opts_extend can be a list of dotted keys that will be extended instead of merged 2024-06-07 09:02:52 +02:00
Folke Lemaitre
89ddc59d19
Revert "feat(util): opts merging now supports lists extending by tagging a table with __extend = true. Use with care"
This reverts commit 74fd3611f2.
2024-06-06 23:27:29 +02:00
Folke Lemaitre
74fd3611f2
feat(util): opts merging now supports lists extending by tagging a table with __extend = true. Use with care 2024-06-06 23:23:52 +02:00
github-actions[bot]
70f2c090d3
chore(main): release 10.22.2 (#1500)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-06 12:47:53 +02:00
Folke Lemaitre
ff90417808
fix(keys): buffer-local nop mappings 2024-06-06 10:15:35 +02:00
github-actions[bot]
0c1ec520af chore(build): auto-generate vimdoc 2024-06-06 07:29:39 +00:00
Folke Lemaitre
3e4c795cec
fix(keys): never lazy-load <nop> or empty rhs keymaps 2024-06-06 09:28:35 +02:00
github-actions[bot]
0fc34a0cf5 chore(build): auto-generate vimdoc 2024-06-04 04:58:50 +00:00
Vlad
784a726f2e
style: Set vim.opt.rtp type to vim.Option (#1498)
## Details

There is an issue in the `neodev` repo that mentions this:
[#193](https://github.com/folke/neodev.nvim/issues/193)

I think the problem comes from a combination of 2 things:

1. As mentioned in the [Reddit post](https://www.reddit.com/r/neovim/comments/1cvrilk/diagnosticwarning_after_upgrade_to_neovim_010/):
   `Nvim never had Lua type annotations for vim.opt`.
2. Setting `vim.opt.rtp` anywhere in the config will cause Lua-LS to infer the
   type for `vim.opt.rtp`. While users are unlikely to do this it does happen
   in `lazy.nvim`, in places shown in this PR.
2024-06-04 06:58:19 +02:00
github-actions[bot]
ebbf84eb23 chore(build): auto-generate vimdoc 2024-06-03 07:19:16 +00:00
Zhizhen He
f39c79fcb1
style: fix some typo (#1496) 2024-06-03 09:18:43 +02:00
github-actions[bot]
b0ba3f9399
chore(main): release 10.22.1 (#1495)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-02 14:53:20 +02:00
Folke Lemaitre
9242edb739
fix: force new release 2024-06-02 14:51:46 +02:00
github-actions[bot]
1418f30806 chore(build): auto-generate vimdoc 2024-06-02 12:49:18 +00:00
Folke Lemaitre
58536d4c81
Revert "feat: set vim.env.LAZY to lazy root"
This reverts commit 6a141a6dbb.
2024-06-02 14:48:42 +02:00
github-actions[bot]
ad30030b6a
chore(main): release 10.22.0 (#1493)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-01 18:57:42 +02:00
github-actions[bot]
a3edeae34a chore(build): auto-generate vimdoc 2024-06-01 16:21:15 +00:00
Folke Lemaitre
6a141a6dbb
feat: set vim.env.LAZY to lazy root 2024-06-01 18:20:39 +02:00
github-actions[bot]
eab487c252
chore(main): release 10.21.2 (#1492)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-31 20:41:13 +02:00
Anshuman Medhi
b77aaa08cb
fix(ui): deduplicate plugins when selecting multiple (#1491) 2024-05-31 16:28:33 +02:00
github-actions[bot]
4a8f813d81
chore(main): release 10.21.1 (#1490)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-31 14:14:25 +02:00
github-actions[bot]
52244a0c1d chore(build): auto-generate vimdoc 2024-05-31 11:56:30 +00:00
Folke Lemaitre
917dfbe2a9
fix(view): backward compat for older Neovim versions. Fixes #1489 2024-05-31 13:55:54 +02:00
github-actions[bot]
24fa2a9708
chore(main): release 10.21.0 (#1477)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-26 16:59:48 +02:00
github-actions[bot]
a55d275eca chore(build): auto-generate vimdoc 2024-05-26 14:44:42 +00:00
Folke Lemaitre
9dde1f1bce
feat: added support for local spec files .lazy.lua 2024-05-26 16:43:52 +02:00
Christian Clason
ea7b9c3c3f
fix(render): disable underline for diagnostics (#1478)
Problem: On current Nvim nightlies, a regression in a
`vim.highlight.range()` refactor makes underlines for diagnostics at end
of line extend into the next line, leading to visual artifacts in the
update view.

Solution: Suppress underlines for diagnostics, as they are not wanted
anyway.
2024-05-26 15:21:58 +02:00
github-actions[bot]
98210e2f82 chore(build): auto-generate vimdoc 2024-05-26 08:40:48 +00:00
Anshuman Medhi
7667a73dee
feat: single-plugin keys in the lazy view in visual mode (#1476)
Applies to all plugins contained in the range
2024-05-26 10:40:08 +02:00
github-actions[bot]
8f19915175
chore(main): release 10.20.5 (#1445)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-22 00:10:58 +02:00
github-actions[bot]
8411fe9467 chore(build): auto-generate vimdoc 2024-05-21 20:11:25 +00:00
Folke Lemaitre
82cf974e09
fix(keys): properly deal with ft list for keys. Fixes #1448 2024-05-21 22:10:49 +02:00
github-actions[bot]
9895337d1f chore(build): auto-generate vimdoc 2024-05-20 19:15:40 +00:00
Folke Lemaitre
39de11a2fa
fix(keys): properly re-create buffer-local mappings. Fixes #1448 2024-05-20 21:15:04 +02:00
github-actions[bot]
0de782a6b0 chore(build): auto-generate vimdoc 2024-05-19 15:30:17 +00:00
Folke Lemaitre
56a34a825b
fix(help): get rid of any tbl_flatten or iter flatten code 2024-05-19 17:29:43 +02:00
Folke Lemaitre
5d29ffeaa0
style: favorite icon 2024-05-18 13:23:55 +02:00
github-actions[bot]
c717ab88ff chore(build): auto-generate vimdoc 2024-05-18 08:14:46 +00:00
Kevin Traver
2e04a0c02c
fix(checker): ignore dev plugins (#1384) 2024-05-18 10:14:12 +02:00
github-actions[bot]
05240b4154 chore(build): auto-generate vimdoc 2024-05-16 19:45:23 +00:00
Sebastian Lyng Johansen
d039aecddb
fix: use vim.iter():flatten():totable() over vim.tbl_flatten (#1454) 2024-05-16 21:44:51 +02:00
github-actions[bot]
e44636a433 chore(build): auto-generate vimdoc 2024-05-13 06:35:16 +00:00
Folke Lemaitre
d2a4ce22dc
fix(git): force autocrlf=false. Fixes #1055 2024-05-13 08:34:39 +02:00
github-actions[bot]
758bb5de98
chore(main): release 10.20.4 (#1400)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-05-12 10:15:14 +02:00
github-actions[bot]
1651030404 chore(build): auto-generate vimdoc 2024-05-12 07:52:52 +00:00
Markus Koller
bb0179139a
docs: clarify default config implementation (#1407) 2024-05-12 09:52:21 +02:00
Tristan Knight
2fcbcaf07a
fix(reload): strings in lua reload (#1439) 2024-05-12 09:50:06 +02:00
github-actions[bot]
76d321008f chore(build): auto-generate vimdoc 2024-05-12 07:44:06 +00:00
Folke Lemaitre
40845063a2
fix(ui): hover now opens repo url when no diff with main. Fixes #1430 2024-05-12 09:43:34 +02:00
github-actions[bot]
d3974346b6 chore(build): auto-generate vimdoc 2024-05-04 08:01:54 +00:00
Iordanis Petkakis
24234f47a2
fix(ui): add conditional nvim_get_hl_by_name for Neovim 0.8.0 (#1429) 2024-05-04 10:01:20 +02:00
github-actions[bot]
3f13f08043 chore(build): auto-generate vimdoc 2024-04-22 08:34:07 +00:00
Folke Lemaitre
481aed70cc
fix(heath): vim.uv. Fixes #1412 2024-04-22 10:33:32 +02:00
Folke Lemaitre
31ddbea7c1
fix(ui): set backdrop filetype to lazy_backdrop. Fixes #1399 2024-03-29 20:28:47 +01:00
github-actions[bot]
7a2617575a chore(build): auto-generate vimdoc 2024-03-29 07:19:12 +00:00
github-actions[bot]
bef521ac89
chore(main): release 10.20.3 (#1394)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-29 08:18:38 +01:00
Folke Lemaitre
0ccf031227
fix(ui): disable backdrop when Neovim is transparent 2024-03-28 14:52:07 +01:00
github-actions[bot]
ba58b87ed9 chore(build): auto-generate vimdoc 2024-03-28 11:16:10 +00:00
Folke Lemaitre
f61ca6ec70
docs: fix commands table. Fixes #1393 2024-03-28 12:15:31 +01:00
Folke Lemaitre
e753eb6025
ci: better docgen 2024-03-27 22:59:00 +01:00
github-actions[bot]
e888d5b64c chore(build): auto-generate vimdoc 2024-03-27 08:23:55 +00:00
Folke Lemaitre
a836600573
docs: make bootstrap work on stable and nightly. Fixes #1391 2024-03-27 09:23:19 +01:00
github-actions[bot]
65887ea871
chore(main): release 10.20.2 (#1388)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-27 08:55:21 +01:00
github-actions[bot]
b38b2257b6 chore(build): auto-generate vimdoc 2024-03-27 07:49:31 +00:00
Folke Lemaitre
eefb8974d6
fix(ui): special handling for floats closed before VimEnter. Seems that WinClosed events dont execute before that. Fixes #1390 2024-03-27 08:48:55 +01:00
Folke Lemaitre
d37a76b871
fix(ui): only enable backdrop when guicolors is set. Fixes #1387 2024-03-26 22:57:58 +01:00
github-actions[bot]
68941b7b13
chore(main): release 10.20.1 (#1386)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-26 20:32:47 +01:00
Folke Lemaitre
79e2e85934
fix(ui): properly cleanup on :quit. Fixes #1385 2024-03-26 20:31:15 +01:00
github-actions[bot]
107719d31e
chore(main): release 10.20.0 (#1382)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-26 19:54:49 +01:00
github-actions[bot]
6749a259c1 chore(build): auto-generate vimdoc 2024-03-26 18:52:53 +00:00
Folke Lemaitre
a6b74f30d5
feat(ui): backdrop for the lazy floating window. Can be disabled with opts.ui.backdrop 2024-03-26 19:52:19 +01:00
github-actions[bot]
08954f723b chore(build): auto-generate vimdoc 2024-03-24 10:30:32 +00:00
Folke Lemaitre
eade87fb83
fix(types): fixed type for version. Fixes #1381 2024-03-24 11:30:00 +01:00
github-actions[bot]
af6afefbb4
chore(main): release 10.19.0 (#1377)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 23:39:43 +01:00
Folke Lemaitre
66466a2594
feat(util): option to force system app for util.open 2024-03-22 23:35:22 +01:00
github-actions[bot]
8134f2ac04
chore(main): release 10.18.3 (#1376)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 22:51:11 +01:00
Riley Bruins
9131ea4c4a
fix(cache): vim.loop fallback (#1375) 2024-03-22 22:42:17 +01:00
github-actions[bot]
3132d7d27d
chore(main): release 10.18.2 (#1373)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 09:19:32 +01:00
William Mathewson
b6f7ef856b
fix(ui): Add "bot" to dimmed commands list (#1367)
nvim-treesitter has added a bot to automate updating parsers.
This feels similar to the other commands that are dimmed.
2024-03-22 09:18:36 +01:00
github-actions[bot]
c76cc60030
chore(main): release 10.18.1 (#1372)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 09:17:40 +01:00
Michael Braun
61dddaec58
fix: uv shim was not falling back to vim.loop (#1370) 2024-03-22 09:15:46 +01:00
github-actions[bot]
b2174810cd
chore(main): release 10.18.0 (#1369)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-22 09:01:10 +01:00
github-actions[bot]
6705a0f11f chore(build): auto-generate vimdoc 2024-03-22 07:59:10 +00:00
Folke Lemaitre
9e157df077
feat: refactor all vim.loop -> vim.uv and add a shim when needed 2024-03-22 08:58:36 +01:00
github-actions[bot]
83493db50a
chore(main): release 10.17.0 (#1292)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-03-07 17:41:58 +01:00
github-actions[bot]
a5ac16955e chore(build): auto-generate vimdoc 2024-03-07 16:35:04 +00:00
Riley Bruins
298bed190e
fix: update to new treesitter capture groups (#1294) 2024-03-07 17:34:29 +01:00
Wayne Wu
d5c58bb193
fix(ui): remove a single space character from home title (#1309)
Align home pill title spacing with other pills
2024-03-07 17:32:52 +01:00
github-actions[bot]
e1e8d2f0f6 chore(build): auto-generate vimdoc 2024-03-07 16:32:44 +00:00
TheSast
0694651fd3
feat(loader): warn when maplocalleader is changed after init (#1326)
* feat(loader): warn when maplocalleader is changed after init

* docs: default maplocalleader

---------

Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
2024-03-07 17:32:07 +01:00
Folke Lemaitre
c96fc24555
style: format 2024-03-07 17:30:37 +01:00
github-actions[bot]
5be95fe3b4 chore(build): auto-generate vimdoc 2024-03-07 16:28:22 +00:00
再生花
5aea4e7021
fix(types): fix incorrect LuaLS types (#1339) 2024-03-07 17:27:50 +01:00
github-actions[bot]
aedcd79811 chore(build): auto-generate vimdoc 2024-01-23 20:51:51 +00:00
Folke Lemaitre
670a6fec7f
fix(manage): better support for using the default colorscheme during install. See #1277 2024-01-23 21:51:13 +01:00
github-actions[bot]
28126922c9
chore(main): release 10.16.0 (#1284)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-01-21 11:43:48 +01:00
Emilia Simmons
d09084c4b1
fix(keys): fix abbreviation expansion on lazy load (#1219) 2024-01-21 11:40:46 +01:00
Folke Lemaitre
a9b9a4b3a2
fix(keys): make sure we don't delete the global mapping when executing an ft keymap. See #1241 2024-01-21 11:10:29 +01:00
github-actions[bot]
ababf0dab5 chore(build): auto-generate vimdoc 2024-01-21 09:50:53 +00:00
star-szr
7ded44ce2a
feat(ui): add style to dimmed commits (#1210) 2024-01-21 10:50:23 +01:00
github-actions[bot]
17d9c93943 chore(build): auto-generate vimdoc 2024-01-20 14:09:14 +00:00
Tomasz Wysocki
0b507680ee
docs: fix typo in README.md (#1226)
Corrected a typo in Migration Guide section of the README file.

Co-authored-by: Tomasz Wysocki <twysocki5@gmail.com>
2024-01-20 15:08:38 +01:00
Johnny Horvi
89e6840d8b
docs: fix typo (#1230) 2024-01-20 15:08:08 +01:00
Piotr Król
d0d410bc22
fix(git): comment sign detection in get_config function (#1281)
- Modify the condition in the get_config function to correctly ignore
  comments and blank lines.
- Update the regular expression to exclude lines starting with '#' or
  ';'.
- This change ensures that only valid key-value pairs are added to the
  configuration table.
2024-01-20 15:05:26 +01:00
Folke Lemaitre
1b3df6c007
fix(health): dont warn on submodules. Fixes #1174 2024-01-20 14:49:47 +01:00
github-actions[bot]
3e0c0a05bd chore(build): auto-generate vimdoc 2024-01-20 13:19:39 +00:00
atusy
a6f782adc1
feat(plugin): dev.path can now be a function (#1157)
In some case, `dev.path .. plugin.name` is not enoguh.

For example, when using `ghq` to manage projects, plugin directories may
vary by onewrs of the plugins.

With this change, users can do something like below

``` lua
require("lazy").setup("plugins", {
  dev = {
    path = function(p)
      -- ghq
      local path, cnt = string.gsub(p.url, "^https://(.*)%.git$", "~/ghq/%1")
      if cnt == 1 then
        return path
      end

      -- fallback to default
      return "~/projects/" .. plugin.name
    end,
  },
})
```
2024-01-20 14:19:09 +01:00
github-actions[bot]
42694c4fda chore(build): auto-generate vimdoc 2024-01-20 13:12:10 +00:00
Folke Lemaitre
5757b551fc
fix(keys): allow global/local ft keymaps to exist at the same time. Fixes #1241 2024-01-20 14:11:32 +01:00
github-actions[bot]
747bb955c5 chore(build): auto-generate vimdoc 2024-01-19 15:10:07 +00:00
Folke Lemaitre
47d4baafcc
fix(fs): error when plugin directory to delete is not a valid directory 2024-01-19 16:09:28 +01:00
github-actions[bot]
96584866b9
chore(main): release 10.15.1 (#1166)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-11-04 11:12:07 +01:00
Riley Bruins
3674036a59
fix(ui): properly highlight breaking change commit scope (#1160) 2023-11-04 11:05:02 +01:00
github-actions[bot]
32dead0376 chore(build): auto-generate vimdoc 2023-11-04 09:14:45 +00:00
Folke Lemaitre
314193af1d
fix(build): allow build=false to skip building 2023-11-04 10:14:03 +01:00
github-actions[bot]
16603c6917
chore(main): release 10.15.0 (#1147)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-25 20:13:09 +02:00
github-actions[bot]
f82bac799c chore(build): auto-generate vimdoc 2023-10-25 18:01:37 +00:00
Serhii Karvatskyi
312e424a08
fix(loader): when reloading, clear plugin properties cache (#1153)
See #445
2023-10-25 20:00:50 +02:00
github-actions[bot]
e42fccc3cd chore(build): auto-generate vimdoc 2023-10-23 05:53:33 +00:00
Maria José Solano
4446fdb9af
feat(ui): check pinned packages that can't be updated (#1139)
* style: fix filter types

* feat: check outdated pinned plugins
2023-10-23 07:52:54 +02:00
github-actions[bot]
42fb1e89ad chore(build): auto-generate vimdoc 2023-10-22 12:25:19 +00:00
Folke Lemaitre
6b7b4c5b96
style: show full trace when debug=true 2023-10-22 14:24:33 +02:00
github-actions[bot]
9788a19ec0 chore(build): auto-generate vimdoc 2023-10-19 18:14:04 +00:00
SandeshPyakurel
71007c715f
docs: Typos fixed in CHANGELOG.md (#1140) 2023-10-19 20:13:25 +02:00
github-actions[bot]
4c75c8eeb9
chore(main): release 10.14.6 (#1130)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-17 21:52:13 +02:00
Folke Lemaitre
daab5fe280
fix(loader): dont autoload when lazy handlers have not been setup yet. Fixes #1132 2023-10-17 17:44:14 +02:00
Folke Lemaitre
c059eece0c
refactor: Handler.load => Handler.resolve 2023-10-17 17:43:37 +02:00
Folke Lemaitre
03419f3e5f
fix(cmd): shedule error message instead of showing directly 2023-10-17 16:52:32 +02:00
Folke Lemaitre
7613ab2abb
fix(ui): running tasks are now less twitchy 2023-10-17 10:30:23 +02:00
github-actions[bot]
c7298a10db
chore(main): release 10.14.5 (#1129)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-17 10:04:13 +02:00
github-actions[bot]
c373663b49 chore(build): auto-generate vimdoc 2023-10-17 06:36:51 +00:00
Folke Lemaitre
cdfa788881
fix(loader): fixed event check in reload. Fixes #1124 2023-10-17 08:36:11 +02:00
github-actions[bot]
f73986546c
chore(main): release 10.14.4 (#1128)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-17 00:33:20 +02:00
Folke Lemaitre
fb9795e49f
fix(ui): fixed keymaps in debug view 2023-10-17 00:29:13 +02:00
github-actions[bot]
3049575bd8
chore(main): release 10.14.3 (#1127)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-16 23:09:07 +02:00
Folke Lemaitre
c1b9887373
perf(plugin): cache lazy handler values 2023-10-16 23:04:57 +02:00
Folke Lemaitre
2f169e74d4
refactor(handlers): lazy resolving of plugin handlers (#1126)
* refactor(handlers): lazy resolving of plugin handlers

* test: fixed tests
2023-10-16 22:34:44 +02:00
github-actions[bot]
b9c604e839
chore(main): release 10.14.2 (#1125)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-16 18:18:42 +02:00
Folke Lemaitre
2270bbbc48
fix(plugin): work-around for Plugin.values error. Will add proper fix later. Fixes #1124 2023-10-16 18:11:02 +02:00
github-actions[bot]
239f0fa9c1
chore(main): release 10.14.1 (#1123)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-16 15:30:19 +02:00
github-actions[bot]
24a93426c4 chore(build): auto-generate vimdoc 2023-10-16 13:12:01 +00:00
Folke Lemaitre
1ea2eaefa6
test: fixed tests for plugin spec 2023-10-16 15:11:01 +02:00
Folke Lemaitre
1cfd6d1f36
fix(loader): don't load handlers before installing plugins 2023-10-16 15:05:16 +02:00
github-actions[bot]
ed6c9ffe21
chore(main): release 10.14.0 (#1120)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-15 22:24:48 +02:00
github-actions[bot]
c5598617da chore(build): auto-generate vimdoc 2023-10-15 06:53:52 +00:00
Folke Lemaitre
c8e2091e6d
fix(plugin): dont allow dir changes when we already loaded files from the plugin's old dir. Show an error in this case. Fixes #993 2023-10-15 08:51:54 +02:00
Folke Lemaitre
3dc413d6fd
fix(plugin): improved dir/dev merging. Fixes #993 2023-10-15 08:36:15 +02:00
Folke Lemaitre
0c53d4673f
feat(plugin): treat url changes as warnings. They will only be shown with checkhealth 2023-10-14 23:07:01 +02:00
github-actions[bot]
1c16e4236f
chore(main): release 10.13.4 (#1117)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-14 17:33:31 +02:00
Folke Lemaitre
3b31897275
fix(cmd): lazy-cmds no longer show an error for buffer-local commands 2023-10-14 17:30:26 +02:00
sibouras
a993bfd6de
docs: update git.log in readme (#1115)
* docs: update git.log in readme

* Revert "docs: update git.log in readme"

This reverts commit ff602aa987.

* update git.log in lazy.core.config
2023-10-14 17:14:45 +02:00
github-actions[bot]
a27935e0d4
chore(main): release 10.13.3 (#1116)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-14 17:02:44 +02:00
github-actions[bot]
2b8b8b020b chore(build): auto-generate vimdoc 2023-10-14 14:01:16 +00:00
Folke Lemaitre
ad5da0ae20
fix(ui): sort lazy plugin handlers 2023-10-14 16:00:30 +02:00
github-actions[bot]
276e572f64
chore(main): release 10.13.2 (#1110)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-13 13:17:52 +02:00
github-actions[bot]
8d712c8e5d chore(build): auto-generate vimdoc 2023-10-13 11:15:19 +00:00
Folke Lemaitre
9f5637f1d7
docs: another LazyKeys reference. Fixes #1109 2023-10-13 13:14:40 +02:00
github-actions[bot]
8a6379eddd chore(build): auto-generate vimdoc 2023-10-13 10:38:26 +00:00
Folke Lemaitre
a026f73953
docs: fix types for keys. Fixes #1109 2023-10-13 12:37:43 +02:00
github-actions[bot]
e15dfab3c3 chore(build): auto-generate vimdoc 2023-10-13 09:38:43 +00:00
Folke Lemaitre
70f764bf73
fix(util): Util.merge now skips nil args 2023-10-13 11:37:57 +02:00
Folke Lemaitre
3769461194
fix(float): disable swapfile for files shown in Float 2023-10-13 11:37:38 +02:00
github-actions[bot]
33c447b96e
chore(main): release 10.13.1 (#1108)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-12 12:40:23 +02:00
Folke Lemaitre
7f70dd1749
fix(git): unset GIT_INDEX_FILE so we dont accidentally overwrite a different git repo. Fixes #1107 2023-10-12 12:23:42 +02:00
github-actions[bot]
117556d9e7
chore(main): release 10.13.0 (#1106)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-12 11:40:26 +02:00
github-actions[bot]
84ae36f30d chore(build): auto-generate vimdoc 2023-10-12 05:19:35 +00:00
Maria José Solano
43c284a578
feat(keys): include custom keys in help menu (#1105) 2023-10-12 07:18:53 +02:00
github-actions[bot]
906ff8e569
chore(main): release 10.12.0 (#1102)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-11 15:00:30 +02:00
github-actions[bot]
9ca9a63be5 chore(build): auto-generate vimdoc 2023-10-11 12:26:07 +00:00
Folke Lemaitre
99ee284739
fix(ui): use actual handler values for rendering plugin handlers 2023-10-11 14:25:12 +02:00
Folke Lemaitre
b65d308662
feat(event): custom lazy event hook for distros 2023-10-11 14:25:12 +02:00
Folke Lemaitre
303a3ed6a8
feat(event): added support for structured events (see readme on event) 2023-10-11 14:25:12 +02:00
github-actions[bot]
73fbf5ccab
chore(main): release 10.11.0 (#1101)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-10 19:52:13 +02:00
github-actions[bot]
2947f104e1 chore(build): auto-generate vimdoc 2023-10-10 17:13:22 +00:00
Folke Lemaitre
7b84609a06
feat(util): expose pretty stacktraces for notify 2023-10-10 19:12:35 +02:00
Folke Lemaitre
cb3a0555b9
docs: format table 2023-10-10 19:12:07 +02:00
github-actions[bot]
1a47d3b2aa chore(build): auto-generate vimdoc 2023-10-10 16:59:52 +00:00
Artyom Andreev
a617db7e79
docs: icon for require without nerd font (#1100) 2023-10-10 18:59:13 +02:00
github-actions[bot]
84d13c1d7e
chore(main): release 10.10.0 (#1098)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-10 16:15:05 +02:00
Folke Lemaitre
58e5726592
feat(git): show help on how to remove local changes 2023-10-10 11:53:00 +02:00
Folke Lemaitre
92869d0928
fix(process): make sure cwd is a valid directory 2023-10-10 11:52:45 +02:00
Folke Lemaitre
736529d097
fix(git): automatically restore doc/tags when modified 2023-10-10 11:42:01 +02:00
Folke Lemaitre
43e9165994
feat(git): show error for local changes during check/update 2023-10-10 11:42:01 +02:00
github-actions[bot]
067544c74a chore(build): auto-generate vimdoc 2023-10-10 07:31:52 +00:00
0xAdk
89581ce37e
fix(docs): broken table in readme (#1097) 2023-10-10 09:31:06 +02:00
github-actions[bot]
0d9989d46c
chore(main): release 10.9.1 (#1096)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-09 23:45:04 +02:00
Folke Lemaitre
2782f8125e
fix(profiling): ensure proper traces in case of require errors 2023-10-09 23:42:07 +02:00
KANATSU Minoru
5579d72576
fix(manage): prevend auto conversion 'CRLF' to 'LF' in update lazy-lock.json on Windows. Fixes #1093 (#1094) 2023-10-09 16:17:42 +02:00
github-actions[bot]
41d3b2a9db
chore(main): release 10.9.0 (#1092)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-09 12:43:14 +02:00
github-actions[bot]
336bbbebcb chore(build): auto-generate vimdoc 2023-10-09 10:39:27 +00:00
Folke Lemaitre
423a152e94
feat(profiling): added options to enable additional profiling 2023-10-09 12:38:43 +02:00
github-actions[bot]
ce3e8523de chore(build): auto-generate vimdoc 2023-10-09 09:26:35 +00:00
Folke Lemaitre
22bf6ae04b
style: sort requires 2023-10-09 11:25:42 +02:00
Folke Lemaitre
f0cfbf9952
perf: lazy require commands 2023-10-08 20:22:04 +02:00
github-actions[bot]
0a07fa6cd7
chore(main): release 10.8.2 (#1091)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-08 19:32:24 +02:00
Folke Lemaitre
9d92e65fd1
fix(keys): fixed adding managed keys 2023-10-08 19:14:33 +02:00
github-actions[bot]
9102d051a8
chore(main): release 10.8.1 (#1090)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-08 12:57:44 +02:00
Folke Lemaitre
26762c97e6
fix(ui): use correct keymap for display. Fixes #1089 2023-10-08 12:36:21 +02:00
github-actions[bot]
4b5b03f603
chore(main): release 10.8.0 (#1088)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-08 10:13:01 +02:00
github-actions[bot]
cd7493da78 chore(build): auto-generate vimdoc 2023-10-08 08:12:09 +00:00
Folke Lemaitre
b79099cc9d
feat(keys): refactor code and allow disabling keymaps per mode. mode no longer needs to be exactly the same in order to disable. 2023-10-08 10:11:33 +02:00
github-actions[bot]
62745a7320
chore(main): release 10.7.3 (#1087)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-07 20:45:37 +02:00
Folke Lemaitre
09e30f88cd
fix(keys): fixed buffer-local mappings 2023-10-07 20:41:06 +02:00
github-actions[bot]
5aaafcb301
chore(main): release 10.7.2 (#1086)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-07 11:44:13 +02:00
Folke Lemaitre
8871602e54
fix(event): move all ft logic to the event handler 2023-10-07 11:15:14 +02:00
github-actions[bot]
f2132946c7 chore(build): auto-generate vimdoc 2023-10-07 07:49:38 +00:00
Folke Lemaitre
e4ea874e33
fix(ft): fix ft handlers to properly use new events. Fixes #1084 2023-10-07 09:48:53 +02:00
github-actions[bot]
6687afae42
chore(main): release 10.7.1 (#1083)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-06 20:22:13 +02:00
Folke Lemaitre
6b37927be9
fix(event): prevent loading event handler more than once in some cases 2023-10-06 19:42:21 +02:00
github-actions[bot]
25f6009087
chore(main): release 10.7.0 (#1081)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-06 15:53:37 +02:00
Folke Lemaitre
2b2adb9d4d
fix(event): use tbl_contains instead of list_contains 2023-10-06 15:48:41 +02:00
abeldekat
58e954a735
feat(plugin): added support for cond for imports (#1079)
Co-authored-by: abeldekat <abel@nomail.com>
2023-10-06 15:46:46 +02:00
github-actions[bot]
acda8d29ca chore(build): auto-generate vimdoc 2023-10-06 13:41:21 +00:00
Folke Lemaitre
ef2a5d0bd1
fix(event): better dealing with even handlers. Fixes #788 2023-10-06 15:39:18 +02:00
github-actions[bot]
6b6f0a4512
chore(main): release 10.6.0 (#1078)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-05 16:05:05 +02:00
github-actions[bot]
d9509b56ce chore(build): auto-generate vimdoc 2023-10-05 12:01:02 +00:00
Folke Lemaitre
c42e63c198
feat(keys): you can now create buffer-local filetype keymaps by specifying ft=. Fixes #1076 2023-10-05 14:00:11 +02:00
Folke Lemaitre
19d1b3aa72
style: lua annotations 2023-10-05 14:00:11 +02:00
github-actions[bot]
64cb9b16f6
chore(main): release 10.5.1 (#1071)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-04 21:15:11 +02:00
Folke Lemaitre
82da5a0048
refactor(plugin): refactored rebuild 2023-10-04 12:50:48 +02:00
github-actions[bot]
d8453bc137 chore(build): auto-generate vimdoc 2023-10-04 09:49:03 +00:00
Folke Lemaitre
638c8e6382
fix(plugin): rebuild plugins after fixing optional and cond to ensure enabled will work correctly 2023-10-04 11:48:14 +02:00
github-actions[bot]
28a80136b5
chore(main): release 10.5.0 (#1069)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-10-04 00:30:12 +02:00
github-actions[bot]
f4ed421453 chore(build): auto-generate vimdoc 2023-10-03 22:20:59 +00:00
Folke Lemaitre
8eb8de29af
feat(plugin): keep track of the module a spec fragment was defined in 2023-10-04 00:20:08 +02:00
Folke Lemaitre
8b73492249
perf(util): don't try to load nvim-treesitter when markdown parser is builtin 2023-10-04 00:19:29 +02:00
github-actions[bot]
59335c5b9d
chore(main): release 10.4.1 (#1062)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-30 18:08:27 +02:00
github-actions[bot]
1605df75ad chore(build): auto-generate vimdoc 2023-09-30 16:02:55 +00:00
Folke Lemaitre
09e5010741
fix(plugin): prevent recursive loop with cond=false. Fixes #1061 2023-09-30 18:02:07 +02:00
Folke Lemaitre
6a2c47e642
style: lua annotations 2023-09-29 16:37:55 +02:00
github-actions[bot]
753c391b44
chore(main): release 10.4.0 (#1054)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-29 16:14:01 +02:00
github-actions[bot]
7bf6a27458 chore(build): auto-generate vimdoc 2023-09-29 14:12:39 +00:00
Folke Lemaitre
f3c7169dd6
feat(plugin): dont include plugin spec fragments for disabled or optional plugins (#1058)
* feat(plugin): dont include plugin spec fragments for disabled or optional plugins

* test: fixed tests

* fix(plugin): calculate handlers after disabling plugins

* fix(plugin): clear Plugin._.super when rebuilding

* fix(ui): dont process handlers for disabled plugins

* test: added tests for disabling fragments

* fix(plugin): ignore any installed deps of a disabled conditional plugin. Fixes #1053
2023-09-29 16:11:56 +02:00
github-actions[bot]
6b55e4695a chore(build): auto-generate vimdoc 2023-09-28 10:28:53 +00:00
Folke Lemaitre
54ecfc7c24
fix(help): sort readme tags case sensitive. Fixes #67 2023-09-28 12:28:07 +02:00
Folke Lemaitre
4f27fc33c4
fix(ui): sort plugins case insensitive 2023-09-28 12:28:07 +02:00
github-actions[bot]
7ca3bdb566
chore(main): release 10.3.1 (#1051)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-09-27 14:48:20 +02:00
Maria José Solano
0e1d264ab6
fix: return true when opening diff (#970) 2023-09-27 12:51:11 +02:00
Mike
cc24fc0e85
docs: fix spec opts in README (#1030) 2023-09-27 12:49:20 +02:00
github-actions[bot]
fe9f93692e chore(build): auto-generate vimdoc 2023-09-27 10:40:28 +00:00
Folke Lemaitre
24f6b6f1c7
fix: properly setup handlers when loading a plugin before startup (build) etc 2023-09-27 12:39:39 +02:00
github-actions[bot]
2a9354c7d2 chore(build): auto-generate vimdoc 2023-08-26 15:22:34 +00:00
Folke Lemaitre
d179a17fa1
docs: added link to pckr.nvim 2023-08-26 17:21:48 +02:00
github-actions[bot]
0e9c3934ab chore(build): auto-generate vimdoc 2023-08-26 14:47:56 +00:00
Darkhan
4eb3e932e5
Make commit pattern more accurate (#973)
Sometimes when hovering over updated plugins and triggering `diff`
with `d` key, I get an empty `diff` view. I traced the problem to a very
generic `commit_pattern` which currently matches any alphanumeric sequence
of 7 characters surrounded by "word boundary" / frontier patterns.
I adjusted the regex to match only `[a-z0-9] * 7` which should make this
issue appear less. I am keeping the older frontier sets `%f[%w]` and `%f[%W]`
because if I switch to `%f[a-f0-9]` and `%f[^0-9a-f]` I will be matching
strings like `zzz1234567xxx`.
2023-08-26 16:47:18 +02:00
github-actions[bot]
dac844ed61 chore(build): auto-generate vimdoc 2023-07-30 09:09:38 +00:00
Distinct Wind
a977a7ab21
docs: Fix doc missing bracket (#962) 2023-07-30 11:08:52 +02:00
github-actions[bot]
3ad55ae678
chore(main): release 10.3.0 (#948)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-22 10:23:12 +02:00
abeldekat
e7334d8db5
feat(plugins): Given an optional plugin, conditionally discard deps (#947)
* deps_of_all_optional: First, refactor the code responsible for disabling unneeded deps to be more generic

* deps_of_all_optional: Second, also disable unneeded deps from plugins marked as all optional

* deps_of_all_optional: add tests proving unneeded optional deps are now also discarded

* deps_of_all_optional: forgot return type

---------

Co-authored-by: abeldekat <abel@nomail.com>
2023-07-22 10:20:52 +02:00
github-actions[bot]
af4d24b8d0
chore(main): release 10.2.1 (#946)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-22 09:09:46 +02:00
github-actions[bot]
54a2aa4db4 chore(build): auto-generate vimdoc 2023-07-22 06:25:12 +00:00
Folke Lemaitre
e428c5ee4b
fix(loader): getscriptinfo compat with stable. Fixes #944 2023-07-22 08:24:26 +02:00
github-actions[bot]
ed15f6b394 chore(build): auto-generate vimdoc 2023-07-21 06:15:36 +00:00
github-actions[bot]
b7303a6830
chore(main): release 10.2.0 (#939)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-21 08:14:51 +02:00
github-actions[bot]
50c365bfe9 chore(build): auto-generate vimdoc 2023-07-20 21:49:43 +00:00
Folke Lemaitre
61c43455b0
style: lua annotations 2023-07-20 23:49:02 +02:00
3719e04
84266b9f0f
feat(view): add option ui.pills. Set to false to disable the top buttons in the lazy window (#938)
* add option `ui.button`

* add option `ui.button`

* refactor: rename button to pills

---------

Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
2023-07-20 23:48:50 +02:00
github-actions[bot]
25beed5e2e chore(build): auto-generate vimdoc 2023-07-16 06:51:36 +00:00
Kasshi K
2b241f74ed
fix typo in health.lua (#933) 2023-07-16 08:50:53 +02:00
github-actions[bot]
14d76aac4b
chore(main): release 10.1.0 (#927)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-12 17:24:07 +02:00
github-actions[bot]
f6aedf1269 chore(build): auto-generate vimdoc 2023-07-12 15:22:18 +00:00
Folke Lemaitre
ea5b2e00bf
feat(loader): LazyLoad event with plugin name as data field. Useful to do stuff when a plugin loads 2023-07-12 17:21:32 +02:00
github-actions[bot]
da8b00581a
chore(main): release 10.0.2 (#923)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-09 09:46:59 +02:00
github-actions[bot]
8ae6cb4b44 chore(build): auto-generate vimdoc 2023-07-09 07:44:55 +00:00
Folke Lemaitre
fd94e69ceb
fix(event): pass data to event lazy loaders. Fixes #922 2023-07-09 09:44:08 +02:00
github-actions[bot]
5af331ea65
chore(main): release 10.0.1 (#919)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-06 20:44:00 +02:00
yangbinji
867528c0fe
style(cache): fix comment case typo (#915) 2023-07-06 16:30:54 +02:00
Pierre-Antoine Lacaze
5082cd56e4
fix(stats): corrected typo in cputime() for Linux (#916) 2023-07-06 16:19:08 +02:00
github-actions[bot]
29f8e3ecb7
chore(main): release 10.0.0 (#918)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-06 15:40:23 +02:00
github-actions[bot]
c27cd36e6c chore(build): auto-generate vimdoc 2023-07-06 13:39:12 +00:00
Folke Lemaitre
045f23eb35
test: fixed tests 2023-07-06 15:38:21 +02:00
Folke Lemaitre
fbb0bea2db
feat(plugin)!: cond is now the same as enabled, but skips clean 2023-07-06 15:30:01 +02:00
github-actions[bot]
f8611632d0 chore(build): auto-generate vimdoc 2023-07-01 06:51:58 +00:00
github-actions[bot]
0d61488b89
chore(main): release 9.25.1 (#904)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-07-01 08:51:17 +02:00
github-actions[bot]
d65d5441d9 chore(build): auto-generate vimdoc 2023-06-30 19:20:17 +00:00
Folke Lemaitre
189371c8d8
fix(build): allow build command to override plugin's build and option to disable warning 2023-06-30 21:19:33 +02:00
github-actions[bot]
de0a911ad9
chore(main): release 9.25.0 (#898)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-30 18:30:15 +02:00
github-actions[bot]
d54ae0b96d chore(build): auto-generate vimdoc 2023-06-30 16:29:13 +00:00
Folke Lemaitre
2ea3c54b5f
docs: added docs about new build.lua 2023-06-30 18:28:29 +02:00
Folke Lemaitre
4c26421785
feat(build): added support for build.lua, build/init.lua (#903) 2023-06-30 18:22:39 +02:00
github-actions[bot]
2772cc587e chore(build): auto-generate vimdoc 2023-06-30 16:11:15 +00:00
Folke Lemaitre
d5c31f1ed7
style: lua annotations 2023-06-30 18:08:52 +02:00
github-actions[bot]
4c8b625bc8 chore(build): auto-generate vimdoc 2023-06-26 05:55:00 +00:00
Mayrixon
24803fcbe3
fix(health): false warning when checking plugins configured with 'optional' key (#897) 2023-06-26 07:54:12 +02:00
github-actions[bot]
b7043f2983
chore(main): release 9.24.2 (#890)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-22 11:17:54 +02:00
Folke Lemaitre
d7d5842d1c
fix(config): on windows default concurrency is now set to 2*available parallelism. See #887 2023-06-22 11:04:28 +02:00
Folke Lemaitre
3867a81bb2
style: better uv annotations 2023-06-22 10:47:50 +02:00
github-actions[bot]
ccd96bfa2e chore(build): auto-generate vimdoc 2023-06-22 08:24:44 +00:00
Folke Lemaitre
6c42a305b7
docs: make it clear that a plugin is loaded before build. Fixes #888 2023-06-22 10:23:54 +02:00
github-actions[bot]
c1aad95243
chore(main): release 9.24.1 (#882)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-19 11:28:26 +02:00
github-actions[bot]
bf11e4907b chore(build): auto-generate vimdoc 2023-06-19 08:22:30 +00:00
Folke Lemaitre
410a7360c1
fix(ui): trailing space in button row. Fixes #884 2023-06-19 10:21:40 +02:00
Folke Lemaitre
56b1f7715e
fix(debug): show original keymaps instead of ids for the keys handler 2023-06-19 10:21:40 +02:00
github-actions[bot]
3b0632977e chore(build): auto-generate vimdoc 2023-06-18 20:38:52 +00:00
Folke Lemaitre
616341372d
fix(manage): trigger LazySyncPre. Fixes #881 2023-06-18 22:38:05 +02:00
github-actions[bot]
67af46a7f5
chore(main): release 9.24.0 (#870)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-17 08:40:02 +02:00
github-actions[bot]
15cdefee46 chore(build): auto-generate vimdoc 2023-06-17 06:38:16 +00:00
Folke Lemaitre
0bca18de5d
feat: added Pre events. Fixes #856. Fixes #877 2023-06-17 08:37:33 +02:00
github-actions[bot]
10d4371745 chore(build): auto-generate vimdoc 2023-06-12 06:29:01 +00:00
Folke Lemaitre
7f4da7d511
fix(ui): set wo options with local. don't use vim.wo. See #829 2023-06-12 08:28:14 +02:00
github-actions[bot]
678179543e chore(build): auto-generate vimdoc 2023-06-09 10:57:36 +00:00
github-actions[bot]
6b2311a46a
chore(main): release 9.23.0 (#859)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-09 12:56:48 +02:00
github-actions[bot]
d1b02c2dda chore(build): auto-generate vimdoc 2023-06-08 15:23:54 +00:00
Folke Lemaitre
f131606190
feat(startup): added data/site to the rtp. Will be used by upcoming treesitter version 2023-06-08 17:23:02 +02:00
Folke Lemaitre
ae25448d39
Revert "fix(event): dont use autocmd pattern to detect event retriggering. Fixes #858"
This reverts commit bc89502357.
2023-06-06 15:06:24 +02:00
github-actions[bot]
27c12ff0a9 chore(build): auto-generate vimdoc 2023-06-06 12:30:22 +00:00
Folke Lemaitre
bc89502357
fix(event): dont use autocmd pattern to detect event retriggering. Fixes #858 2023-06-06 14:29:38 +02:00
github-actions[bot]
f145e6f42a
chore(main): release 9.22.2 (#854)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-03 15:39:09 +02:00
Folke Lemaitre
dbb2b609f6
fix(ui): setup colors when loading a float 2023-06-03 14:40:17 +02:00
github-actions[bot]
6ad76ecc26
chore(main): release 9.22.1 (#853)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-03 13:47:20 +02:00
Folke Lemaitre
d65a3d6755
fix(keys): replace term codes to calculate ids 2023-06-03 13:45:21 +02:00
github-actions[bot]
9223c1aa20
chore(main): release 9.22.0 (#852)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-06-03 10:55:15 +02:00
github-actions[bot]
33448b968b chore(build): auto-generate vimdoc 2023-06-03 08:46:32 +00:00
Folke Lemaitre
94472b8303
feat(float): floats can now be persistent 2023-06-03 10:45:53 +02:00
github-actions[bot]
e6bf3a0d9c chore(build): auto-generate vimdoc 2023-05-30 14:50:20 +00:00
Zach Himsel
beb5ff7f3f
docs: Add example for non-headless sync from CLI (#847) 2023-05-30 16:49:32 +02:00
github-actions[bot]
ebdd049955
chore(main): release 9.21.1 (#840)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-28 12:55:02 +02:00
Folke Lemaitre
36a91320f9
fix(loader): don't run ftdetect twice for paths already on the rtp during startup. Fixes #839 2023-05-28 11:02:40 +02:00
github-actions[bot]
b4e520579b chore(build): auto-generate vimdoc 2023-05-28 08:43:07 +00:00
Folke Lemaitre
fe9fcdb0b9
docs: added version=false 2023-05-28 10:42:23 +02:00
github-actions[bot]
a93d8983c4
chore(main): release 9.21.0 (#837)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-27 16:14:24 +02:00
Folke Lemaitre
efa02ff8d3
fix(ui): make progress bar work again 2023-05-27 16:11:01 +02:00
Folke Lemaitre
a6c8f22362
feat(commands): added highly experimental Lazy reload ... command. See #445 2023-05-27 15:19:55 +02:00
Folke Lemaitre
d8a5829fda
feat(loader): when reloading, always re-source loaded vimscript files. See #445 2023-05-27 15:19:55 +02:00
github-actions[bot]
7f34cb892b
chore(main): release 9.20.0 (#836)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-27 14:36:14 +02:00
github-actions[bot]
ae7de6b56b chore(build): auto-generate vimdoc 2023-05-27 12:28:58 +00:00
Folke Lemaitre
9dce0816f1
feat(ui): added support for setting a title of the lazy window. Fixes #814 2023-05-27 14:28:09 +02:00
github-actions[bot]
97c2f8858c
chore(main): release 9.19.1 (#835)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-27 10:03:47 +02:00
github-actions[bot]
41b64eaca2 chore(build): auto-generate vimdoc 2023-05-27 06:51:01 +00:00
Folke Lemaitre
42ff6009f6
fix(plugin): fixup. It's fine that Plugin.url doesn't exist 2023-05-27 08:49:45 +02:00
Folke Lemaitre
199e100464
fix(plugin): delay check if plugin ref exists until after loading all plugins. Fixes #833 2023-05-27 08:45:14 +02:00
github-actions[bot]
67ae8bbbe3
chore(main): release 9.19.0 (#826)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-25 09:13:34 +02:00
Folke Lemaitre
c325c50ba4
fix(plugin): check that import is a string. See #825 2023-05-25 08:26:55 +02:00
github-actions[bot]
721e37b4dd chore(build): auto-generate vimdoc 2023-05-25 06:11:00 +00:00
Folke Lemaitre
32170a8891
fix(plugin): fix url based plugin name and added extra safety checks. Fixes #824 2023-05-25 08:10:08 +02:00
Folke Lemaitre
57062f3a09
feat(plugin): trigger LazyPlugins after loading plugin specs 2023-05-25 08:09:19 +02:00
Folke Lemaitre
49a7f21ee3
feat(git): change default log args to last 8 2023-05-25 08:07:44 +02:00
github-actions[bot]
761b8388af
chore(main): release 9.18.2 (#820)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-23 09:01:50 +02:00
github-actions[bot]
72c3592e04 chore(build): auto-generate vimdoc 2023-05-23 06:58:38 +00:00
Folke Lemaitre
b0aa5348d8
docs: added docs on optional 2023-05-23 08:57:57 +02:00
github-actions[bot]
b1ad64a73e chore(build): auto-generate vimdoc 2023-05-23 06:44:18 +00:00
tzachar
f125a7d333
fix(commands): completion error (#819)
When Lazy commands are searched in command line mode, completion fails
horribly (sometime crashing nvim entirely) when the partial string to
complete contains non-escape characters.
For example, running `:Lazy up[` results in a crash.

The fix is to instruct string.find to perform a literal search, treating
the string to search not as a regular expression.
2023-05-23 08:43:27 +02:00
github-actions[bot]
6610b15dfd
chore(main): release 9.18.1 (#815)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 14:58:33 +02:00
Folke Lemaitre
9177778891
fix(plugin): rename weak => optional. Makes more sense :) 2023-05-22 14:53:36 +02:00
github-actions[bot]
8cd4a59674
chore(main): release 9.18.0 (#809)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 14:37:25 +02:00
Folke Lemaitre
af39d61d3f
fix: better weak handling 2023-05-22 14:31:28 +02:00
github-actions[bot]
cd3802a54b chore(build): auto-generate vimdoc 2023-05-22 12:25:06 +00:00
Folke Lemaitre
8564f6d22b
feat(plugin): added support for weak specs. They will not be included in the final spec if not specified somwhere else 2023-05-22 14:24:18 +02:00
github-actions[bot]
b382495d51 chore(build): auto-generate vimdoc 2023-05-21 18:52:18 +00:00
Folke Lemaitre
451f217e9b
fix(ui): take border into account for window position. Fixes #812 2023-05-21 20:51:41 +02:00
github-actions[bot]
5f316cea4f chore(build): auto-generate vimdoc 2023-05-20 07:27:08 +00:00
Folke Lemaitre
cc7a764aec
fix(ui): close ui when opening a help file. Fixes #808 2023-05-20 09:26:23 +02:00
github-actions[bot]
91564cb0a6 chore(build): auto-generate vimdoc 2023-05-19 08:24:27 +00:00
github-actions[bot]
c711b4f8a6
chore(main): release 9.17.0 (#806)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 10:23:49 +02:00
github-actions[bot]
6d4135d83d chore(build): auto-generate vimdoc 2023-05-18 17:52:02 +00:00
Folke Lemaitre
11131eafa1
feat(cmd): added Lazy load all to load all plugins 2023-05-18 19:51:18 +02:00
github-actions[bot]
53e1c49bae
chore(main): release 9.16.1 (#804)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 19:38:31 +02:00
github-actions[bot]
a4e49029b9 chore(build): auto-generate vimdoc 2023-05-17 17:36:45 +00:00
Folke Lemaitre
aecdaab6a6
fix(loader): reset cache before installing plugins during startup. Fixes #803 2023-05-17 19:36:00 +02:00
Folke Lemaitre
80c4decc32
fix(loader): dont clear tasks when istalling missing plugins 2023-05-17 19:35:16 +02:00
github-actions[bot]
aba872ec78
chore(main): release 9.16.0 (#801)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 16:12:49 +02:00
Folke Lemaitre
dab6cd5080
feat(loader): added explicit support for finding the main module for mini.nvim plugins 2023-05-13 16:10:15 +02:00
github-actions[bot]
e9b3b83914
chore(main): release 9.15.0 (#795)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 15:48:53 +02:00
github-actions[bot]
3fef769786 chore(build): auto-generate vimdoc 2023-05-13 11:25:25 +00:00
Folke Lemaitre
96dd2058fb
feat(ui): show the loaded icon for local plugins in a different color 2023-05-13 13:24:38 +02:00
github-actions[bot]
652b6febf8 chore(build): auto-generate vimdoc 2023-05-10 15:26:00 +00:00
Fraser Hanson
d2d67b5a0b
fix(config): use url_format for the lazy plugin (#792)
Co-authored-by: Fraser Hanson <fraser.hanson@netapp.com>
2023-05-10 17:20:06 +02:00
github-actions[bot]
9ac19880b6 chore(build): auto-generate vimdoc 2023-05-07 17:33:12 +00:00
github-actions[bot]
51a3873ccd
chore(main): release 9.14.11 (#782)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-07 19:32:26 +02:00
github-actions[bot]
83a625f5c8 chore(build): auto-generate vimdoc 2023-05-05 12:07:43 +00:00
Folke Lemaitre
dbe0e29d85
fix(ui): don' render extmarks for empty lines 2023-05-05 14:06:59 +02:00
github-actions[bot]
ceb413678d
chore(main): release 9.14.10 (#772)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 21:49:29 +02:00
Folke Lemaitre
98ba47efed
fix(ui): issue with rendering empty lines. Fixes #770 2023-05-02 21:47:36 +02:00
github-actions[bot]
5b7b8eecea
chore(main): release 9.14.9 (#769)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-02 21:32:16 +02:00
github-actions[bot]
5a470ae558 chore(build): auto-generate vimdoc 2023-05-02 19:31:06 +00:00
Karl Yngve Lervåg
b00d6f7102
fix(ui): don't pad empty lines (#768) 2023-05-02 21:30:28 +02:00
github-actions[bot]
bb5cc9ef3b chore(build): auto-generate vimdoc 2023-04-28 08:47:28 +00:00
github-actions[bot]
d6a782c700
chore(main): release 9.14.8 (#759)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-28 10:46:45 +02:00
github-actions[bot]
5d3d5fb31d chore(build): auto-generate vimdoc 2023-04-27 16:21:42 +00:00
Ulibos
0c7b41872e
fix(health): show error if setup didn't run
* Fix back bootstrapping and healthcheck for fresh install with no packages to fetch.

* Revert changes to bootstrapping, make checkhealth produce more meaningful message.
2023-04-27 18:21:02 +02:00
github-actions[bot]
903f0fe542
chore(main): release 9.14.7 (#745)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-24 08:41:31 +02:00
github-actions[bot]
24e8fb0f8d chore(build): auto-generate vimdoc 2023-04-24 05:55:04 +00:00
Folke Lemaitre
a758588008
fix(build): make sure to properly load handlers for plugins that were built during startup. Fixes #744 2023-04-24 07:54:21 +02:00
github-actions[bot]
a55ab60625
chore(main): release 9.14.6 (#741)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-23 16:35:26 +02:00
github-actions[bot]
f66e68c00e chore(build): auto-generate vimdoc 2023-04-23 14:00:22 +00:00
Folke Lemaitre
0cbf466913
fix(util): use vim.o.shell by default 2023-04-23 15:59:31 +02:00
github-actions[bot]
fe28f4b73e chore(build): auto-generate vimdoc 2023-04-22 12:10:51 +00:00
Folke Lemaitre
dff6f07290
style(plugins): more descriptive error when a spec module didnt return any specs 2023-04-22 14:10:06 +02:00
github-actions[bot]
5c89dc52f4
chore(main): release 9.14.5 (#738)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-19 13:14:15 +02:00
github-actions[bot]
349af24861 chore(build): auto-generate vimdoc 2023-04-19 11:00:24 +00:00
Folke Lemaitre
78b981b1f3
fix(loader): keep using the internal lua cache till 0.9.1 2023-04-19 12:59:39 +02:00
github-actions[bot]
5f13f69851
chore(main): release 9.14.4 (#734)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-18 10:21:25 +02:00
github-actions[bot]
a7f18f0192 chore(build): auto-generate vimdoc 2023-04-18 08:18:07 +00:00
Folke Lemaitre
b582fc5545
fix(cmd): show descriptive error when command was not found after loading its plugins 2023-04-18 10:17:22 +02:00
github-actions[bot]
eddee830ed
chore(main): release 9.14.3 (#728)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-16 14:15:55 +02:00
dundargoc
c8cad54895
fix(checkhealth): use non-deprecated versions if possible (#729) 2023-04-16 14:07:41 +02:00
github-actions[bot]
86c1a767f0 chore(build): auto-generate vimdoc 2023-04-16 05:40:19 +00:00
Folke Lemaitre
3c14a0a279
test: fix tests 2023-04-16 07:39:39 +02:00
futsuuu
b7a1a0fbaf
fix(render): show message if not yet committed (#707)
* fix(render): show message if not yet committed

* fix(render): show commit only if it can be shown
2023-04-15 22:54:10 +02:00
github-actions[bot]
57cce98dfd
chore(main): release 9.14.2 (#693)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-25 09:58:08 +01:00
github-actions[bot]
37c0aef4e3 chore(build): auto-generate vimdoc 2023-03-25 08:56:55 +00:00
Folke Lemaitre
9f9d733df9
fix(keys): dont add (n) to keys id 2023-03-25 09:56:16 +01:00
github-actions[bot]
32d5f4af2f
chore(main): release 9.14.1 (#691)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-24 23:08:27 +01:00
github-actions[bot]
983aad3e79 chore(build): auto-generate vimdoc 2023-03-24 20:23:03 +00:00
Folke Lemaitre
db5b67e75c
fix(cache): handle corrupted cache files 2023-03-24 21:22:13 +01:00
github-actions[bot]
a80422f217 chore(build): auto-generate vimdoc 2023-03-23 07:13:26 +00:00
github-actions[bot]
be77c59bf7
chore(main): release 9.14.0 (#684)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-23 08:12:43 +01:00
Folke Lemaitre
0e230caab9
feat(ui): added test to dimmed commits 2023-03-22 16:06:32 +01:00
github-actions[bot]
4cdc8aa8db chore(build): auto-generate vimdoc 2023-03-22 08:05:22 +00:00
luozhiya
261c2d6f95
fix(ui): show full reason for Not-Loaded (#683)
no print
2023-03-22 09:04:36 +01:00
Folke Lemaitre
690f9e88e2
refactor: prepping for vim.loader 2023-03-20 23:51:09 +01:00
github-actions[bot]
887eb75591
chore(main): release 9.13.1 (#671)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-20 08:06:14 +01:00
Andy Dirnberger
e7622b78f6
fix(health): add main key (#679) 2023-03-20 08:02:24 +01:00
github-actions[bot]
c9aeaae699 chore(build): auto-generate vimdoc 2023-03-20 07:02:15 +00:00
Folke Lemaitre
236f8517ba
fix(cache): fix loading libs on Darwin 2023-03-20 08:01:30 +01:00
github-actions[bot]
b306eb3d0f chore(build): auto-generate vimdoc 2023-03-19 19:58:05 +00:00
Folke Lemaitre
29b3bf9535
ci: update templates 2023-03-19 20:57:12 +01:00
github-actions[bot]
8456a867f7 chore(build): auto-generate vimdoc 2023-03-18 07:58:04 +00:00
Folke Lemaitre
67cc8dc07c
docs: updated docs. Fixes #667 2023-03-18 08:57:20 +01:00
github-actions[bot]
f4d53dc18a chore(build): auto-generate vimdoc 2023-03-18 07:39:22 +00:00
Will Norris
37541e57e4
docs(plugins): add example of multiple imports (#669) 2023-03-18 08:38:31 +01:00
github-actions[bot]
7d81994529 chore(build): auto-generate vimdoc 2023-03-18 07:36:54 +00:00
Folke Lemaitre
959f8c36bc
fix(health): allow overriding 1 2023-03-18 08:36:06 +01:00
github-actions[bot]
fdb41229ca
chore(main): release 9.13.0 (#664)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-17 16:44:19 +01:00
github-actions[bot]
357893a288 chore(build): auto-generate vimdoc 2023-03-17 15:18:52 +00:00
abal
e5759d202a
feat(help): allow disabling README magic (#663) 2023-03-17 16:18:02 +01:00
github-actions[bot]
b3eca0c3fb chore(build): auto-generate vimdoc 2023-03-17 07:17:33 +00:00
github-actions[bot]
e2102c3a3a
chore(main): release 9.12.1 (#660)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-17 08:16:47 +01:00
github-actions[bot]
aacaa600cf chore(build): auto-generate vimdoc 2023-03-16 22:54:54 +00:00
Folke Lemaitre
efe36bdfda
fix(cmd): properly deal with commands with nargs=? or nargs=1. Fixes #659 2023-03-16 23:54:09 +01:00
Folke Lemaitre
b4b11f48aa
style: better comments for cache.find 2023-03-16 23:53:36 +01:00
Folke Lemaitre
2e3c16e526
docs: better comments for Cache.find 2023-03-16 14:13:18 +01:00
Folke Lemaitre
6b55862d2d
refactor(cache): refactor for upstreaming to vim.loader 2023-03-15 15:10:56 +01:00
github-actions[bot]
e27c9df5fe
chore(main): release 9.12.0 (#653)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-15 09:04:59 +01:00
github-actions[bot]
6014f8de31 chore(build): auto-generate vimdoc 2023-03-15 08:01:46 +00:00
Folke Lemaitre
21a219a825
refactor(cache): revert all vim.cache changes and disable it if it would ever exist 2023-03-15 09:01:00 +01:00
Folke Lemaitre
942c805b84
fix(cache): remove dependency on jit 2023-03-15 08:53:19 +01:00
Folke Lemaitre
5b7b8c5149
feat(cache): automatically reset topmods when a user changes a file for a path on the rtp 2023-03-14 19:54:44 +01:00
Folke Lemaitre
ea1a044e3c
feat(cache): use vim.cache everywhere. poly-fill when needed 2023-03-14 19:45:22 +01:00
Folke Lemaitre
4446d69c28
build(cache): added script to sync cache implementation with Neovim 2023-03-14 18:37:27 +01:00
Folke Lemaitre
2a88a73ace
style(cache): ignore a luacheck error 2023-03-14 18:33:39 +01:00
Folke Lemaitre
810acc1e86
feat(cache): drop dependency on ffi 2023-03-14 18:33:16 +01:00
Folke Lemaitre
da295017e4
refactor(cache): Cache.track => Cache._track 2023-03-14 18:32:29 +01:00
Folke Lemaitre
0b7596f609
style(cache): disable duplicate warnings 2023-03-14 18:31:43 +01:00
Folke Lemaitre
d0db9f83ef
docs(cache): more code comments 2023-03-14 14:07:41 +01:00
Folke Lemaitre
49dda8751e
feat(cache): remove any mentions of lazy. Move the cache to cache/luac instead of cache/lazy/luac 2023-03-14 13:08:09 +01:00
Folke Lemaitre
1a34636094
refactor(cache): documented the cache in preparation to upstream 2023-03-14 12:56:58 +01:00
github-actions[bot]
5550f99271
chore(main): release 9.11.0 (#652)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-14 11:27:31 +01:00
github-actions[bot]
51c07f734f chore(build): auto-generate vimdoc 2023-03-14 10:20:47 +00:00
Folke Lemaitre
9afba388fa
feat(plugin): added config.defaults.cond. Fixes #640 2023-03-14 11:19:56 +01:00
Folke Lemaitre
10f5844abf
fix(loader): never load lua files from a plugin where cond=false. Show error instead 2023-03-14 11:19:56 +01:00
github-actions[bot]
623e00cabb
chore(main): release 9.10.3 (#646)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-13 22:56:12 +01:00
github-actions[bot]
8279309934 chore(build): auto-generate vimdoc 2023-03-13 21:51:35 +00:00
tobiaslieber
8d73b9bccd
fix(cache): path (#645) 2023-03-13 22:50:50 +01:00
github-actions[bot]
5b4444f0d7
chore(main): release 9.10.2 (#623)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-07 19:13:36 +01:00
github-actions[bot]
3efcb149cf chore(build): auto-generate vimdoc 2023-03-07 18:12:25 +00:00
Folke Lemaitre
355312eb51
fix(plugin): properly pass is_list for recursively merging props 2023-03-07 19:11:33 +01:00
github-actions[bot]
e89acede13 chore(build): auto-generate vimdoc 2023-03-06 06:41:03 +00:00
Folke Lemaitre
47fc27e3f1
style: typo. Fixes #625 2023-03-06 07:40:21 +01:00
github-actions[bot]
f9ddb2d41b chore(build): auto-generate vimdoc 2023-03-05 13:09:59 +00:00
Sean Baildon
53be2c0ee1
fix(git): always set origin name when cloning (#622)
* fix(git): force origin name

* Revert "fix(git): honor clone.defaultRemoteName. Fixes #602"

This reverts commit 5af93806aa.
2023-03-05 14:09:15 +01:00
github-actions[bot]
1407565713
chore(main): release 9.10.1 (#619)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-04 18:28:10 +01:00
github-actions[bot]
b5667ec94d chore(build): auto-generate vimdoc 2023-03-04 17:21:19 +00:00
Folke Lemaitre
c60f7ea985
fix(process): unset GIT_WORK_TREE 2023-03-04 18:20:27 +01:00
github-actions[bot]
8d18ef44e7
chore(main): release 9.10.0 (#613)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-02 14:29:16 +01:00
github-actions[bot]
2691c8f7a5 chore(build): auto-generate vimdoc 2023-03-02 13:26:43 +00:00
kylo252
1f7ffec177
feat(render): dim housekeeping commits by default (#612)
* feat(render): dim housekeeping commits by default

use `LazyComment` highlight group for commits with
housekeeping types, i.e. chore/ci/doc

* refactor: some small improvments to unimportant commits

---------

Co-authored-by: Folke Lemaitre <folke.lemaitre@gmail.com>
2023-03-02 14:25:50 +01:00
github-actions[bot]
26d121ea13
chore(main): release 9.9.0 (#601)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-28 12:59:22 +01:00
Folke Lemaitre
79f85e5fed
fix(cache): add hack to work-around incorrect requires back. Not a fan of this. Fixes #603 2023-02-28 12:38:20 +01:00
Folke Lemaitre
77223786aa
fix(git): properly deal with failed clones. Fixes #571 2023-02-28 11:51:16 +01:00
Folke Lemaitre
5af93806aa
fix(git): honor clone.defaultRemoteName. Fixes #602 2023-02-28 10:51:17 +01:00
Folke Lemaitre
0f713b2958
fix(ui): always show diagnostics virtual text 2023-02-28 09:55:21 +01:00
github-actions[bot]
25132fc08f chore(build): auto-generate vimdoc 2023-02-28 06:28:08 +00:00
adrian5
c7a8e702f7
docs: update some wording and capitalization (#576) 2023-02-28 07:27:19 +01:00
Folke Lemaitre
9bd1c946d6
feat(health): check for paths on the rtp from plugged or packer 2023-02-27 20:38:05 +01:00
Folke Lemaitre
b814d87089
style(cache): removed hack for relative paths 2023-02-27 20:25:03 +01:00
Folke Lemaitre
5694483e87
fix(health): whitelist deactivate prop 2023-02-27 13:42:59 +01:00
github-actions[bot]
8cbd95bd05 chore(build): auto-generate vimdoc 2023-02-27 09:00:46 +00:00
Folke Lemaitre
1657ae9b8c
fix(keys): set nowait for lazy keymaps when needed. Fixes #600 2023-02-27 09:59:47 +01:00
github-actions[bot]
8077428e63
chore(main): release 9.8.5 (#563)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-20 09:06:09 +01:00
github-actions[bot]
8d5553d11b chore(build): auto-generate vimdoc 2023-02-20 07:31:46 +00:00
Lucas Tavares
43496fa82c
fix(ui): disable colorcolumn on floating window (#575) 2023-02-20 08:31:03 +01:00
Folke Lemaitre
7339145a22
fix(ui): don't close on BufLeave. Fixes #561 2023-02-17 21:08:46 +01:00
github-actions[bot]
f2cc9ef6ac
chore(main): release 9.8.4 (#557)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-17 17:06:19 +01:00
Folke Lemaitre
ff76e58961
fix(spec): make sure imported specs are sorted alphabetically 2023-02-17 13:58:23 +01:00
github-actions[bot]
e5ba443416 chore(build): auto-generate vimdoc 2023-02-17 12:42:16 +00:00
Folke Lemaitre
5cfe1560c5
fix(ui): return abort key instead of <c-c> 2023-02-17 13:41:21 +01:00
github-actions[bot]
8186cc5db3
chore(main): release 9.8.3 (#549)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-16 13:29:23 +01:00
github-actions[bot]
258ee6b30d chore(build): auto-generate vimdoc 2023-02-16 11:34:49 +00:00
vanppo
6771c7e23c
fix(ui): disable folding of floating window (#550) 2023-02-16 12:33:53 +01:00
Folke Lemaitre
e916f41df2
fix(cache): hack to work around plugins trying to load relatve modules. Fixes #543 2023-02-15 18:20:02 +01:00
github-actions[bot]
4a0857cc23
chore(main): release 9.8.2 (#548)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-15 17:14:00 +01:00
github-actions[bot]
8f752bb288 chore(build): auto-generate vimdoc 2023-02-15 16:09:23 +00:00
Folke Lemaitre
9ca3222061
fix(cache): lsmod now also supports lua libs. Fixes #544 2023-02-15 17:08:36 +01:00
Folke Lemaitre
78264fb935
style: added proper types to process 2023-02-15 17:07:57 +01:00
github-actions[bot]
c249ea376b
chore(main): release 9.8.1 (#538)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-14 22:05:14 +01:00
Folke Lemaitre
6a18404b7d
fix(keys): fixed keys types. rhs can be false 2023-02-14 12:19:49 +01:00
github-actions[bot]
8aa90c3423 chore(build): auto-generate vimdoc 2023-02-14 10:01:58 +00:00
Folke Lemaitre
17a3c3acea
perf: more cache optims 2023-02-14 11:00:56 +01:00
Folke Lemaitre
6351a2e8f3
refactor: Cache.stats -> Cache.stats.find 2023-02-13 17:24:15 +01:00
Folke Lemaitre
b1f7ae68a7
perf: use modkey instead of modpath 2023-02-13 17:22:00 +01:00
github-actions[bot]
c778b7aa04
chore(main): release 9.8.0 (#520)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-13 12:07:52 +01:00
github-actions[bot]
27fdb9b468 chore(build): auto-generate vimdoc 2023-02-13 11:02:38 +00:00
Folke Lemaitre
462633bae1
perf: new file-based cache that ensures correct rtp order (#532)
* perf: new file-based cache that ensures rtp is alweays correct and will cache all files, including those after startup

* refactor: new cache

* test: fix tests

* fix(cache): cache file names on Windows

* feat(cache): allow to disable the cache

* docs: updated cache settings
2023-02-13 12:01:56 +01:00
github-actions[bot]
06f835d0b4 chore(build): auto-generate vimdoc 2023-02-12 11:57:29 +00:00
Folke Lemaitre
0d3f2c4042
feat(git): Plugin.submodules = false will now skip fetching git submodules 2023-02-12 12:56:42 +01:00
kyoh86
4917222c7e
fix(util): executable checks for Util.open (#528) 2023-02-11 09:04:59 +01:00
github-actions[bot]
b5eb07e728 chore(build): auto-generate vimdoc 2023-02-11 08:03:55 +00:00
ryuryu-ymj
bc978ca9be
fix(icons): replace an obsolete Nerd icon (#529) 2023-02-11 09:03:10 +01:00
github-actions[bot]
bab744565e chore(build): auto-generate vimdoc 2023-02-10 16:48:16 +00:00
Folke Lemaitre
c83d2aeb27
fix(loader): don't deactivate when not loaded 2023-02-10 17:47:25 +01:00
dundargoc
e28555950f
ci: fix typo. (#523) 2023-02-09 22:10:36 +01:00
Yahir Eduardo Bravo Tafur
a147110390
fix(cmd): fix Error when trigger on range defined command that doesn't support count (#519) 2023-02-09 18:02:40 +01:00
github-actions[bot]
2730814434 chore(build): auto-generate vimdoc 2023-02-09 13:45:04 +00:00
github-actions[bot]
d13fe93535
chore(main): release 9.7.0 (#505)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-09 14:44:13 +01:00
Folke Lemaitre
c734d941b4
fix(keys): feed keys instead of returning expr for Neovim 0.8.x. Fixes #511 2023-02-08 16:00:56 +01:00
Folke Lemaitre
ddaffa0715
fix(keys): replace keycodes manually 2023-02-08 09:33:38 +01:00
github-actions[bot]
382c8fac56 chore(build): auto-generate vimdoc 2023-02-08 06:33:17 +00:00
kyoh86
2451ea4e65
feat: use "wslview" instead of "xsl-open" if it exsits (#509) 2023-02-08 07:32:29 +01:00
MurdeRM3L0DY
4272d2100a
fix(keys): refactor retrigger mechanism (#428)
* fix keymap retrigger in operator mode

* remove unnecessary retrigger logic

we can just eval `"<Ignore>" .. lhs` to retrigger the mapping

* remove unused function

---------

Co-authored-by: MurdeRM3L0DY <>
2023-02-08 00:45:28 +01:00
Folke Lemaitre
57a3960faf
feat: deactivate WIP 2023-02-07 23:52:02 +01:00
Folke Lemaitre
49b43def14
fix(install): dont load the colorscheme again if a config() of the colorscheme also loads it. Fixes #488 2023-02-07 22:59:05 +01:00
github-actions[bot]
48c9b37294
chore(main): release 9.6.0 (#504)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 22:02:20 +01:00
Folke Lemaitre
3c29f196f4
feat(cmd): use cmd table instead of trying to create the cmd string. Fixes #472 2023-02-07 20:57:00 +01:00
github-actions[bot]
0dcc9071df chore(build): auto-generate vimdoc 2023-02-07 16:10:30 +00:00
github-actions[bot]
0e4017152d
chore(main): release 9.5.1 (#478)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-02-07 17:09:39 +01:00
github-actions[bot]
326556008a chore(build): auto-generate vimdoc 2023-02-06 08:25:32 +00:00
Maurice Mertens
812ffcf21c
docs: clarifies install step (#495)
Co-authored-by: Maurice Mertens <m.mertens@simplicity.ag>
2023-02-06 09:24:24 +01:00
github-actions[bot]
2e8f6e6e8f chore(build): auto-generate vimdoc 2023-02-06 08:17:59 +00:00
Folke Lemaitre
452d4eb719
fix(process): allow overriding GIT_SSH_COMMAND. Fixes #491. Fixes #492 2023-02-06 09:17:08 +01:00
Folke Lemaitre
3d2dcb2d5e
fix(log): properly check if plugin dir is a git repo before running git log 2023-02-01 08:26:20 +01:00
Folke Lemaitre
527f83cae5
fix(health): existing packages on windows. Fixes #474 2023-02-01 08:09:02 +01:00
github-actions[bot]
c83563d34a chore(build): auto-generate vimdoc 2023-02-01 07:08:28 +00:00
Folke Lemaitre
0c980312fd
fix(commands): sync with plugins list should not delete those plugins. Fixes #475 2023-02-01 08:06:48 +01:00
github-actions[bot]
15fe46a728 chore(build): auto-generate vimdoc 2023-01-25 21:34:44 +00:00
Folke Lemaitre
07fda7bb98
docs: use another bug emoji. #452 2023-01-25 22:33:50 +01:00
github-actions[bot]
b64ebb71d4 chore(build): auto-generate vimdoc 2023-01-25 08:27:21 +00:00
github-actions[bot]
9b208696e1
chore(main): release 9.5.0 (#444)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-25 09:10:46 +01:00
github-actions[bot]
a24331762c chore(build): auto-generate vimdoc 2023-01-24 22:01:59 +00:00
Folke Lemaitre
31dd419aaa
docs: updated 2023-01-24 23:01:11 +01:00
Folke Lemaitre
9b5cc1bf53
feat(health): check for git in health checks 2023-01-24 22:58:40 +01:00
github-actions[bot]
39c4770d81 chore(build): auto-generate vimdoc 2023-01-24 21:56:22 +00:00
Null Chilly
772d8888cc
feat(dev): optionally fallback to git when local plugin doesn't exist (#446)
* feat: fallback to git when local plugin isn't found

* feat(option): fallback to git when local plugin doesn't exist
2023-01-24 22:55:34 +01:00
Folke Lemaitre
809d67fcf0
ci: update actions/checkout to v3 2023-01-23 20:49:52 +01:00
github-actions[bot]
9e0b8c399f chore(build): auto-generate vimdoc 2023-01-23 18:19:49 +00:00
Folke Lemaitre
5d9d35404f
feat(util): utility method to walk over all modules in a directory 2023-01-23 19:19:00 +01:00
Folke Lemaitre
26a67e3c48
feat(config): added option to disable git filter. NOT recommended. Fixes #442 2023-01-23 19:19:00 +01:00
Folke Lemaitre
c32a6185ac
fix(checker): dont check for updates when there's tasks with errors 2023-01-23 19:19:00 +01:00
Folke Lemaitre
ed210702f5
fix(checker): dont clear tasks when running update check 2023-01-23 19:18:59 +01:00
github-actions[bot]
cab4682d22 chore(build): auto-generate vimdoc 2023-01-22 14:25:05 +00:00
Folke Lemaitre
908d71872b
docs: typo 2023-01-22 15:24:13 +01:00
Sizhe Zhao
21871f2269
docs: Fix typo in README.md (#433) 2023-01-22 15:23:26 +01:00
github-actions[bot]
7674ee6254
chore(main): release 9.4.0 (#417)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-22 15:18:43 +01:00
github-actions[bot]
fc3104c44b chore(build): auto-generate vimdoc 2023-01-22 13:31:18 +00:00
Folke Lemaitre
4008b57d88
fix(checker): make sure we show logs when only doing a fast check 2023-01-22 14:30:12 +01:00
github-actions[bot]
96d759d1cb chore(build): auto-generate vimdoc 2023-01-20 19:42:27 +00:00
Folke Lemaitre
9858001c3c
fix(git): unset GIT_DIR when spawning a process. Fixes #434 2023-01-20 20:41:36 +01:00
github-actions[bot]
75dcd5741d chore(build): auto-generate vimdoc 2023-01-19 21:09:52 +00:00
Folke Lemaitre
3f8cc2c0df
docs: generated docs 2023-01-19 22:08:58 +01:00
github-actions[bot]
4739c2d95a chore(build): auto-generate vimdoc 2023-01-19 07:46:21 +00:00
Folke Lemaitre
d6fc848067
feat: added config.ui.wrap and improved wrapping when wrap=true. Fixes #422 2023-01-19 08:45:27 +01:00
Folke Lemaitre
c389ad552b
fix(spec): dont complain about an invalid short url, when a full url is set. Fixes #421 2023-01-18 08:39:02 +01:00
Folke Lemaitre
813fc944d7
feat(checker): checker will now save last check time and only check at configured frequency even after restarting Neovim 2023-01-18 08:39:02 +01:00
github-actions[bot]
835731f102 chore(build): auto-generate vimdoc 2023-01-18 07:35:12 +00:00
Daniel M. Capella
c3a0d444f6
docs: fix indentation (#419) 2023-01-18 08:34:29 +01:00
Hans Chen
27ca918bc3
fix(render): get profile_{sort,filter} key bindings from ViewConfig (#416) 2023-01-17 22:03:23 +01:00
github-actions[bot]
4f60facf18
chore(main): release 9.3.1 (#410)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-17 14:37:11 +01:00
Folke Lemaitre
c791c0ed7d
fix: work-around for libuv issue where fs_scandir_next sometimes fails to return a file type 2023-01-17 14:35:21 +01:00
Folke Lemaitre
1b2a6f631c
perf(plugin): de-duplicate dependencies, keys, ft, event and cmd 2023-01-17 14:00:42 +01:00
Folke Lemaitre
da4e8cc245
fix(spec): dont copy dep and super state from existing plugins 2023-01-17 14:00:42 +01:00
Folke Lemaitre
baaf8ddfff
fix(spec): when overriding a spec by name that has not been imported yet, show an error when needed 2023-01-17 14:00:42 +01:00
github-actions[bot]
f95d97a91c chore(build): auto-generate vimdoc 2023-01-17 12:15:13 +00:00
Folke Lemaitre
bd37afc96e
fix(git): when a Plugin.branch is set, don't use config.defaults.version. Fixes #409 2023-01-17 13:14:25 +01:00
github-actions[bot]
c05d61d208
chore(main): release 9.3.0 (#385)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-16 22:18:55 +01:00
Folke Lemaitre
870af80c68
feat(spec): overriding keys with an rhs of false will remove the key instead 2023-01-16 21:27:55 +01:00
Folke Lemaitre
208f91b52f
feat(git): some debugging tools for git 2023-01-16 20:41:29 +01:00
Folke Lemaitre
0cbd91d2cd
feat(spec): you can now override specs using only the plugin name instead of the short url 2023-01-16 17:03:43 +01:00
Folke Lemaitre
efe72d98e6
perf(util): properly check that Neovim is exiting. Dont run VeryLazy when that's the case 2023-01-16 12:37:28 +01:00
Folke Lemaitre
e8cb863703
fix(util): rever 2023-01-16 12:33:03 +01:00
Folke Lemaitre
1e67dc0d56
perf(util): dont trigger VeryLazy autocmds when exiting 2023-01-16 12:29:19 +01:00
github-actions[bot]
02482b1ec9 chore(build): auto-generate vimdoc 2023-01-16 09:17:20 +00:00
Folke Lemaitre
fdf0332fe1
feat(keys): allow overriding a keys value to vim.NIL to not add the key 2023-01-16 10:16:35 +01:00
Folke Lemaitre
984008f7ae
refactor: add lazy.nvim with full url. Fixes #396 2023-01-15 20:04:52 +01:00
Folke Lemaitre
7160ca419e
fix(loader): load plugin opts inside a try clause to report errors 2023-01-15 20:00:12 +01:00
github-actions[bot]
9375f68dcd chore(build): auto-generate vimdoc 2023-01-15 18:57:33 +00:00
Jay Patel
1b219c1704
docs: Update plugin table config to represent how require works (#399) 2023-01-15 19:56:51 +01:00
github-actions[bot]
6ac67d46dc chore(build): auto-generate vimdoc 2023-01-15 11:02:12 +00:00
Axel Dahlberg
891cdfacde
docs: clarify config = true (#390) 2023-01-15 12:01:12 +01:00
Folke Lemaitre
666ed7bf73
fix(build): make sure rplugin.vim is loaded when doing a build. Fixes #382 2023-01-13 09:20:00 +01:00
github-actions[bot]
0d0d5870a3
chore(main): release 9.2.0 (#376)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-13 09:13:19 +01:00
hgigas
7b78ce3332
feat(commands): allow commands like Lazy ... | ... (#377)
Set bar attribute:
```
-bar	    The command can be followed by a "|" and another command.
```
2023-01-13 09:05:13 +01:00
github-actions[bot]
e2556e38c7 chore(build): auto-generate vimdoc 2023-01-13 08:02:17 +00:00
Folke Lemaitre
7b0d1a7866
fix(float): only clear diagnostics for valid buffers 2023-01-13 09:01:24 +01:00
Folke Lemaitre
b73312aa32
fix: use vim.api.nvim_exec_autocmds instead of vim.cmd[[do]] to prevent weird vim.notify behavior 2023-01-13 09:01:24 +01:00
Folke Lemaitre
81017b99e7
fix(cache): de-duplicate topmods. Fixes #349 2023-01-13 09:01:24 +01:00
github-actions[bot]
70e5e08dc1 chore(build): auto-generate vimdoc 2023-01-12 12:17:08 +00:00
Folke Lemaitre
f3695bc5be
test: fixed tests for Util.merge 2023-01-12 13:16:23 +01:00
Folke Lemaitre
3f3d9df324
test: fixed tests for Plugin.opts 2023-01-12 13:13:45 +01:00
Folke Lemaitre
784bb3c100
refactor: removed special __merge functionality 2023-01-12 13:13:30 +01:00
Folke Lemaitre
2128ca90fb
feat(spec): event, keys, ft and cmd can now also be a function that returns the values to be used 2023-01-12 13:08:43 +01:00
github-actions[bot]
bcd87a0215 chore(build): auto-generate vimdoc 2023-01-12 08:02:16 +00:00
Folke Lemaitre
3fbe4fe27a
fix(ui): open diff and others over the ui. Don't try to be smart about it. Fixes #361 2023-01-12 09:01:36 +01:00
github-actions[bot]
0741d62319
chore(main): release 9.1.3 (#374)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-11 23:13:41 +01:00
Folke Lemaitre
07fd7adb34
fix(cache): use cached chunk when specs are loading for valid plugins 2023-01-11 23:11:38 +01:00
Folke Lemaitre
e1cd9cd0ad
fix(loader): prevent loading plugins when loading specs 2023-01-11 23:08:07 +01:00
github-actions[bot]
9d494e0594
chore(main): release 9.1.2 (#362)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-11 21:45:02 +01:00
Folke Lemaitre
a64623899d
fix(ui): possible error during initial install 2023-01-11 17:13:10 +01:00
github-actions[bot]
41c7a6a6c0 chore(build): auto-generate vimdoc 2023-01-11 12:45:07 +00:00
Folke Lemaitre
74bc61ab97
fix(handlers): allow overriding handler values 2023-01-11 13:44:09 +01:00
Folke Lemaitre
3b44c3c14a
fix(ui): reset buf and win options on resize 2023-01-11 13:43:17 +01:00
Folke Lemaitre
5aca9280df
perf(util): execute VeryLazy right after UIEnter 2023-01-11 13:40:19 +01:00
Folke Lemaitre
8756c0950c
fix(ui): properly position Lazy tabs when opening another cmd. Fixes #361 2023-01-10 14:26:34 +01:00
github-actions[bot]
d2110278be
chore(main): release 9.1.1 (#360)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-10 11:21:52 +01:00
Folke Lemaitre
5faadf6398
fix(ui): get_plugin should return when ui is not showing 2023-01-10 11:19:47 +01:00
github-actions[bot]
18eb724dff
chore(main): release 9.1.0 (#352)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-10 09:40:28 +01:00
Folke Lemaitre
70b07ebad5
ci: let release-please update Config.version 2023-01-10 09:28:59 +01:00
Folke Lemaitre
ad7aafb257
fix(spec): don't import specs more than once 2023-01-10 09:28:59 +01:00
Folke Lemaitre
9fa62ea8ea
fix(cache): dont keep invalid entries in the cache (cleanup) 2023-01-10 09:28:59 +01:00
Folke Lemaitre
d3a963d51c
refactor(util): improved notify functions 2023-01-10 09:28:59 +01:00
github-actions[bot]
1f17bb79b7 chore(build): auto-generate vimdoc 2023-01-10 06:33:21 +00:00
Folke Lemaitre
b28c6b9000
feat(util): Util.merge now support advanced merging strategies. Docs coming soon 2023-01-10 07:32:28 +01:00
Folke Lemaitre
e6ee0fa610
fix(ui): keymap for building a single plugin changed from b to gb. Fixes #358 2023-01-09 20:21:31 +01:00
Folke Lemaitre
4304035ef4
feat(spec): allow git@ and http urls in Plugin[1] without url=. Fixes #357 2023-01-09 13:25:50 +01:00
Folke Lemaitre
d813c518d5
docs: improvements to readme updater 2023-01-09 13:09:16 +01:00
github-actions[bot]
1ca3f101c8 chore(build): auto-generate vimdoc 2023-01-09 07:22:56 +00:00
Folke Lemaitre
d5345910a7
docs: clarified opts/config a bit 2023-01-09 08:22:05 +01:00
github-actions[bot]
55e86f855a chore(build): auto-generate vimdoc 2023-01-09 07:06:45 +00:00
Folke Lemaitre
3a216d008d
fix(docs): auto-gen of readme stuff 2023-01-09 08:05:46 +01:00
Folke Lemaitre
a32e307981
fix(diffview): fixed parameter for showing single commit with DiffView. Fixes #304 2023-01-09 08:05:32 +01:00
Folke Lemaitre
e77be3cf3b
fix(spec): Plugin.opts is now always a table. Fixes #351 2023-01-08 18:45:40 +01:00
github-actions[bot]
ef87c24e8e
chore(main): release 9.0.0 (#350)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-08 15:18:50 +01:00
github-actions[bot]
2b1fccb817 chore(build): auto-generate vimdoc 2023-01-08 14:02:50 +00:00
Folke Lemaitre
7260a2b28b
feat(spec)!: setting a table to Plugin.config is now deprecated. Please use Plugin.opts instead. (backward compatible for now) 2023-01-08 15:01:58 +01:00
Folke Lemaitre
6a31b97e37
feat(util): better deep merging with Util.merge 2023-01-08 15:01:58 +01:00
github-actions[bot]
b178daf9dc chore(build): auto-generate vimdoc 2023-01-08 07:32:49 +00:00
Folke Lemaitre
615781aebf
feat(git): lazy now detects origin changes and will fix it on update. Fixes #346. Fixes #331 2023-01-08 08:32:03 +01:00
Folke Lemaitre
a39fa0f0ce
feat(git): added fast Git.get_origin and Git.get_config 2023-01-08 08:05:44 +01:00
github-actions[bot]
8a37547171
chore(main): release 8.1.0 (#341)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-07 22:59:05 +01:00
Folke Lemaitre
ad00eb1be2
test: fixed helper function to delete test directory 2023-01-07 22:52:49 +01:00
Folke Lemaitre
d34c85d580
fix(cache): check that modpaths still exist when finding mod root 2023-01-07 22:24:53 +01:00
github-actions[bot]
8798ccc950 chore(build): auto-generate vimdoc 2023-01-07 11:11:08 +00:00
Folke Lemaitre
735f2a280e
docs: LazyVim 2023-01-07 12:10:23 +01:00
github-actions[bot]
a1c926f87b chore(build): auto-generate vimdoc 2023-01-07 11:09:20 +00:00
Folke Lemaitre
ae12dd9686
docs: updated LazyVim links 2023-01-07 12:08:31 +01:00
Folke Lemaitre
c313249271
feat(spec): show error when loading two specs with the same name and a different url. Fixes #337 2023-01-07 09:37:03 +01:00
Folke Lemaitre
5ed89b5a0d
fix(config): properly handle uis connecting after startup 2023-01-07 09:12:59 +01:00
github-actions[bot]
457e65eec8 chore(build): auto-generate vimdoc 2023-01-07 08:02:29 +00:00
Brian Koropoff
05b55deb16
fix(config): Don't cache check for attached UIs (#340)
UIs can attach and detach from headless nvim dynamically
(indeed, this is one of its use cases).
2023-01-07 09:01:45 +01:00
github-actions[bot]
7eadaacc48
chore(main): release 8.0.0 (#329)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-06 22:13:50 +01:00
Folke Lemaitre
102bc2722e
fix(loader): source runtime files without silent. Fixes #336 2023-01-06 19:16:39 +01:00
Folke Lemaitre
4f76b431f7
refactor(util)!: require("lazy.util").open_cmd() is deprecated. See the docs 2023-01-06 11:20:08 +01:00
github-actions[bot]
317df42fcf chore(build): auto-generate vimdoc 2023-01-06 06:13:06 +00:00
Folke Lemaitre
eed1ef3c2d
feat(commands): :Lazy! load now skips cond checks when loading plugins. Fixes #330 2023-01-06 07:11:50 +01:00
Folke Lemaitre
2ef44e2dee
fix(loader): revert change that loaded /plugin after config. Fixes #328 2023-01-05 19:43:47 +01:00
Folke Lemaitre
e89e938991
refactor: split open_cmd in float_cmd and float_term 2023-01-05 17:36:01 +01:00
Folke Lemaitre
13af39b83e
refactor: easier to pass window options for floats 2023-01-05 17:01:56 +01:00
github-actions[bot]
d3b0d3e851
chore(main): release 7.12.1 (#321)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-05 14:32:13 +01:00
github-actions[bot]
caf3897841 chore(build): auto-generate vimdoc 2023-01-05 13:29:20 +00:00
Folke Lemaitre
aadc912694
docs: removed my dots in favor of LazyVim 2023-01-05 14:28:28 +01:00
Folke Lemaitre
b2dec14824
fix(cache): check full paths of cached modpaths. Fixes #324 2023-01-05 13:42:23 +01:00
github-actions[bot]
af351f69ba chore(build): auto-generate vimdoc 2023-01-05 10:31:58 +00:00
Folke Lemaitre
e4f79a42d6
fix(util): Util.try can now work without an error message 2023-01-05 11:31:13 +01:00
Folke Lemaitre
847ef091fa
style: disabled stats debug 2023-01-05 11:30:47 +01:00
Folke Lemaitre
c59c05c7a8
fix(loader): run plugin config before sourcing runtime 2023-01-04 23:17:29 +01:00
github-actions[bot]
457f0bb7ce
chore(main): release 7.12.0 (#317)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-04 22:50:23 +01:00
Folke Lemaitre
886a91c688
ci: new templates 2023-01-04 20:23:36 +01:00
Folke Lemaitre
dea43afc4a
feat(spec): allow import property on a plugin spec 2023-01-04 17:50:57 +01:00
Tsakiris Tryfon
3bde7b5ba8
fix(keys): Use vim's default value for an unset g:mapleader (#316) 2023-01-04 14:02:48 +01:00
github-actions[bot]
d5e6bdf90c
chore(main): release 7.11.0 (#312)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-04 12:44:35 +01:00
Folke Lemaitre
a7ac2ad020
feat(loader): disable plugins 2023-01-04 12:40:00 +01:00
Folke Lemaitre
09fd8fabd2
fix(loader): dont show error of missing plugins if they are disabled 2023-01-04 11:02:29 +01:00
Folke Lemaitre
81cb352fe6
feat(spec): spec merging now properly works with Plugin.enabled 2023-01-04 10:36:51 +01:00
Folke Lemaitre
bce0c6e327
perf(spec): more efficient merging of specs and added Plugin._.super 2023-01-04 09:35:00 +01:00
Folke Lemaitre
6d46a3028d
style(keys): remove debug output 2023-01-04 09:22:52 +01:00
Folke Lemaitre
b4d4e6b41b
fix(loader): move mapleader check to loader, so it can be set by spec files 2023-01-04 09:07:30 +01:00
Folke Lemaitre
2e87520826
fix(util): assume type is file when no type is returned by scandir. Fixes #306 2023-01-04 08:57:50 +01:00
Folke Lemaitre
e61b334cee
fix(diff): make diffview work again. Fixes #304 2023-01-04 08:13:51 +01:00
github-actions[bot]
62214df989 chore(build): auto-generate vimdoc 2023-01-04 06:55:41 +00:00
Folke Lemaitre
507b695753
fix(keys): only replace localleader and maplocalleader. Fixes #307, fixes #308 2023-01-04 07:54:45 +01:00
github-actions[bot]
a11a317a92
chore(main): release 7.10.0 (#281)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-04 00:32:33 +01:00
Folke Lemaitre
588caef4e9
test: fixed tests 2023-01-04 00:30:14 +01:00
Folke Lemaitre
b2673f1057
style: debug formatting 2023-01-04 00:27:31 +01:00
Folke Lemaitre
1c854d7a6d
fix(health): check for all packages on the rtp, excluding dist packs 2023-01-03 23:48:00 +01:00
Folke Lemaitre
c85f929bd9
fix(install): dont try re-installing failed missing plugins during startup. Fixes #303 2023-01-03 22:50:14 +01:00
Folke Lemaitre
1fd80159d0
fix(spec): show error when users load a plugins module called lazy 2023-01-03 22:49:04 +01:00
Folke Lemaitre
953c2791d8
fix(util): made Util.lsmod more robust. See #298 2023-01-03 22:31:18 +01:00
Folke Lemaitre
f36c7cb0dc
feat(version): allow version=false to override default version 2023-01-03 21:19:20 +01:00
Folke Lemaitre
7b9fa284f8
style: better debug 2023-01-03 16:17:15 +01:00
Folke Lemaitre
e93f50fd1b
fix(keys): operator pending mode 2023-01-03 16:16:49 +01:00
Folke Lemaitre
2e3e65b0f7
fix(keys): operator 2023-01-03 11:17:37 +01:00
Folke Lemaitre
cdb998c6fe
fix(keys): make operator pending mode work. Fixes #286 2023-01-03 11:16:15 +01:00
Folke Lemaitre
299ffdfd53
feat(ui): added section with disabled plugins 2023-01-03 10:43:10 +01:00
Folke Lemaitre
05aec48968
feat(spec): allow overriding Plugin.enabled 2023-01-03 10:34:53 +01:00
Folke Lemaitre
dc9c92a9b3
fix(git): properly compare git commits with short refs 2023-01-03 09:36:43 +01:00
github-actions[bot]
3ad6d95a30 chore(build): auto-generate vimdoc 2023-01-03 08:14:21 +00:00
Folke Lemaitre
ff1e322b4f
style: debug 2023-01-03 09:13:22 +01:00
Folke Lemaitre
e749e68b68
fix(ui): check if win is still valid 2023-01-03 09:13:11 +01:00
Folke Lemaitre
b5f4106892
fix(stats): more robust checks for native cputime 2023-01-03 09:12:51 +01:00
Folke Lemaitre
06db1ec3c6
fix(stats): fixed cputime on linux 2023-01-02 20:50:10 +01:00
Folke Lemaitre
277a2ab10b
fix(git): better errors when a branch/tag/version could not be found. Fixes #276 2023-01-02 19:01:02 +01:00
Folke Lemaitre
85173dcc4d
fix(stats): windows 2023-01-02 17:42:17 +01:00
github-actions[bot]
2ea0751a23 chore(build): auto-generate vimdoc 2023-01-02 16:21:19 +00:00
colton
e039ff6e28
docs: fix references to config.plugins (#282) 2023-01-02 17:20:32 +01:00
Folke Lemaitre
ddcdc5e447
fix(stats): use fallback for cputime on windows. Fixes #280 2023-01-02 17:11:01 +01:00
github-actions[bot]
c1a50a7fc5
chore(main): release 7.9.0 (#265)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-01-02 15:49:03 +01:00
Folke Lemaitre
ce3e1fc560
fix(plugin): only get plugin from spec when needed. 2023-01-02 15:27:01 +01:00
Folke Lemaitre
9893430187
fix(cache): dont return directories in lsmod 2023-01-02 15:08:20 +01:00
Folke Lemaitre
60e96b478a
fix(loader): always load init.lua in plugin mods 2023-01-02 15:04:32 +01:00
Folke Lemaitre
9e90852a47
fix(cache): autoloading was broken! 2023-01-02 14:50:34 +01:00
Folke Lemaitre
1ec8f08480
fix(cache): properly return two values for finddir 2023-01-02 14:46:56 +01:00
github-actions[bot]
8b6a98ad26 chore(build): auto-generate vimdoc 2023-01-02 13:36:19 +00:00
Folke Lemaitre
69121c7721
tests: fixed tests 2023-01-02 14:35:36 +01:00
Folke Lemaitre
8063523471
ci: added debug info when #topmods>1 2023-01-02 14:29:55 +01:00
Folke Lemaitre
0bc73db503
fix(cache): only autoload when plugins have been parsed. Needed to support import 2023-01-02 12:54:38 +01:00
Folke Lemaitre
f6b0172e92
fix(cache): allow lazyvim as a plugin 2023-01-02 12:54:00 +01:00
Folke Lemaitre
bc4133cb3e
feat(spec): show spec warnings in checkhealth only 2023-01-02 12:53:35 +01:00
Folke Lemaitre
d992387912
perf: track some additional cputimes 2023-01-02 11:28:18 +01:00
Folke Lemaitre
46997de1c9
feat(event): track event trigger times 2023-01-02 11:26:54 +01:00
Folke Lemaitre
50a456c189
feat(util): added trackfn that wraps a function and tracks timings 2023-01-02 11:26:40 +01:00
Folke Lemaitre
2d06faa941
feat(loader): incrementally install missing plugins and rebuild spec, so imported specs from plugins work as expected 2023-01-02 10:08:45 +01:00
Folke Lemaitre
919b7f5de3
feat(spec): added import to import other plugin modules 2023-01-02 09:44:28 +01:00
Folke Lemaitre
313015fdb4
feat(spec): allow mergig of config, priority and dependencies 2023-01-02 09:41:09 +01:00
Folke Lemaitre
7d755987ba
fix(spec): normalize deps before adding spec to make sure merging works as expected 2023-01-02 09:40:19 +01:00
Folke Lemaitre
77ff7beaa4
perf(cache): cache all lua files till UIEnter instead of VimEnter 2023-01-02 09:39:28 +01:00
Folke Lemaitre
4d77cf2efe
fix(handler): properly show errors generated by setting up handlers 2023-01-02 09:36:52 +01:00
Folke Lemaitre
6ff480bdee
fix(health): always use main spec 2023-01-01 21:09:20 +01:00
Folke Lemaitre
39b66027a5
feat(spec): added support for importing multiple spec modules with import = "foobar" 2023-01-01 21:07:05 +01:00
Folke Lemaitre
3974a6cbe3
refactor(help): replace non-word characters by - for readme filenames 2023-01-01 20:31:34 +01:00
Folke Lemaitre
51c23b661e
fix(spec): allow a spec module to be on the rtp and not only in config 2023-01-01 20:31:34 +01:00
github-actions[bot]
963e6f72a7 chore(build): auto-generate vimdoc 2023-01-01 19:24:31 +00:00
Munif Tanjim
d521a25cfc
feat(help): accept patterns for readme (#269) 2023-01-01 20:23:41 +01:00
Folke Lemaitre
11eee43c7e
fix(cache): keep ordering of topmods the same as in rtp 2023-01-01 18:52:07 +01:00
Folke Lemaitre
b23a5dc8d5
fix(loader): setup handlers after installing missing plugins. Fixes #272 2023-01-01 18:45:20 +01:00
Munif Tanjim
1edd1b8945
fix(help): properly escape helptags search pattern (#268) 2023-01-01 10:56:18 +01:00
github-actions[bot]
0a0f1b95e9 chore(build): auto-generate vimdoc 2023-01-01 08:42:34 +00:00
Folke Lemaitre
23c0587791
feat(commands): added build command to force rebuild of a plugin 2023-01-01 09:41:43 +01:00
Folke Lemaitre
205ce42cdc
fix(commands): fixed plugin completion for commands 2023-01-01 09:40:51 +01:00
Folke Lemaitre
0fadb5e1ce
feat(ui): when updating to a new version, show the version instead of the commit refs 2022-12-31 16:08:09 +01:00
Folke Lemaitre
34e2c78e06
feat(ui): show new version that is available instead of general message 2022-12-31 16:08:09 +01:00
Folke Lemaitre
a9de5910f2
fix(fetch): always fetch latest origin tags. Fixes #264 2022-12-31 16:08:09 +01:00
github-actions[bot]
3711176164
chore(main): release 7.8.0 (#263)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-31 15:40:45 +01:00
Folke Lemaitre
d6b5d6e756
feat(ui): press <c-c> to abort any running tasks. Fixes #258 2022-12-31 10:38:03 +01:00
Folke Lemaitre
ed0583e82b
fix(util): remove double forward slashes 2022-12-31 09:55:55 +01:00
github-actions[bot]
3da6c74ed3 chore(build): auto-generate vimdoc 2022-12-31 08:45:05 +00:00
Folke Lemaitre
b4edbd09f5
docs: updated bootstrap code to stable branch 2022-12-31 09:44:22 +01:00
github-actions[bot]
cba99de3eb
chore(main): release 7.7.0 (#251)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-31 09:39:47 +01:00
Folke Lemaitre
cb29427926
fix(git): always get both tag and version 2022-12-31 09:36:08 +01:00
Folke Lemaitre
865ff414c7
feat(git): added support for packed-refs. Fixes #260 2022-12-31 09:32:44 +01:00
github-actions[bot]
f656706de0 chore(build): auto-generate vimdoc 2022-12-31 07:51:48 +00:00
Folke Lemaitre
5575d2b2a9
feat(ui): show when plugin would be loaded for unloaded plugins. Fixes #261 2022-12-31 08:51:09 +01:00
github-actions[bot]
d02a10d832 chore(build): auto-generate vimdoc 2022-12-30 23:33:10 +00:00
Folke Lemaitre
d1ed91d8c7
docs: fixed code block 2022-12-31 00:32:25 +01:00
github-actions[bot]
1de5c3d059 chore(build): auto-generate vimdoc 2022-12-30 23:14:42 +00:00
Alexandre Desjardins
2c632e849f
docs: add how to accomplish packer's rtp (#259) 2022-12-31 00:13:54 +01:00
Folke Lemaitre
fb46cb5862
build: utility method to create plugin list in markdown 2022-12-30 23:58:01 +01:00
Folke Lemaitre
45d669f61c
fix(ui): only show plugins to clean under clean 2022-12-30 21:23:12 +01:00
Folke Lemaitre
a834b30c70
fix(keys): forward count to keymaps. Fixes #252 2022-12-30 20:51:18 +01:00
github-actions[bot]
a59cd089dc chore(build): auto-generate vimdoc 2022-12-30 19:42:08 +00:00
Folke Lemaitre
679d85c9ff
feat(ui): make brower configurable. Fixes #248 2022-12-30 20:41:23 +01:00
Folke Lemaitre
730bb84364
perf(loader): re-use topmod cache to find setup() module 2022-12-30 20:14:46 +01:00
github-actions[bot]
887c602957 chore(build): auto-generate vimdoc 2022-12-30 17:56:17 +00:00
WilliamHsieh
51fb95e4a8
fix: duplicate state check in bootstrap (#255) 2022-12-30 18:55:36 +01:00
github-actions[bot]
8d452e37bb chore(build): auto-generate vimdoc 2022-12-30 13:47:17 +00:00
Folke Lemaitre
de82a99197
fix(bootstrap): fixed bootstrap script 2022-12-30 14:46:25 +01:00
github-actions[bot]
a2f5c515de
chore(main): release 7.6.0 (#244)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-30 11:57:31 +01:00
Folke Lemaitre
32511a1214
feat(health): added spec parsing errors to :checkhealth 2022-12-30 11:52:20 +01:00
Folke Lemaitre
def5cc5816
fix(cache): clear cached entry on errors 2022-12-30 11:52:20 +01:00
github-actions[bot]
d50eab2164 chore(build): auto-generate vimdoc 2022-12-30 10:30:22 +00:00
Folke Lemaitre
86dff1b59a
feat(commands): added health command to run :checkhealth lazy 2022-12-30 11:29:22 +01:00
github-actions[bot]
716b6cc2b5 chore(build): auto-generate vimdoc 2022-12-30 09:44:26 +00:00
Folke Lemaitre
2a617a7024
feat(api): allow passing options to float so it can be used outside of lazy 2022-12-30 10:43:46 +01:00
Bojan Stipic
d205cd45d0
docs: Add lazy Unicode symbol (#246) 2022-12-30 10:43:37 +01:00
github-actions[bot]
8baedf2cd2 chore(build): auto-generate vimdoc 2022-12-30 08:18:51 +00:00
Folke Lemaitre
81ee02b8f6
feat(startup): missing plugins will now install the versions in the lockfile if available. Fixes #138 2022-12-30 09:17:53 +01:00
Folke Lemaitre
1283c2b288
feat(restore): you can now restore a plugin to a certain commit. Fixes #234 2022-12-30 09:17:53 +01:00
Folke Lemaitre
4b29f7e3d5
ci: added support for code block lang 2022-12-30 09:17:53 +01:00
github-actions[bot]
60ccfe3e27 chore(build): auto-generate vimdoc 2022-12-30 00:02:25 +00:00
Folke Lemaitre
291dd6a74b
docs: updated bootstrap code to exclude single-branch 2022-12-30 01:01:22 +01:00
github-actions[bot]
0063e439a3 chore(build): auto-generate vimdoc 2022-12-29 22:37:17 +00:00
Folke Lemaitre
c30c89bc09
docs: bootstrap code will now bootstrap with latest stable lazy release. Fixes #236 2022-12-29 23:36:31 +01:00
github-actions[bot]
5a78451c30
chore(main): release 7.5.0 (#240)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-29 23:33:51 +01:00
Folke Lemaitre
929198bc4f
feat(bootstrap): bootstrap with last lazy stable release 2022-12-29 23:32:02 +01:00
Folke Lemaitre
1682edc505
test: annotations for tests 2022-12-29 23:27:06 +01:00
Folke Lemaitre
5d9c528771
ci: fixed stable tag for release-please (again) 2022-12-29 23:27:06 +01:00
github-actions[bot]
67cb4e74c8
chore(main): release 7.4.2 (#239)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-29 23:17:03 +01:00
Folke Lemaitre
563519eee7
ci: fixed release-please stable tag 2022-12-29 23:15:39 +01:00
Folke Lemaitre
e6c24914e8
test: fixed selene issues for tests 2022-12-29 23:12:38 +01:00
Folke Lemaitre
a4bd4dc4a7
fix(loader): normalize rtp paths on windows #230 2022-12-29 23:06:51 +01:00
github-actions[bot]
68ee0cbe2d
chore(main): release 7.4.1 (#238)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-29 23:00:02 +01:00
Folke Lemaitre
0c386bbea2
ci: added stable tag that gets moved with every release 2022-12-29 22:58:10 +01:00
Folke Lemaitre
9f3fb38402
fix(ftdetect): source ftdetect files only once. Fixes #235 2022-12-29 22:40:57 +01:00
github-actions[bot]
717cd2f3d6
chore(main): release 7.4.0 (#197)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-29 18:42:54 +01:00
Folke Lemaitre
853d4d5838
fix(cache): added support for top level lua linked directories. Fixes #233 2022-12-29 18:40:28 +01:00
Folke Lemaitre
8544c389ab
fix(cache): always normalize modname separators 2022-12-29 18:26:39 +01:00
Folke Lemaitre
c7c1295c3e
fix: only show fired ft events in debug obvioulsy. Fixes #232 2022-12-29 18:06:40 +01:00
Folke Lemaitre
a2eac68575
fix(cmd): fixed signature of cmd._del. Fixes #229 2022-12-29 17:32:54 +01:00
Folke Lemaitre
e2925748df
build: added jit to selene 2022-12-29 17:30:29 +01:00
Folke Lemaitre
7de662d037
fix(ft): only trigger filetypepluing and filetypeindent for ft handler. Fixes #228 2022-12-29 17:26:38 +01:00
Folke Lemaitre
db043da829
fix(config): reset packpath to include VIMRUNTIME only. Fixes #214 2022-12-29 16:04:45 +01:00
Folke Lemaitre
3a1a10cd75
fix(loader): implemented correct adding to rtp. fix #230, fix #226 2022-12-29 16:03:23 +01:00
Folke Lemaitre
c7122d64cd
fix(loader): temporary fix for Vimtex and others. See #230 2022-12-29 10:51:25 +01:00
Folke Lemaitre
044e28bf8b
fix(cache): check package.loaded after auto-load and return existing module if present. Fixes #224 2022-12-29 09:06:23 +01:00
Folke Lemaitre
b8c5ab5dae
fix(cache): reload file if compiled code is incompatible. Fixes #225 2022-12-29 08:25:24 +01:00
Folke Lemaitre
4e3a973f85
fix(rtp): correct order of adding to rtp. Fixes #226 2022-12-29 08:21:27 +01:00
github-actions[bot]
72ab3e2933 chore(build): auto-generate vimdoc 2022-12-29 07:03:28 +00:00
XXiaoA
15b5b94422
docs: Add migration for config from packer (#227) 2022-12-29 08:02:46 +01:00
Folke Lemaitre
e3ffcff7cc
fix(cache): ad jit.verion to cache version string. Fixes #225 2022-12-29 08:01:05 +01:00
Folke Lemaitre
95b9cf743c
fix(cache): properly get rtp during fast events 2022-12-29 01:25:17 +01:00
github-actions[bot]
55335138ce chore(build): auto-generate vimdoc 2022-12-29 00:05:27 +00:00
Folke Lemaitre
4b75d06c07
fix(cache): dont update rtp in fast events 2022-12-29 01:04:39 +01:00
Folke Lemaitre
6c0b803999
fix(git): add --no-show-signature. Fixes #218 2022-12-29 01:02:05 +01:00
Folke Lemaitre
c8553ca44f
feat(plugin): allow some lazy.nvim spec props to be set by the user 2022-12-29 00:49:38 +01:00
Folke Lemaitre
9997523841
fix(cache): OptionSet is not triggered during startup, so use #rtp instead to see if it changed 2022-12-29 00:48:59 +01:00
Folke Lemaitre
370b1b982e
fix(cache): make it work again... #fixup 2022-12-28 23:50:25 +01:00
Folke Lemaitre
c2f7e2d098
feat(ui): added extra cache stats to the debug tab 2022-12-28 17:58:24 +01:00
Folke Lemaitre
34977c2b80
perf: move autoloader to cache and always use lazy's modname path resolver which is much faster 2022-12-28 17:58:24 +01:00
Folke Lemaitre
956164d27d
fix(loader): show proper error message when trying to load a plugin that is not installed. Fixes #201. Fixes #202 2022-12-28 17:58:24 +01:00
Folke Lemaitre
5f423b29c6
fix(loader): when config=true, pass nil to setup(). Fixes #208 2022-12-28 17:58:24 +01:00
Folke Lemaitre
021e54655f
feat(cache): update package.loaded on require 2022-12-28 17:58:23 +01:00
max397574
b813fae61c
fix(health): add cond key (#203) 2022-12-28 17:39:51 +01:00
tzachar
acd6697d88
fix(commands): E5108 in getcompletions (#207) 2022-12-28 17:39:31 +01:00
github-actions[bot]
0b1e083937 chore(build): auto-generate vimdoc 2022-12-28 16:38:51 +00:00
Dr. David A. Kunz
ff8f3783fa
feat(profile): nicer threshold prompt (#210) 2022-12-28 17:38:08 +01:00
Darkhan
dc03fa1ae5
fix(health): add new key priority to :checkhealth lazy (#196) 2022-12-28 00:03:09 +01:00
github-actions[bot]
9ab61b3479
chore(main): release 7.3.0 (#177)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-27 22:38:28 +01:00
Folke Lemaitre
0d0d11acb2
fix(ui): removed newlines from profile tab 2022-12-27 19:50:11 +01:00
Folke Lemaitre
3b46160c01
feat(ui): added new section specifically for updates 2022-12-27 19:35:23 +01:00
github-actions[bot]
7d20364dba chore(build): auto-generate vimdoc 2022-12-27 16:25:37 +00:00
Folke Lemaitre
edf8310288
feat(plugin): added Plugin.priority for start plugins 2022-12-27 17:24:47 +01:00
github-actions[bot]
eec0485d45 chore(build): auto-generate vimdoc 2022-12-27 15:46:41 +00:00
Folke Lemaitre
81943f32d9
docs: documented event patterns. Fixes #191 2022-12-27 16:45:47 +01:00
github-actions[bot]
5a5487b015 chore(build): auto-generate vimdoc 2022-12-27 12:35:05 +00:00
Folke Lemaitre
a2fdf369f2
feat(profile): added accurate startuptime to ui/stats/docs 2022-12-27 13:34:12 +01:00
Folke Lemaitre
d1739cb7e1
feat(util): use treesitter to highlight notify messages when available 2022-12-27 13:34:12 +01:00
github-actions[bot]
e183601763 chore(build): auto-generate vimdoc 2022-12-27 07:58:39 +00:00
Folke Lemaitre
5618076a45
fix(ft): always trigger FileType when lazy-loading on ft 2022-12-27 08:57:49 +01:00
Folke Lemaitre
b1e1b337a6
docs: clarified dependencies plugin names 2022-12-27 08:57:49 +01:00
github-actions[bot]
0f3782c066 chore(build): auto-generate vimdoc 2022-12-27 07:31:21 +00:00
Folke Lemaitre
38a9541939
style(plugin): improved types a bit, but sumneko still can't handle them since they're recursive 2022-12-27 08:30:28 +01:00
Folke Lemaitre
8a3152de93
fix(plugin): find plugins with /lua/ instead of /lua 2022-12-27 07:44:28 +01:00
github-actions[bot]
b5b2ab6b6c chore(build): auto-generate vimdoc 2022-12-26 22:20:42 +00:00
Folke Lemaitre
96e82986ee
docs: updated docs 2022-12-26 23:19:37 +01:00
Folke Lemaitre
b6ebed5888
fix(plugin): pass plugin as arg to config/init/build 2022-12-26 22:59:07 +01:00
github-actions[bot]
de383740a2 chore(build): auto-generate vimdoc 2022-12-26 19:46:34 +00:00
Moshe Avni
3a67d2ad25
docs: fix plugin setup example (#175) 2022-12-26 20:45:46 +01:00
Folke Lemaitre
3c24c506ce
docs: update config.plugins link. Fixes #182 2022-12-26 20:45:06 +01:00
Tsakiris Tryfon
c4d924acee
fix(reloader): remove extra trailing separator (#180) 2022-12-26 19:42:42 +01:00
github-actions[bot]
511524ebff chore(build): auto-generate vimdoc 2022-12-26 18:02:16 +00:00
Folke Lemaitre
7ffbead674
docs: added LazyReload 2022-12-26 19:01:28 +01:00
Folke Lemaitre
4e4493b21d
feat(reloader): trigger LazyReload when changes were detected and after reload. Fixes #178 2022-12-26 19:00:11 +01:00
Folke Lemaitre
bb53b8473c
fix(cache): never use packer paths from cache 2022-12-26 18:35:07 +01:00
github-actions[bot]
5697098e97
chore(main): release 7.2.0 (#166)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-26 16:12:23 +01:00
Folke Lemaitre
46280a191b
fix(keys): don't escape pendig keys twice and only convert when number 2022-12-26 15:55:40 +01:00
Folke Lemaitre
9a2ecc8750
feat(ui): re-render after resize. Fixes #174 2022-12-26 14:19:39 +01:00
max397574
1d3da277da
docs: don't fold other plugin managers with colors (#169) 2022-12-26 11:20:40 +01:00
github-actions[bot]
e6de63bc9c chore(build): auto-generate vimdoc 2022-12-26 09:25:34 +00:00
Folke Lemaitre
0ea771bd70
feat(ui): made all highlight groups and icons configurable 2022-12-26 10:24:53 +01:00
github-actions[bot]
3d22c496da chore(build): auto-generate vimdoc 2022-12-26 08:38:12 +00:00
Folke Lemaitre
5f017bf655
docs: document highlight groups 2022-12-26 09:37:31 +01:00
Folke Lemaitre
aed842ae1e
feat(plugin): added Plugin.cond. Fixes #89, #168 2022-12-26 09:37:30 +01:00
Folke Lemaitre
2f5c1be525
fix(ui): get plugin details from the correct plugin in case it was deleted 2022-12-26 09:37:30 +01:00
github-actions[bot]
6c5af82589 chore(build): auto-generate vimdoc 2022-12-25 15:27:12 +00:00
Folke Lemaitre
4aa362e8dc
feat(cache): make ttl configurable 2022-12-25 16:26:17 +01:00
Folke Lemaitre
9837d5be7e
fix(keys): only delete key handler mappings once 2022-12-25 16:17:50 +01:00
github-actions[bot]
7421e70c08 chore(build): auto-generate vimdoc 2022-12-25 13:41:45 +00:00
NEX
1dca6edd89
docs: Fix README.md wrong indent (#165) 2022-12-25 14:41:01 +01:00
github-actions[bot]
bdd7f0585a chore(build): auto-generate vimdoc 2022-12-25 13:31:44 +00:00
Folke Lemaitre
3efb849d73
docs: clarified that only top-level submodules are merged in the final spec. #139 2022-12-25 14:30:55 +01:00
Folke Lemaitre
90952239d2
fix(loader): add proper error message when trying to load a plugin that doesn't exist. Fixes #160 2022-12-25 14:06:53 +01:00
Folke Lemaitre
e632eb4ae0
style: mode no longer needed as param for view 2022-12-25 13:46:42 +01:00
jdrouhard
037f242430
fix(diff): use git show when only displaying one commit (#155) 2022-12-25 13:45:56 +01:00
github-actions[bot]
ed8259b7c1 chore(build): auto-generate vimdoc 2022-12-25 12:43:16 +00:00
Jeremy Goh
db14d4b2a1
ci: fix minor typos in the github template (#159)
* chore: fix minor typos in the github template

* fix typo in repro.lua
2022-12-25 13:42:26 +01:00
max397574
8ea9d8b024
feat(ui): make lazy icon configurable (#163)
* feat(ui): make lazy icon configurable

* docs: add lazy icon config option
2022-12-25 13:41:33 +01:00
github-actions[bot]
434b7d3edd chore(build): auto-generate vimdoc 2022-12-24 11:57:51 +00:00
Folke Lemaitre
2fabc0958d
docs: added VeryLazy to docs 2022-12-24 12:57:13 +01:00
github-actions[bot]
f22dfd4a44
chore(main): release 7.1.0 (#129)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-24 12:23:46 +01:00
github-actions[bot]
9f2fb24b10 chore(build): auto-generate vimdoc 2022-12-24 10:56:27 +00:00
Folke Lemaitre
a36d506393
feat(manage): added user events when operations finish. Fixes #135 2022-12-24 11:55:42 +01:00
Folke Lemaitre
3352fc6265
docs: added diff keybindings to help page 2022-12-24 11:41:06 +01:00
github-actions[bot]
b40ec94523 chore(build): auto-generate vimdoc 2022-12-24 10:31:06 +00:00
Folke Lemaitre
be3909c544
feat(ui): added custom commands for lazygit and opening a terminal for a plugin 2022-12-24 11:30:16 +01:00
Folke Lemaitre
7d02da2ff0
feat(ui): added multiple options for diff command 2022-12-24 11:30:16 +01:00
Folke Lemaitre
8ad05feef1
feat(util): open terminal commands in a float 2022-12-24 11:30:16 +01:00
Folke Lemaitre
7c2eb15444
feat: util method to open a float 2022-12-24 11:30:16 +01:00
Folke Lemaitre
b34e25873a
refactor: float is now a separate module 2022-12-24 11:30:16 +01:00
Folke Lemaitre
fc182f7c5d
fix(manage): only clear plugins for the op instead of all 2022-12-24 11:30:16 +01:00
Folke Lemaitre
74d8b8e4e1
fix: plugin list can be string[]. Fixes #145 2022-12-24 11:30:16 +01:00
Folke Lemaitre
86f2c67aa8
fix(checker): update updated after every manage operation. Fixes #141 2022-12-24 11:30:15 +01:00
Folke Lemaitre
9110371120
feat(build): build can now be a list to execute multiple build commands. Fixes #143 2022-12-24 11:30:15 +01:00
Folke Lemaitre
593d6e400b
feat(ui): you can now hover over a plugin to open a diff of updates or the plugin homepage 2022-12-24 11:30:15 +01:00
github-actions[bot]
a973c2edc2 chore(build): auto-generate vimdoc 2022-12-23 19:56:43 +00:00
Folke Lemaitre
83270cc5e5
refactor(commands): move ui/commands config to separate file 2022-12-23 20:55:56 +01:00
github-actions[bot]
c1f39f997d chore(build): auto-generate vimdoc 2022-12-23 18:53:40 +00:00
Folke Lemaitre
011125ccc2
docs: cleanup 2022-12-23 19:52:56 +01:00
github-actions[bot]
f822a2c12b chore(build): auto-generate vimdoc 2022-12-23 18:52:21 +00:00
max397574
3991cf56f8
docs(readme): added explanation for dependencies (#137) 2022-12-23 19:51:35 +01:00
github-actions[bot]
aec3baa555 chore(build): auto-generate vimdoc 2022-12-23 18:04:19 +00:00
Folke Lemaitre
74b076e030
docs: added after/wants to migration guide and added an example that sets a key mode 2022-12-23 19:03:30 +01:00
Aaron
5a1812a633
Better terminology (#132) 2022-12-23 14:58:11 +01:00
Folke Lemaitre
a062641c85
ci: more formatting 2022-12-23 14:30:25 +01:00
Folke Lemaitre
2bd563ce99
ci: formatting of issue template 2022-12-23 14:30:05 +01:00
Folke Lemaitre
60fdea7aed
ci: added link to docs to issue template for the very lazy people 2022-12-23 14:29:38 +01:00
Folke Lemaitre
68db6337bf
ci: deleted old feature request template 2022-12-23 14:16:04 +01:00
Folke Lemaitre
451de7e19e
ci: added new feature request template 2022-12-23 14:15:27 +01:00
Folke Lemaitre
5ef7ce80a3
ci: even better issue template 2022-12-23 14:06:51 +01:00
Folke Lemaitre
a5d402abed
ci: better issue template 2022-12-23 14:03:07 +01:00
Folke Lemaitre
6a6d6f73ee
ci: new issue template 2022-12-23 13:53:52 +01:00
Folke Lemaitre
f360e336a5
fix(help): make sure we always generate lazy helptags 2022-12-23 13:13:34 +01:00
github-actions[bot]
4cf1f7b26e chore(build): auto-generate vimdoc 2022-12-23 11:27:29 +00:00
Folke Lemaitre
d6304f0b42
docs: added keys to packer migration 2022-12-23 12:26:38 +01:00
github-actions[bot]
7f10386e23
chore(main): release 7.0.0 (#96)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-23 11:48:54 +01:00
Folke Lemaitre
50e3b91767
fix(ui): sort profiling chronological by default 2022-12-23 11:47:05 +01:00
Folke Lemaitre
e973323e95
fix(ui): fixed extmarks while wrapping. Fixes #124 2022-12-23 11:18:32 +01:00
Folke Lemaitre
3594bfd47d
docs: todo 2022-12-23 10:43:30 +01:00
Folke Lemaitre
7dfb9c1f5c
feat(ui): added options to sort/filter profiling data 2022-12-23 10:43:22 +01:00
Folke Lemaitre
fde5feea6d
refactor: refactored ui code 2022-12-23 10:18:19 +01:00
Folke Lemaitre
cd023dc709
style: remove setting colors on startup 2022-12-23 08:41:42 +01:00
Folke Lemaitre
e2bbf3deef
refactor: better annotations to make sumneko faster 2022-12-23 08:34:55 +01:00
Folke Lemaitre
65e903652b
fix: added error message to debug failing extmarks #117 2022-12-23 08:05:32 +01:00
github-actions[bot]
040aeb68f1 chore(build): auto-generate vimdoc 2022-12-23 06:51:44 +00:00
Aaron
c8da1c19e7
docs: fixed typos and capitalization (#118)
* Fix typos and capitialization

* Update README.md

Co-authored-by: Jonas Strittmatter <40792180+smjonas@users.noreply.github.com>

Co-authored-by: Jonas Strittmatter <40792180+smjonas@users.noreply.github.com>
2022-12-23 07:51:03 +01:00
github-actions[bot]
8bd8e6c98a chore(build): auto-generate vimdoc 2022-12-23 06:49:37 +00:00
Folke Lemaitre
cc6276e9b0
refactor!: default lazy cache path is now under cache instead of state 2022-12-23 07:48:45 +01:00
Folke Lemaitre
004b11d5ad
docs: improved docs on build. Fixes #119 2022-12-23 07:48:45 +01:00
Folke Lemaitre
8251c23c90
fix(checker): dont report updates on install during startup 2022-12-23 07:48:45 +01:00
Folke Lemaitre
7b9b476a62
fix(install): make sure to setup loaders before attempting install so colorscheme can load. Fixes #122 2022-12-23 07:48:45 +01:00
github-actions[bot]
e5dcc87149 chore(build): auto-generate vimdoc 2022-12-22 22:09:14 +00:00
Folke Lemaitre
81126403a8
feat!: init() no longer implies lazy-loading. Add lazy=false for affected plugins 2022-12-22 23:08:12 +01:00
github-actions[bot]
6f9845e2f8 chore(build): auto-generate vimdoc 2022-12-22 21:50:05 +00:00
Folke Lemaitre
2a7b0047dd
feat(spec): config can be true or a table that will be passed to require("plugin").setup(config) 2022-12-22 22:48:22 +01:00
Sebastian Lyng Johansen
9e983898b1
fix(ui): fix buffer being properly deleted (#112) 2022-12-22 22:01:01 +01:00
Folke Lemaitre
3f60f2dc13
fix(keys): key handlers were not working after reload 2022-12-22 21:58:19 +01:00
Folke Lemaitre
b5d6afc4fa
fix(manage): do not reload pugins on clear 2022-12-22 21:58:19 +01:00
github-actions[bot]
037973c6cb chore(build): auto-generate vimdoc 2022-12-22 20:08:10 +00:00
Folke Lemaitre
b440b3ac2d
fix(keys): don't create with remap! 2022-12-22 21:07:24 +01:00
Folke Lemaitre
9e869a409c
docs: migration 2022-12-22 21:02:49 +01:00
Folke Lemaitre
72b38999bc
fix(keys): dont delete handlers manually. Let loader do that 2022-12-22 18:53:19 +01:00
Folke Lemaitre
08d458c5ba
fix: remove debug print 2022-12-22 18:50:31 +01:00
github-actions[bot]
455a1f485b chore(build): auto-generate vimdoc 2022-12-22 17:48:24 +00:00
Folke Lemaitre
2756a6f756
fix!: run init() before loading start plugins. Fixes #107 2022-12-22 18:47:34 +01:00
github-actions[bot]
fb8287c73d chore(build): auto-generate vimdoc 2022-12-22 17:16:41 +00:00
Wil Thomason
4b4ccdb16a
docs: Add migration for tag = '*' from packer (#105)
* Add migration for tag = '*' from packer

Adds a missing migration point from `packer`

* Add note about disable vs enabled
2022-12-22 18:15:47 +01:00
Folke Lemaitre
56890ce5f4
fix: remove lazy keymaps with the correct mode. Fixes #97 2022-12-22 17:49:32 +01:00
Folke Lemaitre
42f5aa76e2
fix: pass plugins instead of plugin names to command. Fixes #103 2022-12-22 17:25:12 +01:00
Folke Lemaitre
4bf771a6b2
feat(spec): allow using plugin names in dependencies 2022-12-22 17:25:12 +01:00
github-actions[bot]
eb01b6dc0b chore(build): auto-generate vimdoc 2022-12-22 12:50:12 +00:00
Folke Lemaitre
07b467738d
feat(loader): automatically lazy-load colorschemes 2022-12-22 13:49:17 +01:00
github-actions[bot]
210d1703ec
chore(main): release 6.0.0 (#76)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-22 10:46:27 +01:00
Folke Lemaitre
3415a61789
fix(ui): properly wrap ui elements on small screens. Fixes #92 2022-12-22 10:45:45 +01:00
Folke Lemaitre
c0c2e1bd68
fix(cmd): allow ranges. Fixes #93 2022-12-22 10:37:02 +01:00
github-actions[bot]
a8fe63e4d5 chore(build): auto-generate vimdoc 2022-12-22 09:33:10 +00:00
Folke Lemaitre
1c07ea15a3
feat(keys): more advanced options for setting lazy key mappings 2022-12-22 10:32:21 +01:00
Folke Lemaitre
28f1511e0a
fix: show mapleader warning with vim.schedule. Fixes #91 2022-12-22 09:12:06 +01:00
Folke Lemaitre
2200284165
fix(cache): overwrite cache entry with new modpath when loading a file. Fixes #90 2022-12-22 09:10:11 +01:00
Folke Lemaitre
63042310f4
feat(ui): show modpaths in debug 2022-12-22 09:09:35 +01:00
EdenEast
dd9648f8ec
fix(clean): update lockfile on clean (#88) 2022-12-22 08:09:28 +01:00
github-actions[bot]
63418e8932 chore(build): auto-generate vimdoc 2022-12-22 07:08:53 +00:00
Folke Lemaitre
488b48779c
fix(git): remove --also-filter-submodules. Fixes #86 #83 2022-12-22 08:08:07 +01:00
Folke Lemaitre
dc150df456
test(lockfile): create config dir if it does not exist 2022-12-21 23:22:04 +01:00
Folke Lemaitre
4cf176bdab
fix(install): update lockfile also on install 2022-12-21 23:18:35 +01:00
Folke Lemaitre
7f6f31d66f
fix(git): make sure we properly fetch git submodules. Fixes #72 2022-12-21 23:13:18 +01:00
github-actions[bot]
a39d37b51a chore(build): auto-generate vimdoc 2022-12-21 21:28:58 +00:00
Folke Lemaitre
2e14a2f324
feat: added support for nvim --headless "+Lazy! sync" +qa 2022-12-21 22:28:09 +01:00
Folke Lemaitre
bc617474a0
feat!: lazy api commands now take an opts table instead of a list of plugins 2022-12-21 22:27:36 +01:00
Folke Lemaitre
fd1fbefc3d
feat(checker): defer checker to after VeryLazy to make sure nvim-notify and others are loaded 2022-12-21 21:08:13 +01:00
Folke Lemaitre
58f0876e81
fix: removed spell again from site. not needed. can download in config/spell 2022-12-21 20:09:12 +01:00
Folke Lemaitre
94d012511d
fix(rtp): keep site in rtp 2022-12-21 19:58:28 +01:00
github-actions[bot]
6dbcdcec83 chore(build): auto-generate vimdoc 2022-12-21 18:49:36 +00:00
C.D. MacEachern
1fb10b987b
docs: 'cmd' repeat twice (#75)
Probably meant `keys`?
2022-12-21 19:48:53 +01:00
github-actions[bot]
472a091b77
chore(main): release 5.2.0 (#55)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-21 19:08:11 +01:00
Folke Lemaitre
f0e1b853a0
feat: make hover easy to override 2022-12-21 19:04:08 +01:00
Folke Lemaitre
2ab651864f
fix(keys): feedkeys should include pending keys. Fixes #71 2022-12-21 19:02:14 +01:00
Folke Lemaitre
d34a02d7b2
ci: Update issue templates 2022-12-21 18:49:00 +01:00
Folke Lemaitre
2fd78fbed8
fix(help): sort tags files for readmes so tags work properly. Fixes #67 2022-12-21 18:23:27 +01:00
Folke Lemaitre
eab449b9e5
build: added .repro and debug to .gitignore 2022-12-21 18:22:50 +01:00
Folke Lemaitre
b7c489b08f
fix(loader): lua modules can be links instead of files. Fixes #66 2022-12-21 16:28:01 +01:00
github-actions[bot]
7a57ea28d3 chore(build): auto-generate vimdoc 2022-12-21 15:08:40 +00:00
Folke Lemaitre
c228908ffc
fix(health): don't show warning on module=false 2022-12-21 16:07:53 +01:00
Folke Lemaitre
b68f94b95a
ci: Update issue templates 2022-12-21 15:39:44 +01:00
Folke Lemaitre
bbebb67934
ci: Update issue templates 2022-12-21 15:37:46 +01:00
github-actions[bot]
95fc814818 chore(build): auto-generate vimdoc 2022-12-21 14:19:58 +00:00
Folke Lemaitre
876f7bd471
feat(loader): allow to add extra paths to rtp reset. Fixes #64 2022-12-21 15:19:14 +01:00
Folke Lemaitre
a345649510
fix(cache): if we can't load from the cache modpath, find path again instead of erroring right away 2022-12-21 14:56:46 +01:00
Folke Lemaitre
bbace14dc9
fix(git): only mark a plugin as dirty if an update changed the commit HEAD. Fixes #62 2022-12-21 14:45:32 +01:00
Tsakiris Tryfon
a939243639
fix(checker): allow git checks only for non-pinned plugins (#61) 2022-12-21 14:39:08 +01:00
github-actions[bot]
57bea32e4f chore(build): auto-generate vimdoc 2022-12-21 13:35:54 +00:00
Folke Lemaitre
ff24f493ee
fix(loader): source rtp /plugin files after loading start plugins. Fixes 2022-12-21 14:34:31 +01:00
github-actions[bot]
b802729bf6 chore(build): auto-generate vimdoc 2022-12-21 10:43:46 +00:00
Folke Lemaitre
9dfeface3f
docs: fixed indentation of auto-generated code blocks 2022-12-21 11:43:05 +01:00
Folke Lemaitre
71b2e2ff7d
docs: lazy works on all OSs now 2022-12-21 11:35:43 +01:00
Folke Lemaitre
232232da5a
fix(ui): install command can have plugins as a parameter 2022-12-21 11:18:41 +01:00
Folke Lemaitre
4ca30390ec
feat(loader): warn when mapleader is changed after init 2022-12-21 10:51:31 +01:00
Folke Lemaitre
540847b7cb
fix: strip / from dirs. Fixes #60 2022-12-21 10:17:10 +01:00
Folke Lemaitre
86eaa118c6
fix(git): dereference tag refs. Fixes #54 2022-12-21 10:13:23 +01:00
Folke Lemaitre
e95da35d09
feat(util): utility method to get sync process output 2022-12-21 10:13:22 +01:00
github-actions[bot]
3c3a711dda chore(build): auto-generate vimdoc 2022-12-21 08:04:42 +00:00
Folke Lemaitre
44f80a7f5d
feat(plugin): allow plugin files only without a main plugin module. Fixes #53 2022-12-21 09:03:47 +01:00
github-actions[bot]
f5734f512f chore(build): auto-generate vimdoc 2022-12-21 07:34:02 +00:00
Folke Lemaitre
3814883aaa
fix(ui): set current win only when its valid 2022-12-21 08:33:10 +01:00
github-actions[bot]
3a7b8c8132
chore(main): release 5.1.0 (#30)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-20 23:35:55 +01:00
Folke Lemaitre
3606d62918
fix: add after directories to rtp to make after/ftplugin and others work. Fixes #47 2022-12-20 23:35:06 +01:00
Folke Lemaitre
b193f96f7b
fix(spec): only process a spec once 2022-12-20 23:14:49 +01:00
Folke Lemaitre
7be46bceef
style: removed unused requires 2022-12-20 22:32:16 +01:00
Dan Sully
897d6df5ac
fix: add filetype to window buffer. (#41)
Add a filetype to the Lazy window buffer, which allows plugins like codewindow to ignore it.
2022-12-20 21:23:00 +01:00
github-actions[bot]
14300b3d04 chore(build): auto-generate vimdoc 2022-12-20 20:16:27 +00:00
Folke Lemaitre
78e9d6c01d
docs: add a note about mapleader 2022-12-20 21:15:39 +01:00
Folke Lemaitre
06ac8bda66
perf(ui): clear existing extmarks before rendering 2022-12-20 20:53:00 +01:00
Folke Lemaitre
ffcd0ab7bb
fix(loader): source filetype.lua before plugins. Fixes #35 2022-12-20 20:32:37 +01:00
Folke Lemaitre
9d12cdcc06
fix(git): don't run git log for submodules. Fixes #33 2022-12-20 19:58:56 +01:00
github-actions[bot]
06ffcf5874 chore(build): auto-generate vimdoc 2022-12-20 18:44:49 +00:00
Folke Lemaitre
7fb0652dba
docs: added docs on update checker 2022-12-20 19:43:51 +01:00
github-actions[bot]
1f86cb37d1 chore(build): auto-generate vimdoc 2022-12-20 18:39:54 +00:00
Folke Lemaitre
3cffb2acef
docs: added change detection to the readme 2022-12-20 19:39:07 +01:00
Folke Lemaitre
6c767a604d
feat: added options to configure change detection. Fixes #32 2022-12-20 19:38:37 +01:00
github-actions[bot]
cd162f342a chore(build): auto-generate vimdoc 2022-12-20 18:30:15 +00:00
Folke Lemaitre
941df31a41
feat(ui): make the windoww size configurable. Fixes #34 2022-12-20 19:29:28 +01:00
Folke Lemaitre
52984419ff
fix: use nvim_feekeys instead of nvim_input for keys handler. Fixes #28 2022-12-20 18:24:48 +01:00
Folke Lemaitre
2927b0597e
docs: added lincense 2022-12-20 17:56:21 +01:00
github-actions[bot]
4d782030c8
chore(main): release 5.0.1 (#17)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-20 16:59:11 +01:00
Folke Lemaitre
1371a14167
fix(build): use the shell to execute build commands 2022-12-20 16:57:02 +01:00
Folke Lemaitre
ffabe91b2d
fix(cache): if mod is loaded already in the loader, then return that 2022-12-20 16:41:11 +01:00
Folke Lemaitre
316503f124
fix: dont autoload cached modules when module=false 2022-12-20 16:02:22 +01:00
Folke Lemaitre
992c6791ef
fix: always set Config.me regardless of reset rtp 2022-12-20 16:02:06 +01:00
Folke Lemaitre
df6c9863dc
fix: add neovim libs to rtp for treesitter parsers etc 2022-12-20 15:03:26 +01:00
github-actions[bot]
49b69b7f9f chore(build): auto-generate vimdoc 2022-12-20 13:14:47 +00:00
Folke Lemaitre
e9d3a73bbc
fix: default logs are now since 3 days ago to be in line with the docs 2022-12-20 14:13:58 +01:00
github-actions[bot]
423432254d chore(build): auto-generate vimdoc 2022-12-20 13:02:51 +00:00
Folke Lemaitre
6e32759c5d
fix: deepcopy lazyspec before processing 2022-12-20 14:01:59 +01:00
Folke Lemaitre
ec0f8d0947
docs: added config.dev.path to the example 2022-12-20 13:49:29 +01:00
Folke Lemaitre
6404d42155
fix: move re-sourcing check to the top 2022-12-20 13:47:53 +01:00
Folke Lemaitre
ddf36d7748
fix: checker should not error on non-existing dirs 2022-12-20 13:44:21 +01:00
Folke Lemaitre
50ba619d9e
test: fix tests 2022-12-20 13:40:09 +01:00
Folke Lemaitre
f78d8bf376
fix: show error when merging, but continue 2022-12-20 13:36:18 +01:00
github-actions[bot]
b8a005510c chore(build): auto-generate vimdoc 2022-12-20 11:35:11 +00:00
Folke Lemaitre
1754056475
fix: use jobstart instead of system to open urls 2022-12-20 12:34:24 +01:00
Folke Lemaitre
5ecc988610
docs: use https to bootstrap lazy 2022-12-20 12:34:05 +01:00
Folke Lemaitre
ae644a604d
fix: only run updated checker for installed plugins. Fixes #16 2022-12-20 11:58:54 +01:00
github-actions[bot]
7225b055f5 chore(build): auto-generate vimdoc 2022-12-20 10:40:52 +00:00
Folke Lemaitre
17fd57a5f3
docs: added docs for statusline and count 2022-12-20 11:40:12 +01:00
github-actions[bot]
48a596e1d4 chore(build): auto-generate vimdoc 2022-12-20 10:03:19 +00:00
Folke Lemaitre
dfe8a65d7d
docs: removed extra performance section 2022-12-20 11:02:28 +01:00
Folke Lemaitre
1fa2d87ae2
docs: moved my dots to structuring plugins 2022-12-20 11:01:43 +01:00
github-actions[bot]
9916318522 chore(build): auto-generate vimdoc 2022-12-20 09:56:46 +00:00
Folke Lemaitre
abe026a5ae
docs: added section on performance 2022-12-20 10:55:58 +01:00
github-actions[bot]
82aea47c35 chore(build): auto-generate vimdoc 2022-12-20 09:27:34 +00:00
Folke Lemaitre
72d66cdd73
docs: updated lua stuff 2022-12-20 10:26:52 +01:00
github-actions[bot]
ca430184b3 chore(build): auto-generate vimdoc 2022-12-20 09:25:55 +00:00
Folke Lemaitre
36cb7ea597
docs: migration guide 2022-12-20 10:25:02 +01:00
github-actions[bot]
2f59ead574
chore(main): release 5.0.0 (#12)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-20 10:20:19 +01:00
github-actions[bot]
dbcf675f87 chore(build): auto-generate vimdoc 2022-12-20 09:20:06 +00:00
Folke Lemaitre
b906ad959c
docs: added windows to supported platforms 2022-12-20 10:19:04 +01:00
Folke Lemaitre
cb87aa3893
ci: run tests on linux only for nw 2022-12-20 08:56:59 +01:00
github-actions[bot]
75a36f3c94 chore(build): auto-generate vimdoc 2022-12-20 07:47:50 +00:00
Folke Lemaitre
af87108605
fix(util): fixed double slashes 2022-12-20 08:47:01 +01:00
Folke Lemaitre
62c1542141
fix(cache): normalize paths 2022-12-20 08:31:19 +01:00
Folke Lemaitre
bb1c2f4c3e
feat: added support for Windows 2022-12-20 07:19:55 +01:00
Folke Lemaitre
198963fdab
feat: utility method to normalize a path 2022-12-20 07:19:41 +01:00
Folke Lemaitre
a18988372f
fix: check for installed plugins with plain find 2022-12-20 07:15:26 +01:00
github-actions[bot]
833b387213 chore(build): auto-generate vimdoc 2022-12-19 20:28:48 +00:00
Folke Lemaitre
ff893190f2
docs: removed dots from features 2022-12-19 21:27:36 +01:00
Folke Lemaitre
b7bf18abd3
style: spelling 2022-12-19 21:11:33 +01:00
github-actions[bot]
66dad89f58 chore(build): auto-generate vimdoc 2022-12-19 20:06:18 +00:00
Folke Lemaitre
0c0b8b7231
docs: todo 2022-12-19 21:05:22 +01:00
Folke Lemaitre
92fd0d43a0
docs: updated installation and structuring plugins 2022-12-19 21:05:22 +01:00
Folke Lemaitre
1baa92f8ca
docs: added docs on <cr> and <K> 2022-12-19 21:05:22 +01:00
Folke Lemaitre
d827d8a402
docs: collapse semver examples 2022-12-19 21:05:22 +01:00
github-actions[bot]
1e163632e4 chore(build): auto-generate vimdoc 2022-12-19 18:10:49 +00:00
Folke Lemaitre
980cfa95f3
docs: added config example when not using a Nerd Font 2022-12-19 19:09:54 +01:00
Folke Lemaitre
713dcb6901
build: added markdownlint config 2022-12-19 19:09:54 +01:00
github-actions[bot]
706fe6f9c5 chore(build): auto-generate vimdoc 2022-12-19 14:23:42 +00:00
Folke Lemaitre
5ed9855d1c
feat: added completion for all lazy commands 2022-12-19 15:22:47 +01:00
Folke Lemaitre
b46278751f
docs: added optional plugins to docs for commands and methods 2022-12-19 15:22:47 +01:00
github-actions[bot]
f29f3d2157 chore(build): auto-generate vimdoc 2022-12-19 13:57:32 +00:00
Folke Lemaitre
1efa710210
feat: added module=false to skip auto-loading of plugins on require 2022-12-19 14:56:48 +01:00
github-actions[bot]
55d194cf9c chore(build): auto-generate vimdoc 2022-12-19 13:31:18 +00:00
Folke Lemaitre
bac34cc6b6
docs: added section on uninstalling 2022-12-19 14:30:36 +01:00
github-actions[bot]
c065ca2b32 chore(build): auto-generate vimdoc 2022-12-19 13:23:33 +00:00
Folke Lemaitre
2dd6230018
feat: added :Lazy load foobar.nvim to load a plugin 2022-12-19 14:22:43 +01:00
Folke Lemaitre
8a0da3b27e
config: move lazy cache to state/nvim/lazy/cache 2022-12-19 13:55:04 +01:00
github-actions[bot]
7eb60345d6 chore(build): auto-generate vimdoc 2022-12-19 12:38:06 +00:00
Folke Lemaitre
65675808d1
chore: todo 2022-12-19 13:37:14 +01:00
Folke Lemaitre
6f00cdedee
docs: typos 2022-12-19 13:36:11 +01:00
Folke Lemaitre
faac2dd11c
perf(cache): cache loadfile and no find modpaths without package.loaders 2022-12-19 13:34:37 +01:00
Folke Lemaitre
32f2b71ff8
fix(cache): do a fast check to see if a cached modpath is still valid. find it again otherwise 2022-12-19 12:21:20 +01:00
Folke Lemaitre
1fe43f3e29
fix(ui): focus Lazy window when auto-installing plugins in VimEnter 2022-12-19 12:20:02 +01:00
Folke Lemaitre
d4aee2715f
feat!: removed the LazyUpdate etc commands. sub-commands only from now on 2022-12-19 10:11:21 +01:00
Folke Lemaitre
b89e6bffd2
perf: lazy-load the commands available on the lazy module 2022-12-18 17:36:37 +01:00
github-actions[bot]
48309ddf09
chore(main): release 4.2.0 (#11)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-18 15:03:51 +01:00
Folke Lemaitre
c87673c4b9
feat(ui): added help for <CR> on a plugin 2022-12-18 14:51:39 +01:00
github-actions[bot]
b88b7d75eb chore(build): auto-generate vimdoc 2022-12-18 13:50:01 +00:00
Folke Lemaitre
e42a18099a
docs: added line on :checkhealth 2022-12-18 14:49:18 +01:00
github-actions[bot]
2526a011e5 chore(build): auto-generate vimdoc 2022-12-18 13:48:03 +00:00
Folke Lemaitre
968fa3fe20
style: removed bold from home button 2022-12-18 14:47:12 +01:00
Folke Lemaitre
5fc87f924a
docs: updated screenshots 2022-12-18 14:46:33 +01:00
github-actions[bot]
cd3d87cc82 chore(build): auto-generate vimdoc 2022-12-18 13:34:41 +00:00
Folke Lemaitre
d0651e4782
docs: added section about the lockfile 2022-12-18 14:33:55 +01:00
github-actions[bot]
39f629eedf chore(build): auto-generate vimdoc 2022-12-18 13:29:46 +00:00
Folke Lemaitre
628d421c27
docs: added my dots to the examples 2022-12-18 14:29:02 +01:00
Folke Lemaitre
c88ad91e31
docs: added section on versioning 2022-12-18 14:29:02 +01:00
Folke Lemaitre
78b284c065
docs: added section on lazy loading 2022-12-18 14:29:02 +01:00
Folke Lemaitre
c0d3617e0b
feat: check if ffi is available and error if not 2022-12-18 14:29:02 +01:00
github-actions[bot]
0f62ec0ad6 chore(build): auto-generate vimdoc 2022-12-18 10:59:37 +00:00
Folke Lemaitre
b70bb1955b
docs: added more detailed requirements 2022-12-18 11:58:45 +01:00
github-actions[bot]
db469ed275 chore(build): auto-generate vimdoc 2022-12-18 10:44:05 +00:00
Folke Lemaitre
671b163dd7
docs: added more details on startup sequence 2022-12-18 11:43:10 +01:00
Folke Lemaitre
1730661ec2
docs: generate docs for commands 2022-12-18 11:42:54 +01:00
Folke Lemaitre
f25f942eb7
feat: expose all commands on main lazy module 2022-12-18 11:42:27 +01:00
Folke Lemaitre
0b4a04de7d
feat(ui): make home bold 2022-12-17 17:36:09 +01:00
Folke Lemaitre
a46c0c04f1
feat: never source packer_compiled.lua 2022-12-17 17:35:45 +01:00
Folke Lemaitre
9026a0e25d
feat(ui): made it look a little less like a Mason rip-off :) 2022-12-17 15:56:47 +01:00
Folke Lemaitre
85e375223f
fix(ui): always clear complete tasks with the same name when starting a new task 2022-12-17 15:56:47 +01:00
Folke Lemaitre
5c0c381b56
fix(loader): runtime files are now sourced alphabetically per directory 2022-12-17 15:56:47 +01:00
Folke Lemaitre
eeb06a5a50
feat(loader): added error handler to sourcing of runtime files 2022-12-17 15:56:47 +01:00
github-actions[bot]
53affcaaf4 chore(build): auto-generate vimdoc 2022-12-17 11:53:24 +00:00
Folke Lemaitre
f18efa1da1
fix(ui): split window before opening a file from the Lazy ui, otherwise it'll get closed immediately 2022-12-17 12:52:31 +01:00
Folke Lemaitre
6f728e698d
fix(ui): show first tag for each help doc in details 2022-12-17 12:52:30 +01:00
Folke Lemaitre
97366711be
feat(ui): added dir to props 2022-12-17 12:52:30 +01:00
Folke Lemaitre
23984dd1f3
fix: set correct dir for lazy plugin 2022-12-17 12:52:30 +01:00
Folke Lemaitre
2d6559302e
docs: removed toc 2022-12-17 12:52:30 +01:00
github-actions[bot]
fc55edc22e
chore(main): release 4.1.0 (#10)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-16 15:21:03 +01:00
github-actions[bot]
dcae07d01e chore(build): auto-generate vimdoc 2022-12-16 14:11:06 +00:00
Folke Lemaitre
c5d092ed9e
docs: added a section on startup sequence 2022-12-16 15:10:05 +01:00
Folke Lemaitre
0df47d91d1
docs: fixed bootstrap code and make it work for beta testers 2022-12-16 15:09:50 +01:00
Folke Lemaitre
060cf23aca
perf: when reloading plugin specs always use cache 2022-12-16 15:08:09 +01:00
Folke Lemaitre
e897524b1f
refactor: split autoload in autoload and check_load 2022-12-16 13:07:16 +01:00
Folke Lemaitre
f23a6eef8c
perf: prevent string.match to find plugin name from a modpath 2022-12-16 13:06:30 +01:00
Folke Lemaitre
ecf03a6892
refactor: simplified handler code 2022-12-16 12:53:08 +01:00
Folke Lemaitre
17d1653b4a
fix: bootstrap code now uses git url instead of https for beta testers + fixed rtp path 2022-12-15 23:24:16 +01:00
Folke Lemaitre
b8fa6f960f
fix: add lazy.nvim with dev=false to prevent using the dev version for myself 2022-12-15 23:23:45 +01:00
Folke Lemaitre
7134417e89
fix: use initial rtp for rtp plugin after files and use loaded plugins for their after files 2022-12-15 23:23:18 +01:00
github-actions[bot]
6ca03dcd1a chore(build): auto-generate vimdoc 2022-12-15 13:44:45 +00:00
Folke Lemaitre
57dfb05e2f
docs: updated config 2022-12-15 14:43:52 +01:00
github-actions[bot]
9f0a02fb0f chore(build): auto-generate vimdoc 2022-12-15 13:36:25 +00:00
Folke Lemaitre
fd600be2e5
docs: added docs on readme help indexing 2022-12-15 14:34:08 +01:00
Folke Lemaitre
4dfab59c87
refactor: use Util.read_file and Util.write_file for docs 2022-12-15 14:08:09 +01:00
Folke Lemaitre
70ca110ca1
feat: README.md files are now automagically added to help. By default only when no doc/ exists 2022-12-15 14:08:09 +01:00
Folke Lemaitre
27178b5e67
feat: utility methods to read/write files 2022-12-15 14:08:09 +01:00
github-actions[bot]
a2f0637c77 chore(build): auto-generate vimdoc 2022-12-15 08:18:19 +00:00
Folke Lemaitre
aa2f982d22
ci: corrected Neovim version in panvimdoc 2022-12-15 09:15:55 +01:00
github-actions[bot]
1f70834e1c chore(build): auto-generate vimdoc 2022-12-15 08:07:46 +00:00
Folke Lemaitre
c812daf9ee
ci: added lua code blocks to docs 2022-12-15 09:07:01 +01:00
github-actions[bot]
70c0ad1b95 chore(build): auto-generate vimdoc 2022-12-15 07:48:04 +00:00
Folke Lemaitre
d975decf92
docs: added plugin properties 2022-12-15 08:47:01 +01:00
Folke Lemaitre
f4720ee9f7
feat(docs): added toc generator 2022-12-15 08:47:01 +01:00
github-actions[bot]
46d0cdba46 chore(build): auto-generate vimdoc 2022-12-14 23:30:02 +00:00
Folke Lemaitre
f98a663e25
docs: added toc 2022-12-15 00:29:17 +01:00
github-actions[bot]
ed6929c696 chore(build): auto-generate vimdoc 2022-12-14 23:23:54 +00:00
Folke Lemaitre
dc1d71d5cf
docs: added plugin spec code 2022-12-15 00:23:09 +01:00
Folke Lemaitre
80a7839eec
feat: lua code generator for the README.md 2022-12-15 00:23:09 +01:00
Folke Lemaitre
ccdf65b5b8
fix: Plugin.init implies lazy-loading 2022-12-15 00:23:09 +01:00
Folke Lemaitre
869e6dab4b
docs: bootstrap 2022-12-15 00:23:09 +01:00
github-actions[bot]
48edfecb69
chore(main): release 4.0.0 (#9)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-14 22:34:37 +01:00
github-actions[bot]
72914b9166 chore(build): auto-generate vimdoc 2022-12-14 21:11:38 +00:00
Folke Lemaitre
650e192c87
docs: updated feature list 2022-12-14 22:10:50 +01:00
github-actions[bot]
7ca0746fbf chore(build): auto-generate vimdoc 2022-12-14 20:59:50 +00:00
Folke Lemaitre
1adebbbcc7
docs: fixed the cache options 2022-12-14 21:59:01 +01:00
github-actions[bot]
0a34571e49 chore(build): auto-generate vimdoc 2022-12-14 20:58:18 +00:00
Folke Lemaitre
df80b8845a
docs: updates 2022-12-14 21:57:27 +01:00
github-actions[bot]
136776744b chore(build): auto-generate vimdoc 2022-12-14 20:55:03 +00:00
Folke Lemaitre
4392a58c22
docs: added usage and config 2022-12-14 21:54:17 +01:00
github-actions[bot]
eccc3883eb chore(build): auto-generate vimdoc 2022-12-14 20:42:10 +00:00
Folke Lemaitre
a27be6eb31
docs: added bootstrap code 2022-12-14 21:41:19 +01:00
Folke Lemaitre
1ee4e8b719
fix: updated the bootstrap code 2022-12-14 21:38:40 +01:00
Folke Lemaitre
5128d896c7
fix: destroy the cache when VIMRUNTIME has changed 2022-12-14 21:38:24 +01:00
Folke Lemaitre
72f64ce1f7
feat: added checks for Neovim version 2022-12-14 21:25:16 +01:00
Folke Lemaitre
675dece832
docs: added requirements 2022-12-14 21:25:15 +01:00
github-actions[bot]
4d19babf7e chore(build): auto-generate vimdoc 2022-12-14 20:18:23 +00:00
Folke Lemaitre
0f56097612
docs: better screenshot 2022-12-14 21:17:38 +01:00
github-actions[bot]
51cbff1c8b chore(build): auto-generate vimdoc 2022-12-14 20:11:48 +00:00
Folke Lemaitre
c6b76bdc70
docs: updated docs 2022-12-14 21:11:06 +01:00
github-actions[bot]
1daf321580 chore(build): auto-generate vimdoc 2022-12-14 20:09:17 +00:00
Folke Lemaitre
e651e0110d
docs: screenshots 2022-12-14 21:08:28 +01:00
github-actions[bot]
861d180dc8 chore(build): auto-generate vimdoc 2022-12-14 20:07:51 +00:00
Folke Lemaitre
832ba79b77
docs: added screenshot 2022-12-14 21:07:06 +01:00
github-actions[bot]
3a14258e79 chore(build): auto-generate vimdoc 2022-12-14 20:06:06 +00:00
Folke Lemaitre
002210710f
docs: added screenshot 2022-12-14 21:05:25 +01:00
github-actions[bot]
fee15244aa chore(build): auto-generate vimdoc 2022-12-14 20:05:17 +00:00
Folke Lemaitre
861f2d8a56
docs: added feature list 2022-12-14 21:04:04 +01:00
Folke Lemaitre
ec2f432a84
feat!: lazy now handles the full startup sequence (vim.go.loadplugins=false) 2022-12-14 21:03:53 +01:00
Folke Lemaitre
ad0b4caa64
feat(ui): show updates available diagnostic when an update is available 2022-12-14 16:07:53 +01:00
Folke Lemaitre
8de617c01b
feat: getter for plugins 2022-12-14 16:07:32 +01:00
github-actions[bot]
5c7d29e09d
chore(main): release 3.0.0 (#8)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-13 10:36:11 +01:00
github-actions[bot]
b7713856e0 chore(build): auto-generate vimdoc 2022-12-13 09:30:42 +00:00
Folke Lemaitre
1375409642
test: fixed tests 2022-12-13 10:29:48 +01:00
Folke Lemaitre
12ded3f422
fix: replace ~ by HOME for Plugin.dir 2022-12-13 10:29:40 +01:00
Folke Lemaitre
c1fe69afd5
docs: updated todo 2022-12-13 10:10:17 +01:00
Folke Lemaitre
0625493aad
feat!: local plugins now always need to set Plugin.dir 2022-12-13 10:10:17 +01:00
Folke Lemaitre
2a7466abad
feat(checker): only report an update once and do a fast update check after each manage operation 2022-12-13 10:10:17 +01:00
Folke Lemaitre
f24c055fe9
feat: better way of dealing with lazy loaded completions (thanks to @lewis6991) 2022-12-13 10:10:17 +01:00
Folke Lemaitre
4cfe0b5315
refactor: Plugin.uri => Plugin.url 2022-12-13 10:10:17 +01:00
Folke Lemaitre
43b303bd8f
fix: dev plugins with dev=false should be configured as remote 2022-12-13 10:10:17 +01:00
github-actions[bot]
f52cf32f96 chore(build): auto-generate vimdoc 2022-12-06 09:58:23 +00:00
Folke Lemaitre
0393e524e5
refactor: moved plugin handler types to plugin 2022-12-06 10:36:31 +01:00
Folke Lemaitre
be509c01f9
perf: added profiling for sourcing of runtime files 2022-12-05 23:14:04 +01:00
Folke Lemaitre
08d081f21d
fix(ui): open with noautocmd=true and close with vim.schedule to prevent weird errors by other plugins 2022-12-05 22:33:33 +01:00
github-actions[bot]
836cdb2bea chore(build): auto-generate vimdoc 2022-12-05 20:45:14 +00:00
Folke Lemaitre
01c6ee41ba
docs: updated todo 2022-12-05 21:44:26 +01:00
github-actions[bot]
4a2b954d2c chore(build): auto-generate vimdoc 2022-12-05 20:32:21 +00:00
Folke Lemaitre
dc2dcd2d5a
feat: added health checks 2022-12-05 21:31:26 +01:00
Folke Lemaitre
8531995ec7
docs: updated todo 2022-12-05 21:05:20 +01:00
Folke Lemaitre
315be83afc
feat(ui): added statusline component to show pending updates 2022-12-05 20:49:45 +01:00
Folke Lemaitre
65cd28e613
feat(ui): added update checker 2022-12-05 20:49:23 +01:00
Folke Lemaitre
71e4b92fd6
feat(api): return runner from manage operations 2022-12-05 20:36:49 +01:00
github-actions[bot]
dda5c6c0ed
chore(main): release 2.2.0 (#7)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-05 14:49:34 +01:00
github-actions[bot]
f2bfbba134 chore(build): auto-generate vimdoc 2022-12-05 13:48:18 +00:00
Folke Lemaitre
82f5f617f5
docs: update todo 2022-12-05 14:47:30 +01:00
Folke Lemaitre
6d68cc6ea2
feat(ui): added debug interface to inspect active handlers and the module cache 2022-12-05 14:47:30 +01:00
Folke Lemaitre
d36ad410ee
feat: util.foreach with sorted keys 2022-12-05 14:47:30 +01:00
Folke Lemaitre
b8d8648d28
refactor: moved handler to separate modules 2022-12-05 14:47:30 +01:00
github-actions[bot]
1ae4e0ce9a chore(build): auto-generate vimdoc 2022-12-03 22:47:38 +00:00
Folke Lemaitre
7b945eec58
feat: dont run setup again when a user re-sources their config & show a warning 2022-12-03 23:46:50 +01:00
Folke Lemaitre
3f517abfa4
feat: cleanup keys/cmd handlers when loading a plugin 2022-12-03 23:42:05 +01:00
Folke Lemaitre
c98e722fa4
fix: always add config/after to rtp 2022-12-03 21:08:35 +01:00
Folke Lemaitre
13b5688487
feat(ui): show any helps files and added hover handler 2022-12-03 21:07:11 +01:00
Folke Lemaitre
6e44be0f2d
fix(ui): always show branch name in details 2022-12-03 21:06:50 +01:00
Folke Lemaitre
b2727d98a3
perf: disable cache by default on VimEnter or on BufReadPre 2022-12-03 18:59:53 +01:00
github-actions[bot]
c1e44cbc3f
chore(main): release 2.1.0 (#6)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2022-12-03 17:50:13 +01:00
github-actions[bot]
df95e60bdc chore(build): auto-generate vimdoc 2022-12-03 16:47:26 +00:00
Folke Lemaitre
24424f59a0
docs: added pact.nvim 2022-12-03 17:46:34 +01:00
Folke Lemaitre
3ed24baeb0
fix: source plugin files for plugins that want to run a build script during startup 2022-12-03 17:46:34 +01:00
Folke Lemaitre
93d30722a0
fix: add plugin after dir to rtp for start plugins so it gets picked up during startup 2022-12-03 17:46:34 +01:00
Folke Lemaitre
ccc506d5f7
perf: added option to reset rtp to just your config and the neovim runtime 2022-12-03 17:46:34 +01:00
github-actions[bot]
6affae6454 chore(build): auto-generate vimdoc 2022-12-03 14:48:54 +00:00
Folke Lemaitre
dbe2d0942a
feat: plugins no longer need to be installed under site/pack/*/opt 2022-12-03 15:48:06 +01:00
Folke Lemaitre
37c7366ab0
feat: symlinking local plugins is no longer needed 2022-12-03 15:31:21 +01:00
Folke Lemaitre
7b272b6ed6
feat: automatically detect config module changes in or oustside Neovim and reload 2022-12-03 00:12:49 +01:00
Folke Lemaitre
fbfa790d46
refactor: Plugin.local => Plugin.dev 2022-12-02 22:48:47 +01:00
Folke Lemaitre
ec858db225
fix: temporary colorscheme should only load when installing 2022-12-02 22:45:33 +01:00
Folke Lemaitre
7ec65e4cd9
feat: temporary colorscheme to use during install during startup 2022-12-02 19:18:10 +01:00
Folke Lemaitre
0ba218a065
feat: Plugin.local to use a local project instead of fetching remote 2022-12-02 19:17:38 +01:00
Folke Lemaitre
afcba52b1a
fix: return nil when fs_stat fails and return nil in module loader 2022-12-02 19:16:21 +01:00
Folke Lemaitre
756b4849d9
refactor: Plugin.dep => Plugin._.dep 2022-12-02 17:09:40 +01:00
Folke Lemaitre
330dbe7203
feat: Plugin.specs() can now reload and keeps existing state 2022-12-02 17:02:25 +01:00
Folke Lemaitre
ebf15fc198
feat: for event=, fire any new autocmds created by loading the plugins for the event 2022-12-02 17:01:05 +01:00
Folke Lemaitre
e4cf8b1416
feat: added debug option 2022-12-02 16:52:22 +01:00
Folke Lemaitre
fe6b0b03ea
feat: moved Config.package.reset -> Config.performance.reset_packpath 2022-12-02 12:52:06 +01:00
Folke Lemaitre
6fe425c91a
perf: caching strategy is now configurable 2022-12-02 12:43:34 +01:00
Folke Lemaitre
ae379a62dc
fix(git): fixed branch detection, get target commit from origin and always checkout a tag or commit so we dont need to use git merge 2022-12-02 11:26:07 +01:00
Folke Lemaitre
3e143c6017
fix(fs): dont set cloned=true if symlink already existed 2022-12-02 11:24:23 +01:00
Folke Lemaitre
59fb050767
fix: respect --noplugin 2022-12-02 10:02:41 +01:00
github-actions[bot]
60e8a01b94 chore(main): release 2.0.0 2022-12-02 09:27:54 +01:00
github-actions[bot]
d04962b231 chore(build): auto-generate vimdoc 2022-12-02 08:26:19 +00:00
Folke Lemaitre
b0091d40e3
docs: updated todo 2022-12-02 09:25:30 +01:00
Folke Lemaitre
45e18c977d
test: fix tests with module= 2022-12-02 09:25:30 +01:00
Folke Lemaitre
98ccf556d8
fix(ui): use Plugin.find to detect loading reason 2022-12-02 09:25:30 +01:00
Folke Lemaitre
575421b3fb
feat!: plugins are now autmatically loaded on require. module= no longer needed! 2022-12-02 09:25:30 +01:00
Folke Lemaitre
0b6dec46e0
perf: module now caches all lua modules used till VimEnter 2022-12-02 09:25:30 +01:00
Folke Lemaitre
723274efee
feat(ui): better detection of plugins/config files that loaded a plugin 2022-12-02 09:25:30 +01:00
Folke Lemaitre
e22e8e4506
style: added more comments to init 2022-12-02 09:25:30 +01:00
Folke Lemaitre
ac9e5401dc
test: test XDG paths for tests and added a test that checks if they are setup correctly 2022-12-02 09:25:30 +01:00
Folke Lemaitre
d46bc7795c
fix: always overwrite any plugin spec for lazy.nvim to manage itself 2022-12-02 09:25:30 +01:00
Folke Lemaitre
714bc0a136
feat(ui): improvements to profiling and rendering of loaded reasons 2022-12-02 09:25:30 +01:00
Folke Lemaitre
5eb2622a4e
fix: prepend package path to packpath if package.reset=false 2022-12-02 09:25:30 +01:00
Folke Lemaitre
041a716f4e
feat: show module source if loading source is under config 2022-12-02 09:25:30 +01:00
github-actions[bot]
64af691be3 chore(build): auto-generate vimdoc 2022-12-01 12:34:59 +00:00
Folke Lemaitre
af8b8e128e
feat: lazy setup with either a plugins module, or a plugins spec 2022-12-01 13:34:01 +01:00
github-actions[bot]
f0894be69d chore(build): auto-generate vimdoc 2022-12-01 10:33:48 +00:00
Folke Lemaitre
0dbf72f67e
docs: opt => lazy 2022-12-01 11:32:52 +01:00
Folke Lemaitre
4653119625
perf: reset packpath to only include the lazy package. Improved my startup time by 2ms 2022-12-01 11:23:39 +01:00
Folke Lemaitre
5134e797f3
feat!: all plugins are now opt. Plugin.opt => Plugin.lazy 2022-12-01 11:23:39 +01:00
Folke Lemaitre
5e0662727d
style: fixed some selene errors/warnings 2022-12-01 11:23:39 +01:00
Folke Lemaitre
44b6e54dcb
build: added selene 2022-12-01 11:23:39 +01:00
github-actions[bot]
2d676b35d2 chore(build): auto-generate vimdoc 2022-12-01 06:44:31 +00:00
Folke Lemaitre
042aaa4f87
feat!: renamed Plugin.run => Plugin.build 2022-12-01 07:43:34 +01:00
github-actions[bot]
ec4199bada chore(main): release 1.2.0 2022-11-30 23:45:53 +01:00
Folke Lemaitre
c1a05a5f9b
test: process config timeout can be nil 2022-11-30 23:44:10 +01:00
Folke Lemaitre
bd2d64230f
feat: added config option for process timeout 2022-11-30 23:38:52 +01:00
github-actions[bot]
f2072f0158 chore(build): auto-generate vimdoc 2022-11-30 22:16:15 +00:00
Folke Lemaitre
2eb11b1f69
docs: todo 2022-11-30 23:15:26 +01:00
Folke Lemaitre
b2339ade84
feat: config option for runner concurrency 2022-11-30 23:15:26 +01:00
Folke Lemaitre
a87b6e1005
style: cleanup 2022-11-30 23:15:26 +01:00
Folke Lemaitre
a197f751f9
feat: config option for ui throttle 2022-11-30 23:15:26 +01:00
Folke Lemaitre
0cff878b2e
feat: config for ui border 2022-11-30 23:15:26 +01:00
Folke Lemaitre
fb96183753
feat: allow config of default for version field 2022-11-30 23:15:26 +01:00
Folke Lemaitre
334f32e595
refactor: renamed Config.opt => Config.defaults.opt 2022-11-30 23:15:26 +01:00
Folke Lemaitre
5d81c5062b
refactor: renamed plugins_local to dev 2022-11-30 23:15:26 +01:00
Folke Lemaitre
47f5c124aa
config: removed interactive option. not needed 2022-11-30 23:15:26 +01:00
Folke Lemaitre
0369278159
fix: update state after running operation so the ui reflects any changes from cleaning 2022-11-30 23:15:26 +01:00
Folke Lemaitre
1e2f5273bb
fix: show proper installed/clean state for local plugins 2022-11-30 23:15:26 +01:00
Folke Lemaitre
39c7e21c5f
refactor: Loader.source_runtime 2022-11-30 23:15:26 +01:00
github-actions[bot]
fc0a10150f chore(build): auto-generate vimdoc 2022-11-30 13:20:44 +00:00
Folke Lemaitre
e1c08d64b3
perf: merge module/cache and use ffi to pack cache data 2022-11-30 14:19:50 +01:00
Folke Lemaitre
4438faf9a9
perf: removed partial spec caching. not worth the tiny performance boost 2022-11-30 00:19:08 +01:00
Folke Lemaitre
9be3d3d840
feat: config option install_missing=true 2022-11-30 00:19:08 +01:00
Folke Lemaitre
3ec5a2ce4c
perf: run cache autosave after loading 2022-11-30 00:19:08 +01:00
102 changed files with 132754 additions and 2068 deletions

11
.busted Normal file
View file

@ -0,0 +1,11 @@
return {
_all = {
coverage = false,
},
default = {
verbose = true,
},
tests = {
verbose = true,
},
}

7
.editorconfig Normal file
View file

@ -0,0 +1,7 @@
root = true
[*]
insert_final_newline = true
indent_style = space
indent_size = 2
charset = utf-8

3
.github/.release-please-manifest.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
".": "11.17.1"
}

View file

@ -1,36 +0,0 @@
---
name: Bug report
about: "Create a report to help us improve"
title: ""
labels: "bug"
assignees: ""
---
**Describe the bug**
A clear and concise description of what the bug is.
**Which version of Neovim are you using?**
Gui(specify which GUI client you are using)? Nightly? Version?
**To Reproduce**
Steps to reproduce the behavior:
1.
2.
3.
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Log**
Please include any related errors from the Noice log file. (open with `:Lazy log`)
<details>
<summary>Lazy log</summary>
<pre>
paste log here
</pre>
</details>

75
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View file

@ -0,0 +1,75 @@
name: Bug Report
description: File a bug/issue
title: "bug: "
labels: [bug]
body:
- type: markdown
attributes:
value: |
**Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/lazy.nvim)
and search [existing issues](https://github.com/folke/lazy.nvim/issues).
Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/lazy.nvim/discussions) and will be closed.
- type: checkboxes
attributes:
label: Did you check docs and existing issues?
description: Make sure you checked all of the below before submitting an issue
options:
- label: I have read all the lazy.nvim docs
required: true
- label: I have updated the plugin to the latest version before submitting this issue
required: true
- label: I have searched the existing issues of lazy.nvim
required: true
- label: I have searched the existing issues of plugins related to this issue
required: true
- type: input
attributes:
label: "Neovim version (nvim -v)"
placeholder: "0.8.0 commit db1b0ee3b30f"
validations:
required: true
- type: input
attributes:
label: "Operating system/version"
placeholder: "MacOS 11.5"
validations:
required: true
- type: textarea
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is. Please include any related errors you see in Neovim.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: Steps to reproduce the behavior.
placeholder: |
1.
2.
3.
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: Repro
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
value: |
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
-- add any other plugins here
},
})
render: lua
validations:
required: false

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Ask a question
url: https://github.com/folke/lazy.nvim/discussions
about: Use Github discussions instead

View file

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'enhancement'
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -0,0 +1,36 @@
name: Feature Request
description: Suggest a new feature
title: "feature: "
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Did you check the docs?
description: Make sure you read all the docs before submitting a feature request
options:
- label: I have read all the lazy.nvim docs
required: true
- type: textarea
validations:
required: true
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
- type: textarea
validations:
required: true
attributes:
label: Describe the solution you'd like
description: A clear and concise description of what you want to happen.
- type: textarea
validations:
required: true
attributes:
label: Describe alternatives you've considered
description: A clear and concise description of any alternative solutions or features you've considered.
- type: textarea
validations:
required: false
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,16 @@
## Description
<!-- Describe the big picture of your changes to communicate to the maintainers
why we should accept this pull request. -->
## Related Issue(s)
<!--
If this PR fixes any issues, please link to the issue here.
- Fixes #<issue_number>
-->
## Screenshots
<!-- Add screenshots of the changes if applicable. -->

6
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

9
.github/release-please-config.json vendored Normal file
View file

@ -0,0 +1,9 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"packages": {
".": {
"release-type": "simple",
"extra-files": ["lua/lazy/core/config.lua"]
}
}
}

View file

@ -1,48 +1,15 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Neovim
run: |
wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.deb -O /tmp/nvim.deb
sudo dpkg -i /tmp/nvim.deb
- name: Run Tests
run: |
nvim --version
./tests/run
docs:
runs-on: ubuntu-latest
needs: tests
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v3
- name: panvimdoc
uses: kdheepak/panvimdoc@main
with:
vimdoc: lazy.nvim
demojify: true
- name: Push changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore(build): auto-generate vimdoc"
commit_user_name: "github-actions[bot]"
commit_user_email: "github-actions[bot]@users.noreply.github.com"
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
release:
name: release
if: ${{ github.ref == 'refs/heads/main' }}
needs:
- docs
- tests
runs-on: ubuntu-latest
steps:
- uses: google-github-actions/release-please-action@v3
with:
release-type: simple
package-name: lazy.nvim
ci:
uses: folke/github/.github/workflows/ci.yml@main
secrets: inherit
with:
plugin: lazy.nvim
repo: folke/lazy.nvim
docs: false

30
.github/workflows/community.yml vendored Normal file
View file

@ -0,0 +1,30 @@
name: Community
on:
push:
branches:
- main
jobs:
community:
runs-on: ubuntu-latest
if: ${{ github.ref == 'refs/heads/main' && github.repository_owner == 'folke' }}
steps:
- uses: actions/checkout@v4
- uses: folke/github/neovim@main
- name: Rockspec Build
id: rockspec-build
uses: actions/cache@v4
with:
path: build
key: rockspec-build
- name: Generate Rockspec
if: steps.rockspec-build.cache-hit != 'true'
run: |
nvim -l lua/lazy/build.lua
- name: Push changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore(build): auto-generate rockspec mappings"
commit_user_name: "github-actions[bot]"
commit_user_email: "github-actions[bot]@users.noreply.github.com"
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"

19
.github/workflows/docs.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: Docs
on:
push:
branches:
- main
jobs:
docs:
runs-on: ubuntu-latest
if: ${{ github.ref == 'refs/heads/main' && github.repository_owner == 'folke' }}
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
with:
ref: docs
- name: Generate Docs
shell: bash
run: gh workflow run "Deploy to Github Pages" --ref docs

8
.github/workflows/labeler.yml vendored Normal file
View file

@ -0,0 +1,8 @@
name: "PR Labeler"
on:
- pull_request_target
jobs:
labeler:
uses: folke/github/.github/workflows/labeler.yml@main
secrets: inherit

18
.github/workflows/pr.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: PR Title
on:
pull_request_target:
types:
- opened
- edited
- synchronize
- reopened
- ready_for_review
permissions:
pull-requests: read
jobs:
pr-title:
uses: folke/github/.github/workflows/pr.yml@main
secrets: inherit

11
.github/workflows/stale.yml vendored Normal file
View file

@ -0,0 +1,11 @@
name: Stale Issues & PRs
on:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
if: contains(fromJSON('["folke", "LazyVim"]'), github.repository_owner)
uses: folke/github/.github/workflows/stale.yml@main
secrets: inherit

13
.github/workflows/update.yml vendored Normal file
View file

@ -0,0 +1,13 @@
name: Update Repo
on:
workflow_dispatch:
schedule:
# Run every hour
- cron: "0 * * * *"
jobs:
update:
if: contains(fromJSON('["folke", "LazyVim"]'), github.repository_owner)
uses: folke/github/.github/workflows/update.yml@main
secrets: inherit

12
.gitignore vendored
View file

@ -1,3 +1,9 @@
tt.lua
.tests
doc/tags
*.log
/.repro
/.tests
/build
/debug
/doc/tags
foo.*
node_modules
tt.*

12
.markdownlint.yaml Normal file
View file

@ -0,0 +1,12 @@
MD013:
line_length: 120
tables: false
MD033:
allowed_elements:
- "details"
- "summary"
- "b"
- "table"
- "tr"
- "td"
- "a"

View file

@ -7,7 +7,7 @@
}
},
"lspconfig": {
"sumneko_lua": {
"lua_ls": {
"Lua.runtime.version": "LuaJIT",
"Lua.workspace.checkThirdParty": false
}

1
.styluaignore Normal file
View file

@ -0,0 +1 @@
lua/lazy/community/_generated.lua

File diff suppressed because it is too large Load diff

201
LICENSE Normal file
View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

110
README.md
View file

@ -1,55 +1,69 @@
# lazy.nvim
<h4 align="center">
<a href="https://lazy.folke.io/installation">Install</a>
·
<a href="https://lazy.folke.io/configuration">Configure</a>
·
<a href="https://lazy.folke.io">Docs</a>
</h4>
<div align="center"><p>
<a href="https://github.com/folke/lazy.nvim/releases/latest">
<img alt="Latest release" src="https://img.shields.io/github/v/release/folke/lazy.nvim?style=for-the-badge&logo=starship&color=C9CBFF&logoColor=D9E0EE&labelColor=302D41&include_prerelease&sort=semver" />
</a>
<a href="https://github.com/folke/lazy.nvim/pulse">
<img alt="Last commit" src="https://img.shields.io/github/last-commit/folke/lazy.nvim?style=for-the-badge&logo=starship&color=8bd5ca&logoColor=D9E0EE&labelColor=302D41"/>
</a>
<a href="https://github.com/folke/lazy.nvim/blob/main/LICENSE">
<img alt="License" src="https://img.shields.io/github/license/folke/lazy.nvim?style=for-the-badge&logo=starship&color=ee999f&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/folke/lazy.nvim/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/folke/lazy.nvim?style=for-the-badge&logo=starship&color=c69ff5&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/folke/lazy.nvim/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/folke/lazy.nvim?style=for-the-badge&logo=bilibili&color=F5E0DC&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/folke/lazy.nvim">
<img alt="Repo Size" src="https://img.shields.io/github/repo-size/folke/lazy.nvim?color=%23DDB6F2&label=SIZE&logo=codesandbox&style=for-the-badge&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://twitter.com/intent/follow?screen_name=folke">
<img alt="follow on Twitter" src="https://img.shields.io/twitter/follow/folke?style=for-the-badge&logo=twitter&color=8aadf3&logoColor=D9E0EE&labelColor=302D41" />
</a>
</div>
**lazy.nvim** is a modern plugin manager for Neovim.
![image](https://user-images.githubusercontent.com/292349/208301737-68fb279c-ba70-43ef-a369-8c3e8367d6b1.png)
## ✨ Features
- [x] Partial clones instead of shallow clones
- [x] waits till missing deps are installed (bootstrap Neovim and start using it right away)
- [x] Async
- [x] No need for compile
- [x] Fast
- [x] Correct sequencing of dependencies (deps should always be opt. Maybe make everything opt?)
- [ ] Import specs from Packer
- [x] Config in multiple files
- [x] Patterns for local packages
- [x] Profiling
- [x] lockfile
- [x] upvalues in `config` & `init`
- [x] check for updates
- [ ] package.lua
- [ ] package-lock.lua
- [x] tag/version support `git tag --sort version:refname`
- [x] auto-loading on completion for lazy-loaded commands
- [x] bootstrap code
- [x] semver https://devhints.io/semver
https://semver.npmjs.com/
- 📦 Manage all your Neovim plugins with a powerful UI
- 🚀 Fast startup times thanks to automatic caching and bytecode compilation of Lua modules
- 💾 Partial clones instead of shallow clones
- 🔌 Automatic lazy-loading of Lua modules and lazy-loading on events, commands, filetypes, and key mappings
- ⏳ Automatically install missing plugins before starting up Neovim, allowing you to start using it right away
- 💪 Async execution for improved performance
- 🛠️ No need to manually compile plugins
- 🧪 Correct sequencing of dependencies
- 📁 Configurable in multiple files
- 📚 Generates helptags of the headings in `README.md` files for plugins that don't have vimdocs
- 💻 Dev options and patterns for using local plugins
- 📊 Profiling tools to optimize performance
- 🔒 Lockfile `lazy-lock.json` to keep track of installed plugins
- 🔎 Automatically check for updates
- 📋 Commit, branch, tag, version, and full [Semver](https://devhints.io/semver) support
- 📈 Statusline component to see the number of pending updates
- 🎨 Automatically lazy-loads colorschemes
## ✅ TODO
## ⚡️ Requirements
- [ ] health checks: check merge conflicts async
- [ ] allow setting up plugins through config
- [x] support for Plugin.lock
- [x] defaults for git log
- [x] view keybindings for update/clean/...
- [x] add profiler to view
- [x] add buttons for actions
- [x] show time taken for op in view
- [ ] package meta index (package.lua cache for all packages)
- [ ] auto lazy-loading of lua modules
- [ ] use uv file watcher to check for config changes
- [x] clear errors
- [x] add support for versions `git tag --sort v:refname`
- [x] rename requires to dependencies
- [x] move tasks etc to Plugin.state
- [x] handlers imply opt
- [x] dependencies imply opt for deps
- [x] fix local plugin spec
- [ ] investigate all opt=true. Simplifies logic (easily switch between opt/start afterwards)
- [ ] add support to specify `engines`, `os` and `cpu` like in `package.json`
- Neovim >= **0.8.0** (needs to be built with **LuaJIT**)
- Git >= **2.19.0** (for partial clones support)
- a [Nerd Font](https://www.nerdfonts.com/) **_(optional)_**
- [luarocks](https://luarocks.org/) to install rockspecs.
You can remove `rockspec` from `opts.pkg.sources` to disable this feature.
## 📦 Differences with Packer
## 🚀 Getting Started
- **Plugin Spec**:
- `setup` => `init`
- `requires` => `dependencies`
- `as` => `name`
Check the [documentation website](https://lazy.folke.io/) for more information.

79
TODO.md Normal file
View file

@ -0,0 +1,79 @@
# ✅ TODO
- [x] progress bar?
- [x] options when opening file
- [x] lazy notify? not ideal when installing missing stuff
- [x] topmods?
- [ ] better merging options?
- [ ] especially what to do with merging of handlers?
- [ ] overwriting keymaps probably doesn't work
- [ ] disabled deps?
- [x] fancy UI to manage all your Neovim plugins
- [x] auto lazy-loading of lua modules
- [x] lazy-loading on events, commands, filetypes and key mappings
- [x] Partial clones instead of shallow clones
- [x] waits till missing deps are installed (bootstrap Neovim and start using it right away)
- [x] Async
- [x] No need to manually compile
- [x] Fast. Automatically caches and compiles byte code of all lua modules needed during startup
- [x] Correct sequencing of dependencies (deps should always be opt. Maybe make everything opt?)
- [x] Config in multiple files
- [x] dev option and patterns for local packages
- [x] Profiling
- [x] lockfile `lazy-lock.json`
- [x] upvalues in `config` & `init`
- [x] automatically check for updates
- [x] commit, branch, tag, version and full semver support
- [x] statusline component to see number of pending updates
- [x] semver https://devhints.io/semver
- [x] auto-loading on completion for lazy-loaded commands
- [x] bootstrap code
- [x] Background update checker
- [x] health checks: check merge conflicts async
- [x] unsupported props or props from other managers
- [x] other packages still in site?
- [x] other package manager artifacts still present? compiled etc
- [x] status page showing running handlers and cache stats
- [x] temp colorscheme used during startup when installing missing plugins
- [x] automatically reloads when config changes are detected
- [x] handlers imply opt
- [x] dependencies imply opt for deps
- [x] show spec errors in health
- [x] fix plugin details
- [ ] show disabled plugins (strikethrough?)
- [ ] log file
- [x] git tests
- [x] Import specs from other plugin managers
- [ ] [packspec](https://github.com/nvim-lua/nvim-package-specification)
- [ ] add support to specify `engines`, `os` and `cpu` like in `package.json`
- [ ] semver merging. Should check if two or more semver ranges are compatible and calculate the union range
- default semver merging strategy: if no version matches all, then use the highest version?
- [ ] package meta index (package.lua cache for all packages)
- [x] document highlight groups
- [x] document user events
- [x] document API, like lazy.plugins()
- [x] icons
- [x] check in cache if rtp files match
- [x] I think the installation section, specifically the loading part, could use an
extra sentence or two. I was confused on what `config.plugins` was initially.
Maybe a quick, "for example, if you have a lua file
`~/.config/nvim/lua/config/plugins.lua` that returns a table" or something it'd
remove most question marks I think.
- [x] When auto-installing the plugins the cursor isn't focused on the floating
window, but on the non-floating window in the background.
- [x] Doing `:Lazy clean` doesn't show which plugins were removed.
- [x] Shouldn't the "Versioning" section be in the "Lockfile" chapter?
- [x] Why are personal dotfiles used as examples? Dotfiles change all the time,
there's no guarantee this will be relevant or even exist in two years.
- [x] What's the difference between lazy-loading and verylazy-loading?
- [x] Most emojis in "Configuration" aren't shown for me.
- [x] add section on how to uninstall
- [x] add `:Packadd` command or something similar
- [x] headless install
- [x] better keys handling

51
bootstrap.lua Normal file
View file

@ -0,0 +1,51 @@
-- Lazy Bootstrapper
-- Usage:
-- ```lua
-- load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
-- ```
local M = {}
function M.setup()
local uv = vim.uv or vim.loop
if vim.env.LAZY_STDPATH then
local root = vim.fn.fnamemodify(vim.env.LAZY_STDPATH, ":p"):gsub("[\\/]$", "")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
end
if vim.env.LAZY_PATH and not uv.fs_stat(vim.env.LAZY_PATH) then
vim.env.LAZY_PATH = nil
end
local lazypath = vim.env.LAZY_PATH or vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.env.LAZY_PATH and not uv.fs_stat(lazypath) then
vim.api.nvim_echo({
{
"Cloning lazy.nvim\n\n",
"DiagnosticInfo",
},
}, true, {})
local lazyrepo = "https://github.com/folke/lazy.nvim.git"
local ok, out = pcall(vim.fn.system, {
"git",
"clone",
"--filter=blob:none",
lazyrepo,
lazypath,
})
if not ok or vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim\n", "ErrorMsg" },
{ vim.trim(out or ""), "WarningMsg" },
{ "\nPress any key to exit...", "MoreMsg" },
}, true, {})
vim.fn.getchar()
os.exit(1)
end
end
vim.opt.rtp:prepend(lazypath)
end
M.setup()
return M

0
doc/.keep Normal file
View file

File diff suppressed because it is too large Load diff

222
lua/lazy/async.lua Normal file
View file

@ -0,0 +1,222 @@
local Util = require("lazy.core.util")
local M = {}
---@type Async[]
M._active = {}
---@type Async[]
M._suspended = {}
M._executor = assert(vim.loop.new_check())
M.BUDGET = 10
---@type table<thread, Async>
M._threads = setmetatable({}, { __mode = "k" })
---@alias AsyncEvent "done" | "error" | "yield" | "ok"
---@class Async
---@field _co thread
---@field _fn fun()
---@field _suspended? boolean
---@field _on table<AsyncEvent, fun(res:any, async:Async)[]>
local Async = {}
---@param fn async fun()
---@return Async
function Async.new(fn)
local self = setmetatable({}, { __index = Async })
return self:init(fn)
end
---@param fn async fun()
---@return Async
function Async:init(fn)
self._fn = fn
self._on = {}
self._co = coroutine.create(function()
local ok, err = pcall(self._fn)
if not ok then
self:_emit("error", err)
end
self:_emit("done")
end)
M._threads[self._co] = self
return M.add(self)
end
---@param event AsyncEvent
---@param cb async fun(res:any, async:Async)
function Async:on(event, cb)
self._on[event] = self._on[event] or {}
table.insert(self._on[event], cb)
return self
end
---@private
---@param event AsyncEvent
---@param res any
function Async:_emit(event, res)
for _, cb in ipairs(self._on[event] or {}) do
cb(res, self)
end
end
function Async:running()
return coroutine.status(self._co) ~= "dead"
end
---@async
function Async:sleep(ms)
vim.defer_fn(function()
self:resume()
end, ms)
self:suspend()
end
---@async
---@param yield? boolean
function Async:suspend(yield)
self._suspended = true
if coroutine.running() == self._co and yield ~= false then
M.yield()
end
end
function Async:resume()
self._suspended = false
M._run()
end
---@async
---@param yield? boolean
function Async:wake(yield)
local async = M.running()
assert(async, "Not in an async context")
self:on("done", function()
async:resume()
end)
async:suspend(yield)
end
---@async
function Async:wait()
if coroutine.running() == self._co then
error("Cannot wait on self")
end
local async = M.running()
if async then
self:wake()
else
while self:running() do
vim.wait(10)
end
end
return self
end
function Async:step()
if self._suspended then
return true
end
local status = coroutine.status(self._co)
if status == "suspended" then
local ok, res = coroutine.resume(self._co)
if not ok then
error(res)
elseif res then
self:_emit("yield", res)
end
end
return self:running()
end
function M.abort()
for _, async in ipairs(M._active) do
coroutine.resume(async._co, "abort")
end
end
function M.yield()
if coroutine.yield() == "abort" then
error("aborted", 2)
end
end
function M.step()
local start = vim.uv.hrtime()
for _ = 1, #M._active do
if Util.exiting() or vim.uv.hrtime() - start > M.BUDGET * 1e6 then
break
end
local state = table.remove(M._active, 1)
if state:step() then
if state._suspended then
table.insert(M._suspended, state)
else
table.insert(M._active, state)
end
end
end
for _ = 1, #M._suspended do
local state = table.remove(M._suspended, 1)
table.insert(state._suspended and M._suspended or M._active, state)
end
-- M.debug()
if #M._active == 0 or Util.exiting() then
return M._executor:stop()
end
end
function M.debug()
local lines = {
"- active: " .. #M._active,
"- suspended: " .. #M._suspended,
}
for _, async in ipairs(M._active) do
local info = debug.getinfo(async._fn)
local file = vim.fn.fnamemodify(info.short_src:sub(1), ":~:.")
table.insert(lines, ("%s:%d"):format(file, info.linedefined))
if #lines > 10 then
break
end
end
local msg = table.concat(lines, "\n")
M._notif = vim.notify(msg, nil, { replace = M._notif })
end
---@param async Async
function M.add(async)
table.insert(M._active, async)
M._run()
return async
end
function M._run()
if not Util.exiting() and not M._executor:is_active() then
M._executor:start(vim.schedule_wrap(M.step))
end
end
function M.running()
local co = coroutine.running()
if co then
return M._threads[co]
end
end
---@async
---@param ms number
function M.sleep(ms)
local async = M.running()
assert(async, "Not in an async context")
async:sleep(ms)
end
M.Async = Async
M.new = Async.new
return M

100
lua/lazy/build.lua Normal file
View file

@ -0,0 +1,100 @@
vim.opt.rtp:append(".")
local Rocks = require("lazy.pkg.rockspec")
local Semver = require("lazy.manage.semver")
local Util = require("lazy.util")
local M = {}
M.patterns = { "nvim", "treesitter", "tree-sitter", "cmp", "neo" }
function M.fetch(url, file, prefix)
if not vim.uv.fs_stat(file) then
print((prefix or "") .. "Fetching " .. url .. " to " .. file .. "\n")
vim.cmd.redraw()
local out = vim.fn.system("wget " .. url .. " -O " .. file)
if vim.v.shell_error ~= 0 then
pcall(vim.uv.fs_unlink, file)
error("Failed to fetch " .. url .. ":\n" .. out)
end
end
end
---@return RockManifest?
function M.fetch_manifest()
local manifest_file = "build/manifest.lua"
M.fetch("https://luarocks.org/manifest-5.1", manifest_file)
return Rocks.parse(manifest_file)
end
function M.fetch_rockspec(name, version, prefix)
version = version or "scm-1"
local url = "https://luarocks.org/" .. name .. "-" .. version .. ".rockspec"
M.fetch(url, "build/" .. name .. ".rockspec", prefix)
end
function M.build()
vim.fn.mkdir("build", "p")
local manifest = M.fetch_manifest() or {}
---@type {name:string, version:string, url:string}[]
local nvim_rocks = {}
for rock, vv in pairs(manifest.repository or {}) do
local matches = false
for _, pattern in ipairs(M.patterns) do
if rock:find(pattern, 1, true) then
matches = true
break
end
end
if matches then
local versions = vim.tbl_map(Semver.version, vim.tbl_keys(vv))
versions = vim.tbl_filter(function(v)
return not not v
end, versions)
local last = Semver.last(versions) or next(vv)
last = type(last) == "table" and last.input or last
table.insert(nvim_rocks, { name = rock, version = last })
end
end
table.sort(nvim_rocks, function(a, b)
return a.name < b.name
end)
for r, rock in ipairs(nvim_rocks) do
local progress = string.format("[%d/%d] ", r, #nvim_rocks)
local ok, err = pcall(M.fetch_rockspec, rock.name, rock.version, progress)
if not ok then
err = vim.trim("Error: " .. err)
local lines = vim.split(err, "\n")
lines = vim.tbl_map(function(line)
return " " .. line
end, lines)
print(table.concat(lines, "\n") .. "\n")
end
end
for _, rock in ipairs(nvim_rocks) do
local rockspec = Rocks.rockspec("build/" .. rock.name .. ".rockspec")
if rockspec then
local url = rockspec.source and rockspec.source.url
-- parse github short url
if url and url:find("://github.com/") then
url = url:gsub("^.*://github.com/", "")
local parts = vim.split(url, "/")
url = parts[1] .. "/" .. parts[2]
url = url:gsub("%.git$", "")
end
if url then
rock.url = url
print(rock.name .. " " .. url)
else
print("Error: " .. rock.name .. " missing source url\n\n")
print(vim.inspect(rockspec) .. "\n")
end
end
end
Util.write_file("lua/lazy/community/_generated.lua", "return \n" .. vim.inspect(nvim_rocks))
end
M.build()
return M

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
local M = {}
---@type table<string, string>
local mapping = nil
local function load()
if not mapping then
mapping = {}
---@type {name:string, url:string, version:string}[]
local gen = require("lazy.community._generated")
for _, rock in ipairs(gen) do
mapping[rock.name] = rock.url
end
end
return mapping
end
---@param rock string
---@return string?
function M.get_url(rock)
return load()[rock]
end
function M.get_spec(name)
return require("lazy.community.specs")[name]
end
return M

View file

@ -0,0 +1,7 @@
---@type table<string, LazySpec>
return {
["plenary.nvim"] = {
"nvim-lua/plenary.nvim",
lazy = true,
},
}

View file

@ -1,104 +1,528 @@
-- Simple string cache with fast saving and loading from file
local uv = vim.uv or vim.loop
local M = {}
M.dirty = false
---@alias CacheHash {mtime: {sec:number, nsec:number}, size:number}
---@alias CacheEntry {hash:CacheHash, chunk:string}
local cache_path = vim.fn.stdpath("state") .. "/lazy.state"
---@type string
local cache_hash = ""
---@type table<string,boolean>
local used = {}
---@type table<string,string>
local cache = {}
---@class ModuleFindOpts
---@field all? boolean Search for all matches (defaults to `false`)
---@field rtp? boolean Search for modname in the runtime path (defaults to `true`)
---@field patterns? string[] Patterns to use (defaults to `{"/init.lua", ".lua"}`)
---@field paths? string[] Extra paths to search for modname
---@return string?
function M.get(key)
if cache[key] then
used[key] = true
return cache[key]
---@class ModuleInfo
---@field modpath string Path of the module
---@field modname string Name of the module
---@field stat? uv_fs_t File stat of the module path
---@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?>
M.path = vim.fn.stdpath("cache") .. "/luac"
M.enabled = false
---@class Loader
---@field _rtp string[]
---@field _rtp_pure string[]
---@field _rtp_key string
local Loader = {
VERSION = 3,
---@type table<string, table<string,ModuleInfo>>
_indexed = {},
---@type table<string, string[]>
_topmods = {},
_loadfile = loadfile,
---@type LoaderStats
_stats = {
find = { total = 0, time = 0, not_found = 0 },
},
}
--- Tracks the time spent in a function
---@private
function Loader.track(stat, start)
Loader._stats[stat] = Loader._stats[stat] or { total = 0, time = 0 }
Loader._stats[stat].total = Loader._stats[stat].total + 1
Loader._stats[stat].time = Loader._stats[stat].time + uv.hrtime() - start
end
--- slightly faster/different version than vim.fs.normalize
--- we also need to have it here, since the loader will load vim.fs
---@private
function Loader.normalize(path)
if path:sub(1, 1) == "~" then
local home = uv.os_homedir() or "~"
if home:sub(-1) == "\\" or home:sub(-1) == "/" then
home = home:sub(1, -2)
end
path = home .. path:sub(2)
end
path = path:gsub("\\", "/"):gsub("/+", "/")
return path:sub(-1) == "/" and path:sub(1, -2) or path
end
function M.debug()
local ret = {}
for key, value in pairs(cache) do
ret[key] = #value
--- Gets the rtp excluding after directories.
--- The result is cached, and will be updated if the runtime path changes.
--- When called from a fast event, the cached value will be returned.
--- @return string[] rtp, boolean updated
---@private
function Loader.get_rtp()
local start = uv.hrtime()
if vim.in_fast_event() then
Loader.track("get_rtp", start)
return (Loader._rtp or {}), false
end
return ret
local updated = false
local key = vim.go.rtp
if key ~= Loader._rtp_key then
Loader._rtp = {}
for _, path in ipairs(vim.api.nvim_get_runtime_file("", true)) do
path = Loader.normalize(path)
-- skip after directories
if path:sub(-6, -1) ~= "/after" and not (Loader._indexed[path] and vim.tbl_isempty(Loader._indexed[path])) then
Loader._rtp[#Loader._rtp + 1] = path
end
end
updated = true
Loader._rtp_key = key
end
Loader.track("get_rtp", start)
return Loader._rtp, updated
end
function M.set(key, value)
cache[key] = value
used[key] = true
M.dirty = true
--- Returns the cache file name
---@param name string can be a module name, or a file name
---@return string file_name
---@private
function Loader.cache_file(name)
local ret = M.path .. "/" .. name:gsub("[/\\:]", "%%")
return ret:sub(-4) == ".lua" and (ret .. "c") or (ret .. ".luac")
end
function M.del(key)
cache[key] = nil
M.dirty = true
--- Saves the cache entry for a given module or file
---@param name string module name or filename
---@param entry CacheEntry
---@private
function Loader.write(name, entry)
local cname = Loader.cache_file(name)
local f = assert(uv.fs_open(cname, "w", 438))
local header = {
Loader.VERSION,
entry.hash.size,
entry.hash.mtime.sec,
entry.hash.mtime.nsec,
}
uv.fs_write(f, table.concat(header, ",") .. "\0")
uv.fs_write(f, entry.chunk)
uv.fs_close(f)
end
function M.hash(file)
local stat = vim.loop.fs_stat(file)
return stat and (stat.mtime.sec .. stat.mtime.nsec .. stat.size)
--- Loads the cache entry for a given module or file
---@param name string module name or filename
---@return CacheEntry?
---@private
function Loader.read(name)
local start = uv.hrtime()
local cname = Loader.cache_file(name)
local f = uv.fs_open(cname, "r", 438)
if f then
local hash = uv.fs_fstat(f) --[[@as CacheHash]]
local data = uv.fs_read(f, hash.size, 0) --[[@as string]]
uv.fs_close(f)
local zero = data:find("\0", 1, true)
if not zero then
return
end
---@type integer[]|{[0]:integer}
local header = vim.split(data:sub(1, zero - 1), ",")
if tonumber(header[1]) ~= Loader.VERSION then
return
end
Loader.track("read", start)
return {
hash = { size = tonumber(header[2]), mtime = { sec = tonumber(header[3]), nsec = tonumber(header[4]) } },
chunk = data:sub(zero + 1),
}
end
Loader.track("read", start)
end
function M.setup()
M.load()
vim.api.nvim_create_autocmd("User", {
pattern = "LazyDone",
once = true,
callback = function()
vim.api.nvim_create_autocmd("VimLeavePre", {
callback = function()
if M.dirty then
local hash = M.hash(cache_path)
-- abort when the file was changed in the meantime
if hash == nil or cache_hash == hash then
M.save()
--- The `package.loaders` loader for lua files using the cache.
---@param modname string module name
---@return string|function
---@private
function Loader.loader(modname)
local start = uv.hrtime()
local ret = M.find(modname)[1]
if ret then
local chunk, err = Loader.load(ret.modpath, { hash = ret.stat })
Loader.track("loader", start)
return chunk or error(err)
end
Loader.track("loader", start)
return "\ncache_loader: module " .. modname .. " not found"
end
--- The `package.loaders` loader for libs
---@param modname string module name
---@return string|function
---@private
function Loader.loader_lib(modname)
local start = uv.hrtime()
local sysname = uv.os_uname().sysname:lower() or ""
local is_win = sysname:find("win", 1, true) and not sysname:find("darwin", 1, true)
local ret = M.find(modname, { patterns = is_win and { ".dll" } or { ".so" } })[1]
---@type function?, string?
if ret then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
-- a) strip prefix up to and including the first dash, if any
-- b) replace all dots by underscores
-- c) prepend "luaopen_"
-- So "foo-bar.baz" should result in "luaopen_bar_baz"
local dash = modname:find("-", 1, true)
local funcname = dash and modname:sub(dash + 1) or modname
local chunk, err = package.loadlib(ret.modpath, "luaopen_" .. funcname:gsub("%.", "_"))
Loader.track("loader_lib", start)
return chunk or error(err)
end
Loader.track("loader_lib", start)
return "\ncache_loader_lib: module " .. modname .. " not found"
end
--- `loadfile` using the cache
---@param filename? string
---@param mode? "b"|"t"|"bt"
---@param env? table
---@param hash? CacheHash
---@return function?, string? error_message
---@private
-- luacheck: ignore 312
function Loader.loadfile(filename, mode, env, hash)
local start = uv.hrtime()
filename = Loader.normalize(filename)
mode = nil -- ignore mode, since we byte-compile the lua source files
local chunk, err = Loader.load(filename, { mode = mode, env = env, hash = hash })
Loader.track("loadfile", start)
return chunk, err
end
--- Checks whether two cache hashes are the same based on:
--- * file size
--- * mtime in seconds
--- * mtime in nanoseconds
---@param h1 CacheHash
---@param h2 CacheHash
---@private
function Loader.eq(h1, h2)
return h1 and h2 and h1.size == h2.size and h1.mtime.sec == h2.mtime.sec and h1.mtime.nsec == h2.mtime.nsec
end
--- Loads the given module path using the cache
---@param modpath string
---@param opts? {hash?: CacheHash, mode?: "b"|"t"|"bt", env?:table} (table|nil) Options for loading the module:
--- - hash: (table) the hash of the file to load if it is already known. (defaults to `vim.uv.fs_stat({modpath})`)
--- - mode: (string) the mode to load the module with. "b"|"t"|"bt" (defaults to `nil`)
--- - env: (table) the environment to load the module in. (defaults to `nil`)
---@see |luaL_loadfile()|
---@return function?, string? error_message
---@private
function Loader.load(modpath, opts)
local start = uv.hrtime()
opts = opts or {}
local hash = opts.hash or uv.fs_stat(modpath)
---@type function?, string?
local chunk, err
if not hash then
-- trigger correct error
chunk, err = Loader._loadfile(modpath, opts.mode, opts.env)
Loader.track("load", start)
return chunk, err
end
local entry = Loader.read(modpath)
if entry and Loader.eq(entry.hash, hash) then
-- found in cache and up to date
-- selene: allow(incorrect_standard_library_use)
chunk, err = load(entry.chunk --[[@as string]], "@" .. modpath, opts.mode, opts.env)
if not (err and err:find("cannot load incompatible bytecode", 1, true)) then
Loader.track("load", start)
return chunk, err
end
end
entry = { hash = hash, modpath = modpath }
chunk, err = Loader._loadfile(modpath, opts.mode, opts.env)
if chunk then
entry.chunk = string.dump(chunk)
Loader.write(modpath, entry)
end
Loader.track("load", start)
return chunk, err
end
--- Finds lua modules for the given module name.
---@param modname string Module name, or `"*"` to find the top-level modules instead
---@param opts? ModuleFindOpts (table|nil) Options for finding a module:
--- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`)
--- - paths: (string[]) Extra paths to search for modname (defaults to `{}`)
--- - patterns: (string[]) List of patterns to use when searching for modules.
--- A pattern is a string added to the basename of the Lua module being searched.
--- (defaults to `{"/init.lua", ".lua"}`)
--- - all: (boolean) Return all matches instead of just the first one (defaults to `false`)
---@return ModuleInfo[] (list) A list of results with the following properties:
--- - modpath: (string) the path to the module
--- - modname: (string) the name of the module
--- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"`
function M.find(modname, opts)
local start = uv.hrtime()
opts = opts or {}
modname = modname:gsub("/", ".")
local basename = modname:gsub("%.", "/")
local idx = modname:find(".", 1, true)
-- HACK: fix incorrect require statements. Really not a fan of keeping this,
-- but apparently the regular lua loader also allows this
if idx == 1 then
modname = modname:gsub("^%.+", "")
basename = modname:gsub("%.", "/")
idx = modname:find(".", 1, true)
end
-- get the top-level module name
local topmod = idx and modname:sub(1, idx - 1) or modname
-- OPTIM: search for a directory first when topmod == modname
local patterns = opts.patterns or (topmod == modname and { "/init.lua", ".lua" } or { ".lua", "/init.lua" })
for p, pattern in ipairs(patterns) do
patterns[p] = "/lua/" .. basename .. pattern
end
---@type ModuleInfo[]
local results = {}
-- Only continue if we haven't found anything yet or we want to find all
---@private
local function continue()
return #results == 0 or opts.all
end
-- Checks if the given paths contain the top-level module.
-- If so, it tries to find the module path for the given module name.
---@param paths string[]
---@private
local function _find(paths)
for _, path in ipairs(paths) do
if topmod == "*" then
for _, r in pairs(Loader.lsmod(path)) do
results[#results + 1] = r
if not continue() then
return
end
end
elseif Loader.lsmod(path)[topmod] then
for _, pattern in ipairs(patterns) do
local modpath = path .. pattern
Loader._stats.find.stat = (Loader._stats.find.stat or 0) + 1
local hash = uv.fs_stat(modpath)
if hash then
results[#results + 1] = { modpath = modpath, stat = hash, modname = modname }
if not continue() then
return
end
end
end,
})
end
end
end
end
-- always check the rtp first
if opts.rtp ~= false then
_find(Loader._rtp or {})
if continue() then
local rtp, updated = Loader.get_rtp()
if updated then
_find(rtp)
end
end
end
-- check any additional paths
if continue() and opts.paths then
_find(opts.paths)
end
Loader.track("find", start)
if #results == 0 then
-- module not found
Loader._stats.find.not_found = Loader._stats.find.not_found + 1
end
return results
end
--- Resets the topmods cache for the path, or all the paths
--- if path is nil.
---@param path string? path to reset
function M.reset(path)
if path then
Loader._indexed[Loader.normalize(path)] = nil
else
Loader._indexed = {}
end
end
--- Enables the experimental Lua module loader:
--- * overrides loadfile
--- * adds the lua loader using the byte-compilation cache
--- * adds the libs loader
--- * removes the default Neovim loader
function M.enable()
if M.enabled then
return
end
M.enabled = true
vim.fn.mkdir(vim.fn.fnamemodify(M.path, ":p"), "p")
-- selene: allow(global_usage)
_G.loadfile = Loader.loadfile
-- add lua loader
table.insert(package.loaders, 2, Loader.loader)
-- add libs loader
table.insert(package.loaders, 3, Loader.loader_lib)
-- remove Neovim loader
for l, loader in ipairs(package.loaders) do
if loader == vim._load_package then
table.remove(package.loaders, l)
break
end
end
-- this will reset the top-mods in case someone adds a new
-- top-level lua module to a path already on the rtp
vim.api.nvim_create_autocmd("BufWritePost", {
group = vim.api.nvim_create_augroup("cache_topmods_reset", { clear = true }),
callback = function(event)
local bufname = event.match ---@type string
local idx = bufname:find("/lua/", 1, true)
if idx then
M.reset(bufname:sub(1, idx - 1))
end
end,
})
end
function M.save()
require("lazy.core.plugin").save()
require("lazy.core.module").save()
local f = assert(io.open(cache_path, "wb"))
for key, value in pairs(cache) do
if used[key] then
f:write(key, "\0", tostring(#value), "\0", value)
--- Disables the experimental Lua module loader:
--- * removes the loaders
--- * adds the default Neovim loader
function M.disable()
if not M.enabled then
return
end
M.enabled = false
-- selene: allow(global_usage)
_G.loadfile = Loader._loadfile
---@diagnostic disable-next-line: no-unknown
for l, loader in ipairs(package.loaders) do
if loader == Loader.loader or loader == Loader.loader_lib then
table.remove(package.loaders, l)
end
end
f:close()
table.insert(package.loaders, 2, vim._load_package)
vim.api.nvim_del_augroup_by_name("cache_topmods_reset")
end
function M.load()
cache = {}
local f = io.open(cache_path, "rb")
if f then
cache_hash = M.hash(cache_path)
---@type string
local data = f:read("*a")
f:close()
--- Return the top-level `/lua/*` modules for this path
---@param path string path to check for top-level lua modules
---@private
function Loader.lsmod(path)
if not Loader._indexed[path] then
local start = uv.hrtime()
Loader._indexed[path] = {}
local handle = uv.fs_scandir(path .. "/lua")
while handle do
local name, t = uv.fs_scandir_next(handle)
if not name then
break
end
local modpath = path .. "/lua/" .. name
-- HACK: type is not always returned due to a bug in luv
t = t or uv.fs_stat(modpath).type
---@type string
local topname
local ext = name:sub(-4)
if ext == ".lua" or ext == ".dll" then
topname = name:sub(1, -5)
elseif name:sub(-3) == ".so" then
topname = name:sub(1, -4)
elseif t == "link" or t == "directory" then
topname = name
end
if topname then
Loader._indexed[path][topname] = { modpath = modpath, modname = topname }
Loader._topmods[topname] = Loader._topmods[topname] or {}
if not vim.tbl_contains(Loader._topmods[topname], path) then
table.insert(Loader._topmods[topname], path)
end
end
end
Loader.track("lsmod", start)
end
return Loader._indexed[path]
end
local from = 1
local to = data:find("\0", from, true)
while to do
local key = data:sub(from, to - 1)
from = to + 1
to = data:find("\0", from, true)
local len = tonumber(data:sub(from, to - 1))
from = to + 1
cache[key] = data:sub(from, from + len - 1)
from = from + len
to = data:find("\0", from, true)
--- Debug function that wraps all loaders and tracks stats
---@private
function M._profile_loaders()
for l, loader in pairs(package.loaders) do
local loc = debug.getinfo(loader, "Sn").source:sub(2)
package.loaders[l] = function(modname)
local start = uv.hrtime()
local ret = loader(modname)
Loader.track("loader " .. l .. ": " .. loc, start)
Loader.track("loader_all", start)
return ret
end
end
end
--- Prints all cache stats
---@param opts? {print?:boolean}
---@return LoaderStats
---@private
function M._inspect(opts)
if opts and opts.print then
---@private
local function ms(nsec)
return math.floor(nsec / 1e6 * 1000 + 0.5) / 1000 .. "ms"
end
local chunks = {} ---@type string[][]
---@type string[]
local stats = vim.tbl_keys(Loader._stats)
table.sort(stats)
for _, stat in ipairs(stats) do
vim.list_extend(chunks, {
{ "\n" .. stat .. "\n", "Title" },
{ "* total: " },
{ tostring(Loader._stats[stat].total) .. "\n", "Number" },
{ "* time: " },
{ ms(Loader._stats[stat].time) .. "\n", "Bold" },
{ "* avg time: " },
{ ms(Loader._stats[stat].time / Loader._stats[stat].total) .. "\n", "Bold" },
})
for k, v in pairs(Loader._stats[stat]) do
if not vim.tbl_contains({ "time", "total" }, k) then
chunks[#chunks + 1] = { "* " .. k .. ":" .. string.rep(" ", 9 - #k) }
chunks[#chunks + 1] = { tostring(v) .. "\n", "Number" }
end
end
end
vim.api.nvim_echo(chunks, true, {})
end
return Loader._stats
end
return M

View file

@ -1,47 +1,253 @@
local Util = require("lazy.core.util")
---@class LazyCoreConfig
local M = {}
---@class LazyConfig
M.defaults = {
opt = true,
plugins = "config.plugins",
plugins_local = {
path = vim.fn.expand("~/projects"),
---@type string[]
patterns = {},
root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed
defaults = {
-- Set this to `true` to have all your plugins lazy-loaded by default.
-- Only do this if you know what you are doing, as it can lead to unexpected behavior.
lazy = false, -- should plugins be lazy-loaded?
-- It's recommended to leave version=false for now, since a lot the plugin that support versioning,
-- have outdated releases, which may break your Neovim install.
version = nil, -- always use the latest git commit
-- version = "*", -- try installing the latest stable version for plugins that support semver
-- default `cond` you can use to globally disable a lot of plugins
-- when running inside vscode for example
cond = nil, ---@type boolean|fun(self:LazyPlugin):boolean|nil
},
interactive = true,
packpath = vim.fn.stdpath("data") .. "/site/pack/lazy",
lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json",
view = {
icons = {
start = "",
plugin = "",
source = "",
config = "",
event = "",
keys = "",
cmd = "",
ft = "",
task = "",
-- leave nil when passing the spec as the first argument to setup()
spec = nil, ---@type LazySpec
local_spec = true, -- load project specific .lazy.lua spec files. They will be added at the end of the spec.
lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json", -- lockfile generated after running update.
---@type number? limit the maximum amount of concurrent tasks
concurrency = jit.os:find("Windows") and (vim.uv.available_parallelism() * 2) or nil,
git = {
-- defaults for the `Lazy log` command
-- log = { "--since=3 days ago" }, -- show commits from the last 3 days
log = { "-8" }, -- show the last 8 commits
timeout = 120, -- kill processes that take more than 2 minutes
url_format = "https://github.com/%s.git",
-- lazy.nvim requires git >=2.19.0. If you really want to use lazy with an older version,
-- then set the below to false. This should work, but is NOT supported and will
-- increase downloads a lot.
filter = true,
-- rate of network related git operations (clone, fetch, checkout)
throttle = {
enabled = false, -- not enabled by default
-- max 2 ops every 5 seconds
rate = 2,
duration = 5 * 1000, -- in ms
},
-- Time in seconds to wait before running fetch again for a plugin.
-- Repeated update/check operations will not run again until this
-- cooldown period has passed.
cooldown = 0,
},
pkg = {
enabled = true,
cache = vim.fn.stdpath("state") .. "/lazy/pkg-cache.lua",
-- the first package source that is found for a plugin will be used.
sources = {
"lazy",
"rockspec", -- will only be used when rocks.enabled is true
"packspec",
},
},
git = {
-- defaults for `Lazy log`
log = { "-10" }, -- last 10 commits
-- log = { "--since=3 days ago" }, -- commits from the last 3 days
rocks = {
enabled = true,
root = vim.fn.stdpath("data") .. "/lazy-rocks",
server = "https://nvim-neorocks.github.io/rocks-binaries/",
-- use hererocks to install luarocks?
-- set to `nil` to use hererocks when luarocks is not found
-- set to `true` to always use hererocks
-- set to `false` to always use luarocks
hererocks = nil,
},
dev = {
-- Directory where you store your local plugin projects. If a function is used,
-- the plugin directory (e.g. `~/projects/plugin-name`) must be returned.
---@type string | fun(plugin: LazyPlugin): string
path = "~/projects",
---@type string[] plugins that match these patterns will use your local versions instead of being fetched from GitHub
patterns = {}, -- For example {"folke"}
fallback = false, -- Fallback to git when local plugin doesn't exist
},
install = {
-- install missing plugins on startup. This doesn't increase startup time.
missing = true,
-- try to load one of these colorschemes when starting an installation during startup
colorscheme = { "habamax" },
},
ui = {
-- a number <1 is a percentage., >1 is a fixed size
size = { width = 0.8, height = 0.8 },
wrap = true, -- wrap the lines in the ui
-- The border to use for the UI window. Accepts same border values as |nvim_open_win()|.
border = "none",
-- The backdrop opacity. 0 is fully opaque, 100 is fully transparent.
backdrop = 60,
title = nil, ---@type string only works when border is not "none"
title_pos = "center", ---@type "center" | "left" | "right"
-- Show pills on top of the Lazy window
pills = true, ---@type boolean
icons = {
cmd = "",
config = "",
debug = "",
event = "",
favorite = "",
ft = "",
init = "",
import = "",
keys = "",
lazy = "󰒲 ",
loaded = "",
not_loaded = "",
plugin = "",
runtime = "",
require = "󰢱 ",
source = "",
start = "",
task = "",
list = {
"",
"",
"",
"",
},
},
-- leave nil, to automatically select a browser depending on your OS.
-- If you want to use a specific browser, you can define it here
browser = nil, ---@type string?
throttle = 1000 / 30, -- how frequently should the ui process render events
custom_keys = {
-- You can define custom key maps here. If present, the description will
-- be shown in the help menu.
-- To disable one of the defaults, set it to false.
["<localleader>l"] = {
function(plugin)
require("lazy.util").float_term({ "lazygit", "log" }, {
cwd = plugin.dir,
})
end,
desc = "Open lazygit log",
},
["<localleader>i"] = {
function(plugin)
Util.notify(vim.inspect(plugin), {
title = "Inspect " .. plugin.name,
lang = "lua",
})
end,
desc = "Inspect Plugin",
},
["<localleader>t"] = {
function(plugin)
require("lazy.util").float_term(nil, {
cwd = plugin.dir,
})
end,
desc = "Open terminal in plugin dir",
},
},
},
-- Output options for headless mode
headless = {
-- show the output from process commands like git
process = true,
-- show log messages
log = true,
-- show task start/end
task = true,
-- use ansi colors
colors = true,
},
diff = {
-- diff command <d> can be one of:
-- * browser: opens the github compare view. Note that this is always mapped to <K> as well,
-- so you can have a different command for diff <d>
-- * git: will run git diff and open a buffer with filetype git
-- * terminal_git: will open a pseudo terminal with git diff
-- * diffview.nvim: will open Diffview to show the diff
cmd = "git",
},
checker = {
-- automatically check for plugin updates
enabled = false,
concurrency = nil, ---@type number? set to 1 to check for updates very slowly
notify = true, -- get a notification when new updates are found
frequency = 3600, -- check for updates every hour
check_pinned = false, -- check for pinned packages that can't be updated
},
change_detection = {
-- automatically check for config file changes and reload the ui
enabled = true,
notify = true, -- get a notification when changes are found
},
performance = {
cache = {
enabled = true,
},
reset_packpath = true, -- reset the package path to improve startup time
rtp = {
reset = true, -- reset the runtime path to $VIMRUNTIME and your config directory
---@type string[]
paths = {}, -- add any custom paths here that you want to includes in the rtp
---@type string[] list any plugins you want to disable here
disabled_plugins = {
-- "gzip",
-- "matchit",
-- "matchparen",
-- "netrwPlugin",
-- "tarPlugin",
-- "tohtml",
-- "tutor",
-- "zipPlugin",
},
},
},
-- lazy can generate helptags from the headings in markdown readme files,
-- so :help works even for plugins that don't have vim docs.
-- when the readme opens with :help it will be correctly displayed as markdown
readme = {
enabled = true,
root = vim.fn.stdpath("state") .. "/lazy/readme",
files = { "README.md", "lua/**/README.md" },
-- only generate markdown helptags for plugins that don't have docs
skip_if_doc_exists = true,
},
state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things
-- Enable profiling of lazy.nvim. This will add some overhead,
-- so only enable this when you are debugging lazy.nvim
profiling = {
-- Enables extra stats on the debug tab related to the loader cache.
-- Additionally gathers stats about all package.loaders
loader = false,
-- Track each new require in the Lazy profiling tab
require = false,
},
debug = false,
}
function M.hererocks()
if M.options.rocks.hererocks == nil then
M.options.rocks.hererocks = vim.fn.executable("luarocks") == 0
end
return M.options.rocks.hererocks
end
M.version = "11.17.1" -- x-release-please-version
M.ns = vim.api.nvim_create_namespace("lazy")
M.paths = {
---@type string
main = nil,
---@type string
plugins = nil,
}
---@type LazySpecLoader
M.spec = nil
---@type table<string, LazyPlugin>
M.plugins = {}
@ -52,25 +258,114 @@ M.to_clean = {}
---@type LazyConfig
M.options = {}
---@type string
M.me = nil
---@type string
M.mapleader = nil
---@type string
M.maplocalleader = nil
M.suspended = false
function M.headless()
return not M.suspended and #vim.api.nvim_list_uis() == 0
end
---@param opts? LazyConfig
function M.setup(opts)
M.options = vim.tbl_deep_extend("force", M.defaults, opts or {})
M.paths.plugins = vim.fn.stdpath("config") .. "/lua/" .. M.options.plugins:gsub("%.", "/")
M.paths.main = M.paths.plugins .. (vim.loop.fs_stat(M.paths.plugins .. ".lua") and ".lua" or "/init.lua")
-- TODO: check what this does inside a GUI. Probably still ok
if #vim.api.nvim_list_uis() == 0 then
M.options.interactive = false
if type(M.options.spec) == "string" then
M.options.spec = { import = M.options.spec }
end
table.insert(M.options.install.colorscheme, "habamax")
-- root
M.options.root = Util.norm(M.options.root)
if type(M.options.dev.path) == "string" then
M.options.dev.path = Util.norm(M.options.dev.path)
end
M.options.lockfile = Util.norm(M.options.lockfile)
M.options.readme.root = Util.norm(M.options.readme.root)
vim.fn.mkdir(M.options.root, "p")
if M.options.performance.reset_packpath then
vim.go.packpath = vim.env.VIMRUNTIME
end
vim.api.nvim_create_autocmd("User", {
pattern = "VeryLazy",
M.me = debug.getinfo(1, "S").source:sub(2)
M.me = Util.norm(vim.fn.fnamemodify(M.me, ":p:h:h:h:h"))
local lib = vim.fn.fnamemodify(vim.v.progpath, ":p:h:h") .. "/lib"
lib = vim.uv.fs_stat(lib .. "64") and (lib .. "64") or lib
lib = lib .. "/nvim"
if M.options.performance.rtp.reset then
---@type vim.Option
vim.opt.rtp = {
vim.fn.stdpath("config"),
vim.fn.stdpath("data") .. "/site",
M.me,
vim.env.VIMRUNTIME,
lib,
vim.fn.stdpath("config") .. "/after",
}
end
for _, path in ipairs(M.options.performance.rtp.paths) do
vim.opt.rtp:append(path)
end
vim.opt.rtp:append(M.options.readme.root)
-- disable plugin loading since we do all of that ourselves
vim.go.loadplugins = false
M.mapleader = vim.g.mapleader
M.maplocalleader = vim.g.maplocalleader
vim.api.nvim_create_autocmd("UIEnter", {
once = true,
callback = function()
require("lazy.view").setup()
require("lazy.stats").on_ui_enter()
end,
})
if M.headless() then
require("lazy.view.commands").setup()
else
vim.api.nvim_create_autocmd("User", {
pattern = "VeryLazy",
once = true,
callback = function()
require("lazy.view.commands").setup()
if M.options.change_detection.enabled then
require("lazy.manage.reloader").enable()
end
if M.options.checker.enabled then
vim.defer_fn(function()
require("lazy.manage.checker").start()
end, 10)
end
-- useful for plugin developers when making changes to a packspec file
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = { "lazy.lua", "pkg.json", "*.rockspec" },
callback = function()
local plugin = require("lazy.core.plugin").find(vim.uv.cwd() .. "/lua/")
if plugin then
require("lazy").pkg({ plugins = { plugin } })
end
end,
})
vim.api.nvim_create_autocmd({ "VimSuspend", "VimResume" }, {
callback = function(ev)
M.suspended = ev.event == "VimSuspend"
end,
})
end,
})
end
Util.very_lazy()
end

174
lua/lazy/core/fragments.lua Normal file
View file

@ -0,0 +1,174 @@
local Config = require("lazy.core.config")
local Util = require("lazy.core.util")
--- This class is used to manage the fragments of a plugin spec.
--- It keeps track of the fragments and their relations to other fragments.
--- A fragment can be a dependency (dependencies) or a child (specs) of another fragment.
---@class LazyFragments
---@field fragments table<number, LazyFragment>
---@field frag_stack number[]
---@field dep_stack number[]
---@field dirty table<number, boolean>
---@field plugins table<LazyPlugin, number>
---@field spec LazySpecLoader
local M = {}
M._fid = 0
local function next_id()
M._fid = M._fid + 1
return M._fid
end
---@param spec LazySpecLoader
---@return LazyFragments
function M.new(spec)
local self = setmetatable({}, { __index = M })
self.fragments = {}
self.frag_stack = {}
self.dep_stack = {}
self.spec = spec
self.dirty = {}
self.plugins = {}
return self
end
---@param id number
function M:get(id)
return self.fragments[id]
end
--- Remove a fragment and all its children.
--- This will also remove the fragment from its parent's children list.
---@param id number
function M:del(id)
-- del fragment
local fragment = self.fragments[id]
if not fragment then
return
end
self.dirty[id] = true
-- remove from parent
local pid = fragment.pid
if pid then
local parent = self.fragments[pid]
if parent.frags then
---@param fid number
parent.frags = Util.filter(function(fid)
return fid ~= id
end, parent.frags)
end
if parent.deps then
---@param fid number
parent.deps = Util.filter(function(fid)
return fid ~= id
end, parent.deps)
end
self.dirty[pid] = true
end
-- remove children
if fragment.frags then
for _, fid in ipairs(fragment.frags) do
self:del(fid)
end
end
self.fragments[id] = nil
end
--- Add a fragment to the fragments list.
--- This also resolves its name, url, dir, dependencies and child specs.
---@param plugin LazyPluginSpec
function M:add(plugin)
if self.plugins[plugin] then
return self.fragments[self.plugins[plugin]]
end
local id = next_id()
setmetatable(plugin, nil)
self.plugins[plugin] = id
local pid = self.frag_stack[#self.frag_stack]
---@type LazyFragment
local fragment = {
id = id,
pid = pid,
name = plugin.name,
url = plugin.url,
dir = plugin.dir,
spec = plugin --[[@as LazyPlugin]],
}
-- short url / ref
if plugin[1] then
local slash = plugin[1]:find("/", 1, true)
if slash then
local prefix = plugin[1]:sub(1, 4)
if prefix == "http" or prefix == "git@" then
fragment.url = fragment.url or plugin[1]
else
fragment.name = fragment.name or plugin[1]:sub(slash + 1)
fragment.url = fragment.url or Config.options.git.url_format:format(plugin[1])
end
else
fragment.name = fragment.name or plugin[1]
end
end
-- name
fragment.name = fragment.name
or fragment.url and self.spec.get_name(fragment.url)
or fragment.dir and self.spec.get_name(fragment.dir)
if not fragment.name or fragment.name == "" then
return self.spec:error("Invalid plugin spec " .. vim.inspect(plugin))
end
if type(plugin.config) == "table" then
self.spec:warn(
"{" .. fragment.name .. "}: setting a table to `Plugin.config` is deprecated. Please use `Plugin.opts` instead"
)
---@diagnostic disable-next-line: assign-type-mismatch
plugin.opts = plugin.config
plugin.config = nil
end
self.fragments[id] = fragment
-- add to parent
if pid then
local parent = self.fragments[pid]
parent.frags = parent.frags or {}
table.insert(parent.frags, id)
end
-- add to parent's deps
local did = self.dep_stack[#self.dep_stack]
if did and did == pid then
fragment.dep = true
local parent = self.fragments[did]
parent.deps = parent.deps or {}
table.insert(parent.deps, id)
end
table.insert(self.frag_stack, id)
-- dependencies
if plugin.dependencies then
table.insert(self.dep_stack, id)
self.spec:normalize(plugin.dependencies)
table.remove(self.dep_stack)
end
-- child specs
if plugin.specs then
self.spec:normalize(plugin.specs)
end
table.remove(self.frag_stack)
return fragment
end
return M

View file

@ -1,158 +0,0 @@
local Util = require("lazy.core.util")
local Loader = require("lazy.core.loader")
---@class LazyPluginHandlers
---@field event? string|string[]
---@field cmd? string|string[]
---@field ft? string|string[]
---@field module? string|string[]
---@field keys? string|string[]
local M = {}
---@alias LazyHandler fun(grouped:table<string, string[]>)
---@type table<string, table<string, string[]>>
M._groups = nil
---@param plugins LazyPlugin[]
---@param rebuild? boolean
function M.group(plugins, rebuild)
if M._groups == nil or rebuild then
M._groups = {}
local types = vim.tbl_keys(M.handlers) --[[@as string[] ]]
for _, key in ipairs(types) do
M._groups[key] = {}
for _, plugin in pairs(plugins) do
if plugin[key] then
---@diagnostic disable-next-line: no-unknown
for _, value in pairs(type(plugin[key]) == "table" and plugin[key] or { plugin[key] }) do
M._groups[key][value] = M._groups[key][value] or {}
table.insert(M._groups[key][value], plugin.name)
end
end
end
end
end
return M._groups
end
---@type table<string, LazyHandler>
M.handlers = {}
function M.handlers.event(grouped)
local group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true })
for event, plugins in pairs(grouped) do
---@cast event string
if event == "VimEnter" and vim.v.vim_did_enter == 1 then
Loader.load(plugins, { event = event })
else
local _event, pattern = event:match("^(%w+)%s+(.*)$")
vim.api.nvim_create_autocmd(_event or event, {
group = group,
once = true,
pattern = pattern,
callback = function()
Util.track({ event = event })
Loader.load(plugins, { event = event })
Util.track()
end,
})
end
end
end
function M.handlers.keys(grouped)
for keys, plugins in pairs(grouped) do
---@cast keys string
vim.keymap.set("n", keys, function()
vim.keymap.del("n", keys)
Util.track({ keys = keys })
Loader.load(plugins, { keys = keys })
vim.api.nvim_input(keys)
Util.track()
end)
end
end
function M.handlers.ft(grouped)
local group = vim.api.nvim_create_augroup("lazy_handler_ft", { clear = true })
for ft, plugins in pairs(grouped) do
---@cast ft string
vim.api.nvim_create_autocmd("FileType", {
once = true,
pattern = ft,
group = group,
callback = function()
Util.track({ ft = ft })
Loader.load(plugins, { ft = ft })
Util.track()
end,
})
end
end
function M.handlers.cmd(grouped)
for cmd, plugins in pairs(grouped) do
---@cast cmd string
local function _load()
vim.api.nvim_del_user_command(cmd)
Util.track({ cmd = cmd })
Loader.load(plugins, { cmd = cmd })
Util.track()
end
vim.api.nvim_create_user_command(cmd, function(event)
_load()
vim.cmd(
("%s %s%s%s %s"):format(
event.mods or "",
event.line1 == event.line2 and "" or event.line1 .. "," .. event.line2,
cmd,
event.bang and "!" or "",
event.args or ""
)
)
end, {
bang = true,
nargs = "*",
complete = function()
_load()
-- HACK: trick Neovim to show the newly loaded command completion
vim.api.nvim_input("<space><bs><tab>")
end,
})
end
end
function M.handlers.module(grouped)
---@param modname string
table.insert(package.loaders, 2, function(modname)
local idx = modname:find(".", 1, true) or #modname + 1
while idx do
local name = modname:sub(1, idx - 1)
---@diagnostic disable-next-line: redefined-local
local plugins = grouped[name]
if plugins then
grouped[name] = nil
local reason = { require = modname }
if #Loader.loading == 0 then
local f = 3
while not reason.source do
local info = debug.getinfo(f, "S")
if not info then
break
end
if info.what ~= "C" then
reason.source = info.source:sub(2)
end
f = f + 1
end
end
Loader.load(plugins, reason)
end
idx = modname:find(".", idx + 1, true)
end
end)
end
return M

View file

@ -0,0 +1,66 @@
local Loader = require("lazy.core.loader")
local Util = require("lazy.core.util")
---@class LazyCmdHandler:LazyHandler
local M = {}
function M:_load(cmd)
vim.api.nvim_del_user_command(cmd)
Util.track({ cmd = cmd })
Loader.load(self.active[cmd], { cmd = cmd })
Util.track()
end
---@param cmd string
function M:_add(cmd)
vim.api.nvim_create_user_command(cmd, function(event)
local command = {
cmd = cmd,
bang = event.bang or nil,
mods = event.smods,
args = event.fargs,
count = event.count >= 0 and event.range == 0 and event.count or nil,
}
if event.range == 1 then
command.range = { event.line1 }
elseif event.range == 2 then
command.range = { event.line1, event.line2 }
end
---@type string
local plugins = "`" .. table.concat(vim.tbl_values(self.active[cmd]), ", ") .. "`"
self:_load(cmd)
local info = vim.api.nvim_get_commands({})[cmd] or vim.api.nvim_buf_get_commands(0, {})[cmd]
if not info then
vim.schedule(function()
Util.error("Command `" .. cmd .. "` not found after loading " .. plugins)
end)
return
end
command.nargs = info.nargs
if event.args and event.args ~= "" and info.nargs and info.nargs:find("[1?]") then
command.args = { event.args }
end
vim.cmd(command)
end, {
bang = true,
range = true,
nargs = "*",
complete = function(_, line)
self:_load(cmd)
-- NOTE: return the newly loaded command completion
return vim.fn.getcompletion(line, "cmdline")
end,
})
end
---@param value string
function M:_del(value)
pcall(vim.api.nvim_del_user_command, value)
end
return M

View file

@ -0,0 +1,171 @@
local Config = require("lazy.core.config")
local Loader = require("lazy.core.loader")
local Util = require("lazy.core.util")
---@class LazyEventOpts
---@field event string
---@field group? string
---@field exclude? string[]
---@field data? any
---@field buffer? number
---@alias LazyEvent {id:string, event:string[]|string, pattern?:string[]|string}
---@alias LazyEventSpec string|{event?:string|string[], pattern?:string|string[]}|string[]
---@class LazyEventHandler:LazyHandler
---@field events table<string,true>
---@field group number
local M = {}
-- Event dependencies
M.triggers = {
FileType = "BufReadPost",
BufReadPost = "BufReadPre",
}
-- A table of mappings for custom events
-- Can be used by distros to add custom events (see usage in LazyVim)
---@type table<string, LazyEvent>
M.mappings = {
VeryLazy = { id = "VeryLazy", event = "User", pattern = "VeryLazy" },
-- Example:
-- LazyFile = { id = "LazyFile", event = { "BufReadPost", "BufNewFile", "BufWritePre" } },
}
M.mappings["User VeryLazy"] = M.mappings.VeryLazy
M.group = vim.api.nvim_create_augroup("lazy_handler_event", { clear = true })
---@param spec LazyEventSpec
---@return LazyEvent
function M:_parse(spec)
local ret = M.mappings[spec] --[[@as LazyEvent?]]
if ret then
return ret
end
if type(spec) == "string" then
local event, pattern = spec:match("^(%w+)%s+(.*)$")
event = event or spec
return { id = spec, event = event, pattern = pattern }
elseif Util.is_list(spec) then
ret = { id = table.concat(spec, "|"), event = spec }
else
ret = spec --[[@as LazyEvent]]
if not ret.id then
---@diagnostic disable-next-line: assign-type-mismatch, param-type-mismatch
ret.id = type(ret.event) == "string" and ret.event or table.concat(ret.event, "|")
if ret.pattern then
---@diagnostic disable-next-line: assign-type-mismatch, param-type-mismatch
ret.id = ret.id .. " " .. (type(ret.pattern) == "string" and ret.pattern or table.concat(ret.pattern, ", "))
end
end
end
return ret
end
---@param event LazyEvent
function M:_add(event)
local done = false
vim.api.nvim_create_autocmd(event.event, {
group = self.group,
once = true,
pattern = event.pattern,
callback = function(ev)
if done or not self.active[event.id] then
return
end
-- HACK: work-around for https://github.com/neovim/neovim/issues/25526
done = true
if event.id ~= "VeryLazy" then
Util.track({ [self.type] = event.id })
end
local state = M.get_state(ev.event, ev.buf, ev.data)
-- load the plugins
Loader.load(self.active[event.id], { [self.type] = event.id })
-- check if any plugin created an event handler for this event and fire the group
for _, s in ipairs(state) do
M.trigger(s)
end
if event.id ~= "VeryLazy" then
Util.track()
end
end,
})
end
-- Get the current state of the event and all the events that will be fired
---@param event string
---@param buf number
---@param data any
function M.get_state(event, buf, data)
local state = {} ---@type LazyEventOpts[]
while event do
table.insert(state, 1, {
event = event,
exclude = event ~= "FileType" and M.get_augroups(event) or nil,
buffer = buf,
data = data,
})
data = nil -- only pass the data to the first event
event = M.triggers[event]
end
return state
end
-- Get all augroups for the events
---@param event string
function M.get_augroups(event)
local groups = {} ---@type string[]
for _, autocmd in ipairs(vim.api.nvim_get_autocmds({ event = event })) do
if autocmd.group_name then
table.insert(groups, autocmd.group_name)
end
end
return groups
end
-- Trigger an event. When a group is given, only the events in that group will be triggered.
-- When exclude is set, the events in those groups will be skipped.
---@param opts LazyEventOpts
function M.trigger(opts)
if opts.group or opts.exclude == nil then
return M._trigger(opts)
end
local done = {} ---@type table<string,true>
for _, autocmd in ipairs(vim.api.nvim_get_autocmds({ event = opts.event })) do
local id = autocmd.event .. ":" .. (autocmd.group or "") ---@type string
local skip = done[id] or (opts.exclude and vim.tbl_contains(opts.exclude, autocmd.group_name))
done[id] = true
if autocmd.group and not skip then
opts.group = autocmd.group_name
M._trigger(opts)
end
end
end
-- Trigger an event
---@param opts LazyEventOpts
function M._trigger(opts)
if Config.options.debug then
Util.info({
"# Firing Events",
" - **event:** " .. opts.event,
opts.group and (" - **group:** " .. opts.group),
opts.buffer and (" - **buffer:** " .. opts.buffer),
})
end
Util.track({ event = opts.group or opts.event })
Util.try(function()
vim.api.nvim_exec_autocmds(opts.event, {
buffer = opts.buffer,
group = opts.group,
modeline = false,
data = opts.data,
})
Util.track()
end)
end
return M

View file

@ -0,0 +1,25 @@
local Event = require("lazy.core.handler.event")
local Loader = require("lazy.core.loader")
---@class LazyFiletypeHandler:LazyEventHandler
local M = {}
M.extends = Event
---@param plugin LazyPlugin
function M:add(plugin)
self.super.add(self, plugin)
if plugin.ft then
Loader.ftdetect(plugin.dir)
end
end
---@return LazyEvent
function M:_parse(value)
return {
id = value,
event = "FileType",
pattern = value,
}
end
return M

View file

@ -0,0 +1,139 @@
local Config = require("lazy.core.config")
local Util = require("lazy.core.util")
---@class LazyHandler
---@field type LazyHandlerTypes
---@field extends? LazyHandler
---@field active table<string,table<string,string>>
---@field managed table<string,string> mapping handler keys to plugin names
---@field super LazyHandler
local M = {}
---@enum LazyHandlerTypes
M.types = {
keys = "keys",
event = "event",
cmd = "cmd",
ft = "ft",
}
---@type table<string,LazyHandler>
M.handlers = {}
M.did_setup = false
function M.init()
for _, type in pairs(M.types) do
M.handlers[type] = M.new(type)
end
end
function M.setup()
M.did_setup = true
for _, plugin in pairs(Config.plugins) do
Util.try(function()
M.enable(plugin)
end, "Failed to setup handlers for " .. plugin.name)
end
end
---@param plugin LazyPlugin
function M.disable(plugin)
for type in pairs(plugin._.handlers or {}) do
M.handlers[type]:del(plugin)
end
end
---@param plugin LazyPlugin
function M.enable(plugin)
if not plugin._.loaded then
if not plugin._.handlers then
M.resolve(plugin)
end
for type in pairs(plugin._.handlers or {}) do
M.handlers[type]:add(plugin)
end
end
end
---@param type LazyHandlerTypes
function M.new(type)
---@type LazyHandler
local handler = require("lazy.core.handler." .. type)
local super = handler.extends or M
local self = setmetatable({}, { __index = setmetatable(handler, { __index = super }) })
self.super = super
self.active = {}
self.managed = {}
self.type = type
return self
end
---@param _value string
---@protected
function M:_add(_value) end
---@param _value string
---@protected
function M:_del(_value) end
---@param value any
---@param _plugin LazyPlugin
---@return string|{id:string}
function M:_parse(value, _plugin)
assert(type(value) == "string", "Expected string, got " .. vim.inspect(value))
return value
end
---@param values any[]
---@param plugin LazyPlugin
function M:_values(values, plugin)
---@type table<string,any>
local ret = {}
for _, value in ipairs(values) do
local parsed = self:_parse(value, plugin)
ret[type(parsed) == "string" and parsed or parsed.id] = parsed
end
return ret
end
---@param plugin LazyPlugin
function M.resolve(plugin)
local Plugin = require("lazy.core.plugin")
plugin._.handlers = {}
for type, handler in pairs(M.handlers) do
if plugin[type] then
plugin._.handlers[type] = handler:_values(Plugin.values(plugin, type, true), plugin)
end
end
end
---@param plugin LazyPlugin
function M:add(plugin)
for key, value in pairs(plugin._.handlers[self.type] or {}) do
if not self.active[key] then
self.active[key] = {}
self:_add(value)
self.managed[key] = plugin.name
end
self.active[key][plugin.name] = plugin.name
end
end
---@param plugin LazyPlugin
function M:del(plugin)
if not plugin._.handlers then
return
end
for key, value in pairs(plugin._.handlers[self.type] or {}) do
if self.active[key] and self.active[key][plugin.name] then
self.active[key][plugin.name] = nil
if vim.tbl_isempty(self.active[key]) then
self:_del(value)
self.active[key] = nil
end
end
end
end
return M

View file

@ -0,0 +1,202 @@
local Loader = require("lazy.core.loader")
local Util = require("lazy.core.util")
---@class LazyKeysBase
---@field desc? string
---@field noremap? boolean
---@field remap? boolean
---@field expr? boolean
---@field nowait? boolean
---@field ft? string|string[]
---@class LazyKeysSpec: LazyKeysBase
---@field [1] string lhs
---@field [2]? string|fun():string?|false rhs
---@field mode? string|string[]
---@class LazyKeys: LazyKeysBase
---@field lhs string lhs
---@field rhs? string|fun() rhs
---@field mode? string
---@field id string
---@field name string
---@class LazyKeysHandler:LazyHandler
local M = {}
local skip = { mode = true, id = true, ft = true, rhs = true, lhs = true }
---@param value string|LazyKeysSpec
---@param mode? string
---@return LazyKeys
function M.parse(value, mode)
value = type(value) == "string" and { value } or value --[[@as LazyKeysSpec]]
local ret = vim.deepcopy(value) --[[@as LazyKeys]]
ret.lhs = ret[1] or ""
ret.rhs = ret[2]
---@diagnostic disable-next-line: no-unknown
ret[1] = nil
---@diagnostic disable-next-line: no-unknown
ret[2] = nil
ret.mode = mode or "n"
ret.id = vim.api.nvim_replace_termcodes(ret.lhs, true, true, true)
if ret.ft then
local ft = type(ret.ft) == "string" and { ret.ft } or ret.ft --[[@as string[] ]]
ret.id = ret.id .. " (" .. table.concat(ft, ", ") .. ")"
end
if ret.mode ~= "n" then
ret.id = ret.id .. " (" .. ret.mode .. ")"
end
return ret
end
---@param keys LazyKeys
function M.to_string(keys)
return keys.lhs .. (keys.mode == "n" and "" or " (" .. keys.mode .. ")")
end
---@param lhs string
---@param mode? string
function M:have(lhs, mode)
local keys = M.parse(lhs, mode)
return self.managed[keys.id] ~= nil
end
function M:_values(values)
return M.resolve(values)
end
---@param spec? (string|LazyKeysSpec)[]
function M.resolve(spec)
---@type LazyKeys[]
local values = {}
---@diagnostic disable-next-line: no-unknown
for _, value in ipairs(spec or {}) do
value = type(value) == "string" and { value } or value --[[@as LazyKeysSpec]]
value.mode = value.mode or "n"
local modes = (type(value.mode) == "table" and value.mode or { value.mode }) --[=[@as string[]]=]
for _, mode in ipairs(modes) do
local keys = M.parse(value, mode)
if keys.rhs == vim.NIL or keys.rhs == false then
values[keys.id] = nil
else
values[keys.id] = keys
end
end
end
return values
end
---@param keys LazyKeys
function M.opts(keys)
local opts = {} ---@type LazyKeysBase
---@diagnostic disable-next-line: no-unknown
for k, v in pairs(keys) do
if type(k) ~= "number" and not skip[k] then
---@diagnostic disable-next-line: no-unknown
opts[k] = v
end
end
return opts
end
---@param keys LazyKeys
function M.is_nop(keys)
return type(keys.rhs) == "string" and (keys.rhs == "" or keys.rhs:lower() == "<nop>")
end
---@param keys LazyKeys
function M:_add(keys)
local lhs = keys.lhs
local opts = M.opts(keys)
---@param buf? number
local function add(buf)
if M.is_nop(keys) then
return self:_set(keys, buf)
end
vim.keymap.set(keys.mode, lhs, function()
local plugins = self.active[keys.id]
-- always delete the mapping immediately to prevent recursive mappings
self:_del(keys)
self.active[keys.id] = nil
if plugins then
local name = M.to_string(keys)
Util.track({ keys = name })
Loader.load(plugins, { keys = name })
Util.track()
end
if keys.mode:sub(-1) == "a" then
lhs = lhs .. "<C-]>"
end
local feed = vim.api.nvim_replace_termcodes("<Ignore>" .. lhs, true, true, true)
-- insert instead of append the lhs
vim.api.nvim_feedkeys(feed, "i", false)
end, {
desc = opts.desc,
nowait = opts.nowait,
-- we do not return anything, but this is still needed to make operator pending mappings work
expr = true,
buffer = buf,
})
end
-- buffer-local mappings
if keys.ft then
vim.api.nvim_create_autocmd("FileType", {
pattern = keys.ft,
callback = function(event)
if self.active[keys.id] and not M.is_nop(keys) then
add(event.buf)
else
-- Only create the mapping if its managed by lazy
-- otherwise the plugin is supposed to manage it
self:_set(keys, event.buf)
end
end,
})
else
add()
end
end
-- Delete a mapping and create the real global/buffer-local
-- mapping when needed
---@param keys LazyKeys
function M:_del(keys)
-- bufs will be all buffers of the filetype for a buffer-local mapping
-- OR `false` for a global mapping
local bufs = { false }
if keys.ft then
local ft = type(keys.ft) == "string" and { keys.ft } or keys.ft --[[@as string[] ]]
bufs = vim.tbl_filter(function(buf)
return vim.tbl_contains(ft, vim.bo[buf].filetype)
end, vim.api.nvim_list_bufs())
end
for _, buf in ipairs(bufs) do
pcall(vim.keymap.del, keys.mode, keys.lhs, { buffer = buf or nil })
self:_set(keys, buf or nil)
end
end
-- Create a mapping if it is managed by lazy
---@param keys LazyKeys
---@param buf number?
function M:_set(keys, buf)
if keys.rhs then
local opts = M.opts(keys)
---@diagnostic disable-next-line: inject-field
opts.buffer = buf
vim.keymap.set(keys.mode, keys.lhs, keys.rhs, opts)
end
end
return M

View file

@ -1,104 +1,576 @@
local Util = require("lazy.core.util")
local Cache = require("lazy.core.cache")
local Config = require("lazy.core.config")
local Handler = require("lazy.core.handler")
local Plugin = require("lazy.core.plugin")
local Util = require("lazy.core.util")
---@class LazyCoreLoader
local M = {}
local DEFAULT_PRIORITY = 50
---@type LazyPlugin[]
M.loading = {}
M.init_done = false
---@type table<string,true>
M.disabled_rtp_plugins = { packer_compiled = true }
---@type table<string,string>
M.did_ftdetect = {}
M.did_handlers = false
function M.disable_rtp_plugin(plugin)
M.disabled_rtp_plugins[plugin] = true
end
function M.setup()
local Handler = require("lazy.core.handler")
local groups = Handler.group(Config.plugins)
for t, handler in pairs(Handler.handlers) do
if groups[t] then
Util.track(t)
handler(groups[t])
Util.track()
for _, file in ipairs(Config.options.performance.rtp.disabled_plugins) do
M.disable_rtp_plugin(file)
end
vim.api.nvim_create_autocmd("ColorSchemePre", {
callback = function(event)
M.colorscheme(event.match)
end,
})
-- load the plugins
Plugin.load()
Handler.init()
-- install missing plugins
if Config.options.install.missing then
Util.track("install")
local count = 0
while M.install_missing() do
count = count + 1
if count > 5 then
Util.error("Too many rounds of missing plugins")
break
end
end
Util.track()
end
Config.mapleader = vim.g.mapleader
Config.maplocalleader = vim.g.maplocalleader
-- report any warnings & errors
Config.spec:report()
-- setup handlers
Util.track("handlers")
Handler.setup()
M.did_handlers = true
Util.track()
end
-- this will incrementally install missing plugins
-- multiple rounds can happen when importing a spec from a missing plugin
function M.install_missing()
for _, plugin in pairs(Config.plugins) do
local installed = plugin._.installed
local has_errors = Plugin.has_errors(plugin)
if not has_errors and not (installed and not plugin._.build) then
for _, colorscheme in ipairs(Config.options.install.colorscheme) do
if colorscheme == "default" then
break
end
M.colorscheme(colorscheme)
if vim.g.colors_name or pcall(vim.cmd.colorscheme, colorscheme) then
break
end
end
Cache.reset()
require("lazy.manage").install({ wait = true, lockfile = true, clear = false })
-- remove any installed plugins from indexed, so cache will index again
for _, p in pairs(Config.plugins) do
if p._.installed then
Cache.reset(p.dir)
end
end
-- reload plugins
Plugin.load()
return true
end
end
end
function M.init_plugins()
Util.track("plugin_init")
-- Startup sequence
-- 1. load any start plugins and do init
function M.startup()
Util.track({ start = "startup" })
-- load filetype.lua first since plugins might depend on that
M.source(vim.env.VIMRUNTIME .. "/filetype.lua")
-- backup original rtp
local rtp = vim.opt.rtp:get() --[[@as string[] ]]
-- 1. run plugin init
Util.track({ start = "init" })
for _, plugin in pairs(Config.plugins) do
if plugin.init then
Util.track({ plugin = plugin.name, start = "init" })
Util.try(plugin.init, "Failed to run `init` for **" .. plugin.name .. "**")
Util.track({ plugin = plugin.name, init = "init" })
Util.try(function()
plugin.init(plugin)
end, "Failed to run `init` for **" .. plugin.name .. "**")
Util.track()
end
if plugin.opt == false then
end
Util.track()
-- 2. load start plugin
Util.track({ start = "start" })
for _, plugin in ipairs(M.get_start_plugins()) do
-- plugin may be loaded by another plugin in the meantime
if not plugin._.loaded then
M.load(plugin, { start = "start" })
end
end
Util.track()
-- 3. load plugins from the original rtp, excluding after
Util.track({ start = "rtp plugins" })
for _, path in ipairs(rtp) do
if not path:find("after/?$") then
-- these paths don't will already have their ftdetect ran,
-- by sourcing filetype.lua above, so skip them
M.did_ftdetect[path] = path
M.packadd(path)
end
end
Util.track()
-- 4. load after plugins
Util.track({ start = "after" })
for _, path in
ipairs(vim.opt.rtp:get() --[[@as string[] ]])
do
if path:find("after/?$") then
M.source_runtime(path, "plugin")
end
end
Util.track()
M.init_done = true
Util.track()
end
function M.get_start_plugins()
---@type LazyPlugin[]
local start = {}
for _, plugin in pairs(Config.plugins) do
if not plugin._.loaded and (plugin._.rtp_loaded or plugin.lazy == false) then
start[#start + 1] = plugin
end
end
table.sort(start, function(a, b)
local ap = a.priority or DEFAULT_PRIORITY
local bp = b.priority or DEFAULT_PRIORITY
return ap > bp
end)
return start
end
---@class Loader
---@param plugins string|LazyPlugin|string[]|LazyPlugin[]
---@param reason {[string]:string}
---@param opts? {load_start: boolean}
---@param opts? {force:boolean} when force is true, we skip the cond check
function M.load(plugins, reason, opts)
---@diagnostic disable-next-line: cast-local-type
plugins = type(plugins) == "string" or plugins.name and { plugins } or plugins
plugins = (type(plugins) == "string" or plugins.name) and { plugins } or plugins
---@cast plugins (string|LazyPlugin)[]
for _, plugin in ipairs(plugins) do
plugin = type(plugin) == "string" and Config.plugins[plugin] or plugin
---@cast plugin LazyPlugin
if not plugin._.loaded then
---@diagnostic disable-next-line: assign-type-mismatch
plugin._.loaded = {}
for k, v in pairs(reason) do
plugin._.loaded[k] = v
for _, plugin in pairs(plugins) do
if type(plugin) == "string" then
if Config.plugins[plugin] then
plugin = Config.plugins[plugin]
elseif Config.spec.disabled[plugin] then
plugin = nil
else
Util.error("Plugin " .. plugin .. " not found")
plugin = nil
end
if #M.loading > 0 then
plugin._.loaded.plugin = M.loading[#M.loading].name
end
table.insert(M.loading, plugin)
Util.track({ plugin = plugin.name, start = reason.start })
M.packadd(plugin, opts and opts.load_start)
if plugin.dependencies then
M.load(plugin.dependencies, {})
end
if plugin.config then
Util.try(plugin.config, "Failed to run `config` for " .. plugin.name)
end
plugin._.loaded.time = Util.track().time
table.remove(M.loading)
vim.schedule(function()
vim.cmd("do User LazyRender")
end)
end
if plugin and not plugin._.loaded then
M._load(plugin, reason, opts)
end
end
end
---@param plugin LazyPlugin
function M.packadd(plugin, load_start)
if plugin.opt then
vim.cmd.packadd(plugin.name)
M.source_plugin_files(plugin, true)
elseif load_start then
vim.opt.runtimepath:append(plugin.dir)
M.source_plugin_files(plugin)
M.source_plugin_files(plugin, true)
function M.deactivate(plugin)
if not plugin._.loaded then
return
end
local main = M.get_main(plugin)
if main then
Util.try(function()
local mod = require(main)
if mod.deactivate then
mod.deactivate(plugin)
end
end, "Failed to deactivate plugin " .. plugin.name)
end
-- execute deactivate when needed
if plugin.deactivate then
Util.try(function()
plugin.deactivate(plugin)
end, "Failed to deactivate plugin " .. plugin.name)
end
-- disable handlers
Handler.disable(plugin)
-- clear plugin properties cache
plugin._.cache = nil
-- remove loaded lua modules
Util.walkmods(plugin.dir .. "/lua", function(modname)
package.loaded[modname] = nil
package.preload[modname] = nil
end)
-- clear vim.g.loaded_ for plugins
Util.ls(plugin.dir .. "/plugin", function(_, name, type)
if type == "file" then
vim.g["loaded_" .. name:gsub("%..*", "")] = nil
end
end)
-- set as not loaded
plugin._.loaded = nil
end
--- reload a plugin
---@param plugin LazyPlugin|string
function M.reload(plugin)
if type(plugin) == "string" then
plugin = Config.plugins[plugin]
end
if not plugin then
error("Plugin not found")
end
local load = plugin._.loaded ~= nil
M.deactivate(plugin)
-- enable handlers
Handler.enable(plugin)
-- run init
if plugin.init then
Util.try(function()
plugin.init(plugin)
end, "Failed to run `init` for **" .. plugin.name .. "**")
end
-- if this is a start plugin, load it now
if plugin.lazy == false then
load = true
end
local events = plugin._.handlers and plugin._.handlers.event and plugin._.handlers.event or {}
for _, event in pairs(events) do
if event.id:find("VimEnter") or event.id:find("UIEnter") or event.id:find("VeryLazy") then
load = true
break
end
end
-- reload any vimscript files for this plugin
local scripts = vim.fn.getscriptinfo()
local loaded_scripts = {}
for _, s in ipairs(scripts) do
---@type string
local path = s.name
if
path:sub(-4) == ".vim"
and path:find(plugin.dir, 1, true) == 1
and not path:find("/plugin/", 1, true)
and not path:find("/ftplugin/", 1, true)
then
loaded_scripts[#loaded_scripts + 1] = path
end
end
if load then
M.load(plugin, { start = "reload" })
for _, s in ipairs(loaded_scripts) do
M.source(s)
end
end
end
---@param plugin LazyPlugin
---@param after? boolean
function M.source_plugin_files(plugin, after)
Util.walk(plugin.dir .. (after and "/after" or "") .. "/plugin", function(path, _, t)
local ext = path:sub(-3)
if t == "file" and (ext == "lua" or ext == "vim") then
vim.cmd("silent source " .. path)
end
---@param reason {[string]:string}
---@param opts? {force:boolean} when force is true, we skip the cond check
function M._load(plugin, reason, opts)
if not plugin._.installed then
return Util.error("Plugin " .. plugin.name .. " is not installed")
end
if plugin._.cond == false and not (opts and opts.force) then
return
end
if not Handler.did_setup then
Util.try(function()
Handler.enable(plugin)
end, "Failed to setup handlers for " .. plugin.name)
end
---@diagnostic disable-next-line: assign-type-mismatch
plugin._.loaded = {}
for k, v in pairs(reason) do
plugin._.loaded[k] = v
end
if #M.loading > 0 then
plugin._.loaded.plugin = M.loading[#M.loading].name
elseif reason.require then
plugin._.loaded.source = Util.get_source()
end
table.insert(M.loading, plugin)
Util.track({ plugin = plugin.name, start = reason.start })
Handler.disable(plugin)
if not plugin.virtual then
M.add_to_rtp(plugin)
end
if plugin._.pkg and plugin._.pkg.source == "rockspec" then
M.add_to_luapath(plugin)
end
if plugin.dependencies then
Util.try(function()
M.load(plugin.dependencies, {})
end, "Failed to load deps for " .. plugin.name)
end
if not plugin.virtual then
M.packadd(plugin.dir)
end
if plugin.config or plugin.opts then
M.config(plugin)
end
plugin._.loaded.time = Util.track().time
table.remove(M.loading)
vim.schedule(function()
vim.api.nvim_exec_autocmds("User", { pattern = "LazyLoad", modeline = false, data = plugin.name })
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
end)
end
--- runs plugin config
---@param plugin LazyPlugin
function M.config(plugin)
local fn
if type(plugin.config) == "function" then
fn = function()
local opts = Plugin.values(plugin, "opts", false)
plugin.config(plugin, opts)
end
else
local main = M.get_main(plugin)
if main then
fn = function()
local opts = Plugin.values(plugin, "opts", false)
require(main).setup(opts)
end
else
return Util.error(
"Lua module not found for config of " .. plugin.name .. ". Please use a `config()` function instead"
)
end
end
Util.try(fn, "Failed to run `config` for " .. plugin.name)
end
---@param plugin LazyPlugin
function M.get_main(plugin)
if plugin.main then
return plugin.main
end
if plugin.name ~= "mini.nvim" and plugin.name:match("^mini%..*$") then
return plugin.name
end
local normname = Util.normname(plugin.name)
---@type string[]
local mods = {}
for _, mod in ipairs(Cache.find("*", { all = true, rtp = false, paths = { plugin.dir } })) do
local modname = mod.modname
mods[#mods + 1] = modname
local modnorm = Util.normname(modname)
-- if we found an exact match, then use that
if modnorm == normname then
mods = { modname }
break
end
end
return #mods == 1 and mods[1] or nil
end
---@param path string
function M.packadd(path)
M.source_runtime(path, "plugin")
M.ftdetect(path)
if M.init_done then
M.source_runtime(path, "after/plugin")
end
end
---@param path string
function M.ftdetect(path)
if not M.did_ftdetect[path] then
M.did_ftdetect[path] = path
vim.cmd("augroup filetypedetect")
M.source_runtime(path, "ftdetect")
vim.cmd("augroup END")
end
end
---@param ... string
function M.source_runtime(...)
local dir = table.concat({ ... }, "/")
---@type string[]
local files = {}
Util.walk(dir, function(path, name, t)
local ext = name:sub(-3)
name = name:sub(1, -5)
if (t == "file" or t == "link") and (ext == "lua" or ext == "vim") and not M.disabled_rtp_plugins[name] then
files[#files + 1] = path
end
end)
-- plugin files are sourced alphabetically per directory
table.sort(files)
for _, path in ipairs(files) do
M.source(path)
end
end
-- This does the same as runtime.c:add_pack_dir_to_rtp
-- * find first after
-- * find lazy pack path
-- * insert right after lazy pack path or right before first after or at the end
-- * insert after dir right before first after or append to the end
---@param plugin LazyPlugin
function M.add_to_rtp(plugin)
local rtp = vim.api.nvim_get_runtime_file("", true)
local idx_dir, idx_after
for i, path in ipairs(rtp) do
if Util.is_win then
path = Util.norm(path)
end
if path == Config.me then
idx_dir = i + 1
elseif not idx_after and path:sub(-6, -1) == "/after" then
idx_after = i + 1 -- +1 to offset the insert of the plugin dir
idx_dir = idx_dir or i
break
end
end
table.insert(rtp, idx_dir or (#rtp + 1), plugin.dir)
local after = plugin.dir .. "/after"
if vim.uv.fs_stat(after) then
table.insert(rtp, idx_after or (#rtp + 1), after)
end
---@type vim.Option
vim.opt.rtp = rtp
end
---@param plugin LazyPlugin
function M.add_to_luapath(plugin)
local root = Config.options.rocks.root .. "/" .. plugin.name
local path = root .. "/share/lua/5.1"
local cpath = root .. "/lib/lua/5.1"
local cpath2 = root .. "/lib64/lua/5.1"
package.path = package.path .. ";" .. path .. "/?.lua;" .. path .. "/?/init.lua;"
package.cpath = package.cpath .. ";" .. cpath .. "/?." .. (jit.os:find("Windows") and "dll" or "so") .. ";"
package.cpath = package.cpath .. ";" .. cpath2 .. "/?." .. (jit.os:find("Windows") and "dll" or "so") .. ";"
end
function M.source(path)
Util.track({ runtime = path })
Util.try(function()
vim.cmd("source " .. path)
end, "Failed to source `" .. path .. "`")
Util.track()
end
function M.colorscheme(name)
if vim.tbl_contains(vim.fn.getcompletion("", "color"), name) then
return
end
for _, plugin in pairs(Config.plugins) do
if not plugin._.loaded then
for _, ext in ipairs({ "lua", "vim" }) do
local path = plugin.dir .. "/colors/" .. name .. "." .. ext
if vim.uv.fs_stat(path) then
return M.load(plugin, { colorscheme = name })
end
end
end
end
end
function M.auto_load(modname, modpath)
local plugin = Plugin.find(modpath, { fast = not M.did_handlers })
if plugin then
plugin._.rtp_loaded = true
-- don't load if:
-- * handlers haven't been setup yet
-- * we're loading specs
-- * the plugin is already loaded
if M.did_handlers and not (Plugin.loading or plugin._.loaded) then
if plugin.module == false then
error("Plugin " .. plugin.name .. " is not loaded and is configured with module=false")
end
M.load(plugin, { require = modname })
if plugin._.cond == false then
error("You're trying to load `" .. plugin.name .. "` for which `cond==false`")
end
end
end
end
---@param modname string
function M.loader(modname)
local paths, cached = Util.get_unloaded_rtp(modname, { cache = true })
local ret = Cache.find(modname, { rtp = false, paths = paths })[1]
if not ret and cached then
paths = Util.get_unloaded_rtp(modname)
ret = Cache.find(modname, { rtp = false, paths = paths })[1]
end
if ret then
-- explicitly set to nil to prevent loading errors
package.loaded[modname] = nil
M.auto_load(modname, ret.modpath)
local mod = package.loaded[modname]
if type(mod) == "table" then
return function()
return mod
end
end
-- selene: allow(incorrect_standard_library_use)
return loadfile(ret.modpath, nil, nil, ret.stat)
end
end
return M

360
lua/lazy/core/meta.lua Normal file
View file

@ -0,0 +1,360 @@
local Config = require("lazy.core.config")
local Pkg = require("lazy.pkg")
local Util = require("lazy.core.util")
--- This class is used to manage the plugins.
--- A plugin is a collection of fragments that are related to each other.
---@class LazyMeta
---@field plugins table<string, LazyPlugin>
---@field str_to_meta table<string, LazyPlugin>
---@field frag_to_meta table<number, LazyPlugin>
---@field dirty table<string, boolean>
---@field spec LazySpecLoader
---@field fragments LazyFragments
---@field pkgs table<string, number>
local M = {}
---@param spec LazySpecLoader
---@return LazyMeta
function M.new(spec)
local self = setmetatable({}, { __index = M })
self.spec = spec
self.fragments = require("lazy.core.fragments").new(spec)
self.plugins = {}
self.frag_to_meta = {}
self.str_to_meta = {}
self.dirty = {}
self.pkgs = {}
return self
end
-- import package specs
function M:load_pkgs()
if not Config.options.pkg.enabled then
return
end
for _, pkg in ipairs(Pkg.get()) do
local last_id = self.fragments._fid
local meta, fragment = self:add(pkg.spec)
if meta and fragment then
meta._.pkg = pkg
-- tag all top-level package fragments that were added as optional
for _, fid in ipairs(meta._.frags) do
if fid > last_id then
local frag = self.fragments:get(fid)
frag.spec.optional = true
end
end
-- keep track of the top-level package fragment
self.pkgs[pkg.dir] = fragment.id
end
end
end
--- Remove a plugin and all its fragments.
---@param name string
function M:del(name)
local meta = self.plugins[name]
if not meta then
return
end
for _, fid in ipairs(meta._.frags or {}) do
self.fragments:del(fid)
end
self.plugins[name] = nil
end
--- Add a fragment to a plugin.
--- This will create a new plugin if it does not exist.
--- It also keeps track of renames.
---@param plugin LazyPluginSpec
function M:add(plugin)
local fragment = self.fragments:add(plugin)
if not fragment then
return
end
local meta = self.plugins[fragment.name]
or fragment.url and self.str_to_meta[fragment.url]
or fragment.dir and self.str_to_meta[fragment.dir]
if not meta then
meta = { name = fragment.name, _ = { frags = {} } }
local url, dir = fragment.url, fragment.dir
-- add to index
if url then
self.str_to_meta[url] = meta
end
if dir then
self.str_to_meta[dir] = meta
end
end
table.insert(meta._.frags, fragment.id)
if meta._ and meta._.rtp_loaded and meta.dir then
local old_dir = meta.dir
self:_rebuild(meta.name)
local new_dir = meta.dir
if old_dir ~= new_dir then
local msg = "Plugin `" .. meta.name .. "` changed `dir`:\n- from: `" .. old_dir .. "`\n- to: `" .. new_dir .. "`"
msg = msg .. "\n\nThis plugin was already partially loaded, so things may break.\nPlease fix your config."
self.spec:error(msg)
end
end
if plugin.name then
-- handle renames
if meta.name ~= plugin.name then
self.plugins[meta.name] = nil
meta.name = plugin.name
end
end
self.plugins[meta.name] = meta
self.frag_to_meta[fragment.id] = meta
self.dirty[meta.name] = true
return meta, fragment
end
--- Rebuild all plugins based on dirty fragments,
--- or dirty plugins. Will remove plugins that no longer have fragments.
function M:rebuild()
local frag_count = vim.tbl_count(self.fragments.dirty)
local plugin_count = vim.tbl_count(self.dirty)
if frag_count == 0 and plugin_count == 0 then
return
end
if Config.options.debug then
Util.track("rebuild plugins frags=" .. frag_count .. " plugins=" .. plugin_count)
end
for fid in pairs(self.fragments.dirty) do
local meta = self.frag_to_meta[fid]
if meta then
if self.fragments:get(fid) then
-- fragment still exists, so mark plugin as dirty
self.dirty[meta.name] = true
else
-- fragment was deleted, so remove it from plugin
self.frag_to_meta[fid] = nil
---@param f number
meta._.frags = Util.filter(function(f)
return f ~= fid
end, meta._.frags)
-- if no fragments left, delete plugin
if #meta._.frags == 0 then
self:del(meta.name)
else
self.dirty[meta.name] = true
end
end
end
end
self.fragments.dirty = {}
for n, _ in pairs(self.dirty) do
self:_rebuild(n)
end
if Config.options.debug then
Util.track()
end
end
--- Rebuild a single plugin.
--- This will resolve the plugin based on its fragments using metatables.
--- This also resolves dependencies, dep, optional, dir, dev, and url.
---@param name string
function M:_rebuild(name)
if not self.dirty[name] then
return
end
self.dirty[name] = nil
local plugin = self.plugins[name]
if not plugin or #plugin._.frags == 0 then
self.plugins[name] = nil
return
end
setmetatable(plugin, nil)
plugin.dependencies = {}
local super = nil
plugin.url = nil
plugin._.dep = true
plugin._.top = true
plugin.optional = true
assert(#plugin._.frags > 0, "no fragments found for plugin " .. name)
---@type table<number, boolean>
local added = {}
for _, fid in ipairs(plugin._.frags) do
if not added[fid] then
added[fid] = true
local fragment = self.fragments:get(fid)
assert(fragment, "fragment " .. fid .. " not found, for plugin " .. name)
---@diagnostic disable-next-line: no-unknown
super = setmetatable(fragment.spec, super and { __index = super } or nil)
plugin._.dep = plugin._.dep and fragment.dep
plugin.optional = plugin.optional and (rawget(fragment.spec, "optional") == true)
plugin.url = fragment.url or plugin.url
plugin._.top = plugin._.top and fragment.pid == nil
-- dependencies
for _, dep in ipairs(fragment.deps or {}) do
local dep_meta = self.frag_to_meta[dep]
if dep_meta then
table.insert(plugin.dependencies, dep_meta.name)
end
end
end
end
super = super or {}
-- dir / dev
plugin.dev = super.dev
plugin.dir = super.dir
if plugin.dir then
plugin.dir = Util.norm(plugin.dir)
elseif super.virtual then
plugin.dir = Util.norm("/dev/null/" .. plugin.name)
else
if plugin.dev == nil and plugin.url then
for _, pattern in ipairs(Config.options.dev.patterns) do
if plugin.url:find(pattern, 1, true) then
plugin.dev = true
break
end
end
end
if plugin.dev == true then
local dev_dir = type(Config.options.dev.path) == "string" and Config.options.dev.path .. "/" .. plugin.name
or Util.norm(Config.options.dev.path(plugin))
if not Config.options.dev.fallback or vim.fn.isdirectory(dev_dir) == 1 then
plugin.dir = dev_dir
else
plugin.dev = false
end
end
plugin.dir = plugin.dir or Config.options.root .. "/" .. plugin.name
end
-- dependencies
if #plugin.dependencies == 0 and not super.dependencies then
plugin.dependencies = nil
end
-- optional
if not plugin.optional and not super.optional then
plugin.optional = nil
end
setmetatable(plugin, { __index = super })
return plugin
end
--- Disable a plugin.
---@param plugin LazyPlugin
function M:disable(plugin)
plugin._.kind = "disabled"
self:del(plugin.name)
self.spec.disabled[plugin.name] = plugin
end
--- Check if a plugin should be disabled, but ignore uninstalling it.
function M:fix_cond()
for _, plugin in pairs(self.plugins) do
local cond = plugin.cond
if cond == nil then
cond = Config.options.defaults.cond
end
if cond == false or (type(cond) == "function" and not cond(plugin)) then
plugin._.cond = false
local stack = { plugin }
while #stack > 0 do
local p = table.remove(stack) --[[@as LazyPlugin]]
if not self.spec.ignore_installed[p.name] then
for _, dep in ipairs(p.dependencies or {}) do
table.insert(stack, self.plugins[dep])
end
self.spec.ignore_installed[p.name] = true
end
end
plugin.enabled = false
end
end
end
--- Removes plugins for which all its fragments are optional.
function M:fix_optional()
if self.spec.optional then
return 0
end
local changes = 0
for _, plugin in pairs(self.plugins) do
if plugin.optional then
changes = changes + 1
self:del(plugin.name)
end
end
self:rebuild()
return changes
end
--- Removes plugins that are disabled.
function M:fix_disabled()
local changes = 0
local function check(top)
for _, plugin in pairs(self.plugins) do
if (plugin._.top or false) == top then
if plugin.enabled == false or (type(plugin.enabled) == "function" and not plugin.enabled()) then
changes = changes + 1
if plugin.optional then
self:del(plugin.name)
else
self:disable(plugin)
end
self:rebuild()
end
end
end
end
-- disable top-level plugins first, since they may have non-top-level frags
-- that disable other plugins
check(true)
-- then disable non-top-level plugins
check(false)
return changes
end
--- Removes package fragments for plugins that no longer use the same directory.
function M:fix_pkgs()
for dir, fid in pairs(self.pkgs) do
local plugin = self.frag_to_meta[fid]
plugin = plugin and self.plugins[plugin.name]
if plugin then
-- check if plugin is still in the same directory
if plugin.dir ~= dir then
self.fragments:del(fid)
end
end
end
self:rebuild()
end
--- Resolve all plugins, based on cond, enabled and optional.
function M:resolve()
Util.track("resolve plugins")
self:rebuild()
self:fix_pkgs()
self:fix_cond()
-- selene: allow(empty_loop)
while self:fix_disabled() + self:fix_optional() > 0 do
end
Util.track()
end
return M

View file

@ -1,71 +0,0 @@
local Cache = require("lazy.core.cache")
local M = {}
---@type table<string, string>
M.hashes = {}
function M.is_dirty(modname, modpath)
return not (Cache.get(modname) and M.hashes[modname] and M.hashes[modname] == Cache.hash(modpath))
end
---@param modname string
---@param modpath string
---@return any, boolean
function M.load(modname, modpath)
local err
---@type (string|fun())?
local chunk = Cache.get(modname)
local hash = Cache.hash(modpath)
if hash ~= M.hashes[modname] then
M.hashes[modname] = hash
Cache.del(modname)
chunk = nil
end
local cached = false
if chunk then
cached = true
chunk, err = load(chunk --[[@as string]], "@" .. modpath, "b")
else
vim.schedule(function()
vim.notify("loadfile(" .. modname .. ")")
end)
chunk, err = loadfile(modpath)
if chunk and not err then
Cache.set(modname, string.dump(chunk))
end
end
if chunk then
return chunk(), cached
else
error(err)
end
end
function M.setup()
-- load cache
local value = Cache.get("cache.modules")
if value then
M.hashes = vim.json.decode(value)
end
-- preload core modules
local root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h:h")
for _, name in ipairs({ "util", "config", "loader", "plugin", "handler" }) do
local modname = "lazy.core." .. name
---@diagnostic disable-next-line: no-unknown
package.preload[modname] = function()
return M.load(modname, root .. "/core/" .. name:gsub("%.", "/") .. ".lua")
end
end
return M
end
function M.save()
Cache.set("cache.modules", vim.json.encode(M.hashes))
end
return M

View file

@ -1,344 +1,484 @@
local Config = require("lazy.core.config")
local Meta = require("lazy.core.meta")
local Pkg = require("lazy.pkg")
local Util = require("lazy.core.util")
local Module = require("lazy.core.module")
local Cache = require("lazy.core.cache")
local Handler = require("lazy.core.handler")
---@class LazyCorePlugin
local M = {}
---@alias CachedPlugin LazyPlugin | {_funs: string[]}
local skip = { _ = true, dir = true }
local funs = { config = true, init = true, run = true }
M.dirty = false
---@class LazyPluginHooks
---@field init? fun(LazyPlugin) Will always be run
---@field config? fun(LazyPlugin) Will be executed when loading the plugin
---@field run? string|fun()
---@class LazyPluginState
---@field loaded? {[string]:string, time:number}
---@field installed boolean
---@field tasks? LazyTask[]
---@field dirty? boolean
---@field updated? {from:string, to:string}
---@field is_local boolean
---@field is_symlink? boolean
---@field cloned? boolean
---@class LazyPluginRef
---@field branch? string
---@field tag? string
---@field commit? string
---@field version? string
---@field pin? boolean
---@class LazyPlugin: LazyPluginHandlers,LazyPluginHooks,LazyPluginRef
---@field [1] string
---@field name string display name and name used for plugin config files
---@field uri string
---@field dir string
---@field dep? boolean True if this plugin is only in the spec as a dependency
---@field enabled? boolean|(fun():boolean)
---@field opt? boolean
---@field dependencies? string[]
---@field _ LazyPluginState
---@alias LazySpec string|LazyPlugin|LazySpec[]|{dependencies:LazySpec}
M.loading = false
---@class LazySpecLoader
---@field modname string
---@field modpath string
---@field meta LazyMeta
---@field plugins table<string, LazyPlugin>
---@field funs? table<string, string[]>
---@field disabled table<string, LazyPlugin>
---@field ignore_installed table<string, true>
---@field modules string[]
---@field notifs {msg:string, level:number, file?:string}[]
---@field importing? string
---@field optional? boolean
local Spec = {}
M.Spec = Spec
M.LOCAL_SPEC = ".lazy.lua"
---@param spec? LazySpec
function Spec.new(spec)
local self = setmetatable({}, { __index = Spec })
self.plugins = {}
self.modname = nil
self.modpath = nil
---@param opts? {optional?:boolean, pkg?:boolean}
function Spec.new(spec, opts)
local self = setmetatable({}, Spec)
self.meta = Meta.new(self)
self.disabled = {}
self.modules = {}
self.notifs = {}
self.ignore_installed = {}
self.optional = opts and opts.optional
if not (opts and opts.pkg == false) then
self.meta:load_pkgs()
end
if spec then
self:normalize(spec)
self:parse(spec)
end
return self
end
---@param modname string
---@param modpath string
function Spec.load(modname, modpath)
local self = setmetatable({}, { __index = Spec })
self.plugins = {}
self.modname = modname
self.modpath = modpath
local mod, cached = Module.load(modname, modpath)
M.dirty = M.dirty or not cached
self:normalize(assert(mod))
if modname == Config.options.plugins and not self.plugins["lazy.nvim"] then
self:add({ "folke/lazy.nvim", opt = false })
function Spec:__index(key)
if Spec[key] then
return Spec[key]
end
if key == "plugins" then
self.meta:rebuild()
return self.meta.plugins
end
return self
end
---@param plugin LazyPlugin
---@param is_dep? boolean
function Spec:add(plugin, is_dep)
local pkg = plugin[1]
if type(pkg) ~= "string" then
Util.error("Invalid plugin spec " .. vim.inspect(plugin))
end
function Spec:parse(spec)
self:normalize(spec)
self.meta:resolve()
end
if not plugin.uri then
local c = pkg:sub(1, 1)
if c == "~" then
plugin.uri = vim.loop.os_getenv("HOME") .. pkg:sub(2)
elseif c == "/" then
plugin.uri = pkg
elseif pkg:sub(1, 4) == "http" or pkg:sub(1, 3) == "ssh" then
plugin.uri = pkg
else
plugin.uri = ("https://github.com/" .. pkg .. ".git")
-- PERF: optimized code to get package name without using lua patterns
---@return string
function Spec.get_name(pkg)
local name = pkg:sub(-4) == ".git" and pkg:sub(1, -5) or pkg
name = name:sub(-1) == "/" and name:sub(1, -2) or name
local slash = name:reverse():find("/", 1, true) --[[@as number?]]
return slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_")
end
function Spec:error(msg)
self:log(msg, vim.log.levels.ERROR)
end
function Spec:warn(msg)
self:log(msg, vim.log.levels.WARN)
end
---@param msg string
---@param level number
function Spec:log(msg, level)
self.notifs[#self.notifs + 1] = { msg = msg, level = level, file = self.importing }
end
function Spec:report(level)
level = level or vim.log.levels.ERROR
local count = 0
for _, notif in ipairs(self.notifs) do
if notif.level >= level then
Util.notify(notif.msg, { level = notif.level })
count = count + 1
end
end
-- PERF: optimized code to get package name without using lua patterns
if not plugin.name then
local name = pkg:sub(-4) == ".git" and pkg:sub(1, -5) or pkg
local slash = name:reverse():find("/", 1, true) --[[@as number?]]
plugin.name = slash and name:sub(#name - slash + 2) or pkg:gsub("%W+", "_")
end
plugin.dep = is_dep
M.process_local(plugin)
local other = self.plugins[plugin.name]
self.plugins[plugin.name] = other and M.merge(other, plugin) or plugin
return self.plugins[plugin.name]
return count
end
---@param spec LazySpec
---@param results? string[]
---@param is_dep? boolean
function Spec:normalize(spec, results, is_dep)
results = results or {}
---@param spec LazySpec|LazySpecImport
function Spec:normalize(spec)
if type(spec) == "string" then
table.insert(results, self:add({ spec }, is_dep).name)
self.meta:add({ spec })
elseif #spec > 1 or Util.is_list(spec) then
---@cast spec LazySpec[]
for _, s in ipairs(spec) do
self:normalize(s, results, is_dep)
self:normalize(s)
end
elseif spec.enabled == nil or spec.enabled == true or (type(spec.enabled) == "function" and spec.enabled()) then
---@cast spec LazyPlugin
local plugin = self:add(spec, is_dep)
plugin.dependencies = plugin.dependencies and self:normalize(plugin.dependencies, {}, true) or nil
table.insert(results, plugin.name)
elseif spec[1] or spec.dir or spec.url then
---@cast spec LazyPluginSpec
self.meta:add(spec)
---@diagnostic disable-next-line: cast-type-mismatch
---@cast spec LazySpecImport
if spec and spec.import then
self:import(spec)
end
elseif spec.import then
---@cast spec LazySpecImport
self:import(spec)
else
self:error("Invalid plugin spec " .. vim.inspect(spec))
end
return results
end
---@param spec LazySpecLoader
function Spec.revive(spec)
if spec.funs then
---@type LazySpecLoader
local loaded = nil
for fun, plugins in pairs(spec.funs) do
for _, name in pairs(plugins) do
---@diagnostic disable-next-line: no-unknown
spec.plugins[name][fun] = function(...)
loaded = loaded or Spec.load(spec.modname, spec.modpath)
return loaded.plugins[name][fun](...)
end
end
end
---@param spec LazySpecImport
function Spec:import(spec)
if spec.import == "lazy" then
return self:error("You can't name your plugins module `lazy`.")
end
if type(spec.import) == "function" then
if not spec.name then
return self:error("Invalid import spec. Missing name: " .. vim.inspect(spec))
end
elseif type(spec.import) ~= "string" then
return self:error("Invalid import spec. `import` should be a string: " .. vim.inspect(spec))
end
return spec
end
---@param old LazyPlugin
---@param new LazyPlugin
---@return LazyPlugin
function M.merge(old, new)
local is_dep = old.dep and new.dep
local import_name = spec.name or spec.import
---@cast import_name string
---@diagnostic disable-next-line: no-unknown
for k, v in pairs(new) do
if k == "dep" then
elseif old[k] ~= nil and old[k] ~= v then
if Handler.handlers[k] then
local values = type(v) == "string" and { v } or v
vim.list_extend(values, type(old[k]) == "string" and { old[k] } or old[k])
---@diagnostic disable-next-line: no-unknown
old[k] = values
if vim.tbl_contains(self.modules, import_name) then
return
end
if spec.cond == false or (type(spec.cond) == "function" and not spec.cond()) then
return
end
if spec.enabled == false or (type(spec.enabled) == "function" and not spec.enabled()) then
return
end
self.modules[#self.modules + 1] = import_name
local import = spec.import
local imported = 0
---@type {modname: string, load: fun():(LazyPluginSpec?, string?)}[]
local modspecs = {}
if type(import) == "string" then
Util.lsmod(import, function(modname, modpath)
modspecs[#modspecs + 1] = {
modname = modname,
load = function()
local mod, err = loadfile(modpath)
if mod then
return mod()
else
return nil, err
end
end,
}
end)
table.sort(modspecs, function(a, b)
return a.modname < b.modname
end)
else
modspecs = { { modname = import_name, load = spec.import } }
end
for _, modspec in ipairs(modspecs) do
imported = imported + 1
local modname = modspec.modname
Util.track({ import = modname })
self.importing = modname
-- unload the module so we get a clean slate
---@diagnostic disable-next-line: no-unknown
package.loaded[modname] = nil
Util.try(function()
local mod, err = modspec.load()
if err then
self:error("Failed to load `" .. modname .. "`:\n" .. err)
elseif type(mod) ~= "table" then
return self:error(
"Invalid spec module: `"
.. modname
.. "`\nExpected a `table` of specs, but a `"
.. type(mod)
.. "` was returned instead"
)
else
error("Merging plugins is not supported for key `" .. k .. "`")
self:normalize(mod)
end
else
---@diagnostic disable-next-line: no-unknown
old[k] = v
end
end, {
msg = "Failed to load `" .. modname .. "`",
on_error = function(msg)
self:error(msg)
end,
})
self.importing = nil
Util.track()
end
if imported == 0 then
self:error("No specs found for module " .. vim.inspect(spec.import))
end
old.dep = is_dep
return old
end
---@param opts? {clean:boolean, installed:boolean, plugins?: LazyPlugin[]}
function M.update_state(opts)
opts = opts or {}
function M.update_state()
---@type string[]
local cloning = {}
---@type table<"opt"|"start", table<string,FileType>>
local installed = { opt = {}, start = {} }
if opts.installed ~= false then
for opt, packs in pairs(installed) do
Util.ls(Config.options.packpath .. "/" .. opt, function(_, name, type)
if type == "directory" or type == "link" then
packs[name] = type
end
end)
---@type table<string,FileType>
local installed = {}
Util.ls(Config.options.root, function(_, name, type)
if type == "directory" and name ~= "readme" then
installed[name] = type
elseif type == "file" and name:sub(-8) == ".cloning" then
name = name:sub(1, -9)
cloning[#cloning + 1] = name
end
end)
for _, failed in ipairs(cloning) do
installed[failed] = nil
end
for _, plugin in pairs(opts.plugins or Config.plugins) do
for _, plugin in pairs(Config.plugins) do
plugin._ = plugin._ or {}
plugin[1] = plugin["1"] or plugin[1]
if plugin.opt == nil then
plugin.opt = plugin.dep
or Config.options.opt
or plugin.module
if plugin.lazy == nil then
local lazy = plugin._.dep
or Config.options.defaults.lazy
or plugin.event
or plugin.keys
or plugin.ft
or plugin.cmd
plugin.opt = plugin.opt and true or false
plugin.lazy = lazy and true or false
end
local opt = plugin.opt and "opt" or "start"
plugin.dir = Config.options.packpath .. "/" .. opt .. "/" .. plugin.name
plugin._.is_local = plugin.uri:sub(1, 4) ~= "http" and plugin.uri:sub(1, 3) ~= "git"
plugin._.is_symlink = installed[opt][plugin.name] == "link"
plugin._.installed = installed[opt][plugin.name] ~= nil
if plugin._.is_local == plugin._.is_symlink then
installed[opt][plugin.name] = nil
if plugin.virtual then
plugin._.is_local = true
plugin._.installed = true -- local plugins are managed by the user
elseif plugin.dir:find(Config.options.root, 1, true) == 1 then
plugin._.installed = installed[plugin.name] ~= nil
installed[plugin.name] = nil
else
plugin._.is_local = true
plugin._.installed = vim.fn.isdirectory(plugin.dir) == 1
end
end
if opts.clean then
Config.to_clean = {}
for opt, packs in pairs(installed) do
for pack in pairs(packs) do
table.insert(Config.to_clean, {
name = pack,
pack = pack,
dir = Config.options.packpath .. "/" .. opt .. "/" .. pack,
opt = opt == "opt",
_ = {
installed = true,
},
})
end
for name in pairs(Config.spec.ignore_installed) do
installed[name] = nil
end
M.update_rocks_state()
Config.to_clean = {}
for pack, dir_type in pairs(installed) do
table.insert(Config.to_clean, {
name = pack,
dir = Config.options.root .. "/" .. pack,
_ = {
kind = "clean",
installed = true,
is_symlink = dir_type == "link",
is_local = dir_type == "link",
},
})
end
end
function M.update_rocks_state()
local root = Config.options.rocks.root
---@type table<string,string>
local installed = {}
Util.ls(root, function(_, name, type)
if type == "directory" then
installed[name] = name
end
end)
for _, plugin in pairs(Config.plugins) do
if plugin.build == "rockspec" or plugin.name == "hererocks" then
plugin._.build = not installed[plugin.name]
end
end
end
---@param plugin LazyPlugin
function M.process_local(plugin)
for _, pattern in ipairs(Config.options.plugins_local.patterns) do
if plugin[1]:find(pattern, 1, true) then
plugin.uri = Config.options.plugins_local.path .. "/" .. plugin.name
return
---@return LazySpecImport?
function M.find_local_spec()
if not Config.options.local_spec then
return
end
local path = vim.uv.cwd()
while path and path ~= "" do
local file = path .. "/" .. M.LOCAL_SPEC
if vim.fn.filereadable(file) == 1 then
return {
name = vim.fn.fnamemodify(file, ":~:."),
import = function()
local data = vim.secure.read(file)
if data then
return loadstring(data, M.LOCAL_SPEC)()
end
return {}
end,
}
end
local p = vim.fn.fnamemodify(path, ":h")
if p == path then
break
end
path = p
end
end
---@param cache? table<string,LazySpecLoader>
function M.specs(cache)
---@type LazySpecLoader[]
local specs = {}
local function _load(name, modpath)
local modname = Config.options.plugins .. (name and ("." .. name) or "")
Util.try(function()
local spec = cache and cache[modname]
spec = spec and not Module.is_dirty(modname, modpath) and Spec.revive(spec) or Spec.load(modname, modpath)
table.insert(specs, spec)
end, "Failed to load **" .. modname .. "**")
end
_load(nil, Config.paths.main)
Util.lsmod(Config.paths.plugins, _load)
return specs
end
function M.load()
---@type boolean, LazyState?
local ok, state = pcall(vim.json.decode, Cache.get("cache.state"))
if not (ok and state and vim.deep_equal(Config.options, state.config)) then
M.dirty = true
state = nil
M.loading = true
-- load specs
Util.track("spec")
Config.spec = Spec.new()
local specs = {
---@diagnostic disable-next-line: param-type-mismatch
vim.deepcopy(Config.options.spec),
}
specs[#specs + 1] = M.find_local_spec()
specs[#specs + 1] = { "folke/lazy.nvim" }
Config.spec:parse(specs)
-- override some lazy props
local lazy = Config.spec.plugins["lazy.nvim"]
if lazy then
lazy.lazy = true
lazy.dir = Config.me
lazy.config = function()
error("lazy config should not be called")
end
lazy._.loaded = {}
end
-- load specs
Util.track("specs")
local specs = M.specs(state and state.specs)
Util.track()
-- merge
Config.plugins = {}
for _, spec in ipairs(specs) do
for _, plugin in pairs(spec.plugins) do
local other = Config.plugins[plugin.name]
Config.plugins[plugin.name] = other and M.merge(other, plugin) or plugin
-- add hererocks when enabled and needed
for _, plugin in pairs(Config.spec.plugins) do
if plugin.build == "rockspec" then
if Config.hererocks() then
Config.spec.meta:add({
"luarocks/hererocks",
build = "rockspec",
lazy = true,
})
end
break
end
end
local existing = Config.plugins
Config.plugins = Config.spec.plugins
-- copy state. This wont do anything during startup
for name, plugin in pairs(existing) do
if Config.plugins[name] then
local new_state = Config.plugins[name]._
Config.plugins[name]._ = plugin._
Config.plugins[name]._.dep = new_state.dep
Config.plugins[name]._.frags = new_state.frags
Config.plugins[name]._.pkg = new_state.pkg
end
end
Util.track()
Util.track("state")
M.update_state()
Util.track()
if M.dirty then
Cache.dirty = true
elseif state then
require("lazy.core.handler")._groups = state.handlers
if Config.options.pkg.enabled and Pkg.dirty then
Pkg.update()
return M.load()
end
M.loading = false
vim.api.nvim_exec_autocmds("User", { pattern = "LazyPlugins", modeline = false })
end
function M.save()
---@class LazyState
local state = {
---@type table<string, LazySpecLoader>
specs = {},
handlers = require("lazy.core.handler").group(Config.plugins, true),
config = Config.options,
}
for _, spec in ipairs(M.specs()) do
spec.funs = {}
state.specs[spec.modname] = spec
for _, plugin in pairs(spec.plugins) do
if plugin.init or (plugin.opt == false and plugin.config) then
-- no use in caching specs that need init,
-- or specs that are in start and have a config,
-- since we'll load the real spec during startup anyway
state.specs[spec.modname] = nil
break
end
---@cast plugin CachedPlugin
for k, v in pairs(plugin) do
if type(v) == "function" then
if funs[k] then
spec.funs[k] = spec.funs[k] or {}
table.insert(spec.funs[k], plugin.name)
end
plugin[k] = nil
elseif skip[k] then
plugin[k] = nil
-- Finds the plugin that has this path
---@param path string
---@param opts? {fast?:boolean}
function M.find(path, opts)
if not Config.spec then
return
end
opts = opts or {}
local lua = path:find("/lua/", 1, true)
if lua then
local name = path:sub(1, lua - 1)
local slash = name:reverse():find("/", 1, true)
if slash then
name = name:sub(#name - slash + 2)
if name then
if opts.fast then
return Config.spec.meta.plugins[name]
end
return Config.spec.plugins[name]
end
end
end
Cache.set("cache.state", vim.json.encode(state))
end
---@param plugin LazyPlugin
function M.has_errors(plugin)
for _, task in ipairs(plugin._.tasks or {}) do
if task:has_errors() then
return true
end
end
return false
end
-- Merges super values or runs the values function to override values or return new ones.
-- Values are cached for performance.
-- Used for opts, cmd, event, ft and keys
---@param plugin LazyPlugin
---@param prop string
---@param is_list? boolean
function M.values(plugin, prop, is_list)
if not plugin[prop] then
return {}
end
plugin._.cache = plugin._.cache or {}
local key = prop .. (is_list and "_list" or "")
if plugin._.cache[key] == nil then
plugin._.cache[key] = M._values(plugin, plugin, prop, is_list)
end
return plugin._.cache[key]
end
-- Merges super values or runs the values function to override values or return new ones
-- Used for opts, cmd, event, ft and keys
---@param root LazyPlugin
---@param plugin LazyPlugin
---@param prop string
---@param is_list? boolean
function M._values(root, plugin, prop, is_list)
if not plugin[prop] then
return {}
end
local super = getmetatable(plugin)
---@type table
local ret = super and M._values(root, super.__index, prop, is_list) or {}
local values = rawget(plugin, prop)
if not values then
return ret
elseif type(values) == "function" then
ret = values(root, ret) or ret
return type(ret) == "table" and ret or { ret }
end
values = type(values) == "table" and values or { values }
if is_list then
return Util.extend(ret, values)
else
---@type {path:string[], list:any[]}[]
local lists = {}
---@diagnostic disable-next-line: no-unknown
for _, key in ipairs(plugin[prop .. "_extend"] or {}) do
local path = vim.split(key, ".", { plain = true })
local r = Util.key_get(ret, path)
local v = Util.key_get(values, path)
if type(r) == "table" and type(v) == "table" then
lists[key] = { path = path, list = {} }
vim.list_extend(lists[key].list, r)
vim.list_extend(lists[key].list, v)
end
end
local t = Util.merge(ret, values)
for _, list in pairs(lists) do
Util.key_set(t, list.path, list.list)
end
return t
end
end
return M

View file

@ -1,9 +1,11 @@
---@class LazyUtilCore
local M = {}
---@alias LazyProfile {data: string|{[string]:string}, time: number, [number]:LazyProfile}
---@type LazyProfile[]
M._profiles = { { name = "lazy" } }
M.is_win = jit.os:find("Windows")
---@param data (string|{[string]:string})?
---@param time number?
@ -11,7 +13,7 @@ function M.track(data, time)
if data then
local entry = {
data = data,
time = time or vim.loop.hrtime(),
time = time or vim.uv.hrtime(),
}
table.insert(M._profiles[#M._profiles], entry)
@ -22,43 +24,110 @@ function M.track(data, time)
else
---@type LazyProfile
local entry = table.remove(M._profiles)
entry.time = vim.loop.hrtime() - entry.time
entry.time = vim.uv.hrtime() - entry.time
return entry
end
end
function M.try(fn, msg)
function M.exiting()
return vim.v.exiting ~= vim.NIL
end
---@generic T
---@param list T[]
---@param fn fun(v: T):boolean?
---@return T[]
function M.filter(fn, list)
local ret = {}
for _, v in ipairs(list) do
if fn(v) then
table.insert(ret, v)
end
end
return ret
end
---@generic F: fun()
---@param data (string|{[string]:string})?
---@param fn F
---@return F
function M.trackfn(data, fn)
return function(...)
M.track(data)
local ok, ret = pcall(fn, ...)
M.track()
if not ok then
error(ret)
end
return ret
end
end
---@param name string
---@return string
function M.normname(name)
local ret = name:lower():gsub("^n?vim%-", ""):gsub("%.n?vim$", ""):gsub("[%.%-]lua", ""):gsub("[^a-z]+", "")
return ret
end
---@return string
function M.norm(path)
if path:sub(1, 1) == "~" then
local home = vim.uv.os_homedir()
if home:sub(-1) == "\\" or home:sub(-1) == "/" then
home = home:sub(1, -2)
end
path = home .. path:sub(2)
end
path = path:gsub("\\", "/"):gsub("/+", "/")
return path:sub(-1) == "/" and path:sub(1, -2) or path
end
---@param opts? {level?: number}
function M.pretty_trace(opts)
opts = opts or {}
local Config = require("lazy.core.config")
local trace = {}
local level = opts.level or 2
while true do
local info = debug.getinfo(level, "Sln")
if not info then
break
end
if info.what ~= "C" and (Config.options.debug or not info.source:find("lazy.nvim")) then
local source = info.source:sub(2)
if source:find(Config.options.root, 1, true) == 1 then
source = source:sub(#Config.options.root + 1)
end
source = vim.fn.fnamemodify(source, ":p:~:.") --[[@as string]]
local line = " - " .. source .. ":" .. info.currentline
if info.name then
line = line .. " _in_ **" .. info.name .. "**"
end
table.insert(trace, line)
end
level = level + 1
end
return #trace > 0 and ("\n\n# stacktrace:\n" .. table.concat(trace, "\n")) or ""
end
---@generic R
---@param fn fun():R?
---@param opts? string|{msg:string, on_error:fun(msg)}
---@return R
function M.try(fn, opts)
opts = type(opts) == "string" and { msg = opts } or opts or {}
local msg = opts.msg
-- error handler
local error_handler = function(err)
local Config = require("lazy.core.config")
local trace = {}
local level = 1
while true do
local info = debug.getinfo(level, "Sln")
if not info then
break
end
if info.what == "Lua" and not info.source:find("lazy.nvim") then
local source = info.source:sub(2)
if source:find(Config.options.packpath, 1, true) == 1 then
source = source:sub(#Config.options.packpath + 1):gsub("^/opt/", ""):gsub("^/start/", "")
end
source = vim.fn.fnamemodify(source, ":p:~:.")
local line = " - " .. source .. ":" .. info.currentline
if info.name then
line = line .. " _in_ **" .. info.name .. "**"
end
table.insert(trace, line)
end
level = level + 1
msg = (msg and (msg .. "\n\n") or "") .. err .. M.pretty_trace()
if opts.on_error then
opts.on_error(msg)
else
vim.schedule(function()
M.error(msg)
end)
end
msg = msg .. "\n\n" .. err
if #trace > 0 then
msg = msg .. "\n\n# stacktrace:\n" .. table.concat(trace, "\n")
end
vim.schedule(function()
M.error(msg)
end)
return err
end
@ -67,6 +136,20 @@ function M.try(fn, msg)
return ok and result or nil
end
function M.get_source()
local f = 2
while true do
local info = debug.getinfo(f, "S")
if not info then
break
end
if info.what ~= "C" and not info.source:find("lazy.nvim", 1, true) and info.source ~= "@vim/loader.lua" then
return info.source:sub(2)
end
f = f + 1
end
end
-- Fast implementation to check if a table is a list
---@param t table
function M.is_list(t)
@ -83,9 +166,15 @@ end
function M.very_lazy()
local function _load()
vim.defer_fn(function()
vim.cmd("do User VeryLazy")
end, 100)
vim.schedule(function()
if vim.v.exiting ~= vim.NIL then
return
end
vim.g.did_very_lazy = true
M.track({ event = "VeryLazy" })
vim.api.nvim_exec_autocmds("User", { pattern = "VeryLazy", modeline = false })
M.track()
end)
end
vim.api.nvim_create_autocmd("User", {
@ -95,7 +184,7 @@ function M.very_lazy()
if vim.v.vim_did_enter == 1 then
_load()
else
vim.api.nvim_create_autocmd("VimEnter", {
vim.api.nvim_create_autocmd("UIEnter", {
once = true,
callback = function()
_load()
@ -110,13 +199,19 @@ end
---@param path string
---@param fn fun(path: string, name:string, type:FileType):boolean?
function M.ls(path, fn)
local handle = vim.loop.fs_scandir(path)
local handle = vim.uv.fs_scandir(path)
while handle do
local name, t = vim.loop.fs_scandir_next(handle)
local name, t = vim.uv.fs_scandir_next(handle)
if not name then
break
end
if fn(path .. "/" .. name, name, t) == false then
local fname = path .. "/" .. name
-- HACK: type is not always returned due to a bug in luv,
-- so fecth it with fs_stat instead when needed.
-- see https://github.com/folke/lazy.nvim/issues/306
if fn(fname, name, t or vim.uv.fs_stat(fname).type) == false then
break
end
end
@ -135,35 +230,287 @@ end
---@param root string
---@param fn fun(modname:string, modpath:string)
function M.lsmod(root, fn)
---@param modname? string
function M.walkmods(root, fn, modname)
modname = modname and (modname:gsub("%.$", "") .. ".") or ""
M.ls(root, function(path, name, type)
if type == "file" and name:sub(-4) == ".lua" and name ~= "init.lua" then
fn(name:sub(1, -5), path)
elseif type == "directory" and vim.loop.fs_stat(path .. "/init.lua") then
fn(name, path .. "/init.lua")
if name == "init.lua" then
fn(modname:gsub("%.$", ""), path)
elseif (type == "file" or type == "link") and name:sub(-4) == ".lua" then
fn(modname .. name:sub(1, -5), path)
elseif type == "directory" then
M.walkmods(path, fn, modname .. name .. ".")
end
end)
end
function M.notify(msg, level)
vim.notify(msg, level, {
---@param modname string
---@return string
function M.topmod(modname)
return modname:match("^[^./]+") or modname
end
---@type table<string, string[]>
M.unloaded_cache = {}
---@param modname string
---@param opts? {cache?:boolean}
function M.get_unloaded_rtp(modname, opts)
opts = opts or {}
local topmod = M.topmod(modname)
if opts.cache and M.unloaded_cache[topmod] then
return M.unloaded_cache[topmod], true
end
local norm = M.normname(topmod)
---@type string[]
local rtp = {}
local Config = require("lazy.core.config")
if Config.spec then
for _, plugin in pairs(Config.spec.plugins) do
if not (plugin._.loaded or plugin.module == false or plugin.virtual) then
if norm == M.normname(plugin.name) then
table.insert(rtp, 1, plugin.dir)
else
table.insert(rtp, plugin.dir)
end
end
end
end
M.unloaded_cache[topmod] = rtp
return rtp, false
end
function M.find_root(modname)
local paths, cached = M.get_unloaded_rtp(modname, { cache = true })
local ret = require("lazy.core.cache").find(modname, {
rtp = true,
paths = paths,
patterns = { ".lua", "" },
})[1]
if not ret and cached then
paths = M.get_unloaded_rtp(modname)
ret = require("lazy.core.cache").find(modname, {
rtp = false,
paths = paths,
patterns = { ".lua", "" },
})[1]
end
if ret then
return ret.modpath:gsub("%.lua$", ""), ret.modpath
end
end
---@param modname string
---@param fn fun(modname:string, modpath:string)
function M.lsmod(modname, fn)
local root, match = M.find_root(modname)
if not root then
return
end
if match:sub(-4) == ".lua" then
fn(modname, match)
if not vim.uv.fs_stat(root) then
return
end
end
M.ls(root, function(path, name, type)
if name == "init.lua" then
fn(modname, path)
elseif (type == "file" or type == "link") and name:sub(-4) == ".lua" then
fn(modname .. "." .. name:sub(1, -5), path)
elseif type == "directory" and vim.uv.fs_stat(path .. "/init.lua") then
fn(modname .. "." .. name, path .. "/init.lua")
end
end)
end
---@generic T
---@param list T[]
---@param add T[]
---@return T[]
function M.extend(list, add)
local idx = {}
for _, v in ipairs(list) do
idx[v] = v
end
for _, a in ipairs(add) do
if not idx[a] then
table.insert(list, a)
end
end
return list
end
---@alias LazyNotifyOpts {lang?:string, title?:string, level?:number, once?:boolean, stacktrace?:boolean, stacklevel?:number}
---@param msg string|string[]
---@param opts? LazyNotifyOpts
function M.notify(msg, opts)
if vim.in_fast_event() then
return vim.schedule(function()
M.notify(msg, opts)
end)
end
opts = opts or {}
if type(msg) == "table" then
msg = table.concat(
vim.tbl_filter(function(line)
return line or false
end, msg),
"\n"
)
end
if opts.stacktrace then
msg = msg .. M.pretty_trace({ level = opts.stacklevel or 2 })
end
local lang = opts.lang or "markdown"
local n = opts.once and vim.notify_once or vim.notify
n(msg, opts.level or vim.log.levels.INFO, {
ft = lang,
on_open = function(win)
local ok = pcall(function()
vim.treesitter.language.add("markdown")
end)
if not ok then
pcall(require, "nvim-treesitter")
end
vim.wo[win].conceallevel = 3
vim.wo[win].concealcursor = ""
vim.wo[win].spell = false
local buf = vim.api.nvim_win_get_buf(win)
vim.bo[buf].filetype = "markdown"
if not pcall(vim.treesitter.start, buf, lang) then
vim.bo[buf].filetype = lang
vim.bo[buf].syntax = lang
end
end,
title = "lazy.nvim",
title = opts.title or "lazy.nvim",
})
end
function M.error(msg)
M.notify(msg, vim.log.levels.ERROR)
---@param msg string|string[]
---@param opts? LazyNotifyOpts
function M.error(msg, opts)
opts = opts or {}
opts.level = vim.log.levels.ERROR
M.notify(msg, opts)
end
function M.info(msg)
M.notify(msg, vim.log.levels.INFO)
---@param msg string|string[]
---@param opts? LazyNotifyOpts
function M.info(msg, opts)
opts = opts or {}
opts.level = vim.log.levels.INFO
M.notify(msg, opts)
end
---@param msg string|string[]
---@param opts? LazyNotifyOpts
function M.warn(msg, opts)
opts = opts or {}
opts.level = vim.log.levels.WARN
M.notify(msg, opts)
end
---@param msg string|table
---@param opts? LazyNotifyOpts
function M.debug(msg, opts)
if not require("lazy.core.config").options.debug then
return
end
opts = opts or {}
if opts.title then
opts.title = "lazy.nvim: " .. opts.title
end
if type(msg) == "string" then
M.notify(msg, opts)
else
opts.lang = "lua"
M.notify(vim.inspect(msg), opts)
end
end
local function can_merge(v)
return type(v) == "table" and (vim.tbl_isempty(v) or not M.is_list(v))
end
--- Merges the values similar to vim.tbl_deep_extend with the **force** behavior,
--- but the values can be any type, in which case they override the values on the left.
--- Values will me merged in-place in the first left-most table. If you want the result to be in
--- a new table, then simply pass an empty table as the first argument `vim.merge({}, ...)`
--- Supports clearing values by setting a key to `vim.NIL`
---@generic T
---@param ... T
---@return T
function M.merge(...)
local ret = select(1, ...)
if ret == vim.NIL then
ret = nil
end
for i = 2, select("#", ...) do
local value = select(i, ...)
if can_merge(ret) and can_merge(value) then
for k, v in pairs(value) do
ret[k] = M.merge(ret[k], v)
end
elseif value == vim.NIL then
ret = nil
elseif value ~= nil then
ret = value
end
end
return ret
end
function M.lazy_require(module)
local mod = nil
-- if already loaded, return the module
-- otherwise return a lazy module
return type(package.loaded[module]) == "table" and package.loaded[module]
or setmetatable({}, {
__index = function(_, key)
mod = mod or require(module)
return mod[key]
end,
})
end
---@param t table
---@param key string|string[]
---@return any
function M.key_get(t, key)
local path = type(key) == "table" and key or vim.split(key, ".", true)
local value = t
for _, k in ipairs(path) do
if type(value) ~= "table" then
return value
end
value = value[k]
end
return value
end
---@param t table
---@param key string|string[]
---@param value any
function M.key_set(t, key, value)
local path = type(key) == "table" and key or vim.split(key, ".", true)
local last = t
for i = 1, #path - 1 do
local k = path[i]
if type(last[k]) ~= "table" then
last[k] = {}
end
last = last[k]
end
last[path[#path]] = value
end
return M

167
lua/lazy/docs.lua Normal file
View file

@ -0,0 +1,167 @@
local Util = require("lazy.util")
local M = {}
function M.indent(str, indent)
local lines = vim.split(str, "\n")
for l, line in ipairs(lines) do
lines[l] = (" "):rep(indent) .. line
end
return table.concat(lines, "\n")
end
---@param str string
function M.fix_indent(str)
local lines = vim.split(str, "\n")
local first = table.remove(lines, 1)
local width = 120
for _, line in ipairs(lines) do
if not line:find("^%s*$") then
width = math.min(width, #line:match("^%s*"))
end
end
for l, line in ipairs(lines) do
lines[l] = line:sub(width + 1)
end
table.insert(lines, 1, first)
return table.concat(lines, "\n")
end
---@alias ReadmeBlock {content:string, lang?:string}
---@param contents table<string, ReadmeBlock|string>
---@param readme_file? string
function M.save(contents, readme_file)
local readme = Util.read_file(readme_file or "README.md")
for tag, block in pairs(contents) do
if type(block) == "string" then
block = { content = block, lang = "lua" }
end
---@cast block ReadmeBlock
local content = M.fix_indent(block.content)
content = content:gsub("%%", "%%%%")
content = vim.trim(content)
local pattern = "(<%!%-%- " .. tag .. ":start %-%->).*(<%!%-%- " .. tag .. ":end %-%->)"
if not readme:find(pattern) then
error("tag " .. tag .. " not found")
end
if block.lang then
readme = readme:gsub(pattern, "%1\n\n```" .. block.lang .. "\n" .. content .. "\n```\n\n%2")
else
readme = readme:gsub(pattern, "%1\n\n" .. content .. "\n\n%2")
end
end
Util.write_file(readme_file or "README.md", readme)
vim.cmd.checktime()
end
---@return string
function M.extract(file, pattern)
local init = Util.read_file(file)
return assert(init:match(pattern))
end
---@return ReadmeBlock
function M.commands()
local commands = require("lazy.view.commands").commands
local modes = require("lazy.view.config").commands
modes.load.opts = true
local lines = {
{ "Command", "Lua", "Description" },
{ "---", "---", "---" },
}
Util.foreach(modes, function(name, mode)
if commands[name] then
if mode.plugins_required then
lines[#lines + 1] = {
("`:Lazy %s {plugins}`"):format(name),
([[`require("lazy").%s(opts)`]]):format(name),
mode.desc,
}
elseif mode.plugins then
lines[#lines + 1] = {
("`:Lazy %s [plugins]`"):format(name),
([[`require("lazy").%s(opts?)`]]):format(name),
mode.desc,
}
else
lines[#lines + 1] = {
("`:Lazy %s`"):format(name),
([[`require("lazy").%s()`]]):format(name),
mode.desc,
}
end
end
end)
return { content = M.table(lines) }
end
---@param lines string[][]
function M.table(lines)
---@type string[]
local ret = {}
for _, line in ipairs(lines) do
ret[#ret + 1] = "| " .. table.concat(line, " | ") .. " |"
end
return table.concat(ret, "\n")
end
---@param opts? {name?:string, path?:string, modname?:string}
---@return ReadmeBlock
function M.colors(opts)
opts = vim.tbl_extend("force", {
name = "Lazy",
path = "lua/lazy/view/colors.lua",
modname = "lazy.view.colors",
}, opts or {})
local str = M.extract(opts.path, "\nM%.colors = ({.-\n})")
---@type table<string,string>
local comments = {}
for _, line in ipairs(vim.split(str, "\n")) do
local group, desc = line:match("^ (%w+) = .* -- (.*)")
if group then
comments[group] = desc
end
end
local lines = {
{ "Highlight Group", "Default Group", "Description" },
{ "---", "---", "---" },
}
Util.foreach(require(opts.modname).colors, function(group, link)
link = type(link) == "table" and "`" .. vim.inspect(link):gsub("%s+", " ") .. "`" or "***" .. link .. "***"
lines[#lines + 1] = { "**" .. opts.name .. group .. "**", link, comments[group] or "" }
end)
return { content = M.table(lines) }
end
function M.update()
local config = M.extract("lua/lazy/core/config.lua", "\nM%.defaults = ({.-\n})")
config = config:gsub("%s*debug = false.\n", "\n")
M.save({
bootstrap = M.extract("lua/lazy/init.lua", "function M%.bootstrap%(%)\n(.-)\nend"),
stats = M.extract("lua/lazy/stats.lua", "\nM%._stats = ({.-\n})"),
config = config,
spec = Util.read_file("lua/lazy/example.lua"),
commands = M.commands(),
colors = M.colors(),
})
end
---@param plugins? LazyPlugin[]
---@return ReadmeBlock
function M.plugins(plugins)
plugins = plugins or require("lazy.core.config").plugins
---@type string[]
local lines = {}
Util.foreach(plugins, function(name, plugin)
if plugin.url then
lines[#lines + 1] = "- [" .. name .. "](" .. plugin.url:gsub("%.git$", "") .. ")"
end
end)
return { content = table.concat(lines, "\n") }
end
return M

87
lua/lazy/example.lua Normal file
View file

@ -0,0 +1,87 @@
return {
-- the colorscheme should be available when starting Neovim
{
"folke/tokyonight.nvim",
lazy = false, -- make sure we load this during startup if it is your main colorscheme
priority = 1000, -- make sure to load this before all the other start plugins
config = function()
-- load the colorscheme here
vim.cmd([[colorscheme tokyonight]])
end,
},
-- I have a separate config.mappings file where I require which-key.
-- With lazy the plugin will be automatically loaded when it is required somewhere
{ "folke/which-key.nvim", lazy = true },
{
"nvim-neorg/neorg",
-- lazy-load on filetype
ft = "norg",
-- options for neorg. This will automatically call `require("neorg").setup(opts)`
opts = {
load = {
["core.defaults"] = {},
},
},
},
{
"dstein64/vim-startuptime",
-- lazy-load on a command
cmd = "StartupTime",
-- init is called during startup. Configuration for vim plugins typically should be set in an init function
init = function()
vim.g.startuptime_tries = 10
end,
},
{
"hrsh7th/nvim-cmp",
-- load cmp on InsertEnter
event = "InsertEnter",
-- these dependencies will only be loaded when cmp loads
-- dependencies are always lazy-loaded unless specified otherwise
dependencies = {
"hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-buffer",
},
config = function()
-- ...
end,
},
-- if some code requires a module from an unloaded plugin, it will be automatically loaded.
-- So for api plugins like devicons, we can always set lazy=true
{ "nvim-tree/nvim-web-devicons", lazy = true },
-- you can use the VeryLazy event for things that can
-- load later and are not important for the initial UI
{ "stevearc/dressing.nvim", event = "VeryLazy" },
{
"Wansmer/treesj",
keys = {
{ "J", "<cmd>TSJToggle<cr>", desc = "Join Toggle" },
},
opts = { use_default_keymaps = false, max_join_length = 150 },
},
{
"monaqa/dial.nvim",
-- lazy-load on keys
-- mode is `n` by default. For more advanced options, check the section on key mappings
keys = { "<C-a>", { "<C-x>", mode = "n" } },
},
-- local plugins need to be explicitly configured with dir
{ dir = "~/projects/secret.nvim" },
-- you can use a custom url to fetch a plugin
{ url = "git@github.com:folke/noice.nvim.git" },
-- local plugins can also be configured with the dev option.
-- This will use {config.dev.path}/noice.nvim/ instead of fetching it from GitHub
-- With the dev option, you can easily switch between the local and installed version of a plugin
{ "folke/noice.nvim", dev = true },
}

217
lua/lazy/health.lua Normal file
View file

@ -0,0 +1,217 @@
local Config = require("lazy.core.config")
local Process = require("lazy.manage.process")
local uv = vim.uv or vim.loop
local M = {}
-- "report_" prefix has been deprecated, use the recommended replacements if they exist.
local start = vim.health.start or vim.health.report_start
local ok = vim.health.ok or vim.health.report_ok
local warn = vim.health.warn or vim.health.report_warn
local error = vim.health.error or vim.health.report_error
local info = vim.health.info or vim.health.report_info
---@class LazyHealth
---@field error? fun(msg:string)
---@field warn? fun(msg:string)
---@field ok? fun(msg:string)
---@class LazyHealthHave : LazyHealth
---@field version? string
---@field version_pattern? string
---@field optional? boolean
---@param cmd string|string[]
---@param opts? LazyHealthHave
function M.have(cmd, opts)
opts = vim.tbl_extend("force", {
error = error,
warn = warn,
ok = ok,
version = "--version",
}, opts or {})
cmd = type(cmd) == "table" and cmd or { cmd }
---@cast cmd string[]
---@type string?
local found
for _, c in ipairs(cmd) do
if vim.fn.executable(c) == 1 then
local out, exit_code = Process.exec({ c, opts.version })
if exit_code ~= 0 then
opts.error(("failed to get version of {%s}\n%s"):format(c, table.concat(out, "\n")))
else
local version = vim.trim(out[1] or "")
version = version:gsub("^%s*" .. vim.pesc(c) .. "%s*", "")
if opts.version_pattern and not version:find(opts.version_pattern, 1, true) then
opts.warn(("`%s` version `%s` needed, but found `%s`"):format(c, opts.version_pattern, version))
else
found = ("{%s} `%s`"):format(c, version)
break
end
end
end
end
if found then
opts.ok(found)
return true
else
(opts.optional and opts.warn or opts.error)(
("{%s} %snot installed"):format(
table.concat(cmd, "} or {"),
opts.version_pattern and "version `" .. opts.version_pattern .. "` " or ""
)
)
end
end
function M.check()
start("lazy.nvim")
info("{lazy.nvim} version `" .. Config.version .. "`")
M.have("git")
local sites = vim.opt.packpath:get()
local default_site = vim.fn.stdpath("data") .. "/site"
if not vim.tbl_contains(sites, default_site) then
sites[#sites + 1] = default_site
end
local existing = false
for _, site in pairs(sites) do
for _, packs in ipairs(vim.fn.expand(site .. "/pack/*", false, true)) do
if not packs:find("[/\\]dist$") and uv.fs_stat(packs) then
existing = true
warn("found existing packages at `" .. packs .. "`")
end
end
end
if not existing then
ok("no existing packages found by other package managers")
end
for _, name in ipairs({ "packer", "plugged", "paq", "pckr", "mini.deps" }) do
for _, path in ipairs(vim.opt.rtp:get()) do
if path:find(name, 1, true) then
error("Found paths on the rtp from another plugin manager `" .. name .. "`")
break
end
end
end
local packer_compiled = vim.fn.stdpath("config") .. "/plugin/packer_compiled.lua"
if uv.fs_stat(packer_compiled) then
error("please remove the file `" .. packer_compiled .. "`")
else
ok("packer_compiled.lua not found")
end
local spec = Config.spec
if spec == nil then
error('No plugins loaded. Did you forget to run `require("lazy").setup()`?')
else
for _, plugin in pairs(spec.plugins) do
M.check_valid(plugin)
end
if #spec.notifs > 0 then
error("Issues were reported when loading your specs:")
for _, notif in ipairs(spec.notifs) do
local lines = vim.split(notif.msg, "\n")
for _, line in ipairs(lines) do
if notif.level == vim.log.levels.ERROR then
error(line)
else
warn(line)
end
end
end
end
end
start("luarocks")
if Config.options.rocks.enabled then
if Config.hererocks() then
info("checking `hererocks` installation")
else
info("checking `luarocks` installation")
end
local need_luarocks = {}
for _, plugin in pairs(spec.plugins) do
if plugin.build == "rockspec" then
table.insert(need_luarocks, plugin.name)
end
end
if #need_luarocks == 0 then
ok("no plugins require `luarocks`, so you can ignore any warnings below")
else
local lines = vim.tbl_map(function(name)
return " * `" .. name .. "`"
end, need_luarocks)
info("you have some plugins that require `luarocks`:\n" .. table.concat(lines, "\n"))
end
local ok = require("lazy.pkg.rockspec").check({
error = #need_luarocks > 0 and error or warn,
warn = warn,
ok = ok,
})
if not ok then
warn(table.concat({
"Lazy won't be able to install plugins that require `luarocks`.",
"Here's what you can do:",
" - fix your `luarocks` installation",
Config.hererocks() and " - disable *hererocks* with `opts.rocks.hererocks = false`"
or " - enable `hererocks` with `opts.rocks.hererocks = true`",
" - disable `luarocks` support completely with `opts.rocks.enabled = false`",
}, "\n"))
end
else
ok("luarocks disabled")
end
end
---@param plugin LazyPlugin
function M.check_valid(plugin)
for key in pairs(plugin) do
if not vim.tbl_contains(M.valid, key) then
if key ~= "module" or type(plugin.module) ~= "boolean" then
warn("{" .. plugin.name .. "}: unknown key <" .. key .. ">")
end
end
end
end
M.valid = {
1,
"_",
"branch",
"build",
"cmd",
"commit",
"cond",
"config",
"deactivate",
"dependencies",
"dev",
"dir",
"enabled",
"event",
"ft",
"import",
"init",
"keys",
"lazy",
"main",
"module",
"name",
"optional",
"opts",
"pin",
"priority",
"submodules",
"tag",
"url",
"version",
}
return M

71
lua/lazy/help.lua Normal file
View file

@ -0,0 +1,71 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local M = {}
function M.index(plugin)
if Config.options.readme.skip_if_doc_exists and vim.uv.fs_stat(plugin.dir .. "/doc") then
return {}
end
local files = {}
for _, file in ipairs(Config.options.readme.files) do
vim.list_extend(files, vim.fn.expand(plugin.dir .. "/" .. file, false, true))
end
---@type table<string,{file:string, tag:string, line:string}>
local tags = {}
for _, file in ipairs(files) do
file = Util.norm(file)
if vim.uv.fs_stat(file) then
local rel_file = file:sub(#plugin.dir + 1)
local tag_filename = plugin.name .. vim.fn.fnamemodify(rel_file, ":h"):gsub("%W+", "-"):gsub("^%-$", "")
local lines = vim.split(Util.read_file(file), "\n")
for _, line in ipairs(lines) do
local title = line:match("^#+%s*(.*)")
if title then
local tag = tag_filename .. "-" .. title:lower():gsub("%W+", "-")
tag = tag:gsub("%-+", "-"):gsub("%-$", "")
line = line:gsub("([%[%]/])", "\\%1")
tags[tag] = { tag = tag, line = line, file = tag_filename .. ".md" }
end
end
table.insert(lines, [[<!-- vim: set ft=markdown: -->]])
Util.write_file(Config.options.readme.root .. "/doc/" .. tag_filename .. ".md", table.concat(lines, "\n"))
end
end
return tags
end
function M.update()
if Config.plugins["lazy.nvim"] then
vim.cmd.helptags(Config.plugins["lazy.nvim"].dir .. "/doc")
end
if Config.options.readme.enabled == false then
return
end
local docs = Config.options.readme.root .. "/doc"
vim.fn.mkdir(docs, "p")
Util.ls(docs, function(path, name, type)
if type == "file" and name:sub(-2) == "md" then
vim.uv.fs_unlink(path)
end
end)
---@type {file:string, tag:string, line:string}[]
local tags = {}
for _, plugin in pairs(Config.plugins) do
for key, tag in pairs(M.index(plugin)) do
tags[key] = tag
end
end
local lines = { [[!_TAG_FILE_ENCODING utf-8 //]] }
Util.foreach(tags, function(_, tag)
table.insert(lines, ("%s\t%s\t/%s"):format(tag.tag, tag.file, tag.line))
end, { case_sensitive = true })
Util.write_file(docs .. "/tags", table.concat(lines, "\n"))
end
return M

View file

@ -1,90 +1,151 @@
---@class Lazy: LazyCommands
local M = {}
M._start = 0
---@param opts? LazyConfig
function M.setup(opts)
local cache_start = vim.loop.hrtime()
require("lazy.core.cache").setup()
vim.uv = vim.uv or vim.loop
local function profile_require()
local done = {} ---@type table<string, true>
local r = require
_G.require = function(modname)
local Util = package.loaded["lazy.core.util"]
if Util and not done[modname] then
done[modname] = true
Util.track({ require = modname })
local ok, ret = pcall(function()
return vim.F.pack_len(r(modname))
end)
Util.track()
if not ok then
error(ret, 2)
end
return vim.F.unpack_len(ret)
else
return r(modname)
end
end
end
---@overload fun(opts: LazyConfig)
---@overload fun(spec:LazySpec, opts: LazyConfig)
function M.setup(spec, opts)
if type(spec) == "table" and spec.spec then
---@cast spec LazyConfig
opts = spec
else
opts = opts or {}
opts.spec = spec
end
M._start = M._start == 0 and vim.uv.hrtime() or M._start
if vim.g.lazy_did_setup then
return vim.notify(
"Re-sourcing your config is not supported with lazy.nvim",
vim.log.levels.WARN,
{ title = "lazy.nvim" }
)
end
vim.g.lazy_did_setup = true
if not vim.go.loadplugins then
return
end
if vim.fn.has("nvim-0.8.0") ~= 1 then
return vim.notify("lazy.nvim requires Neovim >= 0.8.0", vim.log.levels.ERROR, { title = "lazy.nvim" })
end
if not (pcall(require, "ffi") and jit and jit.version) then
return vim.notify("lazy.nvim requires Neovim built with LuaJIT", vim.log.levels.ERROR, { title = "lazy.nvim" })
end
local start = vim.uv.hrtime()
-- use the Neovim cache if available
if vim.loader and vim.fn.has("nvim-0.9.1") == 1 then
package.loaded["lazy.core.cache"] = vim.loader
end
local Cache = require("lazy.core.cache")
local enable_cache = vim.tbl_get(opts, "performance", "cache", "enabled") ~= false
-- load module cache before anything else
if enable_cache then
Cache.enable()
end
if vim.tbl_get(opts, "profiling", "require") then
profile_require()
end
require("lazy.stats").track("LazyStart")
local module_start = vim.loop.hrtime()
require("lazy.core.module").setup()
local Util = require("lazy.core.util")
local Config = require("lazy.core.config")
local Loader = require("lazy.core.loader")
local Plugin = require("lazy.core.plugin")
Util.track("cache", module_start - cache_start)
Util.track("module", vim.loop.hrtime() - module_start)
table.insert(package.loaders, 3, Loader.loader)
Util.track("setup")
if vim.tbl_get(opts, "profiling", "loader") then
if vim.loader then
vim.loader._profile({ loaders = true })
else
Cache._profile_loaders()
end
end
Util.track({ plugin = "lazy.nvim" }) -- setup start
Util.track("module", vim.uv.hrtime() - start)
-- load config
Util.track("config")
Config.setup(opts)
Util.track()
Util.track("state")
Plugin.load()
Util.track()
Util.track("install")
for _, plugin in pairs(Config.plugins) do
if not plugin._.installed then
vim.cmd("do User LazyInstallPre")
require("lazy.manage").install({
wait = true,
show = Config.options.interactive,
})
break
end
end
Util.track()
Util.track("loader")
-- setup loader and handlers
Loader.setup()
Util.track()
Util.track() -- end setup
local lazy_delta = vim.loop.hrtime() - cache_start
Loader.init_plugins()
-- correct time delta and loaded
local delta = vim.uv.hrtime() - start
Util.track().time = delta -- end setup
if Config.plugins["lazy.nvim"] then
Config.plugins["lazy.nvim"]._.loaded.time = lazy_delta
Config.plugins["lazy.nvim"]._.loaded = { time = delta, source = "init.lua" }
end
vim.cmd("do User LazyDone")
-- load plugins with lazy=false or Plugin.init
Loader.startup()
-- all done!
vim.api.nvim_exec_autocmds("User", { pattern = "LazyDone", modeline = false })
require("lazy.stats").track("LazyDone")
end
function M.stats()
local ret = {
count = 0,
loaded = 0,
}
for _, plugin in pairs(require("lazy.core.config").plugins) do
ret.count = ret.count + 1
if plugin._.loaded then
ret.loaded = ret.loaded + 1
end
end
return ret
return require("lazy.stats").stats()
end
function M.bootstrap()
local lazypath = vim.fn.stdpath("data") .. "/site/pack/lazy/start/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"--single-branch",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
})
vim.opt.runtimepath:append(lazypath)
end
vim.opt.rtp:prepend(lazypath)
end
---@return LazyPlugin[]
function M.plugins()
return vim.tbl_values(require("lazy.core.config").plugins)
end
setmetatable(M, {
__index = function(_, key)
return function(...)
return require("lazy.view.commands").commands[key](...)
end
end,
})
return M

View file

@ -0,0 +1,97 @@
local Config = require("lazy.core.config")
local Git = require("lazy.manage.git")
local Manage = require("lazy.manage")
local Plugin = require("lazy.core.plugin")
local State = require("lazy.state")
local Util = require("lazy.util")
local M = {}
M.running = false
M.updated = {}
M.reported = {}
function M.start()
M.fast_check()
if M.schedule() > 0 and not M.has_errors() then
Manage.log({
clear = false,
show = false,
check = true,
concurrency = Config.options.checker.concurrency,
})
end
end
function M.schedule()
State.read() -- update state
local next_check = State.checker.last_check + Config.options.checker.frequency - os.time()
next_check = math.max(next_check, 0)
vim.defer_fn(M.check, next_check * 1000)
return next_check
end
---@param opts? {report:boolean} report defaults to true
function M.fast_check(opts)
opts = opts or {}
for _, plugin in pairs(Config.plugins) do
-- don't check local plugins here, since we mark them as needing updates
-- only if local is behind upstream (if the git log task gives no output)
if plugin._.installed and not (plugin.pin or plugin._.is_local) then
plugin._.updates = nil
local info = Git.info(plugin.dir)
local ok, target = pcall(Git.get_target, plugin)
if ok and info and target and not Git.eq(info, target) then
plugin._.updates = { from = info, to = target }
end
end
end
M.report(opts.report ~= false)
end
function M.has_errors()
for _, plugin in pairs(Config.plugins) do
if Plugin.has_errors(plugin) then
return true
end
end
return false
end
function M.check()
State.checker.last_check = os.time()
State.write() -- update state
if M.has_errors() then
M.schedule()
else
Manage.check({
clear = false,
show = false,
concurrency = Config.options.checker.concurrency,
}):wait(function()
M.report()
M.schedule()
end)
end
end
---@param notify? boolean
function M.report(notify)
local lines = {}
M.updated = {}
for _, plugin in pairs(Config.plugins) do
if plugin._.updates then
table.insert(M.updated, plugin.name)
if not vim.tbl_contains(M.reported, plugin.name) then
table.insert(lines, "- **" .. plugin.name .. "**")
table.insert(M.reported, plugin.name)
end
end
end
if #lines > 0 and notify and Config.options.checker.notify and not Config.headless() then
table.insert(lines, 1, "# Plugin Updates")
Util.info(lines)
end
end
return M

View file

@ -1,35 +1,49 @@
local Util = require("lazy.util")
local Config = require("lazy.core.config")
local Process = require("lazy.manage.process")
local Semver = require("lazy.manage.semver")
local Util = require("lazy.util")
local M = {}
---@alias GitInfo {branch?:string, commit?:string, tag?:string, version?:Semver}
---@param details? boolean
---@param repo string
---@param details? boolean Fetching details is slow! Don't loop over a plugin to fetch all details!
---@return GitInfo?
function M.info(repo, details)
local line = Util.head(repo .. "/.git/HEAD")
local line = M.head(repo)
if line then
---@type string, string
local ref, branch = line:match("ref: (refs/heads/(.*))")
local ref, branch = line:match("ref: refs/(heads/(.*))")
local ret = ref and {
branch = branch,
commit = Util.head(repo .. "/.git/" .. ref),
commit = M.ref(repo, ref),
} or { commit = line }
if details then
Util.ls(repo .. "/.git/refs/tags", function(_, name)
if M.ref(repo, "tags/" .. name) == ret.commit then
ret.tag = name
ret.version = Semver.version(name)
return false
for tag, tag_ref in pairs(M.get_tag_refs(repo)) do
if tag_ref == ret.commit then
ret.tag = tag
ret.version = ret.version or Semver.version(tag)
end
end)
end
end
return ret
end
end
---@param a GitInfo
---@param b GitInfo
function M.eq(a, b)
local ra = a.commit and a.commit:sub(1, 7)
local rb = b.commit and b.commit:sub(1, 7)
return ra == rb
end
function M.head(repo)
return Util.head(repo .. "/.git/HEAD")
end
---@class TaggedSemver: Semver
---@field tag string
@ -38,74 +52,198 @@ function M.get_versions(repo, spec)
local range = Semver.range(spec or "*")
---@type TaggedSemver[]
local versions = {}
Util.ls(repo .. "/.git/refs/tags", function(_, name)
local v = Semver.version(name)
for _, tag in ipairs(M.get_tags(repo)) do
local v = Semver.version(tag)
---@cast v TaggedSemver
if v and range:matches(v) then
v.tag = name
v.tag = tag
table.insert(versions, v)
end
end)
end
return versions
end
function M.get_tags(repo)
---@type string[]
local ret = {}
Util.ls(repo .. "/.git/refs/tags", function(_, name)
ret[#ret + 1] = name
end)
for name in pairs(M.packed_refs(repo)) do
local tag = name:match("^tags/(.*)")
if tag then
ret[#ret + 1] = tag
end
end
return ret
end
---@param plugin LazyPlugin
---@return {branch:string, commit?:string}?
---@return string?
function M.get_branch(plugin)
if plugin.branch then
return {
branch = plugin.branch,
commit = M.ref(plugin.dir, "heads/" .. plugin.branch),
}
return plugin.branch
else
-- we need to return the default branch
-- Try origin first
local main = M.ref(plugin.dir, "remotes/origin/HEAD")
if main then
local branch = main:match("ref: refs/remotes/origin/(.*)")
if branch then
return {
branch = branch,
commit = M.ref(plugin.dir, "heads/" .. branch),
}
return branch
end
end
-- fallback to local HEAD
main = assert(M.head(plugin.dir))
return main and main:match("ref: refs/heads/(.*)")
end
end
-- Return the last commit for the given branch
---@param repo string
---@param branch string
---@param origin? boolean
function M.get_commit(repo, branch, origin)
if origin then
-- origin ref might not exist if it is the same as local
return M.ref(repo, "remotes/origin", branch) or M.ref(repo, "heads", branch)
else
return M.ref(repo, "heads", branch)
end
end
---@param plugin LazyPlugin
---@return GitInfo?
function M.get_target(plugin)
local branch = M.get_branch(plugin) or M.info(plugin.dir)
if plugin._.is_local then
local info = M.info(plugin.dir)
local branch = assert(info and info.branch or M.get_branch(plugin))
return { branch = branch, commit = M.get_commit(plugin.dir, branch, true) }
end
local branch = assert(M.get_branch(plugin))
if plugin.commit then
return {
branch = branch and branch.branch,
branch = branch,
commit = plugin.commit,
}
end
if plugin.tag then
return {
branch = branch and branch.branch,
branch = branch,
tag = plugin.tag,
commit = M.ref(plugin.dir, "tags/" .. plugin.tag),
}
end
if plugin.version then
local last = Semver.last(M.get_versions(plugin.dir, plugin.version))
local version = (plugin.version == nil and plugin.branch == nil) and Config.options.defaults.version or plugin.version
if version then
local last = Semver.last(M.get_versions(plugin.dir, version))
if last then
return {
branch = branch and branch.branch,
branch = branch,
version = last,
tag = last.tag,
commit = M.ref(plugin.dir, "tags/" .. last.tag),
}
end
end
---@diagnostic disable-next-line: return-type-mismatch
return branch
return { branch = branch, commit = M.get_commit(plugin.dir, branch, true) }
end
function M.ref(repo, ref)
return Util.head(repo .. "/.git/refs/" .. ref)
function M.ref(repo, ...)
local ref = table.concat({ ... }, "/")
-- if this is a tag ref, then dereference it instead
if ref:find("tags/", 1, true) == 1 then
local tags = M.get_tag_refs(repo, ref)
for _, tag_ref in pairs(tags) do
return tag_ref
end
end
-- otherwise just get the ref
return Util.head(repo .. "/.git/refs/" .. ref) or M.packed_refs(repo)[ref]
end
function M.packed_refs(repo)
local ok, refs = pcall(Util.read_file, repo .. "/.git/packed-refs")
---@type table<string,string>
local ret = {}
if ok then
for _, line in ipairs(vim.split(refs, "\n")) do
local ref, name = line:match("^(.*) refs/(.*)$")
if ref then
ret[name] = ref
end
end
end
return ret
end
-- this is slow, so don't use on a loop over all plugins!
---@param tagref string?
function M.get_tag_refs(repo, tagref)
tagref = tagref or "--tags"
---@type table<string,string>
local tags = {}
local ok, lines = pcall(function()
return Process.exec({ "git", "show-ref", "-d", tagref }, { cwd = repo })
end)
if not ok then
return {}
end
for _, line in ipairs(lines) do
local ref, tag = line:match("^(%w+) refs/tags/([^%^]+)%^?{?}?$")
if ref then
tags[tag] = ref
end
end
return tags
end
---@param repo string
function M.get_origin(repo)
return M.get_config(repo)["remote.origin.url"]
end
---@param repo string
function M.get_config(repo)
local ok, config = pcall(Util.read_file, repo .. "/.git/config")
if not ok then
return {}
end
---@type table<string, string>
local ret = {}
---@type string
local current_section = nil
for line in config:gmatch("[^\n]+") do
-- Check if the line is a section header
local section = line:match("^%s*%[(.+)%]%s*$")
if section then
---@type string
current_section = section:gsub('%s+"', "."):gsub('"+%s*$', "")
else
-- Ignore comments and blank lines
if not line:match("^%s*[#;]") and line:match("%S") then
local key, value = line:match("^%s*(%S+)%s*=%s*(.+)%s*$")
ret[current_section .. "." .. key] = value
end
end
end
return ret
end
function M.count(repo, commit1, commit2)
local lines = Process.exec({ "git", "rev-list", "--count", commit1 .. ".." .. commit2 }, { cwd = repo })
return tonumber(lines[1] or "0") or 0
end
function M.age(repo, commit)
local lines = Process.exec({ "git", "show", "-s", "--format=%cr", "--date=short", commit }, { cwd = repo })
return lines[1] or ""
end
return M

View file

@ -1,33 +1,45 @@
local Config = require("lazy.core.config")
local Runner = require("lazy.manage.runner")
local Plugin = require("lazy.core.plugin")
local Runner = require("lazy.manage.runner")
local M = {}
---@class ManagerOpts
---@field wait? boolean
---@field clear? boolean
---@field interactive? boolean
---@field show? boolean
---@field mode? string
---@field plugins? LazyPlugin[]
---@field plugins? (LazyPlugin|string)[]
---@field concurrency? number
---@field lockfile? boolean
---@param ropts RunnerOpts
---@param opts? ManagerOpts
function M.run(ropts, opts)
opts = opts or {}
if opts.interactive == nil then
opts.interactive = Config.options.interactive
local mode = opts.mode
local event = mode and ("Lazy" .. mode:sub(1, 1):upper() .. mode:sub(2))
if event then
vim.api.nvim_exec_autocmds("User", { pattern = event .. "Pre", modeline = false })
end
if opts.plugins then
---@param plugin string|LazyPlugin
opts.plugins = vim.tbl_map(function(plugin)
return type(plugin) == "string" and Config.plugins[plugin] or plugin
end, vim.tbl_values(opts.plugins))
ropts.plugins = opts.plugins
end
ropts.concurrency = ropts.concurrency or opts.concurrency or Config.options.concurrency
if opts.clear then
M.clear()
M.clear(opts.plugins)
end
if opts.interactive then
if opts.show ~= false then
vim.schedule(function()
require("lazy.view").show(opts.mode)
end)
@ -37,11 +49,16 @@ function M.run(ropts, opts)
local runner = Runner.new(ropts)
runner:start()
vim.cmd([[do User LazyRender]])
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
-- wait for post-install to finish
runner:wait(function()
vim.cmd([[do User LazyRender]])
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
Plugin.update_state()
require("lazy.manage.checker").fast_check({ report = false })
if event then
vim.api.nvim_exec_autocmds("User", { pattern = event, modeline = false })
end
end)
if opts.wait then
@ -50,81 +67,171 @@ function M.run(ropts, opts)
return runner
end
---@generic O: ManagerOpts
---@param opts? O
---@param defaults? ManagerOpts
---@return O
function M.opts(opts, defaults)
return vim.tbl_deep_extend("force", { clear = true }, defaults or {}, opts or {})
end
---@param opts? ManagerOpts
function M.install(opts)
M.run({
opts = M.opts(opts, { mode = "install" })
return M.run({
pipeline = {
"fs.symlink",
"plugin.exists",
"git.clone",
"git.checkout",
{ "git.checkout", lockfile = opts.lockfile },
"plugin.docs",
"wait",
"plugin.run",
{
"wait",
---@param runner Runner
sync = function(runner)
require("lazy.pkg").update()
Plugin.load()
runner:update()
end,
},
"plugin.build",
},
plugins = function(plugin)
return plugin.uri and not plugin._.installed
return not (plugin._.installed and not plugin._.build)
end,
}, opts):wait(function()
require("lazy.manage.lock").update()
require("lazy.help").update()
end)
end
---@param opts? ManagerOpts
function M.update(opts)
opts = M.opts(opts, { mode = "update" })
return M.run({
pipeline = {
"plugin.exists",
"git.origin",
"git.branch",
"git.fetch",
"git.status",
{ "git.checkout", lockfile = opts.lockfile },
"plugin.docs",
{
"wait",
---@param runner Runner
sync = function(runner)
require("lazy.pkg").update()
Plugin.load()
runner:update()
end,
},
"plugin.build",
{ "git.log", updated = true },
},
plugins = function(plugin)
return plugin.url and plugin._.installed
end,
}, opts):wait(function()
require("lazy.manage.lock").update()
require("lazy.help").update()
end)
end
--
---@param opts? ManagerOpts
function M.restore(opts)
opts = M.opts(opts, { mode = "restore", lockfile = true })
return M.update(opts)
end
---@param opts? ManagerOpts
function M.check(opts)
opts = M.opts(opts, { mode = "check" })
opts = opts or {}
return M.run({
pipeline = {
"plugin.exists",
{ "git.origin", check = true },
"git.fetch",
"git.status",
"wait",
{ "git.log", check = true },
},
plugins = function(plugin)
return plugin.url and plugin._.installed
end,
}, opts)
end
---@param opts? ManagerOpts|{lockfile?:boolean}
function M.update(opts)
opts = opts or {}
M.run({
---@param opts? ManagerOpts | {check?:boolean}
function M.log(opts)
opts = M.opts(opts, { mode = "log" })
return M.run({
pipeline = {
"fs.symlink",
"git.branch",
"git.fetch",
{ "git.checkout", lockfile = opts.lockfile },
"plugin.docs",
"wait",
"plugin.run",
{ "git.log", updated = true },
{ "git.origin", check = true },
{ "git.log", check = opts.check },
},
plugins = function(plugin)
return plugin.uri and plugin._.installed
return plugin.url and plugin._.installed
end,
}, opts)
end
---@param opts? ManagerOpts
function M.build(opts)
opts = M.opts(opts, { mode = "build" })
return M.run({
pipeline = { { "plugin.build", force = true } },
plugins = function()
return false
end,
}, opts)
end
---@param opts? ManagerOpts
function M.sync(opts)
opts = M.opts(opts)
if opts.clear then
M.clear()
opts.clear = false
end
if opts.show ~= false then
vim.schedule(function()
require("lazy.view").show("sync")
end)
opts.show = false
end
vim.api.nvim_exec_autocmds("User", { pattern = "LazySyncPre", modeline = false })
local clean_opts = vim.deepcopy(opts)
clean_opts.plugins = nil
local clean = M.clean(clean_opts)
local install = M.install(opts)
local update = M.update(opts)
clean:wait(function()
install:wait(function()
update:wait(function()
vim.api.nvim_exec_autocmds("User", { pattern = "LazySync", modeline = false })
end)
end)
end)
end
---@param opts? ManagerOpts
function M.clean(opts)
opts = M.opts(opts, { mode = "clean" })
return M.run({
pipeline = { "fs.clean" },
plugins = Config.to_clean,
}, opts):wait(function()
require("lazy.manage.lock").update()
end)
end
function M.check(opts)
opts = opts or {}
M.run({
pipeline = {
"git.fetch",
"wait",
{ "git.log", check = true },
},
plugins = function(plugin)
return plugin.uri and plugin._.installed
end,
}, opts)
end
---@param opts? ManagerOpts
function M.log(opts)
M.run({
pipeline = { "git.log" },
plugins = function(plugin)
return plugin.uri and plugin._.installed
end,
}, opts)
end
---@param opts? ManagerOpts
function M.clean(opts)
Plugin.update_state({ clean = true })
M.run({
pipeline = { "fs.clean" },
plugins = Config.to_clean,
}, opts)
end
function M.clear()
Plugin.update_state({ clean = true })
for _, plugin in pairs(Config.plugins) do
---@param plugins? LazyPlugin[]
function M.clear(plugins)
for _, plugin in pairs(plugins or Config.plugins) do
plugin._.updates = nil
plugin._.updated = nil
plugin._.cloned = nil
plugin._.dirty = nil
@ -132,11 +239,11 @@ function M.clear()
if plugin._.tasks then
---@param task LazyTask
plugin._.tasks = vim.tbl_filter(function(task)
return task:is_running()
return task:running() or task:has_errors()
end, plugin._.tasks)
end
end
vim.cmd([[do User LazyRender]])
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
end
return M

View file

@ -3,50 +3,53 @@ local Git = require("lazy.manage.git")
local M = {}
---@type table<string, {commit:string, branch:string}>
---@alias LazyLockfile table<string, {commit:string, branch:string}>
---@type LazyLockfile
M.lock = {}
M._loaded = false
function M.update()
local f = assert(io.open(Config.options.lockfile, "w"))
M.load()
vim.fn.mkdir(vim.fn.fnamemodify(Config.options.lockfile, ":p:h"), "p")
local f = assert(io.open(Config.options.lockfile, "wb"))
f:write("{\n")
M.lock = {}
---@param plugin LazyPlugin
local plugins = vim.tbl_filter(function(plugin)
return not plugin._.is_local and plugin._.installed
end, Config.plugins)
-- keep disabled and cond plugins
for name in pairs(M.lock) do
if not (Config.spec.disabled[name] or Config.spec.ignore_installed[name]) then
M.lock[name] = nil
end
end
for _, plugin in pairs(Config.plugins) do
if not plugin._.is_local and plugin._.installed then
local info = assert(Git.info(plugin.dir))
M.lock[plugin.name] = {
branch = info.branch or assert(Git.get_branch(plugin)),
commit = assert(info.commit, "commit is nil"),
}
end
end
---@param plugin LazyPlugin
---@type string[]
local names = vim.tbl_map(function(plugin)
return plugin.name
end, plugins)
local names = vim.tbl_keys(M.lock)
table.sort(names)
for n, name in ipairs(names) do
local plugin = Config.plugins[name]
if not plugin._.is_local and plugin._.installed then
local info = assert(Git.info(plugin.dir))
if not info.branch then
local branch = assert(Git.get_branch(plugin))
info.branch = branch.branch
end
info.commit = info.commit
-- f:write(([[ [%q] = { branch = %q, commit = %q },]]):format(name, info.branch, info.commit) .. "\n")
f:write(([[ %q: { "branch": %q, "commit": %q }]]):format(name, info.branch, info.commit))
if n ~= #names then
f:write(",\n")
end
---@diagnostic disable-next-line: assign-type-mismatch
M.lock[plugin.name] = info
local info = M.lock[name]
f:write(([[ %q: { "branch": %q, "commit": %q }]]):format(name, info.branch, info.commit))
if n ~= #names then
f:write(",\n")
end
end
f:write("\n}")
f:write("\n}\n")
f:close()
end
function M.load()
if M._loaded then
return
end
M.lock = {}
M._loaded = true
local f = io.open(Config.options.lockfile, "r")
@ -64,9 +67,7 @@ end
---@param plugin LazyPlugin
---@return {commit:string, branch:string}
function M.get(plugin)
if not M._loaded then
M.load()
end
M.load()
return M.lock[plugin.name]
end

View file

@ -1,80 +1,239 @@
local Async = require("lazy.async")
local Config = require("lazy.core.config")
---@diagnostic disable-next-line: no-unknown
local uv = vim.uv
---@class ProcessOpts
---@field args string[]
---@field cwd? string
---@field on_line? fun(line:string)
---@field on_exit? fun(ok:boolean, output:string)
---@field on_data? fun(data:string, is_stderr?:boolean)
---@field timeout? number
---@field env? table<string,string>
local M = {}
---@alias ProcessOpts {args: string[], cwd?: string, on_line?:fun(string), on_exit?: fun(ok:boolean, output:string)}
---@type table<uv_process_t, LazyProcess>
M.running = setmetatable({}, { __mode = "k" })
function M.spawn(cmd, opts)
---@class LazyProcess: Async
---@field handle? uv_process_t
---@field pid? number
---@field cmd string
---@field opts ProcessOpts
---@field timeout? uv_timer_t
---@field timedout? boolean
---@field data string
---@field check? uv_check_t
---@field code? number
---@field signal? number
local Process = setmetatable({}, { __index = Async.Async })
---@param cmd string|string[]
---@param opts? ProcessOpts
function Process.new(cmd, opts)
local self = setmetatable({}, { __index = Process })
---@async
Process.init(self, function()
self:_run()
end)
opts = opts or {}
local env = {
"GIT_TERMINAL_PROMPT=0",
"GIT_SSH_COMMAND=ssh -oBatchMode=yes",
}
for key, value in
pairs(vim.loop.os_environ() --[[@as string[] ]])
do
table.insert(env, key .. "=" .. value)
opts.args = opts.args or {}
if type(cmd) == "table" then
self.cmd = cmd[1]
vim.list_extend(opts.args, vim.list_slice(cmd, 2))
else
self.cmd = cmd
end
opts.timeout = opts.timeout or (Config.options.git and Config.options.git.timeout * 1000)
-- make sure the cwd is valid
if not opts.cwd and type(uv.cwd()) ~= "string" then
opts.cwd = uv.os_homedir()
end
opts.on_line = opts.on_line and vim.schedule_wrap(opts.on_line) or nil
opts.on_data = opts.on_data and vim.schedule_wrap(opts.on_data) or nil
self.data = ""
self.opts = opts
self.code = 1
self.signal = 0
return self
end
local stdout = vim.loop.new_pipe()
local stderr = vim.loop.new_pipe()
local output = ""
---@type vim.loop.Process
local handle = nil
handle = vim.loop.spawn(cmd, {
---@async
function Process:_run()
self:guard()
local stdout = assert(uv.new_pipe())
local stderr = assert(uv.new_pipe())
self.handle = uv.spawn(self.cmd, {
stdio = { nil, stdout, stderr },
args = opts.args,
cwd = opts.cwd,
env = env,
}, function(exit_code)
handle:close()
args = self.opts.args,
cwd = self.opts.cwd,
env = self:env(),
}, function(code, signal)
self.code = code
self.signal = signal
if self.timeout then
self.timeout:stop()
end
self.handle:close()
stdout:close()
stderr:close()
local check = vim.loop.new_check()
check:start(function()
if not stdout:is_closing() or not stderr:is_closing() then
return
end
check:stop()
if opts.on_exit then
output = output:gsub("[^\r\n]+\r", "")
vim.schedule(function()
opts.on_exit(exit_code == 0, output)
end)
end
end)
self:resume()
end)
if not handle then
if opts.on_exit then
opts.on_exit(false, "Failed to spawn process " .. cmd .. " " .. vim.inspect(opts))
if self.handle then
M.running[self.handle] = self
stdout:read_start(function(err, data)
self:on_data(err, data)
end)
stderr:read_start(function(err, data)
self:on_data(err, data, true)
end)
self:suspend()
while not (self.handle:is_closing() and stdout:is_closing() and stderr:is_closing()) do
Async.yield()
end
else
self.data = "Failed to spawn process " .. self.cmd .. " " .. vim.inspect(self.opts)
end
self:on_exit()
end
function Process:on_exit()
self.data = self.data:gsub("[^\r\n]+\r", "")
if self.timedout then
self.data = self.data .. "\n" .. "Process was killed because it reached the timeout"
elseif self.signal ~= 0 then
self.data = self.data .. "\n" .. "Process was killed with SIG" .. M.signals[self.signal]:upper()
end
if self.opts.on_exit then
self.opts.on_exit(self.code == 0 and self.signal == 0, self.data)
end
end
function Process:guard()
if self.opts.timeout then
self.timeout = assert(uv.new_timer())
self.timeout:start(self.opts.timeout, 0, function()
self.timedout = true
self:kill()
end)
end
end
function Process:env()
---@type table<string, string>
local env = vim.tbl_extend("force", {
GIT_SSH_COMMAND = "ssh -oBatchMode=yes",
}, uv.os_environ(), self.opts.env or {})
env.GIT_DIR = nil
env.GIT_WORK_TREE = nil
env.GIT_TERMINAL_PROMPT = "0"
env.GIT_INDEX_FILE = nil
---@type string[]
local env_flat = {}
for k, v in pairs(env) do
env_flat[#env_flat + 1] = k .. "=" .. v
end
return env_flat
end
---@param signals uv.aliases.signals|uv.aliases.signals[]|nil
function Process:kill(signals)
if not self.handle or self.handle:is_closing() then
return
end
signals = signals or { "sigterm", "sigkill" }
signals = type(signals) == "table" and signals or { signals }
---@cast signals uv.aliases.signals[]
local timer = assert(uv.new_timer())
timer:start(0, 1000, function()
if self.handle and not self.handle:is_closing() and #signals > 0 then
self.handle:kill(table.remove(signals, 1))
else
timer:stop()
end
end)
end
---@param err? string
---@param data? string
---@param is_stderr? boolean
function Process:on_data(err, data, is_stderr)
assert(not err, err)
if not data then
return
end
---@param data? string
local function on_output(err, data)
assert(not err, err)
if data then
output = output .. data:gsub("\r\n", "\n")
local lines = vim.split(vim.trim(output:gsub("\r$", "")):gsub("[^\n\r]+\r", ""), "\n")
if opts.on_line then
vim.schedule(function()
opts.on_line(lines[#lines])
end)
end
end
if self.opts.on_data then
self.opts.on_data(data, is_stderr)
end
self.data = self.data .. data:gsub("\r\n", "\n")
local lines = vim.split(vim.trim(self.data:gsub("\r$", "")):gsub("[^\n\r]+\r", ""), "\n")
vim.loop.read_start(stdout, on_output)
vim.loop.read_start(stderr, on_output)
if self.opts.on_line then
self.opts.on_line(lines[#lines])
end
end
return handle
M.signals = {
"hup",
"int",
"quit",
"ill",
"trap",
"abrt",
"bus",
"fpe",
"kill",
"usr1",
"segv",
"usr2",
"pipe",
"alrm",
"term",
"chld",
"cont",
"stop",
"tstp",
"ttin",
"ttou",
"urg",
"xcpu",
"xfsz",
"vtalrm",
"prof",
"winch",
"io",
"pwr",
"emt",
"sys",
"info",
}
---@param cmd string|string[]
---@param opts? ProcessOpts
function M.spawn(cmd, opts)
return Process.new(cmd, opts)
end
function M.abort()
for _, proc in pairs(M.running) do
proc:kill()
end
end
---@async
---@param cmd string|string[]
---@param opts? ProcessOpts
function M.exec(cmd, opts)
opts = opts or {}
local proc = M.spawn(cmd, opts)
proc:wait()
return vim.split(proc.data, "\n"), proc.code
end
return M

View file

@ -0,0 +1,107 @@
local Config = require("lazy.core.config")
local Loader = require("lazy.core.loader")
local Plugin = require("lazy.core.plugin")
local Util = require("lazy.util")
local M = {}
---@type table<string, uv.aliases.fs_stat_table>
M.files = {}
---@type uv_timer_t
M.timer = nil
function M.enable()
if M.timer then
M.timer:stop()
end
if #Config.spec.modules > 0 then
M.timer = assert(vim.uv.new_timer())
M.check(true)
M.timer:start(2000, 2000, M.check)
end
end
function M.disable()
if M.timer then
M.timer:stop()
M.timer = nil
end
end
---@param h1 uv.aliases.fs_stat_table
---@param h2 uv.aliases.fs_stat_table
function M.eq(h1, h2)
return h1 and h2 and h1.size == h2.size and h1.mtime.sec == h2.mtime.sec and h1.mtime.nsec == h2.mtime.nsec
end
function M.check(start)
---@type table<string,true>
local checked = {}
---@type {file:string, what:string}[]
local changes = {}
-- spec is a module
local function check(_, modpath)
checked[modpath] = true
local hash = vim.uv.fs_stat(modpath)
if hash then
if M.files[modpath] then
if not M.eq(M.files[modpath], hash) then
M.files[modpath] = hash
table.insert(changes, { file = modpath, what = "changed" })
end
else
M.files[modpath] = hash
table.insert(changes, { file = modpath, what = "added" })
end
end
end
for _, modname in ipairs(Config.spec.modules) do
Util.lsmod(modname, check)
end
for file in pairs(M.files) do
if not checked[file] then
table.insert(changes, { file = file, what = "deleted" })
M.files[file] = nil
end
end
if Loader.init_done and Config.mapleader ~= vim.g.mapleader then
vim.schedule(function()
require("lazy.core.util").warn("You need to set `vim.g.mapleader` **BEFORE** loading lazy")
end)
Config.mapleader = vim.g.mapleader
end
if Loader.init_done and Config.maplocalleader ~= vim.g.maplocalleader then
vim.schedule(function()
require("lazy.core.util").warn("You need to set `vim.g.maplocalleader` **BEFORE** loading lazy")
end)
Config.maplocalleader = vim.g.maplocalleader
end
if not (start or #changes == 0) then
M.reload(changes)
end
end
---@param {file:string, what:string}[]
function M.reload(changes)
vim.schedule(function()
if Config.options.change_detection.notify and not Config.headless() then
local lines = { "# Config Change Detected. Reloading...", "" }
for _, change in ipairs(changes) do
table.insert(lines, "- **" .. change.what .. "**: `" .. vim.fn.fnamemodify(change.file, ":p:~:.") .. "`")
end
Util.warn(lines)
end
Plugin.load()
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
vim.api.nvim_exec_autocmds("User", { pattern = "LazyReload", modeline = false })
end)
end
return M

View file

@ -1,20 +1,23 @@
local Task = require("lazy.manage.task")
local Async = require("lazy.async")
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local Task = require("lazy.manage.task")
---@class RunnerOpts
---@field pipeline (string|{[1]:string, [string]:any})[]
---@field plugins? LazyPlugin[]|fun(plugin:LazyPlugin):any?
---@field concurrency? number
---@alias PipelineStep {task:string, opts?:TaskOptions}
---@alias LazyRunnerTask {co:thread, status: {task?:LazyTask, waiting?:boolean}}
---@class RunnerTask
---@field task? LazyTask
---@field step number
---@alias PipelineStep {task:string, opts?:TaskOptions }
---@class Runner
---@field _plugins LazyPlugin[]
---@field _running LazyRunnerTask[]
---@field _plugins table<string,LazyPlugin>
---@field _pipeline PipelineStep[]
---@field _on_done fun()[]
---@field _opts RunnerOpts
---@field _running? Async
local Runner = {}
---@param opts RunnerOpts
@ -23,13 +26,17 @@ function Runner.new(opts)
self._opts = opts or {}
local plugins = self._opts.plugins
---@type LazyPlugin[]
local pp = {}
if type(plugins) == "function" then
self._plugins = vim.tbl_filter(plugins, Config.plugins)
pp = vim.tbl_filter(plugins, Config.plugins)
else
self._plugins = plugins or Config.plugins
pp = plugins or Config.plugins
end
self._plugins = {}
for _, plugin in ipairs(pp) do
self._plugins[plugin.name] = plugin
end
self._running = {}
self._on_done = {}
---@param step string|(TaskOptions|{[1]:string})
self._pipeline = vim.tbl_map(function(step)
@ -39,112 +46,154 @@ function Runner.new(opts)
return self
end
---@param entry LazyRunnerTask
function Runner:_resume(entry)
if entry.status.task and not entry.status.task:is_done() then
return true
end
local ok, status = coroutine.resume(entry.co)
if not ok then
Util.error("Could not resume a task\n" .. status)
end
entry.status = ok and status
return entry.status ~= nil
function Runner:plugin(name)
return self._plugins[name]
end
function Runner:resume(waiting)
local running = false
for _, entry in ipairs(self._running) do
if entry.status then
if waiting and entry.status.waiting then
entry.status.waiting = false
end
if not entry.status.waiting and self:_resume(entry) then
running = true
end
end
--- Update plugins
function Runner:update()
for name in pairs(self._plugins) do
self._plugins[name] = Config.plugins[name] or self._plugins[name]
end
return running or (not waiting and self:resume(true))
end
function Runner:start()
for _, plugin in pairs(self._plugins) do
local co = coroutine.create(self.run_pipeline)
local ok, status = coroutine.resume(co, self, plugin)
if ok then
table.insert(self._running, { co = co, status = status })
else
Util.error("Could not start tasks for " .. plugin.name .. "\n" .. status)
end
end
local check = vim.loop.new_check()
check:start(function()
if self:resume() then
return
end
check:stop()
self._running = {}
for _, cb in ipairs(self._on_done) do
vim.schedule(cb)
end
self._on_done = {}
---@async
self._running = Async.new(function()
self:_start()
end)
end
---@async
---@param plugin LazyPlugin
function Runner:run_pipeline(plugin)
for _, step in ipairs(self._pipeline) do
if step.task == "wait" then
coroutine.yield({ waiting = true })
else
local task = self:queue(plugin, step.task, step.opts)
if task then
coroutine.yield({ task = task })
assert(task:is_done())
if task.error then
return
function Runner:_start()
---@type string[]
local names = vim.tbl_keys(self._plugins)
table.sort(names)
---@type table<string,RunnerTask>
local state = {}
local active = 1
local waiting = 0
---@type number?
local wait_step = nil
---@async
---@param resume? boolean
local function continue(resume)
active = 0
waiting = 0
wait_step = nil
local next = {} ---@type string[]
-- check running tasks
for _, name in ipairs(names) do
state[name] = state[name] or { step = 0 }
local s = state[name]
local is_running = s.task and s.task:running()
local step = self._pipeline[s.step]
if is_running then
-- still running
active = active + 1
-- selene:allow(empty_if)
elseif s.task and s.task:has_errors() then
-- don't continue tasks if there are errors
elseif step and step.task == "wait" and not resume then
-- waiting for sync
waiting = waiting + 1
wait_step = s.step
else
next[#next + 1] = name
end
end
-- schedule next tasks
for _, name in ipairs(next) do
if self._opts.concurrency and active >= self._opts.concurrency then
break
end
local s = state[name]
local plugin = self:plugin(name)
while s.step <= #self._pipeline do
if s.step == #self._pipeline then
-- done
s.task = nil
plugin._.working = false
break
elseif s.step < #self._pipeline then
-- next
s.step = s.step + 1
local step = self._pipeline[s.step]
if step.task == "wait" then
plugin._.working = false
waiting = waiting + 1
wait_step = s.step
break
else
s.task = self:queue(plugin, step)
plugin._.working = true
if s.task then
active = active + 1
s.task:wake(false)
break
end
end
end
end
end
end
while active > 0 do
continue()
if active == 0 and waiting > 0 then
local sync = self._pipeline[wait_step]
if sync and sync.opts and type(sync.opts.sync) == "function" then
sync.opts.sync(self)
end
continue(true)
end
if active > 0 then
self._running:suspend()
end
end
end
---@param plugin LazyPlugin
---@param task_name string
---@param opts? TaskOptions
---@param step PipelineStep
---@return LazyTask?
function Runner:queue(plugin, task_name, opts)
assert(self._running)
local def = vim.split(task_name, ".", { plain = true })
function Runner:queue(plugin, step)
assert(self._running and self._running:running(), "Runner is not running")
local def = vim.split(step.task, ".", { plain = true })
---@type LazyTaskDef
local task_def = require("lazy.manage.task." .. def[1])[def[2]]
assert(task_def)
opts = opts or {}
assert(task_def, "Task not found: " .. step.task)
local opts = step.opts or {}
if not (task_def.skip and task_def.skip(plugin, opts)) then
local task = Task.new(plugin, def[2], task_def.run, opts)
task:start()
return task
return Task.new(plugin, def[2], task_def.run, opts)
end
end
function Runner:is_running()
return self._running and self._running:running()
end
-- Execute the callback async when done.
-- When no callback is specified, this will wait sync
---@param cb? fun()
function Runner:wait(cb)
if #self._running == 0 then
return cb and cb()
end
if cb then
table.insert(self._on_done, cb)
else
-- sync wait
while #self._running > 0 do
vim.wait(10)
if not self:is_running() then
if cb then
cb()
end
return self
end
if cb then
self._running:on("done", cb)
else
self._running:wait()
end
return self
end
return Runner

View file

@ -9,6 +9,7 @@ local M = {}
---@field patch number
---@field prerelease? string
---@field build? string
---@field input? string
local Semver = {}
Semver.__index = Semver
@ -90,6 +91,7 @@ function M.version(version)
patch = patch == "" and 0 or tonumber(patch),
prerelease = prerelease ~= "" and prerelease or nil,
build = build ~= "" and build or nil,
input = version,
}, Semver)
end
end

View file

@ -1,50 +1,45 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
---@type table<string, LazyTaskDef>
local M = {}
M.clean = {
run = function(self)
local dir = self.plugin.dir:gsub("/+$", "")
local stat = vim.loop.fs_lstat(dir)
if stat.type == "directory" then
Util.walk(dir, function(path, _, type)
if type == "directory" then
vim.loop.fs_rmdir(path)
else
vim.loop.fs_unlink(path)
end
end)
vim.loop.fs_rmdir(dir)
local function rm(dir)
local stat = vim.uv.fs_lstat(dir)
assert(stat and stat.type == "directory", dir .. " should be a directory!")
Util.walk(dir, function(path, _, type)
if type == "directory" then
vim.uv.fs_rmdir(path)
else
vim.loop.fs_unlink(dir)
vim.uv.fs_unlink(path)
end
end)
vim.uv.fs_rmdir(dir)
end
M.clean = {
skip = function(plugin)
return plugin._.is_local
end,
---@param opts? {rocks_only?:boolean}
run = function(self, opts)
opts = opts or {}
local dir = self.plugin.dir:gsub("/+$", "")
assert(dir:find(Config.options.root, 1, true) == 1, self.plugin.dir .. " should be under packpath!")
local rock_root = Config.options.rocks.root .. "/" .. self.plugin.name
if vim.uv.fs_stat(rock_root) then
rm(rock_root)
end
if opts.rocks_only then
return
end
rm(dir)
self.plugin._.installed = false
end,
}
M.symlink = {
skip = function(plugin)
if not plugin._.is_local then
return true
end
return not plugin._.is_symlink and plugin._.installed
end,
run = function(self)
local stat = vim.loop.fs_lstat(self.plugin.dir)
if stat then
assert(stat.type == "link")
if vim.loop.fs_realpath(self.plugin.uri) == vim.loop.fs_realpath(self.plugin.dir) then
return
else
vim.loop.fs_unlink(self.plugin.dir)
end
end
vim.loop.fs_symlink(self.plugin.uri, self.plugin.dir, { dir = true })
vim.opt.runtimepath:append(self.plugin.uri)
end,
}
return M

View file

@ -1,7 +1,53 @@
local Util = require("lazy.util")
local Async = require("lazy.async")
local Config = require("lazy.core.config")
local Git = require("lazy.manage.git")
local Lock = require("lazy.manage.lock")
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local throttle = {}
throttle.running = 0
throttle.waiting = {} ---@type Async[]
throttle.timer = vim.uv.new_timer()
function throttle.next()
throttle.running = 0
while #throttle.waiting > 0 and throttle.running < Config.options.git.throttle.rate do
---@type Async
local task = table.remove(throttle.waiting, 1)
task:resume()
throttle.running = throttle.running + 1
end
if throttle.running == 0 then
throttle.timer:stop()
end
end
function throttle.wait()
if not Config.options.git.throttle.enabled then
return
end
if not throttle.timer:is_active() then
throttle.timer:start(0, Config.options.git.throttle.duration, vim.schedule_wrap(throttle.next))
end
local running = Async.running()
if throttle.running < Config.options.git.throttle.rate then
throttle.running = throttle.running + 1
else
table.insert(throttle.waiting, running)
coroutine.yield("waiting")
running:suspend()
coroutine.yield("")
end
end
---@param plugin LazyPlugin
local function cooldown(plugin)
if not plugin._.last_check then
return false
end
local delta = (vim.uv.now() - plugin._.last_check) / 1000
return delta < Config.options.git.cooldown
end
---@type table<string, LazyTaskDef>
local M = {}
@ -9,13 +55,19 @@ local M = {}
M.log = {
---@param opts {updated?:boolean, check?: boolean}
skip = function(plugin, opts)
if opts.check and plugin.pin then
return true
end
if opts.updated and not (plugin._.updated and plugin._.updated.from ~= plugin._.updated.to) then
return true
end
return not Util.file_exists(plugin.dir .. "/.git")
local stat = vim.uv.fs_stat(plugin.dir .. "/.git")
return not (stat and stat.type == "directory")
end,
---@async
---@param opts {args?: string[], updated?:boolean, check?:boolean}
run = function(self, opts)
-- self:spawn({ "sleep", "5" })
local args = {
"log",
"--pretty=format:%h %s (%cr)",
@ -23,13 +75,35 @@ M.log = {
"--decorate",
"--date=short",
"--color=never",
"--no-show-signature",
}
local info, target
if opts.updated then
table.insert(args, self.plugin._.updated.from .. ".." .. (self.plugin._.updated.to or "HEAD"))
elseif opts.check then
local info = assert(Git.info(self.plugin.dir))
local target = assert(Git.get_target(self.plugin))
info = assert(Git.info(self.plugin.dir))
target = assert(Git.get_target(self.plugin))
if not target.commit then
for k, v in pairs(target) do
error(k .. " '" .. v .. "' not found")
end
error("no target commit found")
end
assert(target.commit, self.plugin.name .. " " .. target.branch)
if not self.plugin._.is_local then
if Git.eq(info, target) then
if Config.options.checker.check_pinned then
local last_commit = Git.get_commit(self.plugin.dir, target.branch, true)
if not Git.eq(info, { commit = last_commit }) then
self.plugin._.outdated = true
end
end
else
self.plugin._.updates = { from = info, to = target }
end
end
table.insert(args, info.commit .. ".." .. target.commit)
else
vim.list_extend(args, opts.args or Config.options.git.log)
@ -39,6 +113,14 @@ M.log = {
args = args,
cwd = self.plugin.dir,
})
-- for local plugins, mark as needing updates only if local is
-- behind upstream, i.e. if git log gave no output
if opts.check and self.plugin._.is_local then
if not vim.tbl_isempty(self:get_log()) then
self.plugin._.updates = { from = info, to = target }
end
end
end,
}
@ -46,23 +128,45 @@ M.clone = {
skip = function(plugin)
return plugin._.installed or plugin._.is_local
end,
---@async
run = function(self)
throttle.wait()
local args = {
"clone",
self.plugin.uri,
"--filter=blob:none",
"--recurse-submodules",
"--single-branch",
"--shallow-submodules",
"--no-checkout",
"--progress",
self.plugin.url,
}
if Config.options.git.filter then
args[#args + 1] = "--filter=blob:none"
end
if self.plugin.submodules ~= false then
args[#args + 1] = "--recurse-submodules"
end
args[#args + 1] = "--origin=origin"
-- If git config --global core.autocrlf is true on a Unix/Linux system, then the git clone
-- process will lead to files with CRLF endings. Vi / vim / neovim cannot handle this.
-- Force git to clone with core.autocrlf=false.
args[#args + 1] = "-c"
args[#args + 1] = "core.autocrlf=false"
args[#args + 1] = "--progress"
if self.plugin.branch then
vim.list_extend(args, { "-b", self.plugin.branch })
end
table.insert(args, self.plugin.dir)
if vim.fn.isdirectory(self.plugin.dir) == 1 then
require("lazy.manage.task.fs").clean.run(self, {})
end
local marker = self.plugin.dir .. ".cloning"
Util.write_file(marker, "")
self:spawn("git", {
args = args,
on_exit = function(ok)
@ -70,28 +174,31 @@ M.clone = {
self.plugin._.cloned = true
self.plugin._.installed = true
self.plugin._.dirty = true
vim.uv.fs_unlink(marker)
end
end,
})
end,
}
-- setup origin branches if needed
-- fetch will retrieve the data
M.branch = {
skip = function(plugin)
if not plugin._.installed or plugin._.is_local then
return true
end
local branch = assert(Git.get_branch(plugin))
return branch and branch.commit
return Git.get_commit(plugin.dir, branch, true)
end,
---@async
run = function(self)
local branch = assert(Git.get_branch(self.plugin))
local args = {
"remote",
"set-branches",
"--add",
"origin",
branch.branch,
assert(Git.get_branch(self.plugin)),
}
self:spawn("git", {
@ -101,35 +208,118 @@ M.branch = {
end,
}
M.fetch = {
-- check and switch origin
M.origin = {
skip = function(plugin)
if not plugin._.installed or plugin._.is_local then
return true
end
local origin = Git.get_origin(plugin.dir)
return origin == plugin.url
end,
---@async
---@param opts {check?:boolean}
run = function(self, opts)
if opts.check then
local origin = Git.get_origin(self.plugin.dir)
self:error({
"Origin has changed:",
" * old: " .. origin,
" * new: " .. self.plugin.url,
"Please run update to fix",
})
return
end
require("lazy.manage.task.fs").clean.run(self, opts)
M.clone.run(self, opts)
end,
}
M.status = {
skip = function(plugin)
return not plugin._.installed or plugin._.is_local
end,
---@async
run = function(self)
local args = {
"fetch",
"--recurse-submodules",
"--update-shallow",
"--progress",
}
self:spawn("git", {
args = args,
args = { "ls-files", "-d", "-m" },
cwd = self.plugin.dir,
on_exit = function(ok, output)
if ok then
local lines = vim.split(output, "\n")
---@type string[]
lines = vim.tbl_filter(function(line)
-- Fix doc/tags being marked as modified
if line:gsub("[\\/]", "/") == "doc/tags" then
local Process = require("lazy.manage.process")
Process.exec({ "git", "checkout", "--", "doc/tags" }, { cwd = self.plugin.dir })
return false
end
return line ~= ""
end, lines)
if #lines > 0 then
local msg = { "You have local changes in `" .. self.plugin.dir .. "`:" }
for _, line in ipairs(lines) do
msg[#msg + 1] = " * " .. line
end
msg[#msg + 1] = "Please remove them to update."
msg[#msg + 1] = "You can also press `x` to remove the plugin and then `I` to install it again."
self:error(msg)
end
end
end,
})
end,
}
-- fetches all needed origin branches
M.fetch = {
skip = function(plugin)
return not plugin._.installed or plugin._.is_local or cooldown(plugin)
end,
---@async
run = function(self)
throttle.wait()
local args = {
"fetch",
"--recurse-submodules",
"--tags", -- also fetch remote tags
"--force", -- overwrite existing tags if needed
"--progress",
}
if self.plugin.submodules == false then
table.remove(args, 2)
end
self:spawn("git", {
args = args,
cwd = self.plugin.dir,
on_exit = function(ok)
if ok then
self.plugin._.last_check = vim.uv.now()
end
end,
})
end,
}
-- checkout to the target commit
-- branches will exists at this point, so so will the commit
M.checkout = {
skip = function(plugin)
return not plugin._.installed or plugin._.is_local
end,
---@async
---@param opts {lockfile?:boolean}
run = function(self, opts)
throttle.wait()
local info = assert(Git.info(self.plugin.dir))
local target = assert(Git.get_target(self.plugin))
-- if the plugin is locked and we did not just clone it,
-- if the plugin is pinned and we did not just clone it,
-- then don't update
if self.plugin.pin and not self.plugin._.cloned then
target = info
@ -137,6 +327,7 @@ M.checkout = {
local lock
if opts.lockfile then
-- restore to the lock if it exists
lock = Lock.get(self.plugin)
if lock then
---@diagnostic disable-next-line: cast-local-type
@ -144,7 +335,9 @@ M.checkout = {
end
end
if not self.plugin._.cloned and info.commit == target.commit and info.branch == target.branch then
-- don't run checkout if target is already reached.
-- unless we just cloned, since then we won't have any data yet
if Git.eq(info, target) and info.branch == target.branch then
self.plugin._.updated = {
from = info.commit,
to = info.commit,
@ -155,16 +348,21 @@ M.checkout = {
local args = {
"checkout",
"--progress",
"--recurse-submodules",
}
if self.plugin.submodules == false then
table.remove(args, 3)
end
if lock then
table.insert(args, lock.commit)
elseif target.tag then
table.insert(args, "tags/" .. target.tag)
elseif self.plugin.commit then
table.insert(args, self.plugin.commit)
elseif target.branch then
table.insert(args, target.branch)
else
table.insert(args, target.commit)
end
self:spawn("git", {
@ -178,8 +376,10 @@ M.checkout = {
from = info.commit,
to = new_info.commit,
}
if self.plugin._.updated.from ~= self.plugin._.updated.to then
self.plugin._.dirty = true
end
end
self.plugin._.dirty = true
end
end,
})

View file

@ -1,24 +1,29 @@
local Async = require("lazy.async")
local Config = require("lazy.core.config")
local Process = require("lazy.manage.process")
local Terminal = require("lazy.terminal")
local colors = Config.options.headless.colors
---@class LazyTaskDef
---@field skip? fun(plugin:LazyPlugin, opts?:TaskOptions):any?
---@field run fun(task:LazyTask, opts:TaskOptions)
---@field run async fun(task:LazyTask, opts:TaskOptions)
---@alias LazyTaskState fun():boolean?
---@alias LazyTaskFn async fun(task:LazyTask, opts:TaskOptions)
---@class LazyTask
---@class LazyMsg
---@field msg string
---@field level? number
---@class LazyTask: Async
---@field plugin LazyPlugin
---@field name string
---@field type string
---@field output string
---@field status string
---@field error? string
---@field private _task fun(task:LazyTask)
---@field private _running LazyPluginState[]
---@field private _started? number
---@field private _log LazyMsg[]
---@field private _started number
---@field private _ended? number
---@field private _opts TaskOptions
local Task = {}
---@field private _level number
local Task = setmetatable({}, { __index = Async.Async })
---@class TaskOptions: {[string]:any}
---@field on_done? fun(task:LazyTask)
@ -26,142 +31,210 @@ local Task = {}
---@param plugin LazyPlugin
---@param name string
---@param opts? TaskOptions
---@param task fun(task:LazyTask)
---@param task LazyTaskFn
function Task.new(plugin, name, task, opts)
local self = setmetatable({}, {
__index = Task,
})
local self = setmetatable({}, { __index = Task })
---@async
Task.init(self, function()
self:_run(task)
end)
self:set_level()
self._opts = opts or {}
self._running = {}
self._task = task
self._started = nil
self._log = {}
self.plugin = plugin
self.name = name
self.output = ""
self.status = ""
plugin._.tasks = plugin._.tasks or {}
self._started = vim.uv.hrtime()
---@param other LazyTask
plugin._.tasks = vim.tbl_filter(function(other)
return other.name ~= name or other:running()
end, plugin._.tasks or {})
table.insert(plugin._.tasks, self)
self:render()
return self
end
function Task:has_started()
return self._started ~= nil
---@param level? number
---@return LazyMsg[]
function Task:get_log(level)
level = level or vim.log.levels.DEBUG
return vim.tbl_filter(function(msg)
return msg.level >= level
end, self._log)
end
function Task:is_done()
return self:has_started() and not self:is_running()
---@param level? number
function Task:output(level)
return table.concat(
---@param m LazyMsg
vim.tbl_map(function(m)
return m.msg
end, self:get_log(level)),
"\n"
)
end
function Task:is_running()
return self:has_started() and self._ended == nil
function Task:status()
local ret = self._log[#self._log]
local msg = ret and vim.trim(ret.msg) or ""
return msg ~= "" and msg or nil
end
function Task:start()
if vim.in_fast_event() then
return vim.schedule(function()
self:start()
function Task:has_errors()
return self._level >= vim.log.levels.ERROR
end
function Task:has_warnings()
return self._level >= vim.log.levels.WARN
end
---@param level? number
function Task:set_level(level)
self._level = level or vim.log.levels.TRACE
end
---@async
---@param task LazyTaskFn
function Task:_run(task)
if Config.headless() and Config.options.headless.task then
self:log("Running task " .. self.name, vim.log.levels.INFO)
end
self
:on("done", function()
self:_done()
end)
:on("error", function(err)
self:error(err)
end)
:on("yield", function(msg)
self:log(msg)
end)
task(self, self._opts)
end
---@param msg string|string[]|LazyMsg
---@param level? number
function Task:log(msg, level)
if type(msg) == "table" and msg.msg then
level = msg.level or level
msg = msg.msg
end
self._started = vim.loop.hrtime()
---@type boolean, string|any
local ok, err = pcall(self._task, self, self._opts)
if not ok then
self.error = err or "failed"
level = level or vim.log.levels.DEBUG
self._level = math.max(self._level or 0, level or 0)
msg = type(msg) == "table" and table.concat(msg, "\n") or msg
---@cast msg string
table.insert(self._log, { msg = msg, level = level })
self:render()
if Config.headless() then
self:headless()
end
self:_check()
end
function Task:render()
vim.schedule(function()
vim.api.nvim_exec_autocmds("User", { pattern = "LazyRender", modeline = false })
end)
end
function Task:headless()
if not Config.options.headless.log then
return
end
local msg = self._log[#self._log]
if not msg or msg.level == vim.log.levels.TRACE then
return
end
local map = {
[vim.log.levels.ERROR] = Terminal.red,
[vim.log.levels.WARN] = Terminal.yellow,
[vim.log.levels.INFO] = Terminal.blue,
}
local color = Config.options.headless.colors and map[msg.level]
io.write(Terminal.prefix(color and color(msg.msg) or msg.msg, self:prefix()))
io.write("\n")
end
---@param msg string|string[]
function Task:error(msg)
self:log(msg, vim.log.levels.ERROR)
end
---@param msg string|string[]
function Task:warn(msg)
self:log(msg, vim.log.levels.WARN)
end
---@private
function Task:_check()
for _, state in ipairs(self._running) do
if state() then
return
end
function Task:_done()
if Config.headless() and Config.options.headless.task then
local ms = math.floor(self:time() + 0.5)
self:log("Finished task " .. self.name .. " in " .. ms .. "ms", vim.log.levels.INFO)
end
self._ended = vim.loop.hrtime()
self._ended = vim.uv.hrtime()
if self._opts.on_done then
self._opts.on_done(self)
end
vim.cmd("do User LazyRender")
vim.api.nvim_exec_autocmds("User", {
pattern = "LazyPlugin" .. self.name:sub(1, 1):upper() .. self.name:sub(2),
data = { plugin = self.plugin.name },
})
self:render()
vim.schedule(function()
vim.api.nvim_exec_autocmds("User", {
pattern = "LazyPlugin" .. self.name:sub(1, 1):upper() .. self.name:sub(2),
data = { plugin = self.plugin.name },
})
end)
end
function Task:time()
if not self:has_started() then
return 0
end
if not self:is_done() then
return (vim.loop.hrtime() - self._started) / 1e6
end
return (self._ended - self._started) / 1e6
end
---@param fn fun()
function Task:schedule(fn)
local done = false
table.insert(self._running, function()
return not done
end)
vim.schedule(function()
---@type boolean, string|any
local ok, err = pcall(fn)
if not ok then
self.error = err or "failed"
end
done = true
self:_check()
end)
return ((self._ended or vim.uv.hrtime()) - self._started) / 1e6
end
---@async
---@param cmd string
---@param opts? ProcessOpts
function Task:spawn(cmd, opts)
opts = opts or {}
local on_line = opts.on_line
local on_exit = opts.on_exit
local headless = Config.headless() and Config.options.headless.process
function opts.on_line(line)
self.status = line
if not headless then
return self:log(line, vim.log.levels.TRACE)
end
if on_line then
pcall(on_line, line)
end
vim.cmd("do User LazyRender")
end
---@param output string
function opts.on_exit(ok, output)
self.output = self.output .. output
if not ok then
self.error = self.error and (self.error .. "\n" .. output) or output
if headless then
opts.on_data = function(data)
-- prefix with plugin name
io.write(Terminal.prefix(data, self:prefix()))
end
if on_exit then
pcall(on_exit, ok, output)
end
self:_check()
end
local proc = Process.spawn(cmd, opts)
table.insert(self._running, function()
return proc and not proc:is_closing()
end)
end
proc:wait()
---@param tasks (LazyTask?)[]
function Task.all_done(tasks)
for _, task in ipairs(tasks) do
if task and not task:is_done() then
return false
local ok = proc.code == 0 and proc.signal == 0
if not headless then
local msg = vim.trim(proc.data)
if #msg > 0 then
self:log(vim.trim(proc.data), ok and vim.log.levels.DEBUG or vim.log.levels.ERROR)
end
end
return true
if opts.on_exit then
pcall(opts.on_exit, ok, proc.data)
end
return ok
end
function Task:wait()
while self:is_running() do
vim.wait(10)
end
function Task:prefix()
local plugin = "[" .. self.plugin.name .. "] "
local task = string.rep(" ", 20 - #(self.name .. self.plugin.name)) .. self.name
return colors and Terminal.magenta(plugin) .. Terminal.cyan(task) .. Terminal.bright_black(" | ")
or plugin .. " " .. task .. " | "
end
return Task

View file

@ -1,29 +1,85 @@
local Util = require("lazy.util")
local Loader = require("lazy.core.loader")
local Rocks = require("lazy.pkg.rockspec")
local Util = require("lazy.util")
---@type table<string, LazyTaskDef>
local M = {}
M.run = {
skip = function(plugin)
return not (plugin._.dirty and (plugin.opt == false or plugin.run))
end,
run = function(self)
Loader.load(self.plugin, { task = "run" }, { load_start = true })
---@param plugin LazyPlugin
local function get_build_file(plugin)
for _, path in ipairs({ "build.lua", "build/init.lua" }) do
if Util.file_exists(plugin.dir .. "/" .. path) then
return path
end
end
end
local run = self.plugin.run
if run then
if type(run) == "string" and run:sub(1, 1) == ":" then
local cmd = vim.api.nvim_parse_cmd(run:sub(2), {})
self.output = vim.api.nvim_cmd(cmd, { output = true })
elseif type(run) == "function" then
run()
else
local args = vim.split(run, "%s+")
return self:spawn(table.remove(args, 1), {
args = args,
cwd = self.plugin.dir,
})
local B = {}
---@param task LazyTask
---@param build string
function B.cmd(task, build)
if task.plugin.build ~= "rockspec" then
Loader.load(task.plugin, { task = "build" })
end
local cmd = vim.api.nvim_parse_cmd(build:sub(2), {}) --[[@as vim.api.keyset.cmd]]
task:log(vim.api.nvim_cmd(cmd, { output = true }))
end
---@async
---@param task LazyTask
---@param build string
function B.shell(task, build)
local shell = vim.env.SHELL or vim.o.shell
local shell_args = shell:find("cmd.exe", 1, true) and "/c" or "-c"
task:spawn(shell, {
args = { shell_args, build },
cwd = task.plugin.dir,
})
end
M.build = {
---@param opts? {force:boolean}
skip = function(plugin, opts)
if opts and opts.force then
return false
end
return not ((plugin._.dirty or plugin._.build) and (plugin.build or get_build_file(plugin)))
end,
---@async
run = function(self)
vim.cmd([[silent! runtime plugin/rplugin.vim]])
local builders = self.plugin.build
-- Skip if `build` is set to `false`
if builders == false then
return
end
builders = builders or get_build_file(self.plugin)
if builders then
builders = type(builders) == "table" and builders or { builders }
---@cast builders (string|fun(LazyPlugin))[]
for _, build in ipairs(builders) do
if type(build) == "function" then
build(self.plugin)
elseif build == "rockspec" then
Rocks.build(self)
elseif build:sub(1, 1) == ":" then
B.cmd(self, build)
elseif build:match("%.lua$") then
local file = self.plugin.dir .. "/" .. build
local chunk, err = loadfile(file)
if not chunk or err then
error(err)
end
chunk()
else
B.shell(self, build)
end
end
end
end,
@ -31,12 +87,23 @@ M.run = {
M.docs = {
skip = function(plugin)
return not plugin._.dirty
return not plugin._.is_local and not plugin._.dirty
end,
run = function(self)
local docs = self.plugin.dir .. "/doc/"
local docs = self.plugin.dir .. "/doc"
if Util.file_exists(docs) then
self.output = vim.api.nvim_cmd({ cmd = "helptags", args = { docs } }, { output = true })
self:log(vim.api.nvim_cmd({ cmd = "helptags", args = { docs } }, { output = true }))
end
end,
}
M.exists = {
skip = function(plugin)
return not plugin._.is_local or plugin.virtual
end,
run = function(self)
if not Util.file_exists(self.plugin.dir) then
self:error("Local plugin does not exist at `" .. self.plugin.dir .. "`")
end
end,
}

214
lua/lazy/minit.lua Normal file
View file

@ -0,0 +1,214 @@
---@diagnostic disable: inject-field
local islist = vim.islist or vim.tbl_islist
local M = {}
---@param opts LazyConfig
---@return LazySpec[]
local function get_spec(opts)
local ret = opts.spec or {}
return ret and type(ret) == "table" and islist(ret) and ret or { ret }
end
---@param defaults LazyConfig
---@param opts LazyConfig
function M.extend(defaults, opts)
local spec = {}
vim.list_extend(spec, get_spec(defaults))
vim.list_extend(spec, get_spec(opts))
return vim.tbl_deep_extend("force", defaults, opts, { spec = spec })
end
---@param opts LazyConfig
function M.setup(opts)
opts = M.extend({
local_spec = false,
change_detection = { enabled = false },
dev = {
patterns = vim.env.LAZY_DEV and vim.split(vim.env.LAZY_DEV, ",") or nil,
},
}, opts)
local args = {}
local is_busted = false
local is_minitest = false
for _, a in ipairs(_G.arg) do
if a == "--busted" then
is_busted = true
elseif a == "--minitest" then
is_minitest = true
else
table.insert(args, a)
end
end
_G.arg = args
if is_busted then
opts = M.busted.setup(opts)
elseif is_minitest then
opts = M.minitest.setup(opts)
end
-- set stdpaths to use .tests
if vim.env.LAZY_STDPATH then
local root = vim.fn.fnamemodify(vim.env.LAZY_STDPATH, ":p")
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
end
vim.o.loadplugins = true
require("lazy").setup(opts)
if vim.g.colors_name == nil then
vim.cmd("colorscheme habamax")
end
require("lazy").update():wait()
if vim.bo.filetype == "lazy" then
local errors = false
for _, plugin in pairs(require("lazy.core.config").spec.plugins) do
errors = errors or require("lazy.core.plugin").has_errors(plugin)
end
if not errors then
vim.cmd.close()
end
end
if is_busted then
M.busted.run()
elseif is_minitest then
M.minitest.run()
end
end
function M.repro(opts)
opts = M.extend({
spec = {
{
"folke/tokyonight.nvim",
priority = 1000,
lazy = false,
config = function()
require("tokyonight").setup({ style = "moon" })
require("tokyonight").load()
end,
},
},
install = { colorscheme = { "tokyonight" } },
}, opts)
M.setup(opts)
end
M.minitest = {}
function M.minitest.run()
local Config = require("lazy.core.config")
-- disable termnial output for the tests
Config.options.headless = {}
if not require("lazy.core.config").headless() then
return vim.notify("busted can only run in headless mode. Please run with `nvim -l`", vim.log.levels.WARN)
end
package.path = package.path .. ";" .. vim.uv.cwd() .. "/tests/?.lua"
local Test = require("mini.test")
local expect = Test.expect
local _assert = assert
local Assert = {
__call = function(_, ...)
return _assert(...)
end,
same = expect.equality,
equal = expect.equality,
are = {
equal = expect.equality,
},
is_not = {
same = expect.no_equality,
},
is_not_nil = function(a)
return expect.no_equality(nil, a)
end,
is_true = function(a)
return expect.equality(true, a)
end,
is_false = function(a)
return expect.equality(false, a)
end,
}
Assert.__index = Assert
assert = setmetatable({}, Assert)
assert = require("luassert")
require("mini.test").run()
end
---@param opts LazyConfig
function M.minitest.setup(opts)
return M.extend({
spec = {
"lunarmodules/luassert",
{
"echasnovski/mini.test",
opts = {
collect = {
find_files = function()
return vim.fn.globpath("tests", "**/*_spec.lua", true, true)
end,
},
-- script_path = "tests/minit.lua",
},
},
{ dir = vim.uv.cwd() },
},
rocks = { hererocks = true },
}, opts)
end
M.busted = {}
function M.busted.run()
local Config = require("lazy.core.config")
-- disable termnial output for the tests
Config.options.headless = {}
if not require("lazy.core.config").headless() then
return vim.notify("busted can only run in headless mode. Please run with `nvim -l`", vim.log.levels.WARN)
end
package.path = package.path .. ";" .. vim.uv.cwd() .. "/tests/?.lua"
-- run busted
return pcall(require("busted.runner"), {
standalone = false,
}) or os.exit(1)
end
---@param opts LazyConfig
function M.busted.setup(opts)
local args = table.concat(_G.arg, " ")
local json = args:find("--output[ =]json")
return M.extend({
spec = {
"lunarmodules/busted",
{ dir = vim.uv.cwd() },
},
headless = {
process = not json,
log = not json,
task = not json,
},
rocks = { hererocks = true },
}, opts)
end
---@param opts LazyConfig
function M.busted.init(opts)
opts = M.busted.setup(opts)
M.setup(opts)
M.busted.run()
end
setmetatable(M.busted, {
__call = function(_, opts)
M.busted.init(opts)
end,
})
return M

137
lua/lazy/pkg/init.lua Normal file
View file

@ -0,0 +1,137 @@
local Config = require("lazy.core.config")
local Util = require("lazy.core.util")
local M = {}
M.VERSION = 12
M.dirty = false
---@class LazyPkg
---@field name string
---@field dir string
---@field source "lazy" | "packspec" | "rockspec"
---@field file string
---@field spec LazyPluginSpec
---@class LazyPkgSpec
---@field file string
---@field source? string
---@field spec? LazySpec
---@field code? string
---@class LazyPkgSource
---@field name string
---@field get fun(plugin:LazyPlugin):LazyPkgSpec?
---@class LazyPkgCache
---@field pkgs LazyPkg[]
---@field version number
---@type LazyPkg[]?
M.cache = nil
function M.update()
---@type LazyPkgSource[]
local sources = {}
for _, s in ipairs(Config.options.pkg.sources) do
if s ~= "rockspec" or Config.options.rocks.enabled then
sources[#sources + 1] = {
name = s,
get = require("lazy.pkg." .. s).get,
}
end
end
---@type LazyPkgCache
local ret = {
version = M.VERSION,
pkgs = {},
}
for _, plugin in pairs(Config.plugins) do
if plugin._.installed then
for _, source in ipairs(sources) do
local spec = source.get(plugin)
if spec then
---@type LazyPkg
local pkg = {
name = plugin.name,
dir = plugin.dir,
source = spec.source or source.name,
file = spec.file,
spec = spec.spec or {},
}
if type(spec.code) == "string" then
pkg.spec = { _raw = spec.code }
end
table.insert(ret.pkgs, pkg)
break
end
end
end
end
table.sort(ret.pkgs, function(a, b)
return a.name < b.name
end)
local U = require("lazy.util")
local code = "return " .. U.dump(ret)
vim.fn.mkdir(vim.fn.fnamemodify(Config.options.pkg.cache, ":h"), "p")
U.write_file(Config.options.pkg.cache, code)
M.dirty = false
M.cache = nil
end
local function _load()
Util.track("pkg")
M.cache = nil
if vim.uv.fs_stat(Config.options.pkg.cache) then
Util.try(function()
local chunk, err = loadfile(Config.options.pkg.cache)
if not chunk then
error(err)
end
---@type LazyPkgCache?
local ret = chunk()
if ret and ret.version == M.VERSION then
M.cache = {}
for _, pkg in ipairs(ret.pkgs) do
if type(pkg.spec) == "function" then
pkg.spec = pkg.spec()
end
-- wrap in the scope of the plugin
pkg.spec = { pkg.name, specs = pkg.spec }
end
M.cache = ret.pkgs
end
end, "Error loading pkg:")
end
if rawget(M, "cache") then
M.dirty = false
else
M.cache = {}
M.dirty = true
end
Util.track()
end
---@param dir string
---@return LazyPkg?
---@overload fun():LazyPkg[]
function M.get(dir)
if dir then
for _, pkg in ipairs(M.cache) do
if pkg.dir == dir then
return pkg
end
end
return
end
return M.cache
end
return setmetatable(M, {
__index = function(_, key)
if key == "cache" then
_load()
return M.cache
end
end,
})

29
lua/lazy/pkg/lazy.lua Normal file
View file

@ -0,0 +1,29 @@
local Util = require("lazy.util")
local M = {}
M.lazy_file = "lazy.lua"
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
local file = Util.norm(plugin.dir .. "/" .. M.lazy_file)
if Util.file_exists(file) then
---@type fun(): LazySpec
local chunk = Util.try(function()
local ret, err = loadfile(file)
return err and error(err) or ret
end, "`" .. M.lazy_file .. "` for **" .. plugin.name .. "** has errors:")
if not chunk then
Util.error("Invalid `" .. M.lazy_file .. "` for **" .. plugin.name .. "**")
return
end
return {
source = "lazy",
file = M.lazy_file,
code = "function()\n" .. Util.read_file(file) .. "\nend",
}
end
end
return M

54
lua/lazy/pkg/packspec.lua Normal file
View file

@ -0,0 +1,54 @@
local Util = require("lazy.util")
---@class PackSpec
---@field dependencies? table<string, string>
---@field lazy? LazyPluginSpec
---
local M = {}
M.pkg_file = "pkg.json"
---@param plugin LazyPlugin
---@return LazyPkg?
function M.get(plugin)
local file = Util.norm(plugin.dir .. "/" .. M.pkg_file)
if not Util.file_exists(file) then
return
end
---@type PackSpec
local pkg = Util.try(function()
return vim.json.decode(Util.read_file(file))
end, "`" .. M.pkg_file .. "` for **" .. plugin.name .. "** has errors:")
if not pkg then
return
end
---@type LazySpec
local ret = {}
if pkg.dependencies then
for url, version in pairs(pkg.dependencies) do
-- HACK: Add `.git` to github urls
if url:find("github") and not url:match("%.git$") then
url = url .. ".git"
end
ret[#ret + 1] = { url = url, version = version }
end
end
local p = pkg.lazy
if p then
p.url = p.url or plugin.url
p.dir = p.dir or plugin.dir
ret[#ret + 1] = p
end
if pkg.lazy then
ret[#ret + 1] = pkg.lazy
end
return {
source = "lazy",
file = M.pkg_file,
spec = ret,
}
end
return M

343
lua/lazy/pkg/rockspec.lua Normal file
View file

@ -0,0 +1,343 @@
--# selene:allow(incorrect_standard_library_use)
local Community = require("lazy.community")
local Config = require("lazy.core.config")
local Health = require("lazy.health")
local Util = require("lazy.util")
---@class RockSpec
---@field rockspec_format string
---@field package string
---@field version string
---@field dependencies string[]
---@field build? {type?: string, modules?: any[]}
---@field source? {url?: string}
---@class RockManifest
---@field repository table<string, table<string,any>>
local M = {}
M.skip = { "lua" }
M.rewrites = {
["plenary.nvim"] = { "nvim-lua/plenary.nvim", lazy = true },
}
M.python = { "python3", "python" }
---@class HereRocks
M.hererocks = {}
---@param task LazyTask
function M.hererocks.build(task)
local root = Config.options.rocks.root .. "/hererocks"
---@param p string
local python = vim.tbl_filter(function(p)
return vim.fn.executable(p) == 1
end, M.python)[1]
task:spawn(python, {
args = {
"hererocks.py",
"--verbose",
"-l",
"5.1",
"-r",
"latest",
root,
},
cwd = task.plugin.dir,
})
end
---@param bin string
function M.hererocks.bin(bin)
local hererocks = Config.options.rocks.root .. "/hererocks/bin"
return Util.norm(hererocks .. "/" .. bin)
end
-- check if hererocks is building
---@return boolean?
function M.hererocks.building()
return vim.tbl_get(Config.plugins.hererocks or {}, "_", "build")
end
---@param opts? LazyHealth
function M.check(opts)
opts = vim.tbl_extend("force", {
error = Util.error,
warn = Util.warn,
ok = function() end,
}, opts or {})
local ok = false
if Config.hererocks() then
if M.hererocks.building() then
ok = true
else
ok = Health.have(M.python, opts)
ok = Health.have(M.hererocks.bin("luarocks")) and ok
Health.have(
M.hererocks.bin("lua"),
vim.tbl_extend("force", opts, {
version = "-v",
version_pattern = "5.1",
})
)
end
else
ok = Health.have("luarocks", opts)
Health.have(
{ "lua5.1", "lua", "lua-5.1" },
vim.tbl_extend("force", opts, {
version = "-v",
version_pattern = "5.1",
})
)
end
return ok
end
---@async
---@param task LazyTask
function M.build(task)
M.check({
error = function(msg)
task:error(msg:gsub("[{}]", "`"))
end,
warn = function(msg)
task:warn(msg)
end,
ok = function(msg) end,
})
if task:has_warnings() then
task:log({
"",
"This plugin requires `luarocks`. Try one of the following:",
" - fix your `luarocks` installation",
Config.hererocks() and " - disable *hererocks* with `opts.rocks.hererocks = false`"
or " - enable `hererocks` with `opts.rocks.hererocks = true`",
" - disable `luarocks` support completely with `opts.rocks.enabled = false`",
})
task:warn("\nWill try building anyway, but will likely fail...")
task:warn("\n" .. string.rep("-", 80) .. "\n")
task:set_level(vim.log.levels.WARN)
end
if task.plugin.name == "hererocks" then
return M.hererocks.build(task)
end
local env = {}
local luarocks = "luarocks"
if Config.hererocks() then
-- hererocks is still building, so skip for now
-- a new build will happen in the next round
if M.hererocks.building() then
return
end
local sep = Util.is_win and ";" or ":"
local hererocks = Config.options.rocks.root .. "/hererocks/bin"
if Util.is_win then
hererocks = hererocks:gsub("/", "\\")
end
local path = vim.split(vim.env.PATH, sep)
table.insert(path, 1, hererocks)
env = {
PATH = table.concat(path, sep),
}
if Util.is_win then
luarocks = luarocks .. ".bat"
end
end
local pkg = task.plugin._.pkg
assert(pkg, "missing rockspec pkg for " .. task.plugin.name .. "\nThis shouldn't happen, please report.")
local rockspec = M.rockspec(task.plugin.dir .. "/" .. pkg.file) or {}
assert(
rockspec.package,
"missing rockspec package name for " .. task.plugin.name .. "\nThis shouldn't happen, please report."
)
local root = Config.options.rocks.root .. "/" .. task.plugin.name
local ok = task:spawn(luarocks, {
args = {
"--tree",
root,
"--server",
Config.options.rocks.server,
"--lua-version",
"5.1",
"install", -- use install so that we can make use of pre-built rocks
"--force-fast",
"--deps-mode",
"one",
rockspec.package,
},
cwd = task.plugin.dir,
env = env,
})
if ok then
return
end
task:warn("Failed installing " .. rockspec.package .. " with `luarocks`.")
task:warn("\n" .. string.rep("-", 80) .. "\n")
task:warn("Trying to build from source.")
-- install failed, so try building from source
task:set_level() -- reset level
ok = task:spawn(luarocks, {
args = {
"--tree",
root,
"--dev",
"--lua-version",
"5.1",
"make",
"--force-fast",
"--deps-mode",
"one",
},
cwd = task.plugin.dir,
env = env,
})
if not ok then
require("lazy.manage.task.fs").clean.run(task, { rocks_only = true })
end
end
---@param rockspec RockSpec
function M.is_simple_build(rockspec)
local type = vim.tbl_get(rockspec, "build", "type")
return type == nil or type == "none" or (type == "builtin" and not rockspec.build.modules)
end
---@param file string
---@return table?
function M.parse(file)
local ret = {}
local ok = pcall(function()
loadfile(file, nil, ret)()
end) and ret or nil
return ok and ret or nil
end
---@param plugin LazyPlugin
function M.deps(plugin)
local root = Config.options.rocks.root .. "/" .. plugin.name
---@type RockManifest?
local manifest = M.parse(root .. "/lib/luarocks/rocks-5.1/manifest")
return manifest and vim.tbl_keys(manifest.repository or {})
end
---@param file string
---@return RockSpec?
function M.rockspec(file)
return M.parse(file)
end
---@param plugin LazyPlugin
function M.find_rockspec(plugin)
local rockspec_file ---@type string?
Util.ls(plugin.dir, function(path, name, t)
if t == "file" then
for _, suffix in ipairs({ "scm", "git", "dev" }) do
suffix = suffix .. "-1.rockspec"
if name:sub(-#suffix) == suffix then
rockspec_file = path
return false
end
end
end
end)
return rockspec_file
end
---@param plugin LazyPlugin
---@return LazyPkgSpec?
function M.get(plugin)
if Community.get_spec(plugin.name) then
return {
file = "community",
source = "lazy",
spec = Community.get_spec(plugin.name),
}
end
local rockspec_file = M.find_rockspec(plugin)
local rockspec = rockspec_file and M.rockspec(rockspec_file)
if not rockspec then
return
end
local has_lua = not not vim.uv.fs_stat(plugin.dir .. "/lua")
---@type LazyPluginSpec
local specs = {}
---@param dep string
local rocks = vim.tbl_filter(function(dep)
local name = dep:gsub("%s.*", "")
local url = Community.get_url(name)
local spec = Community.get_spec(name)
if spec then
-- community spec
table.insert(specs, spec)
return false
elseif url then
-- Neovim plugin rock
table.insert(specs, { url })
return false
end
return not vim.tbl_contains(M.skip, name)
end, rockspec.dependencies or {})
local use =
-- package without a /lua directory
not has_lua
-- has dependencies that are not skipped,
-- not in community specs,
-- and don't have a rockspec mapping
or #rocks > 0
-- has a complex build process
or not M.is_simple_build(rockspec)
if not use then
-- community specs only
return #specs > 0
and {
file = vim.fn.fnamemodify(rockspec_file, ":t"),
spec = {
plugin.name,
specs = specs,
build = false,
},
}
or nil
end
local lazy = nil
if not has_lua then
lazy = false
end
return {
file = vim.fn.fnamemodify(rockspec_file, ":t"),
spec = {
plugin.name,
build = "rockspec",
lazy = lazy,
},
}
end
return M

45
lua/lazy/state.lua Normal file
View file

@ -0,0 +1,45 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
---@type LazyState
local M = {}
---@class LazyState
local defaults = {
checker = {
last_check = 0,
},
}
---@type LazyState
local data = nil
function M.read()
pcall(function()
---@diagnostic disable-next-line: cast-local-type
data = vim.json.decode(Util.read_file(Config.options.state))
end)
data = vim.tbl_deep_extend("force", {}, defaults, data or {})
end
function M.write()
vim.fn.mkdir(vim.fn.fnamemodify(Config.options.state, ":p:h"), "p")
Util.write_file(Config.options.state, vim.json.encode(data))
end
function M.__index(_, key)
if not data then
M.read()
end
return data[key]
end
function M.__setindex(_, key, value)
if not data then
M.read()
end
---@diagnostic disable-next-line: no-unknown
data[key] = value
end
return setmetatable(M, M)

84
lua/lazy/stats.lua Normal file
View file

@ -0,0 +1,84 @@
local ffi = require("ffi")
local M = {}
---@class LazyStats
M._stats = {
-- startuptime in milliseconds till UIEnter
startuptime = 0,
-- when true, startuptime is the accurate cputime for the Neovim process. (Linux & macOS)
-- this is more accurate than `nvim --startuptime`, and as such will be slightly higher
-- when false, startuptime is calculated based on a delta with a timestamp when lazy started.
real_cputime = false,
count = 0, -- total number of plugins
loaded = 0, -- number of loaded plugins
---@type table<string, number>
times = {},
}
---@type ffi.namespace*
M.C = nil
function M.on_ui_enter()
M._stats.startuptime = M.track("UIEnter")
require("lazy.core.util").track({ start = "startuptime" }, M._stats.startuptime * 1e6)
vim.api.nvim_exec_autocmds("User", { pattern = "LazyVimStarted", modeline = false })
end
function M.track(event)
local time = M.cputime()
M._stats.times[event] = time
return time
end
function M.cputime()
if M.C == nil then
pcall(function()
ffi.cdef([[
typedef long time_t;
typedef int clockid_t;
typedef struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
} nanotime;
int clock_gettime(clockid_t clk_id, struct timespec *tp);
]])
M.C = ffi.C
end)
end
local function real()
local pnano = assert(ffi.new("nanotime[?]", 1))
local CLOCK_PROCESS_CPUTIME_ID = jit.os == "OSX" and 12 or 2
ffi.C.clock_gettime(CLOCK_PROCESS_CPUTIME_ID, pnano)
return tonumber(pnano[0].tv_sec) * 1e3 + tonumber(pnano[0].tv_nsec) / 1e6
end
local function fallback()
return (vim.uv.hrtime() - require("lazy")._start) / 1e6
end
local ok, ret = pcall(real)
if ok then
M.cputime = real
M._stats.real_cputime = true
return ret
else
M.cputime = fallback
return fallback()
end
end
function M.stats()
M._stats.count = 0
M._stats.loaded = 0
for _, plugin in pairs(require("lazy.core.config").plugins) do
M._stats.count = M._stats.count + 1
if plugin._.loaded then
M._stats.loaded = M._stats.loaded + 1
end
end
return M._stats
end
return M

16
lua/lazy/status.lua Normal file
View file

@ -0,0 +1,16 @@
local Config = require("lazy.core.config")
local M = {}
function M.updates()
local Checker = require("lazy.manage.checker")
local updates = #Checker.updated
return updates > 0 and (Config.options.ui.icons.plugin .. "" .. updates)
end
function M.has_updates()
local Checker = require("lazy.manage.checker")
return #Checker.updated > 0
end
return M

71
lua/lazy/terminal.lua Normal file
View file

@ -0,0 +1,71 @@
---@class Ansi: table<string, fun(string):string>
local M = {}
M.colors = {
reset = "\27[0m",
black = "\27[30m",
red = "\27[31m",
green = "\27[32m",
yellow = "\27[33m",
blue = "\27[34m",
magenta = "\27[35m",
cyan = "\27[36m",
white = "\27[37m",
bright_black = "\27[90m",
bright_red = "\27[91m",
bright_green = "\27[92m",
bright_yellow = "\27[93m",
bright_blue = "\27[94m",
bright_magenta = "\27[95m",
bright_cyan = "\27[96m",
bright_white = "\27[97m",
}
function M.color(text, color)
return M.colors[color] .. text .. M.colors.reset
end
-- stylua: ignore start
function M.black(text) return M.color(text, "black") end
function M.red(text) return M.color(text, "red") end
function M.green(text) return M.color(text, "green") end
function M.yellow(text) return M.color(text, "yellow") end
function M.blue(text) return M.color(text, "blue") end
function M.magenta(text) return M.color(text, "magenta") end
function M.cyan(text) return M.color(text, "cyan") end
function M.white(text) return M.color(text, "white") end
function M.bright_black(text) return M.color(text, "bright_black") end
function M.bright_red(text) return M.color(text, "bright_red") end
function M.bright_green(text) return M.color(text, "bright_green") end
function M.bright_yellow(text) return M.color(text, "bright_yellow") end
function M.bright_blue(text) return M.color(text, "bright_blue") end
function M.bright_magenta(text) return M.color(text, "bright_magenta") end
function M.bright_cyan(text) return M.color(text, "bright_cyan") end
function M.bright_white(text) return M.color(text, "bright_white") end
-- stylua: ignore end
---@param data string
---@param prefix string
function M.prefix(data, prefix)
-- Normalize Windows-style newlines to simple newlines
data = data:gsub("\r\n", "\n")
-- Handle prefix for the first line, if data starts immediately
data = prefix .. data
-- Prefix new lines ensuring not to double prefix if a line starts with \r
data = data:gsub("(\n)([^\r])", "%1" .. prefix .. "%2")
-- Handle carriage returns properly to avoid double prefixing
-- Replace any \r not followed by \n with \r, then add a prefix only if the following character isn't the start of our prefix
data = data:gsub("\r([^\n])", function(nextChar)
if nextChar:sub(1, #prefix) == prefix then
return "\r" .. nextChar
else
return "\r" .. prefix .. nextChar
end
end)
return data
end
return M

102
lua/lazy/types.lua Normal file
View file

@ -0,0 +1,102 @@
---@alias LazyPluginKind "normal"|"clean"|"disabled"
---@class LazyPluginState
---@field cache? table<string,any>
---@field cloned? boolean
---@field cond? boolean
---@field dep? boolean True if this plugin is only in the spec as a dependency
---@field dir? string Explicit dir or dev set for this plugin
---@field dirty? boolean
---@field build? boolean
---@field frags? number[]
---@field top? boolean
---@field handlers? LazyPluginHandlers
---@field installed? boolean
---@field is_local? boolean
---@field kind? LazyPluginKind
---@field loaded? {[string]:string}|{time:number}
---@field outdated? boolean
---@field rtp_loaded? boolean
---@field tasks? LazyTask[]
---@field updated? {from:string, to:string}
---@field updates? {from:GitInfo, to:GitInfo}
---@field last_check? number
---@field working? boolean
---@field pkg? LazyPkg
---@alias PluginOpts table|fun(self:LazyPlugin, opts:table):table?
---@class LazyPluginHooks
---@field init? fun(self:LazyPlugin) Will always be run
---@field deactivate? fun(self:LazyPlugin) Unload/Stop a plugin
---@field config? fun(self:LazyPlugin, opts:table)|true Will be executed when loading the plugin
---@field build? false|string|async fun(self:LazyPlugin)|(string|async fun(self:LazyPlugin))[]
---@field opts? PluginOpts
---@class LazyPluginHandlers
---@field event? table<string,LazyEvent>
---@field ft? table<string,LazyEvent>
---@field keys? table<string,LazyKeys>
---@field cmd? table<string,string>
---@class LazyPluginRef
---@field branch? string
---@field tag? string
---@field commit? string
---@field version? string|boolean
---@field pin? boolean
---@field submodules? boolean Defaults to true
---@class LazyPluginBase
---@field [1] string?
---@field name string display name and name used for plugin config files
---@field main? string Entry module that has setup & deactivate
---@field url string?
---@field dir string
---@field enabled? boolean|(fun():boolean)
---@field cond? boolean|(fun():boolean)
---@field optional? boolean If set, then this plugin will not be added unless it is added somewhere else
---@field lazy? boolean
---@field priority? number Only useful for lazy=false plugins to force loading certain plugins first. Default priority is 50
---@field dev? boolean If set, then link to the respective folder under your ~/projects
---@field rocks? string[]
---@field virtual? boolean virtual plugins won't be installed or added to the rtp.
---@class LazyPlugin: LazyPluginBase,LazyPluginHandlers,LazyPluginHooks,LazyPluginRef
---@field dependencies? string[]
---@field specs? string|string[]|LazyPluginSpec[]
---@field _ LazyPluginState
---@class LazyPluginSpecHandlers
---@field event? string[]|string|LazyEventSpec[]|fun(self:LazyPlugin, event:string[]):string[]
---@field cmd? string[]|string|fun(self:LazyPlugin, cmd:string[]):string[]
---@field ft? string[]|string|fun(self:LazyPlugin, ft:string[]):string[]
---@field keys? string|string[]|LazyKeysSpec[]|fun(self:LazyPlugin, keys:string[]):((string|LazyKeys)[])
---@field module? false
---@class LazyPluginSpec: LazyPluginBase,LazyPluginSpecHandlers,LazyPluginHooks,LazyPluginRef
---@field name? string display name and name used for plugin config files
---@field dir? string
---@field dependencies? string|string[]|LazyPluginSpec[]
---@field specs? string|string[]|LazyPluginSpec[]
---@alias LazySpec string|LazyPluginSpec|LazySpecImport|LazySpec[]
---@class LazySpecImport
---@field import string|(fun():LazyPluginSpec) spec module to import
---@field name? string
---@field enabled? boolean|(fun():boolean)
---@field cond? boolean|(fun():boolean)
---@class LazyFragment
---@field id number
---@field pkg? boolean
---@field pid? number
---@field deps? number[]
---@field frags? number[]
---@field dep? boolean
---@field name string
---@field url? string
---@field dir? string
---@field spec LazyPlugin

View file

@ -1,24 +1,50 @@
---@class LazyUtil: LazyUtilCore
local M = setmetatable({}, { __index = require("lazy.core.util") })
function M.file_exists(file)
return vim.loop.fs_stat(file) ~= nil
return vim.uv.fs_stat(file) ~= nil
end
function M.open(uri)
if M.file_exists(uri) then
return vim.cmd.view(uri)
---@param opts? LazyFloatOptions
---@return LazyFloat
function M.float(opts)
return require("lazy.view.float")(opts)
end
function M.wo(win, k, v)
if vim.api.nvim_set_option_value then
vim.api.nvim_set_option_value(k, v, { scope = "local", win = win })
else
vim.wo[win][k] = v
end
end
---@param opts? {system?:boolean}
function M.open(uri, opts)
opts = opts or {}
if not opts.system and M.file_exists(uri) then
return M.float({ style = "", file = uri })
end
local Config = require("lazy.core.config")
local cmd
if vim.fn.has("win32") == 1 then
cmd = { "cmd.exe", "/c", "start", '""', vim.fn.shellescape(uri) }
if not opts.system and Config.options.ui.browser then
cmd = { Config.options.ui.browser, uri }
elseif vim.fn.has("win32") == 1 then
cmd = { "explorer", uri }
elseif vim.fn.has("macunix") == 1 then
cmd = { "open", uri }
else
cmd = { "xdg-open", uri }
if vim.fn.executable("xdg-open") == 1 then
cmd = { "xdg-open", uri }
elseif vim.fn.executable("wslview") == 1 then
cmd = { "wslview", uri }
else
cmd = { "open", uri }
end
end
local ret = vim.fn.system(cmd)
if vim.v.shell_error ~= 0 then
local ret = vim.fn.jobstart(cmd, { detach = true })
if ret <= 0 then
local msg = {
"Failed to open uri",
ret,
@ -28,30 +54,139 @@ function M.open(uri)
end
end
function M.read_file(file)
local fd = assert(io.open(file, "r"))
---@type string
local data = fd:read("*a")
fd:close()
return data
end
function M.write_file(file, contents)
local fd = assert(io.open(file, "w+"))
fd:write(contents)
fd:close()
end
---@generic F: fun()
---@param ms number
---@param fn fun()
---@param fn F
---@return F
function M.throttle(ms, fn)
local timer = vim.loop.new_timer()
local running = false
local first = true
---@type Async
local async
local pending = false
return function()
if not running then
if first then
fn()
first = false
end
timer:start(ms, 0, function()
running = false
vim.schedule(fn)
end)
running = true
if async and async:running() then
pending = true
return
end
---@async
async = require("lazy.async").new(function()
repeat
pending = false
fn()
async:sleep(ms)
until not pending
end)
end
end
--- Creates a weak reference to an object.
--- Calling the returned function will return the object if it has not been garbage collected.
---@generic T: table
---@param obj T
---@return T|fun():T?
function M.weak(obj)
local weak = { _obj = obj }
---@return table<any, any>
local function get()
local ret = rawget(weak, "_obj")
return ret == nil and error("Object has been garbage collected", 2) or ret
end
local mt = {
__mode = "v",
__call = function(t)
return rawget(t, "_obj")
end,
__index = function(_, k)
return get()[k]
end,
__newindex = function(_, k, v)
get()[k] = v
end,
__pairs = function()
return pairs(get())
end,
}
return setmetatable(weak, mt)
end
---@class LazyCmdOptions: LazyFloatOptions
---@field cwd? string
---@field env? table<string,string>
---@field float? LazyFloatOptions
-- Opens a floating terminal (interactive by default)
---@param cmd? string[]|string
---@param opts? LazyCmdOptions|{interactive?:boolean}
function M.float_term(cmd, opts)
cmd = cmd or {}
if type(cmd) == "string" then
cmd = { cmd }
end
if #cmd == 0 then
cmd = { vim.o.shell }
end
opts = opts or {}
local float = M.float(opts)
vim.fn.termopen(cmd, vim.tbl_isempty(opts) and vim.empty_dict() or opts)
if opts.interactive ~= false then
vim.cmd.startinsert()
vim.api.nvim_create_autocmd("TermClose", {
once = true,
buffer = float.buf,
callback = function()
float:close({ wipe = true })
vim.cmd.checktime()
end,
})
end
return float
end
--- Runs the command and shows it in a floating window
---@param cmd string[]
---@param opts? LazyCmdOptions|{filetype?:string}
function M.float_cmd(cmd, opts)
opts = opts or {}
local Process = require("lazy.manage.process")
local lines, code = Process.exec(cmd, { cwd = opts.cwd })
if code ~= 0 then
M.error({
"`" .. table.concat(cmd, " ") .. "`",
"",
"## Error",
table.concat(lines, "\n"),
}, { title = "Command Failed (" .. code .. ")" })
return
end
local float = M.float(opts)
if opts.filetype then
vim.bo[float.buf].filetype = opts.filetype
end
vim.api.nvim_buf_set_lines(float.buf, 0, -1, false, lines)
vim.bo[float.buf].modifiable = false
return float
end
---@deprecated use float_term or float_cmd instead
function M.open_cmd()
M.warn([[`require("lazy.util").open_cmd()` is deprecated. Please use `float_term` instead. Check the docs]])
end
---@return string?
function M.head(file)
local f = io.open(file)
@ -91,9 +226,9 @@ function M.markdown(msg, opts)
vim.tbl_deep_extend("force", {
title = "lazy.nvim",
on_open = function(win)
vim.wo[win].conceallevel = 3
vim.wo[win].concealcursor = "n"
vim.wo[win].spell = false
M.wo(win, "conceallevel", 3)
M.wo(win, "concealcursor", "n")
M.wo(win, "spell", false)
vim.treesitter.start(vim.api.nvim_win_get_buf(win), "markdown")
end,
@ -107,20 +242,25 @@ function M._dump(value, result)
table.insert(result, tostring(value))
elseif t == "string" then
table.insert(result, ("%q"):format(value))
elseif t == "table" and value._raw then
table.insert(result, value._raw)
elseif t == "table" then
table.insert(result, "{")
local i = 1
---@diagnostic disable-next-line: no-unknown
for k, v in pairs(value) do
if k == i then
elseif type(k) == "string" then
table.insert(result, ("[%q]="):format(k))
else
table.insert(result, k .. "=")
end
for _, v in ipairs(value) do
M._dump(v, result)
table.insert(result, ",")
i = i + 1
end
---@diagnostic disable-next-line: no-unknown
for k, v in pairs(value) do
if type(k) == "string" then
if k:match("^[a-zA-Z]+$") then
table.insert(result, ("%s="):format(k))
else
table.insert(result, ("[%q]="):format(k))
end
M._dump(v, result)
table.insert(result, ",")
end
end
table.insert(result, "}")
else
@ -134,4 +274,22 @@ function M.dump(value)
return table.concat(result, "")
end
---@generic V
---@param t table<string, V>
---@param fn fun(key:string, value:V)
---@param opts? {case_sensitive?:boolean}
function M.foreach(t, fn, opts)
---@type string[]
local keys = vim.tbl_keys(t)
pcall(table.sort, keys, function(a, b)
if opts and opts.case_sensitive then
return a < b
end
return a:lower() < b:lower()
end)
for _, key in ipairs(keys) do
fn(key, t[key])
end
end
return M

View file

@ -1,40 +1,51 @@
local M = {}
M.colors = {
Error = "ErrorMsg",
H1 = "IncSearch",
H2 = "Bold",
Muted = "Comment",
H1 = "IncSearch", -- home button
H2 = "Bold", -- titles
Comment = "Comment",
Normal = "NormalFloat",
Commit = "@variable.builtin",
Key = "Conceal",
Value = "@string",
ProgressDone = {
bold = true,
default = true,
fg = "#ff007c",
},
ProgressTodo = "LineNr",
Commit = "@variable.builtin", -- commit ref
CommitIssue = "Number",
CommitType = "Title", -- conventional commit type
CommitScope = "Italic", -- conventional commit scope
Dimmed = "Conceal", -- property
Prop = "Conceal", -- property
Value = "@string", -- value of a property
NoCond = "DiagnosticWarn", -- unloaded icon for a plugin where `cond()` was false
Local = "Constant",
ProgressDone = "Constant", -- progress bar done
ProgressTodo = "LineNr", -- progress bar todo
Special = "@punctuation.special",
LoaderPlugin = "Special",
LoaderEvent = "Constant",
LoaderKeys = "Statement",
LoaderStart = "@field",
LoaderSource = "Character",
LoaderCmd = "Operator",
ReasonRuntime = "@macro",
ReasonPlugin = "Special",
ReasonEvent = "Constant",
ReasonKeys = "Statement",
ReasonStart = "@variable.member",
ReasonSource = "Character",
ReasonFt = "Character",
ReasonCmd = "Operator",
ReasonImport = "Identifier",
ReasonRequire = "@variable.parameter",
Button = "CursorLine",
ButtonActive = "Visual",
TaskOutput = "MsgArea", -- task output
Error = "DiagnosticError", -- task errors
Warning = "DiagnosticWarn", -- task errors
Info = "DiagnosticInfo", -- task errors
Dir = "@markup.link", -- directory
Url = "@markup.link", -- url
Bold = { bold = true },
Italic = { italic = true },
}
M.did_setup = false
function M.set_hl()
for hl_group, opts in pairs(M.colors) do
if type(opts) == "string" then
opts = { link = opts }
end
opts.default = true
vim.api.nvim_set_hl(0, "Lazy" .. hl_group, opts)
for hl_group, link in pairs(M.colors) do
local hl = type(link) == "table" and link or { link = link }
hl.default = true
vim.api.nvim_set_hl(0, "Lazy" .. hl_group, hl)
end
end
@ -46,13 +57,12 @@ function M.setup()
M.did_setup = true
M.set_hl()
vim.api.nvim_create_autocmd("ColorScheme", {
vim.api.nvim_create_autocmd("VimEnter", {
callback = function()
M.set_hl()
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "VeryLazy",
vim.api.nvim_create_autocmd("ColorScheme", {
callback = function()
M.set_hl()
end,

View file

@ -1,89 +1,158 @@
local View = require("lazy.view")
local require = require("lazy.core.util").lazy_require
local Config = require("lazy.core.config")
local Manage = require("lazy.manage")
local Util = require("lazy.util")
local View = require("lazy.view")
local ViewConfig = require("lazy.view.config")
local M = {}
---@param cmd string
---@param plugins? LazyPlugin[]
function M.cmd(cmd, plugins)
cmd = cmd == "" and "show" or cmd
local command = M.commands[cmd]
---@param opts? ManagerOpts
function M.cmd(cmd, opts)
cmd = cmd == "" and "home" or cmd
local command = M.commands[cmd] --[[@as fun(opts)]]
if command == nil then
Util.error("Invalid lazy command '" .. cmd .. "'")
elseif
ViewConfig.commands[cmd]
and ViewConfig.commands[cmd].plugins_required
and not (opts and vim.tbl_count(opts.plugins or {}) > 0)
then
return Util.error("`Lazy " .. cmd .. "` requires at least one plugin")
else
command(plugins)
command(opts)
end
end
---@class LazyCommands
M.commands = {
clean = function(plugins)
Manage.clean({ clear = true, interactive = true, mode = "clean", plugins = plugins })
end,
clear = function()
Manage.clear()
View.show()
end,
install = function()
Manage.install({ clear = true, interactive = true, mode = "install" })
health = function()
vim.cmd.checkhealth("lazy")
end,
log = function(plugins)
Manage.log({ clear = true, interactive = true, mode = "log", plugins = plugins })
---@param opts ManagerOpts
pkg = function(opts)
local Pkg = require("lazy.pkg")
Pkg.update()
require("lazy.manage.reloader").reload({
{
file = "pkg",
what = "changed",
},
})
for _, plugin in pairs(opts and opts.plugins or {}) do
local spec = Pkg.get(plugin.dir)
Util.info(vim.inspect(spec), { lang = "lua", title = plugin.name })
end
end,
home = function()
View.show("home")
end,
show = function()
View.show()
View.show("home")
end,
help = function()
View.show("help")
end,
debug = function()
View.show("debug")
end,
profile = function()
View.show("profile")
end,
sync = function()
Manage.clean({ interactive = true, clear = true, wait = true, mode = "sync" })
Manage.update({ interactive = true })
Manage.install({ interactive = true })
---@param opts ManagerOpts
load = function(opts)
-- when a command is executed with a bang, wait will be set
require("lazy.core.loader").load(opts.plugins, { cmd = "Lazy load" }, { force = opts.wait })
end,
update = function(plugins)
Manage.update({ clear = true, interactive = true, mode = "update", plugins = plugins })
end,
check = function(plugins)
Manage.check({ clear = true, interactive = true, mode = "check", plugins = plugins })
end,
restore = function(plugins)
Manage.update({ clear = true, interactive = true, lockfile = true, mode = "restore", plugins = plugins })
reload = function(opts)
for _, plugin in pairs(opts.plugins) do
if type(plugin) == "string" then
plugin = Config.plugins[plugin]
end
Util.warn("Reloading **" .. plugin.name .. "**")
require("lazy.core.loader").reload(plugin)
end
end,
log = Manage.log,
build = Manage.build,
clean = Manage.clean,
install = Manage.install,
sync = Manage.sync,
update = Manage.update,
check = Manage.check,
restore = Manage.restore,
}
function M.complete(cmd, prefix)
if not (ViewConfig.commands[cmd] or {}).plugins and cmd ~= "pkg" then
return
end
---@type string[]
local plugins = {}
if cmd == "load" then
plugins[#plugins + 1] = "all"
end
for name, plugin in pairs(Config.plugins) do
if cmd ~= "load" or not plugin._.loaded then
plugins[#plugins + 1] = name
end
end
table.sort(plugins)
---@param key string
return vim.tbl_filter(function(key)
return key:find(prefix, 1, true) == 1
end, plugins)
end
function M.setup()
vim.api.nvim_create_user_command("Lazy", function(args)
M.cmd(vim.trim(args.args or ""))
vim.api.nvim_create_user_command("Lazy", function(cmd)
---@type ManagerOpts
local opts = { wait = cmd.bang == true }
local prefix, args = M.parse(cmd.args)
if #args == 1 and args[1] == "all" then
args = vim.tbl_keys(Config.plugins)
end
if #args > 0 then
---@param plugin string
opts.plugins = vim.tbl_map(function(plugin)
return Config.plugins[plugin]
end, args)
end
M.cmd(prefix, opts)
end, {
bar = true,
bang = true,
nargs = "?",
desc = "Lazy",
complete = function(_, line)
if line:match("^%s*Lazy %w+ ") then
return {}
local prefix, args = M.parse(line)
if #args > 0 then
return M.complete(prefix, args[#args])
end
local prefix = line:match("^%s*Lazy (%w*)") or ""
---@param key string
return vim.tbl_filter(function(key)
return key:find(prefix) == 1
return key:find(prefix, 1, true) == 1
end, vim.tbl_keys(M.commands))
end,
})
end
for name in pairs(M.commands) do
local cmd = "Lazy" .. name:sub(1, 1):upper() .. name:sub(2)
vim.api.nvim_create_user_command(cmd, function()
M.cmd(name)
end, {
desc = "Lazy " .. name,
})
---@return string, string[]
function M.parse(args)
local parts = vim.split(vim.trim(args), "%s+")
if vim.startswith("Lazy", parts[1]) then
table.remove(parts, 1)
end
if args:sub(-1) == " " then
parts[#parts + 1] = ""
end
return table.remove(parts, 1) or "", parts
end
return M

161
lua/lazy/view/config.lua Normal file
View file

@ -0,0 +1,161 @@
local M = {}
---@class LazyViewCommand
---@field id number
---@field plugins? boolean
---@field plugins_required? boolean
---@field button? boolean
---@field desc? string
---@field desc_plugin? string
---@field key? string
---@field key_plugin? string
---@field toggle? boolean
function M.get_commands()
---@type (LazyViewCommand|{name:string})[]
local ret = {}
for k, v in pairs(M.commands) do
v.name = k
ret[#ret + 1] = v
end
table.sort(ret, function(a, b)
return a.id < b.id
end)
return ret
end
M.dimmed_commits = { "bot", "build", "ci", "chore", "doc", "style", "test" }
M.keys = {
hover = "K",
diff = "d",
close = "q",
details = "<cr>",
profile_sort = "<C-s>",
profile_filter = "<C-f>",
abort = "<C-c>",
next = "]]",
prev = "[[",
}
---@type table<string,LazyViewCommand>
M.commands = {
home = {
button = true,
desc = "Go back to plugin list",
id = 1,
key = "H",
},
install = {
button = true,
desc = "Install missing plugins",
desc_plugin = "Install a plugin",
id = 2,
key = "I",
key_plugin = "i",
plugins = true,
},
update = {
button = true,
desc = "Update plugins. This will also update the lockfile",
desc_plugin = "Update a plugin. This will also update the lockfile",
id = 3,
key = "U",
key_plugin = "u",
plugins = true,
},
sync = {
button = true,
desc = "Run install, clean and update",
desc_plugin = "Run install, clean and update",
id = 4,
key = "S",
plugins = true,
},
clean = {
button = true,
desc = "Clean plugins that are no longer needed",
desc_plugin = "Delete a plugin. WARNING: this will delete the plugin even if it should be installed!",
id = 5,
key = "X",
key_plugin = "x",
plugins = true,
},
check = {
button = true,
desc = "Check for updates and show the log (git fetch)",
desc_plugin = "Check for updates and show the log (git fetch)",
id = 6,
key = "C",
key_plugin = "c",
plugins = true,
},
log = {
button = true,
desc = "Show recent updates",
desc_plugin = "Show recent updates",
id = 7,
key = "L",
key_plugin = "gl",
plugins = true,
},
restore = {
button = true,
desc = "Updates all plugins to the state in the lockfile. For a single plugin: restore it to the state in the lockfile or to a given commit under the cursor",
desc_plugin = "Restore a plugin to the state in the lockfile or to a given commit under the cursor",
id = 8,
key = "R",
key_plugin = "r",
plugins = true,
},
profile = {
button = true,
desc = "Show detailed profiling",
id = 9,
key = "P",
toggle = true,
},
debug = {
button = true,
desc = "Show debug information",
id = 10,
key = "D",
toggle = true,
},
help = {
button = true,
desc = "Toggle this help page",
id = 11,
key = "?",
toggle = true,
},
clear = {
desc = "Clear finished tasks",
id = 12,
},
load = {
desc = "Load a plugin that has not been loaded yet. Similar to `:packadd`. Like `:Lazy load foo.nvim`. Use `:Lazy! load` to skip `cond` checks.",
id = 13,
plugins = true,
plugins_required = true,
},
health = {
desc = "Run `:checkhealth lazy`",
id = 14,
},
build = {
desc = "Rebuild a plugin",
id = 15,
plugins = true,
plugins_required = true,
key_plugin = "gb",
},
reload = {
desc = "Reload a plugin (experimental!!)",
plugins = true,
plugins_required = true,
id = 16,
},
}
return M

64
lua/lazy/view/diff.lua Normal file
View file

@ -0,0 +1,64 @@
local Util = require("lazy.util")
local M = {}
---@alias LazyDiff {commit:string} | {from:string, to:string}
---@alias LazyDiffFun fun(plugin:LazyPlugin, diff:LazyDiff)
M.handlers = {
---@type LazyDiffFun
browser = function(plugin, diff)
if plugin.url then
local url = plugin.url:gsub("%.git$", "")
if diff.commit then
Util.open(url .. "/commit/" .. diff.commit)
else
Util.open(url .. "/compare/" .. diff.from .. ".." .. diff.to)
end
else
Util.error("No url for " .. plugin.name)
end
end,
---@type LazyDiffFun
["diffview.nvim"] = function(plugin, diff)
local args
if diff.commit then
args = ("-C=%s"):format(plugin.dir) .. " " .. diff.commit .. "^!"
else
args = ("-C=%s"):format(plugin.dir) .. " " .. diff.from .. ".." .. diff.to
end
vim.cmd("DiffviewOpen " .. args)
end,
---@type LazyDiffFun
git = function(plugin, diff)
local cmd = { "git" }
if diff.commit then
cmd[#cmd + 1] = "show"
cmd[#cmd + 1] = diff.commit
else
cmd[#cmd + 1] = "diff"
cmd[#cmd + 1] = diff.from
cmd[#cmd + 1] = diff.to
end
Util.float_cmd(cmd, { cwd = plugin.dir, filetype = "git" })
end,
---@type LazyDiffFun
terminal_git = function(plugin, diff)
local cmd = { "git" }
if diff.commit then
cmd[#cmd + 1] = "show"
cmd[#cmd + 1] = diff.commit
else
cmd[#cmd + 1] = "diff"
cmd[#cmd + 1] = diff.from
cmd[#cmd + 1] = diff.to
end
Util.float_term(cmd, { cwd = plugin.dir, interactive = false, env = { PAGER = "cat" } })
end,
}
return M

354
lua/lazy/view/float.lua Normal file
View file

@ -0,0 +1,354 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local ViewConfig = require("lazy.view.config")
---@class LazyFloatOptions
---@field buf? number
---@field file? string
---@field margin? {top?:number, right?:number, bottom?:number, left?:number}
---@field size? {width:number, height:number}
---@field zindex? number
---@field style? "" | "minimal"
---@field border? "none" | "single" | "double" | "rounded" | "solid" | "shadow"
---@field title? string
---@field title_pos? "center" | "left" | "right"
---@field persistent? boolean
---@field ft? string
---@field noautocmd? boolean
---@field backdrop? float
---@class LazyFloat
---@field buf number
---@field win number
---@field opts LazyFloatOptions
---@field win_opts LazyWinOpts
---@field backdrop_buf number
---@field backdrop_win number
---@field id number
---@overload fun(opts?:LazyFloatOptions):LazyFloat
local M = {}
setmetatable(M, {
__call = function(_, ...)
return M.new(...)
end,
})
local _id = 0
local function next_id()
_id = _id + 1
return _id
end
---@param opts? LazyFloatOptions
function M.new(opts)
local self = setmetatable({}, { __index = M })
return self:init(opts)
end
---@param opts? LazyFloatOptions
function M:init(opts)
require("lazy.view.colors").setup()
self.id = next_id()
self.opts = vim.tbl_deep_extend("force", {
size = Config.options.ui.size,
style = "minimal",
border = Config.options.ui.border or "none",
backdrop = Config.options.ui.backdrop or 60,
zindex = 50,
}, opts or {})
---@class LazyWinOpts
---@field width number
---@field height number
---@field row number
---@field col number
self.win_opts = {
relative = "editor",
style = self.opts.style ~= "" and self.opts.style or nil,
border = self.opts.border,
zindex = self.opts.zindex,
noautocmd = self.opts.noautocmd,
title = self.opts.title,
title_pos = self.opts.title and self.opts.title_pos or nil,
}
self:mount()
self:on("VimEnter", function()
vim.schedule(function()
if not self:win_valid() then
self:close()
end
end)
end, { buffer = false })
return self
end
function M:layout()
local function size(max, value)
return value > 1 and math.min(value, max) or math.floor(max * value)
end
self.win_opts.width = size(vim.o.columns, self.opts.size.width)
self.win_opts.height = size(vim.o.lines, self.opts.size.height)
self.win_opts.row = math.floor((vim.o.lines - self.win_opts.height) / 2)
self.win_opts.col = math.floor((vim.o.columns - self.win_opts.width) / 2)
if self.opts.border ~= "none" then
self.win_opts.row = self.win_opts.row - 1
self.win_opts.col = self.win_opts.col - 1
end
if self.opts.margin then
if self.opts.margin.top then
self.win_opts.height = self.win_opts.height - self.opts.margin.top
self.win_opts.row = self.win_opts.row + self.opts.margin.top
end
if self.opts.margin.right then
self.win_opts.width = self.win_opts.width - self.opts.margin.right
end
if self.opts.margin.bottom then
self.win_opts.height = self.win_opts.height - self.opts.margin.bottom
end
if self.opts.margin.left then
self.win_opts.width = self.win_opts.width - self.opts.margin.left
self.win_opts.col = self.win_opts.col + self.opts.margin.left
end
end
end
function M:mount()
if self:buf_valid() then
-- keep existing buffer
self.buf = self.buf
elseif self.opts.file then
self.buf = vim.fn.bufadd(self.opts.file)
vim.bo[self.buf].readonly = true
vim.bo[self.buf].swapfile = false
vim.fn.bufload(self.buf)
vim.bo[self.buf].modifiable = false
elseif self.opts.buf then
self.buf = self.opts.buf
else
self.buf = vim.api.nvim_create_buf(false, true)
end
local normal, has_bg
if vim.fn.has("nvim-0.9.0") == 0 then
normal = vim.api.nvim_get_hl_by_name("Normal", true)
has_bg = normal and normal.background ~= nil
else
normal = vim.api.nvim_get_hl(0, { name = "Normal" })
has_bg = normal and normal.bg ~= nil
end
if has_bg and self.opts.backdrop and self.opts.backdrop < 100 and vim.o.termguicolors then
self.backdrop_buf = vim.api.nvim_create_buf(false, true)
self.backdrop_win = vim.api.nvim_open_win(self.backdrop_buf, false, {
relative = "editor",
width = vim.o.columns,
height = vim.o.lines,
row = 0,
col = 0,
style = "minimal",
focusable = false,
zindex = self.opts.zindex - 1,
})
vim.api.nvim_set_hl(0, "LazyBackdrop", { bg = "#000000", default = true })
Util.wo(self.backdrop_win, "winhighlight", "Normal:LazyBackdrop")
Util.wo(self.backdrop_win, "winblend", self.opts.backdrop)
vim.bo[self.backdrop_buf].buftype = "nofile"
vim.bo[self.backdrop_buf].filetype = "lazy_backdrop"
end
self:layout()
self.win = vim.api.nvim_open_win(self.buf, true, self.win_opts)
self:on("WinClosed", function()
self:close()
self:augroup(true)
end, { win = true })
self:focus()
self:on_key(ViewConfig.keys.close, self.close, "Close")
self:on({ "BufDelete", "BufHidden" }, self.close)
if vim.bo[self.buf].buftype == "" then
vim.bo[self.buf].buftype = "nofile"
end
if vim.bo[self.buf].filetype == "" then
vim.bo[self.buf].filetype = self.opts.ft or "lazy"
end
local function opts()
vim.bo[self.buf].bufhidden = self.opts.persistent and "hide" or "wipe"
Util.wo(self.win, "conceallevel", 3)
Util.wo(self.win, "foldenable", false)
Util.wo(self.win, "spell", false)
Util.wo(self.win, "wrap", true)
Util.wo(self.win, "winhighlight", "Normal:LazyNormal")
Util.wo(self.win, "colorcolumn", "")
end
opts()
vim.api.nvim_create_autocmd("VimResized", {
callback = function()
if not (self.win and vim.api.nvim_win_is_valid(self.win)) then
return true
end
self:layout()
local config = {}
for _, key in ipairs({ "relative", "width", "height", "col", "row" }) do
---@diagnostic disable-next-line: no-unknown
config[key] = self.win_opts[key]
end
config.style = self.opts.style ~= "" and self.opts.style or nil
vim.api.nvim_win_set_config(self.win, config)
if self.backdrop_win and vim.api.nvim_win_is_valid(self.backdrop_win) then
vim.api.nvim_win_set_config(self.backdrop_win, {
width = vim.o.columns,
height = vim.o.lines,
})
end
opts()
vim.api.nvim_exec_autocmds("User", { pattern = "LazyFloatResized", modeline = false })
end,
})
end
---@param clear? boolean
function M:augroup(clear)
return vim.api.nvim_create_augroup("trouble.window." .. self.id, { clear = clear == true })
end
---@param events string|string[]
---@param fn fun(self:LazyFloat, event:{buf:number}):boolean?
---@param opts? vim.api.keyset.create_autocmd | {buffer: false, win?:boolean}
function M:on(events, fn, opts)
opts = opts or {}
if opts.win then
opts.pattern = self.win .. ""
opts.win = nil
elseif opts.buffer == nil then
opts.buffer = self.buf
elseif opts.buffer == false then
opts.buffer = nil
end
if opts.pattern then
opts.buffer = nil
end
local _self = Util.weak(self)
opts.callback = function(e)
local this = _self()
if not this then
-- delete the autocmd
return true
end
return fn(this, e)
end
opts.group = self:augroup()
vim.api.nvim_create_autocmd(events, opts)
end
---@param key string
---@param fn fun(self?)
---@param desc? string
---@param mode? string[]
function M:on_key(key, fn, desc, mode)
vim.keymap.set(mode or "n", key, function()
fn(self)
end, {
nowait = true,
buffer = self.buf,
desc = desc,
})
end
---@param opts? {wipe:boolean}
function M:close(opts)
self:augroup(true)
local buf = self.buf
local win = self.win
local wipe = opts and opts.wipe
if wipe == nil then
wipe = not self.opts.persistent
end
self.win = nil
if wipe then
self.buf = nil
end
local backdrop_buf = self.backdrop_buf
local backdrop_win = self.backdrop_win
self.backdrop_buf = nil
self.backdrop_win = nil
vim.schedule(function()
if backdrop_win and vim.api.nvim_win_is_valid(backdrop_win) then
vim.api.nvim_win_close(backdrop_win, true)
end
if backdrop_buf and vim.api.nvim_buf_is_valid(backdrop_buf) then
vim.api.nvim_buf_delete(backdrop_buf, { force = true })
end
if win and vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
if wipe and buf and vim.api.nvim_buf_is_valid(buf) then
vim.diagnostic.reset(Config.ns, buf)
vim.api.nvim_buf_delete(buf, { force = true })
end
vim.cmd.redraw()
end)
end
function M:win_valid()
return self.win and vim.api.nvim_win_is_valid(self.win)
end
function M:buf_valid()
return self.buf and vim.api.nvim_buf_is_valid(self.buf)
end
function M:hide()
if self:win_valid() then
self:close({ wipe = false })
end
end
function M:toggle()
if self:win_valid() then
self:hide()
return false
else
self:show()
return true
end
end
function M:show()
if self:win_valid() then
self:focus()
elseif self:buf_valid() then
self:mount()
else
error("LazyFloat: buffer closed")
end
end
function M:focus()
vim.api.nvim_set_current_win(self.win)
-- it seems that setting the current win doesn't work before VimEnter,
-- so do that then
if vim.v.vim_did_enter ~= 1 then
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
if self.win and vim.api.nvim_win_is_valid(self.win) then
pcall(vim.api.nvim_set_current_win, self.win)
end
return true
end,
})
end
end
return M

View file

@ -1,219 +1,364 @@
local Util = require("lazy.util")
local Render = require("lazy.view.render")
local Config = require("lazy.core.config")
local Diff = require("lazy.view.diff")
local Float = require("lazy.view.float")
local Git = require("lazy.manage.git")
local Render = require("lazy.view.render")
local Util = require("lazy.util")
local ViewConfig = require("lazy.view.config")
local M = {}
M.modes = {
{ name = "install", key = "I", desc = "Install missing plugins" },
{ name = "update", key = "U", desc = "Update all plugins. This will also update the lockfile" },
{ name = "sync", key = "S", desc = "Run install, clean and update" },
{ name = "clean", key = "X", desc = "Clean plugins that are no longer needed" },
{ name = "check", key = "C", desc = "Check for updates and show the log (git fetch)" },
{ name = "log", key = "L", desc = "Show recent updates for all plugins" },
{ name = "restore", key = "R", desc = "Updates all plugins to the state in the lockfile" },
{ name = "profile", key = "P", desc = "Show detailed profiling", toggle = true },
{ name = "help", key = "?", hide = true, desc = "Toggle this help page", toggle = true },
{ plugin = true, name = "update", key = "u", desc = "Update this plugin. This will also update the lockfile" },
{
plugin = true,
name = "clean",
key = "x",
desc = "Delete this plugin. WARNING: this will delete the plugin even if it should be installed!",
---@class LazyViewState
---@field mode string
---@field plugin? {name:string, kind?: LazyPluginKind}
local default_state = {
mode = "home",
profile = {
threshold = 0,
sort_time_taken = false,
},
{ plugin = true, name = "check", key = "c", desc = "Check for updates for this plugin and show the log (git fetch)" },
{ plugin = true, name = "install", key = "i", desc = "Install this plugin" },
{ plugin = true, name = "log", key = "gl", desc = "Show recent updates for this plugin" },
{ plugin = true, name = "restore", key = "r", desc = "Restore this plugin to the state in the lockfile" },
}
---@type string?
M.mode = nil
---@class LazyView: LazyFloat
---@field render LazyRender
---@field state LazyViewState
local M = {}
function M.setup()
require("lazy.view.commands").setup()
require("lazy.view.colors").setup()
---@type LazyView
M.view = nil
function M.visible()
return M.view and M.view.win and vim.api.nvim_win_is_valid(M.view.win)
end
---@param mode? string
function M.show(mode)
M.mode = mode or M.mode
require("lazy.view.colors").setup()
if M._buf and vim.api.nvim_buf_is_valid(M._buf) then
vim.api.nvim_win_set_cursor(M._win, { 1, 0 })
vim.cmd([[do User LazyRender]])
if Config.headless() then
return
end
local buf = vim.api.nvim_create_buf(false, false)
M._buf = buf
local vpad = 6
local hpad = 20
local opts = {
relative = "editor",
style = "minimal",
width = math.min(vim.o.columns - hpad * 2, 200),
height = math.min(vim.o.lines - vpad * 2, 70),
}
opts.row = (vim.o.lines - opts.height) / 2
opts.col = (vim.o.columns - opts.width) / 2
local win = vim.api.nvim_open_win(buf, true, opts)
M._win = win
M.view = M.visible() and M.view or M.create()
if mode then
M.view.state.mode = mode
end
M.view:update()
end
vim.api.nvim_set_current_win(win)
---@param plugin LazyPlugin
function M:is_selected(plugin)
return vim.deep_equal(self.state.plugin, { name = plugin.name, kind = plugin._.kind })
end
vim.bo[buf].buftype = "nofile"
vim.bo[buf].bufhidden = "wipe"
vim.wo[win].conceallevel = 3
vim.wo[win].spell = false
vim.wo[win].wrap = true
vim.wo[win].winhighlight = "Normal:LazyNormal"
function M.create()
local self = setmetatable({}, { __index = setmetatable(M, { __index = Float }) })
---@cast self LazyView
Float.init(self, {
title = Config.options.ui.title,
title_pos = Config.options.ui.title_pos,
noautocmd = false,
})
local function close()
M._buf = nil
vim.diagnostic.reset(Config.ns, buf)
if vim.api.nvim_buf_is_valid(buf) then
vim.api.nvim_buf_delete(buf, {
force = true,
})
end
if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
if Config.options.ui.wrap then
Util.wo(self.win, "wrap", true)
Util.wo(self.win, "linebreak", true)
Util.wo(self.win, "breakindent", true)
else
Util.wo(self.win, "wrap", false)
end
vim.keymap.set("n", "q", close, {
nowait = true,
buffer = buf,
})
self.state = vim.deepcopy(default_state)
vim.api.nvim_create_autocmd({ "BufDelete", "BufLeave", "BufHidden" }, {
once = true,
buffer = buf,
callback = close,
})
local render = Render.new(buf, win, 2)
local update = Util.throttle(30, function()
if buf and vim.api.nvim_buf_is_valid(buf) then
vim.bo[buf].modifiable = true
render:update()
vim.bo[buf].modifiable = false
vim.cmd.redraw()
end
self.render = Render.new(self)
local update = self.update
self.update = Util.throttle(Config.options.ui.throttle, function()
update(self)
end)
local function get_plugin()
local pos = vim.api.nvim_win_get_cursor(win)
return render:get_plugin(pos[1])
for _, pattern in ipairs({ "LazyRender", "LazyFloatResized" }) do
self:on({ "User" }, function()
if not (self.buf and vim.api.nvim_buf_is_valid(self.buf)) then
return true
end
self:update()
end, { pattern = pattern })
end
vim.keymap.set("n", "<cr>", function()
local plugin = get_plugin()
if plugin then
if render._details == plugin.name then
render._details = nil
else
render._details = plugin.name
end
update()
end
end, {
nowait = true,
buffer = buf,
})
vim.keymap.set("n", ViewConfig.keys.abort, function()
require("lazy.manage.process").abort()
require("lazy.async").abort()
return ViewConfig.keys.abort
end, { silent = true, buffer = self.buf, expr = true, desc = "Abort" })
local function open(path)
local plugin = get_plugin()
vim.keymap.set("n", "gx", "K", { buffer = self.buf, remap = true })
-- plugin details
self:on_key(ViewConfig.keys.details, function()
local plugin = self.render:get_plugin()
if plugin then
local url = plugin.uri:gsub("%.git$", "")
if Util.file_exists(url) then
url = "https://github.com/" .. plugin[1]
local selected = {
name = plugin.name,
kind = plugin._.kind,
}
local open = not vim.deep_equal(self.state.plugin, selected)
if not open then
local row = self.render:get_row(selected)
if row then
vim.api.nvim_win_set_cursor(self.view.win, { row, 8 })
end
end
self.state.plugin = open and selected or nil
self:update()
end
end, "Details")
self:on_key(ViewConfig.keys.next, function()
local cursor = vim.api.nvim_win_get_cursor(self.view.win)
for l = 1, #self.render.locations, 1 do
local loc = self.render.locations[l]
if loc.from > cursor[1] then
vim.api.nvim_win_set_cursor(self.view.win, { loc.from, 8 })
return
end
end
end, "Next Plugin")
self:on_key(ViewConfig.keys.prev, function()
local cursor = vim.api.nvim_win_get_cursor(self.view.win)
for l = #self.render.locations, 1, -1 do
local loc = self.render.locations[l]
if loc.from < cursor[1] then
vim.api.nvim_win_set_cursor(self.view.win, { loc.from, 8 })
return
end
end
end, "Prev Plugin")
self:on_key(ViewConfig.keys.profile_sort, function()
if self.state.mode == "profile" then
self.state.profile.sort_time_taken = not self.state.profile.sort_time_taken
self:update()
end
end, "Sort Profile")
self:on_key(ViewConfig.keys.profile_filter, function()
if self.state.mode == "profile" then
vim.ui.input({
prompt = "Enter time threshold in ms: ",
default = tostring(self.state.profile.threshold),
}, function(input)
if not input then
return
end
local num = input == "" and 0 or tonumber(input)
if not num then
Util.error("Please input a number")
else
self.state.profile.threshold = num
self:update()
end
end)
end
end, "Filter Profile")
for lhs, rhs in pairs(Config.options.ui.custom_keys) do
if rhs then
local handler = type(rhs) == "table" and rhs[1] or rhs
local desc = type(rhs) == "table" and rhs.desc or nil
self:on_key(lhs, function()
local plugin = self.render:get_plugin()
if plugin then
handler(plugin)
end
end, desc)
end
end
self:setup_patterns()
self:setup_modes()
return self
end
function M:update()
if self.buf and vim.api.nvim_buf_is_valid(self.buf) then
self.render:update()
vim.cmd.redraw()
end
end
function M:open_url(path)
local plugin = self.render:get_plugin()
if plugin then
if plugin.url then
local url = plugin.url:gsub("%.git$", "")
Util.open(url .. path)
else
Util.error("No url for " .. plugin.name)
end
end
end
M.keys(buf, {
["%s(" .. string.rep("[a-z0-9]", 7) .. ")%s"] = function(hash)
open("/commit/" .. hash)
end,
["%s(" .. string.rep("[a-z0-9]", 7) .. ")$"] = function(hash)
open("/commit/" .. hash)
end,
["^(" .. string.rep("[a-z0-9]", 7) .. ")%s"] = function(hash)
open("/commit/" .. hash)
function M:setup_patterns()
local commit_pattern = "%f[%w](" .. string.rep("[a-f0-9]", 7) .. ")%f[%W]"
self:on_pattern(ViewConfig.keys.hover, {
[commit_pattern] = function(hash)
self:diff({ commit = hash, browser = true })
end,
["#(%d+)"] = function(issue)
open("/issues/" .. issue)
self:open_url("/issues/" .. issue)
end,
["README.md"] = function()
local plugin = get_plugin()
Util.open(plugin.dir .. "/README.md")
local plugin = self.render:get_plugin()
if plugin then
Util.open(plugin.dir .. "/README.md")
end
end,
["|(%S-)|"] = function(h)
vim.cmd.help(h)
self:close()
end,
["(https?://%S+)"] = function(url)
Util.open(url)
end,
})
for _, m in ipairs(M.modes) do
vim.keymap.set("n", m.key, function()
local Commands = require("lazy.view.commands")
if m.plugin then
local plugin = get_plugin()
if plugin then
Commands.cmd(m.name, { plugin })
end
else
if M.mode == m.name and m.toggle then
M.mode = nil
return update()
end
Commands.cmd(m.name)
end
end, { buffer = buf })
end
vim.api.nvim_create_autocmd("User", {
pattern = "LazyRender",
callback = function()
if not vim.api.nvim_buf_is_valid(buf) then
return true
end
update()
}, self.hover, "Hover")
self:on_pattern(ViewConfig.keys.diff, {
[commit_pattern] = function(hash)
self:diff({ commit = hash })
end,
})
update()
}, self.diff, "Diff")
self:on_pattern(ViewConfig.commands.restore.key_plugin, {
[commit_pattern] = function(hash)
self:restore({ commit = hash })
end,
}, self.restore, "Restore")
end
---@param handlers table<string, fun(str:string)>
function M.keys(buf, handlers)
local function map(lhs)
vim.keymap.set("n", lhs, function()
local line = vim.api.nvim_get_current_line()
local pos = vim.api.nvim_win_get_cursor(0)
local col = pos[2] + 1
---@param opts? {commit:string}
function M:restore(opts)
opts = opts or {}
local Lockfile = require("lazy.manage.lock")
local Commands = require("lazy.view.commands")
local plugin = self.render:get_plugin()
if plugin then
if opts.commit then
Lockfile.get(plugin).commit = opts.commit
end
Commands.cmd("restore", { plugins = { plugin } })
end
end
for pattern, handler in pairs(handlers) do
local from = 1
local to, url
while from do
from, to, url = line:find(pattern, from)
if from and col >= from and col <= to then
return handler(url)
end
if from then
from = to + 1
end
function M:hover()
if self:diff({ browser = true, hover = true }) then
return
end
self:open_url("")
end
---@param opts? {commit?:string, browser:boolean, hover:boolean}
function M:diff(opts)
opts = opts or {}
local plugin = self.render:get_plugin()
if plugin then
local diff
if opts.commit then
diff = { commit = opts.commit }
elseif plugin._.updated then
diff = vim.deepcopy(plugin._.updated)
else
local info = assert(Git.info(plugin.dir))
local target = assert(Git.get_target(plugin))
diff = { from = info.commit, to = target.commit }
if opts.hover and diff.from == diff.to then
return
end
end
if not diff then
return
end
for k, v in pairs(diff) do
diff[k] = v:sub(1, 7)
end
if opts.browser then
Diff.handlers.browser(plugin, diff)
else
Diff.handlers[Config.options.diff.cmd](plugin, diff)
end
return true
end
end
--- will create a key mapping that can be used on certain patterns
---@param key string
---@param patterns table<string, fun(str:string)>
---@param fallback? fun(self)
---@param desc? string
function M:on_pattern(key, patterns, fallback, desc)
self:on_key(key, function()
local line = vim.api.nvim_get_current_line()
local pos = vim.api.nvim_win_get_cursor(0)
local col = pos[2] + 1
for pattern, handler in pairs(patterns) do
local from = 1
local to, url
while from do
from, to, url = line:find(pattern, from)
if from and col >= from and col <= to then
return handler(url)
end
if from then
from = to + 1
end
end
end, { buffer = buf, silent = true })
end
end
if fallback then
fallback(self)
end
end, desc)
end
map("K")
function M:setup_modes()
local Commands = require("lazy.view.commands")
for name, m in pairs(ViewConfig.commands) do
if m.key then
self:on_key(m.key, function()
if self.state.mode == name and m.toggle then
self.state.mode = "home"
return self:update()
end
Commands.cmd(name)
end, m.desc)
end
if m.key_plugin and name ~= "restore" then
self:on_key(m.key_plugin, function()
local esc = vim.api.nvim_replace_termcodes("<esc>", true, true, true)
vim.api.nvim_feedkeys(esc, "n", false)
local plugins = {}
if vim.api.nvim_get_mode().mode:lower() == "v" then
local f, t = vim.fn.line("."), vim.fn.line("v")
if f > t then
f, t = t, f
end
for i = f, t do
local plugin = self.render:get_plugin(i)
if plugin then
plugins[plugin.name] = plugin
end
end
plugins = vim.tbl_values(plugins)
else
plugins[1] = self.render:get_plugin()
end
if #plugins > 0 then
Commands.cmd(name, { plugins = plugins })
end
end, m.desc_plugin, { "n", "x" })
end
end
end
return M

View file

@ -1,40 +1,43 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
local Sections = require("lazy.view.sections")
local Handler = require("lazy.core.handler")
local Git = require("lazy.manage.git")
local Handler = require("lazy.core.handler")
local Keys = require("lazy.core.handler.keys")
local Plugin = require("lazy.core.plugin")
local Sections = require("lazy.view.sections")
local Util = require("lazy.util")
local ViewConfig = require("lazy.view.config")
local Text = require("lazy.view.text")
---@alias LazyDiagnostic {row: number, severity: number, message:string}
---@class Render:Text
---@field buf buffer
---@field win window
---@class LazyRender:Text
---@field view LazyView
---@field plugins LazyPlugin[]
---@field progress {total:number, done:number}
---@field _diagnostics LazyDiagnostic[]
---@field plugin_range table<string, {from: number, to: number}>
---@field _details? string
local M = setmetatable({}, {
__index = Text,
})
---@field locations {name:string, from: number, to: number, kind?: LazyPluginKind}[]
local M = {}
function M.new(buf, win, padding)
local self = setmetatable({}, { __index = M })
self.buf = buf
self.win = win
self.padding = padding or 0
---@return LazyRender
---@param view LazyView
function M.new(view)
---@type LazyRender
local self = setmetatable({}, { __index = setmetatable(M, { __index = Text }) })
self.view = view
self.padding = 2
self.wrap = view.win_opts.width
return self
end
function M:update()
self._lines = {}
self._diagnostics = {}
self.plugin_range = {}
self.locations = {}
self.plugins = vim.tbl_values(Config.plugins)
vim.list_extend(self.plugins, vim.tbl_values(Config.to_clean))
vim.list_extend(self.plugins, vim.tbl_values(Config.spec.disabled))
table.sort(self.plugins, function(a, b)
return a.name < b.name
end)
@ -48,19 +51,22 @@ function M:update()
if plugin._.tasks then
for _, task in ipairs(plugin._.tasks) do
self.progress.total = self.progress.total + 1
if not task:is_running() then
if not task:running() then
self.progress.done = self.progress.done + 1
end
end
end
end
local mode = self:title()
self:title()
local mode = self.view.state.mode
if mode == "help" then
self:help()
elseif mode == "profile" then
self:profile()
elseif mode == "debug" then
self:debug()
else
for _, section in ipairs(Sections) do
self:section(section)
@ -68,76 +74,179 @@ function M:update()
end
self:trim()
self:render(self.buf)
vim.bo[self.view.buf].modifiable = true
local view = vim.api.nvim_win_call(self.view.win, vim.fn.winsaveview)
self:render(self.view.buf)
vim.api.nvim_win_call(self.view.win, function()
vim.fn.winrestview(view)
end)
vim.bo[self.view.buf].modifiable = false
vim.diagnostic.set(
Config.ns,
self.buf,
self.view.buf,
---@param diag LazyDiagnostic
vim.tbl_map(function(diag)
diag.col = 0
diag.lnum = diag.row - 1
return diag
end, self._diagnostics),
{ signs = false }
{ signs = false, virtual_text = true, underline = false, virtual_lines = false }
)
end
---@param row number
---@param row? number
---@return LazyPlugin?
function M:get_plugin(row)
for name, range in pairs(self.plugin_range) do
if row >= range.from and row <= range.to then
return Config.plugins[name]
if not (self.view.win and vim.api.nvim_win_is_valid(self.view.win)) then
return
end
row = row or vim.api.nvim_win_get_cursor(self.view.win)[1]
for _, loc in ipairs(self.locations) do
if row >= loc.from and row <= loc.to then
if loc.kind == "clean" then
for _, plugin in ipairs(Config.to_clean) do
if plugin.name == loc.name then
return plugin
end
end
elseif loc.kind == "disabled" then
return Config.spec.disabled[loc.name]
else
return Config.plugins[loc.name]
end
end
end
end
---@param selected {name:string, kind?: LazyPluginKind}
function M:get_row(selected)
for _, loc in ipairs(self.locations) do
if loc.kind == selected.kind and loc.name == selected.name then
return loc.from
end
end
end
function M:title()
self:append(" lazy.nvim ", "LazyH1"):center():nl()
self:append("press "):append("<?>", "LazySpecial"):append(" for help"):center():nl()
self:append("https://github.com/folke/lazy.nvim", "LazyMuted"):center():nl()
local View = require("lazy.view")
for _, mode in ipairs(View.modes) do
if not mode.hide and not mode.plugin then
local title = " " .. mode.name:sub(1, 1):upper() .. mode.name:sub(2) .. " (" .. mode.key .. ") "
self:append(title, View.mode == mode.name and "LazyButtonActive" or "LazyButton"):append(" ")
end
end
self:nl()
local modes = vim.tbl_filter(function(c)
return c.button
end, ViewConfig.get_commands())
if Config.options.ui.pills then
self:nl()
for c, mode in ipairs(modes) do
local title = " " .. mode.name:sub(1, 1):upper() .. mode.name:sub(2) .. " (" .. mode.key .. ") "
if mode.name == "home" then
if self.view.state.mode == "home" then
title = " lazy.nvim " .. Config.options.ui.icons.lazy
end
end
if self.view.state.mode == mode.name then
if mode.name == "home" then
self:append(title, "LazyH1", { wrap = true })
else
self:append(title, "LazyButtonActive", { wrap = true })
self:highlight({ ["%(.%)"] = "LazySpecial" })
end
else
self:append(title, "LazyButton", { wrap = true })
self:highlight({ ["%(.%)"] = "LazySpecial" })
end
if c == #modes then
break
end
self:append(" ")
end
self:nl()
end
if self.progress.done < self.progress.total then
self:progressbar()
end
self:nl()
if View.mode ~= "help" and View.mode ~= "profile" then
if self.view.state.mode ~= "help" and self.view.state.mode ~= "profile" and self.view.state.mode ~= "debug" then
if self.progress.done < self.progress.total then
self:append("Tasks: ", "LazyH2")
self:append(self.progress.done .. "/" .. self.progress.total, "LazyMuted")
self:append(self.progress.done .. "/" .. self.progress.total, "LazyComment")
else
self:append("Total: ", "LazyH2")
self:append(#self.plugins .. " plugins", "LazyMuted")
self:append(#self.plugins .. " plugins", "LazyComment")
end
self:nl():nl()
end
return View.mode
end
function M:help()
local View = require("lazy.view")
self:append("Help", "LazyH2"):nl():nl()
self:append("Use "):append(ViewConfig.keys.abort, "LazySpecial"):append(" to abort all running tasks."):nl():nl()
self:append("You can press "):append("<CR>", "LazySpecial"):append(" on a plugin to show its details."):nl():nl()
self:append("Most properties can be hovered with ")
self:append("<K>", "LazySpecial")
self:append(" to open links, help files, readmes and git commits."):nl()
self
:append("When hovering with ")
:append("<K>", "LazySpecial")
:append(" on a plugin anywhere else, a diff will be opened if there are updates")
:nl()
self:append("or the plugin was just updated. Otherwise the plugin webpage will open."):nl():nl()
self:append("Use "):append("<d>", "LazySpecial"):append(" on a commit or plugin to open the diff view"):nl():nl()
self
:append("Use ")
:append("<]]>", "LazySpecial")
:append(" and ")
:append("<[[>", "LazySpecial")
:append(" to navigate between plugins")
:nl()
:nl()
self:nl()
self:append("Keyboard Shortcuts", "LazyH2"):nl()
for _, mode in ipairs(View.modes) do
local title = mode.name:sub(1, 1):upper() .. mode.name:sub(2)
self:append("- ", "LazySpecial", { indent = 2 })
self:append(title, "Title"):append(" <" .. mode.key .. "> ", "LazyKey")
self:append(mode.desc or ""):nl()
for _, mode in ipairs(ViewConfig.get_commands()) do
if mode.key then
local title = mode.name:sub(1, 1):upper() .. mode.name:sub(2)
self:append("- ", "LazySpecial", { indent = 2 })
self:append(title, "Title")
if mode.key then
self:append(" <" .. mode.key .. ">", "LazyProp")
end
self:append(" " .. (mode.desc or "")):nl()
end
end
self:nl():append("Keyboard Shortcuts for Plugins", "LazyH2"):nl()
for _, mode in ipairs(ViewConfig.get_commands()) do
if mode.key_plugin then
local title = mode.name:sub(1, 1):upper() .. mode.name:sub(2)
self:append("- ", "LazySpecial", { indent = 2 })
self:append(title, "Title")
if mode.key_plugin then
self:append(" <" .. mode.key_plugin .. ">", "LazyProp")
end
self:append(" " .. (mode.desc_plugin or mode.desc)):nl()
end
end
for lhs, rhs in pairs(Config.options.ui.custom_keys) do
if type(rhs) == "table" and rhs.desc then
self:append("- ", "LazySpecial", { indent = 2 })
self:append("Custom key ", "Title")
self:append(lhs, "LazyProp")
self:append(" " .. rhs.desc):nl()
end
end
end
function M:progressbar()
local width = vim.api.nvim_win_get_width(self.win) - 2 * self.padding
local width = vim.api.nvim_win_get_width(self.view.win) - 2 * self.padding
local done = math.floor((self.progress.done / self.progress.total) * width + 0.5)
if self.progress.done == self.progress.total then
done = 0
@ -166,8 +275,11 @@ function M:section(section)
end, self.plugins)
local count = #section_plugins
table.sort(section_plugins, function(a, b)
return a.name:lower() < b.name:lower()
end)
if count > 0 then
self:append(section.title, "LazyH2"):append(" (" .. count .. ")", "LazyMuted"):nl()
self:append(section.title, "LazyH2"):append(" (" .. count .. ")", "LazyComment"):nl()
for _, plugin in ipairs(section_plugins) do
self:plugin(plugin)
end
@ -182,6 +294,13 @@ function M:diagnostic(diag)
table.insert(self._diagnostics, diag)
end
---@param precision? number
function M:ms(nsec, precision)
precision = precision or 2
local e = math.pow(10, precision)
return math.floor(nsec / 1e6 * e + 0.5) / e .. "ms"
end
---@param reason? {[string]:string, time:number}
---@param opts? {time_right?:boolean}
function M:reason(reason, opts)
@ -193,89 +312,129 @@ function M:reason(reason, opts)
---@type string?
local source = reason.source
if source then
---@type string?
local modname = source:match("/lua/(.*)%.lua$")
if modname then
modname = modname:gsub("/", ".")
end
local name = source:match("/([^/]-)/lua")
for _, other in pairs(Config.plugins) do
if (modname and other.modname == modname) or (name and other.name == name) then
reason.plugin = other.name
reason.source = nil
break
end
end
if reason.source then
reason.source = modname or reason.source
if reason.source == "lua" then
reason.source = Config.options.plugins
source = Util.norm(source)
local plugin = Plugin.find(source)
if plugin then
reason.plugin = plugin.name
reason.source = nil
else
local config = Util.norm(vim.fn.stdpath("config"))
if source == config .. "/init.lua" then
reason.source = "init.lua"
else
config = config .. "/lua"
if source:find(config, 1, true) == 1 then
reason.source = source:sub(#config + 2):gsub("/", "."):gsub("%.lua$", "")
end
end
end
end
local time = " " .. math.floor((reason.time or 0) / 1e6 * 100) / 100 .. "ms"
if not opts.time_right then
if reason.runtime then
reason.runtime = Util.norm(reason.runtime)
reason.runtime = reason.runtime:gsub(".*/([^/]+/plugin/.*)", "%1")
reason.runtime = reason.runtime:gsub(".*/([^/]+/after/.*)", "%1")
reason.runtime = reason.runtime:gsub(".*/([^/]+/ftdetect/.*)", "%1")
reason.runtime = reason.runtime:gsub(".*/(runtime/.*)", "%1")
end
local time = reason.time and (" " .. self:ms(reason.time))
if time and not opts.time_right then
self:append(time, "Bold")
self:append(" ")
end
self:append(" ")
-- self:append(" (", "Conceal")
local first = true
for key, value in pairs(reason) do
if type(key) == "number" then
elseif key == "require" then
-- self:append("require", "@function.builtin")
-- self:append("(", "@punctuation.bracket")
-- self:append('"' .. value .. '"', "@string")
-- self:append(")", "@punctuation.bracket")
elseif key ~= "time" then
local keys = vim.tbl_keys(reason)
table.sort(keys)
if vim.tbl_contains(keys, "plugin") then
keys = vim.tbl_filter(function(key)
return key ~= "plugin"
end, keys)
table.insert(keys, "plugin")
end
for _, key in ipairs(keys) do
local value = reason[key]
local skip = type(key) == "number" or key == "time"
if not skip then
if first then
first = false
else
self:append(" ")
end
if key == "event" then
value = value:match("User (.*)") or value
end
local hl = "LazyLoader" .. key:sub(1, 1):upper() .. key:sub(2)
local icon = Config.options.view.icons[key]
local hl = "LazyReason" .. key:sub(1, 1):upper() .. key:sub(2)
local icon = Config.options.ui.icons[key]
if icon then
icon = icon:gsub("%s*$", "")
self:append(icon .. " ", hl)
self:append(value, hl)
else
self:append(key .. " ", "@field")
self:append(key .. " ", hl)
self:append(value, hl)
end
end
end
if opts.time_right then
if time and opts.time_right then
self:append(time, "Bold")
end
-- self:append(")", "Conceal")
end
---@param plugin LazyPlugin
function M:diagnostics(plugin)
if plugin._.updated then
local skip = false
for _, task in ipairs(plugin._.tasks or {}) do
if task:running() then
self:diagnostic({
severity = vim.diagnostic.severity.WARN,
message = task.name .. (task:status() and (": " .. task:status()) or ""),
})
skip = true
elseif task:has_errors() then
self:diagnostic({
message = task.name .. " failed",
severity = vim.diagnostic.severity.ERROR,
})
skip = true
elseif task:has_warnings() then
self:diagnostic({
message = task.name .. " warning",
severity = vim.diagnostic.severity.WARN,
})
skip = true
end
end
if skip then
return
end
if plugin._.build then
self:diagnostic({
message = "needs build",
severity = vim.diagnostic.severity.WARN,
})
elseif plugin._.updated then
if plugin._.updated.from == plugin._.updated.to then
self:diagnostic({
message = "already up to date",
})
else
self:diagnostic({
message = "updated from " .. plugin._.updated.from:sub(1, 7) .. " to " .. plugin._.updated.to:sub(1, 7),
})
local version = Git.info(plugin.dir, true).version
if version then
self:diagnostic({
message = "updated to " .. tostring(version),
})
else
self:diagnostic({
message = "updated from " .. plugin._.updated.from:sub(1, 7) .. " to " .. plugin._.updated.to:sub(1, 7),
})
end
end
end
for _, task in ipairs(plugin._.tasks or {}) do
if task:is_running() then
elseif plugin._.updates then
local version = plugin._.updates.to.version
if version then
self:diagnostic({
severity = vim.diagnostic.severity.WARN,
message = task.name .. (task.status == "" and "" or (": " .. task.status)),
message = "version " .. tostring(version) .. " is available",
})
elseif task.error then
else
self:diagnostic({
message = task.name .. " failed",
severity = vim.diagnostic.severity.ERROR,
message = "updates available",
})
end
end
@ -283,43 +442,77 @@ end
---@param plugin LazyPlugin
function M:plugin(plugin)
local hl = plugin._.is_local and "LazyLocal" or "LazySpecial"
if plugin._.loaded then
self:append("", "LazySpecial"):append(plugin.name)
self:append(" " .. Config.options.ui.icons.loaded .. " ", hl):append(plugin.name)
elseif plugin._.cond == false then
self:append(" " .. Config.options.ui.icons.not_loaded .. " ", "LazyNoCond"):append(plugin.name)
else
self:append("", "LazySpecial"):append(plugin.name)
self:append(" " .. Config.options.ui.icons.not_loaded .. " ", hl):append(plugin.name)
end
local plugin_start = self:row()
if plugin._.loaded then
-- When the plugin is loaded, only show the loading reason
self:reason(plugin._.loaded)
else
-- otherwise show all lazy handlers
self:append(" ")
self:handlers(plugin)
for _, other in pairs(Config.plugins) do
if vim.tbl_contains(other.dependencies or {}, plugin.name) then
self:reason({ plugin = other.name })
self:append(" ")
end
end
end
self:diagnostics(plugin)
self:nl()
if self._details == plugin.name then
if self.view:is_selected(plugin) then
self:details(plugin)
end
self:tasks(plugin)
self.plugin_range[plugin.name] = { from = plugin_start, to = self:row() - 1 }
self.locations[#self.locations + 1] =
{ name = plugin.name, from = plugin_start, to = self:row() - 1, kind = plugin._.kind }
end
---@param str string
---@param hl? string|Extmark
---@param opts? {indent?: number, prefix?: string, wrap?: boolean}
function M:markdown(str, hl, opts)
local lines = vim.split(str, "\n")
for _, line in ipairs(lines) do
self:append(line, hl, opts):highlight({
["`.-`"] = "@markup.raw.markdown_inline",
["%*.-%*"] = "LazyItalic",
["%*%*.-%*%*"] = "LazyBold",
["^%s*-"] = "Special",
})
self:nl()
end
end
---@param plugin LazyPlugin
function M:tasks(plugin)
for _, task in ipairs(plugin._.tasks or {}) do
if self._details == plugin.name then
self:append("✔ [task] ", "Title", { indent = 4 }):append(task.name)
if self.view:is_selected(plugin) then
self:append(Config.options.ui.icons.task .. "[task] ", "Title", { indent = 4 }):append(task.name)
self:append(" " .. math.floor((task:time()) * 100) / 100 .. "ms", "Bold")
self:nl()
end
if task.name == "log" and not task.error then
if not task:has_warnings() and task.name == "log" then
self:log(task)
elseif task.error or self._details == plugin.name then
if task.error then
self:append(vim.trim(task.error), "LazyError", { indent = 4, prefix = "" })
self:nl()
end
if task.output ~= "" and task.output ~= task.error then
self:append(vim.trim(task.output), "MsgArea", { indent = 4, prefix = "" })
self:nl()
else
local hls = {
[vim.log.levels.ERROR] = "LazyError",
[vim.log.levels.WARN] = "LazyWarning",
[vim.log.levels.INFO] = "LazyInfo",
}
for _, msg in ipairs(task:get_log()) do
if task:has_warnings() or self.view:is_selected(plugin) then
self:markdown(msg.msg, hls[msg.level] or "LazyTaskOutput", { indent = 6 })
end
end
end
end
@ -327,24 +520,36 @@ end
---@param task LazyTask
function M:log(task)
local log = vim.trim(task.output)
local log = vim.trim(task:output())
if log ~= "" then
local lines = vim.split(log, "\n")
for _, line in ipairs(lines) do
local ref, msg, time = line:match("^(%w+) (.*) (%(.*%))$")
if msg:find("^%S+!:") then
self:diagnostic({ message = "Breaking Changes", severity = vim.diagnostic.severity.WARN })
if msg then
if msg:find("^%S+!:") then
self:diagnostic({ message = "Breaking Changes", severity = vim.diagnostic.severity.WARN })
end
self:append(ref:sub(1, 7) .. " ", "LazyCommit", { indent = 6 })
local dimmed = false
for _, dim in ipairs(ViewConfig.dimmed_commits) do
if msg:find("^" .. dim) then
dimmed = true
end
end
self:append(vim.trim(msg), dimmed and "LazyDimmed" or nil):highlight({
["#%d+"] = "LazyCommitIssue",
["^%S+:"] = dimmed and "Bold" or "LazyCommitType",
["^%S+(%(.*%))!?:"] = "LazyCommitScope",
["`.-`"] = "@markup.raw.markdown_inline",
["%*.-%*"] = "Italic",
["%*%*.-%*%*"] = "Bold",
})
self:append(" " .. time, "LazyComment")
self:nl()
-- else
-- self:append(line, "LazyTaskOutput", { indent = 6 }):nl()
end
self:append(ref .. " ", "LazyCommit", { indent = 6 })
self:append(vim.trim(msg)):highlight({
["#%d+"] = "Number",
["^%S+:"] = "Title",
["^%S+(%(.*%)):"] = "Italic",
["`.-`"] = "@text.literal.markdown_inline",
})
-- string.gsub
self:append(" " .. time, "Comment")
self:nl()
end
self:nl()
end
@ -354,9 +559,13 @@ end
function M:details(plugin)
---@type string[][]
local props = {}
table.insert(props, { "uri", (plugin.uri:gsub("%.git$", "")), "@text.reference" })
table.insert(props, { "dir", plugin.dir, "LazyDir" })
if plugin.url then
table.insert(props, { "url", (plugin.url:gsub("%.git$", "")), "LazyUrl" })
end
local git = Git.info(plugin.dir, true)
if git then
git.branch = git.branch or Git.get_branch(plugin)
if git.version then
table.insert(props, { "version", tostring(git.version) })
end
@ -366,60 +575,225 @@ function M:details(plugin)
if git.branch then
table.insert(props, { "branch", git.branch })
end
table.insert(props, { "commit", git.commit:sub(1, 7), "LazyCommit" })
if git.commit then
table.insert(props, { "commit", git.commit:sub(1, 7), "LazyCommit" })
end
end
local rocks = require("lazy.pkg.rockspec").deps(plugin)
if rocks then
table.insert(props, { "rocks", vim.inspect(rocks) })
end
if Util.file_exists(plugin.dir .. "/README.md") then
table.insert(props, { "readme", "README.md" })
end
Util.ls(plugin.dir .. "/doc", function(path, name)
if name:sub(-3) == "txt" then
local data = Util.read_file(path)
local tag = data:match("%*(%S-)%*")
if tag then
table.insert(props, { "help", "|" .. tag .. "|" })
end
end
end)
for handler in pairs(Handler.handlers) do
if plugin[handler] then
table.insert(props, {
handler,
type(plugin[handler]) == "string" and plugin[handler] or table.concat(plugin[handler], ", "),
"@string",
})
for handler in pairs(plugin._.handlers or {}) do
table.insert(props, {
handler,
function()
self:handlers(plugin, handler)
end,
})
end
self:props(props, { indent = 6 })
self:nl()
end
---@param plugin LazyPlugin
---@param types? LazyHandlerTypes[]|LazyHandlerTypes
function M:handlers(plugin, types)
if not plugin._.handlers then
return
end
types = type(types) == "string" and { types } or types
types = types and types or vim.tbl_keys(Handler.types)
for _, t in ipairs(types) do
for id, value in pairs(plugin._.handlers[t] or {}) do
value = t == "keys" and Keys.to_string(value) or id
self:reason({ [t] = value })
self:append(" ")
end
end
end
---@alias LazyProps {[1]:string, [2]:string|fun(), [3]?:string}[]
---@param props LazyProps
---@param opts? {indent: number}
function M:props(props, opts)
opts = opts or {}
local width = 0
for _, prop in ipairs(props) do
width = math.max(width, #prop[1])
end
for _, prop in ipairs(props) do
self:append(prop[1] .. string.rep(" ", width - #prop[1] + 1), "LazyKey", { indent = 6 })
self:append(prop[2], prop[3] or "LazyValue")
self:append(prop[1] .. string.rep(" ", width - #prop[1] + 1), "LazyProp", { indent = opts.indent or 0 })
if type(prop[2]) == "function" then
prop[2]()
else
self:append(tostring(prop[2]), prop[3] or "LazyValue")
end
self:nl()
end
self:nl()
end
function M:profile()
local stats = require("lazy.stats").stats()
local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
self:append("Startuptime: ", "LazyH2"):append(ms .. "ms", "Number"):nl():nl()
if stats.real_cputime then
self:append("Based on the actual CPU time of the Neovim process till "):append("UIEnter", "LazySpecial")
self:append("."):nl()
self:append("This is more accurate than ")
self:append("`nvim --startuptime`", "@markup.raw.markdown_inline")
self:append(".")
else
self:append("An accurate startuptime based on the actual CPU time of the Neovim process is not available."):nl()
self
:append("Startuptime is instead based on a delta with a timestamp when lazy started till ")
:append("UIEnter", "LazySpecial")
self:append(".")
end
self:nl()
local times = {}
for event, time in pairs(require("lazy.stats").stats().times) do
times[#times + 1] = { event, self:ms(time * 1e6), "Bold", time = time }
end
table.sort(times, function(a, b)
return a.time < b.time
end)
for p, prop in ipairs(times) do
if p > 1 then
prop[2] = prop[2] .. " (+" .. self:ms((prop.time - times[p - 1].time) * 1e6) .. ")"
end
end
self:props(times, { indent = 2 })
self:nl()
self:append("Profile", "LazyH2"):nl():nl()
local symbols = {
"",
"",
"",
"",
}
self
:append("You can press ")
:append(ViewConfig.keys.profile_sort, "LazySpecial")
:append(" to change sorting between chronological order & time taken.")
:nl()
self
:append("Press ")
:append(ViewConfig.keys.profile_filter, "LazySpecial")
:append(" to filter profiling entries that took more time than a given threshold")
:nl()
self:nl()
---@param a LazyProfile
---@param b LazyProfile
local function sort(a, b)
return a.time > b.time
end
---@param entry LazyProfile
local function get_children(entry)
---@type LazyProfile[]
local children = entry
if self.view.state.profile.sort_time_taken then
children = {}
for _, child in ipairs(entry) do
children[#children + 1] = child
end
table.sort(children, sort)
end
return children
end
---@param entry LazyProfile
local function _profile(entry, depth)
if entry.time / 1e6 < self.view.state.profile.threshold then
return
end
local data = type(entry.data) == "string" and { source = entry.data } or entry.data
data.time = entry.time
local symbol = symbols[depth] or symbols[#symbols]
self:append((" "):rep(depth)):append(" " .. symbol, "LazySpecial")
local symbol = M.list_icon(depth)
self:append((" "):rep(depth)):append(symbol, "LazySpecial"):append(" ")
self:reason(data, { time_right = true })
self:nl()
for _, child in ipairs(entry) do
for _, child in ipairs(get_children(entry)) do
_profile(child, depth + 1)
end
end
for _, entry in ipairs(Util._profiles[1]) do
for _, entry in ipairs(get_children(Util._profiles[1])) do
_profile(entry, 1)
end
end
function M.list_icon(depth)
local symbols = Config.options.ui.icons.list
return symbols[(depth - 1) % #symbols + 1]
end
function M:debug()
self:append("Active Handlers", "LazyH2"):nl()
self
:append(
"This shows only the lazy handlers that are still active. When a plugin loads, its handlers are removed",
"LazyComment",
{ indent = 2 }
)
:nl()
Util.foreach(require("lazy.core.handler").handlers, function(handler_type, handler)
Util.foreach(handler.active, function(value, plugins)
if not vim.tbl_isempty(plugins) then
---@type string[]
plugins = vim.tbl_values(plugins)
table.sort(plugins)
self:append(Config.options.ui.icons.debug, "LazySpecial", { indent = 2 })
if handler_type == "keys" then
for k, v in pairs(Config.plugins[plugins[1]]._.handlers.keys) do
if k == value then
value = Keys.to_string(v)
break
end
end
end
self:reason({ [handler_type] = value })
for _, plugin in pairs(plugins) do
self:append(" ")
self:reason({ plugin = plugin })
end
self:nl()
end
end)
end)
self:nl()
Util.foreach(require("lazy.core.cache")._inspect(), function(name, stats)
self:append(name, "LazyH2"):nl()
local props = {
{ "total", stats.total or 0, "Number" },
{ "time", self:ms(stats.time or 0, 3), "Bold" },
{ "avg time", self:ms((stats.time or 0) / (stats.total or 0), 3), "Bold" },
}
for k, v in pairs(stats) do
if k ~= "total" and k ~= "time" then
props[#props + 1] = { k, v, "Number" }
end
end
self:props(props, { indent = 2 })
self:nl()
end)
end
return M

View file

@ -17,27 +17,35 @@ return {
{
filter = function(plugin)
return has_task(plugin, function(task)
return task.error ~= nil
return task:has_errors()
end)
end,
title = "Failed",
},
{
filter = function(plugin)
if plugin._.working then
return true
end
return has_task(plugin, function(task)
return task:is_running()
return task:running()
end)
end,
title = "Working",
},
{
filter = function(plugin)
return plugin._.build
end,
title = "Build",
},
{
filter = function(plugin)
return has_task(plugin, function(task)
if task.name ~= "log" then
return
end
local lines = vim.split(task.output, "\n")
for _, line in ipairs(lines) do
for _, line in ipairs(vim.split(task:output(), "\n")) do
if line:find("^%w+ %S+!:") then
return true
end
@ -47,42 +55,53 @@ return {
title = "Breaking Changes",
},
{
---@param plugin LazyPlugin
filter = function(plugin)
return plugin._.updated and plugin._.updated.from ~= plugin._.updated.to
end,
title = "Updated",
},
{
---@param plugin LazyPlugin
filter = function(plugin)
return plugin._.cloned
end,
title = "Installed",
},
{
---@param plugin LazyPlugin
filter = function(plugin)
return plugin._.updates ~= nil
end,
title = "Updates",
},
{
filter = function(plugin)
return has_task(plugin, function(task)
return task.name == "log" and vim.trim(task.output) ~= ""
return task.name == "log" and vim.trim(task:output()) ~= ""
end)
end,
title = "Log",
},
{
filter = function(plugin)
return plugin._.installed and not plugin.uri
return plugin._.kind == "clean" and plugin._.installed
end,
title = "Clean",
},
{
filter = function(plugin)
return not plugin._.installed
return not plugin._.installed and plugin._.kind ~= "disabled"
end,
title = "Not Installed",
},
{
filter = function(plugin)
return plugin._.loaded
return plugin._.outdated
end,
title = "Outdated",
},
{
filter = function(plugin)
return plugin._.loaded ~= nil
end,
title = "Loaded",
},
@ -90,6 +109,12 @@ return {
filter = function(plugin)
return plugin._.installed
end,
title = "Installed",
title = "Not Loaded",
},
{
filter = function(plugin)
return plugin._.kind == "disabled"
end,
title = "Disabled",
},
}

View file

@ -1,4 +1,5 @@
local Config = require("lazy.core.config")
local Util = require("lazy.util")
---@alias TextSegment {str: string, hl?:string|Extmark}
---@alias Extmark {hl_group?:string, col?:number, end_col?:number}
@ -6,12 +7,11 @@ local Config = require("lazy.core.config")
---@class Text
---@field _lines TextSegment[][]
---@field padding number
---@field wrap number
local Text = {}
function Text.new()
local self = setmetatable({}, {
__index = Text,
})
local self = setmetatable({}, { __index = Text })
self._lines = {}
return self
@ -19,7 +19,7 @@ end
---@param str string
---@param hl? string|Extmark
---@param opts? {indent?: number, prefix?: string}
---@param opts? {indent?: number, prefix?: string, wrap?: boolean}
function Text:append(str, hl, opts)
opts = opts or {}
if #self._lines == 0 then
@ -37,6 +37,15 @@ function Text:append(str, hl, opts)
if l > 1 then
self:nl()
end
if
Config.options.ui.wrap
and opts.wrap
and str ~= ""
and self:col() > 0
and self:col() + vim.fn.strwidth(line) + self.padding > self.wrap
then
self:nl()
end
table.insert(self._lines[#self._lines], {
str = line,
hl = hl,
@ -56,35 +65,51 @@ function Text:render(buf)
for _, line in ipairs(self._lines) do
local str = (" "):rep(self.padding)
local has_extmark = false
for _, segment in ipairs(line) do
str = str .. segment.str
if type(segment.hl) == "table" then
has_extmark = true
end
end
if str:match("^%s*$") and not has_extmark then
str = ""
end
table.insert(lines, str)
end
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
vim.api.nvim_buf_clear_namespace(buf, Config.ns, 0, -1)
for l, line in ipairs(self._lines) do
local col = self.padding
if lines[l] ~= "" then
local col = self.padding
for _, segment in ipairs(line) do
local width = vim.fn.strlen(segment.str)
for _, segment in ipairs(line) do
local width = vim.fn.strlen(segment.str)
local extmark = segment.hl
if extmark then
if type(extmark) == "string" then
extmark = { hl_group = extmark, end_col = col + width }
local extmark = segment.hl
if extmark then
if type(extmark) == "string" then
extmark = { hl_group = extmark, end_col = col + width }
end
---@cast extmark Extmark
local extmark_col = extmark.col or col
extmark.col = nil
local ok, err = pcall(vim.api.nvim_buf_set_extmark, buf, Config.ns, l - 1, extmark_col, extmark)
if not ok then
Util.error(
"Failed to set extmark. Please report a bug with this info:\n"
.. vim.inspect({ segment = segment, line = line, error = err })
)
end
end
---@cast extmark Extmark
local extmark_col = extmark.col or col
extmark.col = nil
vim.api.nvim_buf_set_extmark(buf, Config.ns, l - 1, extmark_col, extmark)
col = col + width
end
col = col + width
end
end
end
@ -120,27 +145,7 @@ function Text:highlight(patterns)
end
end
function Text:center()
local last = self._lines[#self._lines]
if not last then
return
end
local width = 0
for _, segment in ipairs(last) do
width = width + vim.fn.strwidth(segment.str)
end
width = vim.api.nvim_win_get_width(self.win) - 2 * self.padding - width
table.insert(last, 1, {
str = string.rep(" ", math.floor(width / 2 + 0.5)),
})
return self
end
function Text:trim()
while #self._lines > 0 and #self._lines[1] == 0 do
table.remove(self._lines, 1)
end
while #self._lines > 0 and #self._lines[#self._lines] == 0 do
table.remove(self._lines)
end

116407
manifest Normal file

File diff suppressed because it is too large Load diff

3
scripts/test Executable file
View file

@ -0,0 +1,3 @@
#!/bin/env bash
nvim -l tests/minit.lua --minitest

4
selene.toml Normal file
View file

@ -0,0 +1,4 @@
std="vim"
[lints]
mixed_table="allow"

View file

@ -1,3 +1,6 @@
indent_type = "Spaces"
indent_width = 2
column_width = 120
column_width = 120
[sort_requires]
enabled = true

10
tests/core/init_spec.lua Normal file
View file

@ -0,0 +1,10 @@
local Util = require("lazy.core.util")
describe("init", function()
it("has correct environment for tests", function()
for _, name in ipairs({ "config", "data", "cache", "state" }) do
local path = Util.norm(vim.fn.stdpath(name) --[[@as string]])
assert(path:find(".tests/" .. name, 1, true), path .. " not in .tests")
end
end)
end)

View file

@ -1,102 +1,526 @@
local Config = require("lazy.core.config")
local Handler = require("lazy.core.handler")
local Plugin = require("lazy.core.plugin")
local assert = require("luassert")
local function inspect(obj)
return vim.inspect(obj):gsub("%s+", " ")
end
Config.setup()
---@param plugin LazyPlugin
local function resolve(plugin)
local meta = getmetatable(plugin)
local ret = meta and type(meta.__index) == "table" and resolve(meta.__index) or {}
for k, v in pairs(plugin) do
ret[k] = v
end
return ret
end
describe("plugin spec uri/name", function()
---@param plugins LazyPlugin[]
local function clean(plugins)
return vim.tbl_map(function(plugin)
plugin = resolve(plugin)
plugin[1] = nil
plugin._.frags = nil
if plugin._.dep == false then
plugin._.dep = nil
end
plugin._.top = nil
return plugin
end, plugins)
end
describe("plugin spec url/name", function()
local tests = {
{ { "~/foo" }, { [1] = "~/foo", name = "foo", uri = vim.fn.fnamemodify("~/foo", ":p") } },
{ { "/tmp/foo" }, { [1] = "/tmp/foo", name = "foo", uri = "/tmp/foo" } },
{ { "foo/bar" }, { [1] = "foo/bar", name = "bar", uri = "https://github.com/foo/bar.git" } },
{ { "foo/bar", name = "foobar" }, { [1] = "foo/bar", name = "foobar", uri = "https://github.com/foo/bar.git" } },
{ { "foo/bar", uri = "123" }, { [1] = "foo/bar", name = "bar", uri = "123" } },
{ { "https://foobar" }, { [1] = "https://foobar", name = "foobar", uri = "https://foobar" } },
{ { "ssh://foobar" }, { [1] = "ssh://foobar", name = "foobar", uri = "ssh://foobar" } },
{ "foo/bar", { [1] = "foo/bar", name = "bar", uri = "https://github.com/foo/bar.git" } },
{ { { { "foo/bar" } } }, { [1] = "foo/bar", name = "bar", uri = "https://github.com/foo/bar.git" } },
{ { dir = "~/foo" }, { name = "foo", dir = vim.fn.fnamemodify("~/foo", ":p") } },
{ { dir = "/tmp/foo" }, { dir = "/tmp/foo", name = "foo" } },
{ { "foo/bar" }, { [1] = "foo/bar", name = "bar", url = "https://github.com/foo/bar.git" } },
{ { "https://foo.bar" }, { [1] = "https://foo.bar", name = "foo.bar", url = "https://foo.bar" } },
{ { "foo/bar", name = "foobar" }, { [1] = "foo/bar", name = "foobar", url = "https://github.com/foo/bar.git" } },
{ { "foo/bar", url = "123" }, { [1] = "foo/bar", name = "bar", url = "123" } },
{ { url = "https://foobar" }, { name = "foobar", url = "https://foobar" } },
{
{ { url = "https://foo", name = "foobar" }, { url = "https://foo" } },
{ name = "foobar", url = "https://foo" },
},
{
{ { url = "https://foo" }, { url = "https://foo", name = "foobar" } },
{ name = "foobar", url = "https://foo" },
},
{ { url = "ssh://foobar" }, { name = "foobar", url = "ssh://foobar" } },
{ "foo/bar", { [1] = "foo/bar", name = "bar", url = "https://github.com/foo/bar.git" } },
{ { { { "foo/bar" } } }, { [1] = "foo/bar", name = "bar", url = "https://github.com/foo/bar.git" } },
}
for _, test in ipairs(tests) do
it("parses " .. vim.inspect(test[1]):gsub("%s+", " "), function()
test[2]._ = {}
it("parses " .. inspect(test[1]), function()
if not test[2].dir then
test[2].dir = Config.options.root .. "/" .. test[2].name
end
local spec = Plugin.Spec.new(test[1])
local plugins = vim.tbl_values(spec.plugins)
assert.equal(1, #plugins)
local all = vim.deepcopy(spec.plugins)
local plugins = vim.tbl_values(all)
plugins = vim.tbl_map(function(plugin)
plugin._ = {}
return plugin
end, plugins)
local notifs = vim.tbl_filter(function(notif)
return notif.level > 3
end, spec.notifs)
assert(#notifs == 0, vim.inspect(spec.notifs))
assert.equal(1, #plugins, vim.inspect(all))
plugins[1]._.super = nil
assert.same(test[2], plugins[1])
end)
end
end)
describe("plugin spec dir", function()
local tests = {
{
"~/projects/gitsigns.nvim",
{ "lewis6991/gitsigns.nvim", opts = {}, dev = true },
{ "lewis6991/gitsigns.nvim" },
},
{
"~/projects/gitsigns.nvim",
{ "lewis6991/gitsigns.nvim", opts = {}, dev = true },
{ "gitsigns.nvim" },
},
{
"~/projects/gitsigns.nvim",
{ "lewis6991/gitsigns.nvim", opts = {} },
{ "lewis6991/gitsigns.nvim", dev = true },
},
{
"~/projects/gitsigns.nvim",
{ "lewis6991/gitsigns.nvim", opts = {} },
{ "gitsigns.nvim", dev = true },
},
}
for _, test in ipairs(tests) do
local dir = vim.fn.expand(test[1])
local input = vim.list_slice(test, 2)
it("parses dir " .. inspect(input), function()
local spec = Plugin.Spec.new(input)
local plugins = vim.tbl_values(spec.plugins)
assert(spec:report() == 0)
assert.equal(1, #plugins)
assert.same(dir, plugins[1].dir)
end)
end
end)
describe("plugin dev", function()
local tests = {
{
{ "lewis6991/gitsigns.nvim", opts = {}, dev = true },
{ "lewis6991/gitsigns.nvim" },
},
{
{ "lewis6991/gitsigns.nvim", opts = {}, dev = true },
{ "gitsigns.nvim" },
},
{
{ "lewis6991/gitsigns.nvim", opts = {} },
{ "lewis6991/gitsigns.nvim", dev = true },
},
{
{ "lewis6991/gitsigns.nvim", opts = {} },
{ "gitsigns.nvim", dev = true },
},
}
for _, test in ipairs(tests) do
local dir = vim.fn.expand("~/projects/gitsigns.nvim")
local input = test
it("parses dir " .. inspect(input), function()
local spec = Plugin.Spec.new(input)
local plugins = vim.tbl_values(spec.plugins)
assert(spec:report() == 0)
assert.equal(1, #plugins)
assert.same(dir, plugins[1].dir)
end)
end
end)
describe("plugin spec opt", function()
it("handles dependencies", function()
Config.options.opt = false
Config.options.defaults.lazy = false
local tests = {
{ "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } },
{ "foo/bar", dependencies = { { "foo/dep1" }, "foo/dep2" } },
{ { { "foo/bar", dependencies = { { "foo/dep1" }, "foo/dep2" } } } },
}
for _, test in ipairs(tests) do
local spec = Plugin.Spec.new(test)
Plugin.update_state({ plugins = spec.plugins })
local spec = Plugin.Spec.new(vim.deepcopy(test))
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Config.spec = spec
Plugin.update_state()
assert(vim.tbl_count(spec.plugins) == 3)
assert(#spec.plugins.bar.dependencies == 2)
assert(spec.plugins.bar.dep ~= true)
assert(spec.plugins.bar.opt == false)
assert(spec.plugins.dep1.dep == true)
assert(spec.plugins.dep1.opt == true)
assert(spec.plugins.dep2.dep == true)
assert(spec.plugins.dep2.opt == true)
assert(spec.plugins.bar._.dep ~= true)
assert(spec.plugins.bar.lazy == false)
assert(spec.plugins.dep1._.dep == true)
assert(spec.plugins.dep1.lazy == true)
assert(spec.plugins.dep2._.dep == true)
assert(spec.plugins.dep2.lazy == true)
spec = Plugin.Spec.new(test)
for _, plugin in pairs(spec.plugins) do
plugin.dir = nil
end
assert.same({
bar = {
_ = {},
dependencies = { "dep1", "dep2" },
name = "bar",
url = "https://github.com/foo/bar.git",
},
dep1 = {
_ = {
dep = true,
},
name = "dep1",
url = "https://github.com/foo/dep1.git",
},
dep2 = {
_ = {
dep = true,
},
name = "dep2",
url = "https://github.com/foo/dep2.git",
},
}, clean(spec.plugins))
end
end)
describe("deps", function()
before_each(function()
Handler.init()
end)
Config.options.defaults.lazy = false
local tests = {
{ { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } }, "foo/dep1" },
{ "foo/dep1", { "foo/bar", dependencies = { { "dep1" }, "foo/dep2" } } },
}
for _, test in ipairs(tests) do
it("handles dep names " .. inspect(test), function()
local spec = Plugin.Spec.new(vim.deepcopy(test))
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
spec = Plugin.Spec.new(test)
for _, plugin in pairs(spec.plugins) do
plugin.dir = nil
end
assert.same({
bar = {
_ = {},
dependencies = { "dep1", "dep2" },
name = "bar",
url = "https://github.com/foo/bar.git",
},
dep1 = {
_ = {},
name = "dep1",
url = "https://github.com/foo/dep1.git",
},
dep2 = {
_ = {
dep = true,
},
name = "dep2",
url = "https://github.com/foo/dep2.git",
},
}, clean(spec.plugins))
end)
end
Config.options.defaults.lazy = false
local tests = {
{
{ "foo/baz", name = "bar" },
{ "foo/fee", dependencies = { "foo/baz" } },
},
{
{ "foo/fee", dependencies = { "foo/baz" } },
{ "foo/baz", name = "bar" },
},
-- {
-- { "foo/baz", name = "bar" },
-- { "foo/fee", dependencies = { "baz" } },
-- },
{
{ "foo/baz", name = "bar" },
{ "foo/fee", dependencies = { "bar" } },
},
}
for _, test in ipairs(tests) do
it("handles dep names " .. inspect(test), function()
local spec = Plugin.Spec.new(vim.deepcopy(test))
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
spec = Plugin.Spec.new(test)
spec.meta:rebuild()
for _, plugin in pairs(spec.plugins) do
plugin.dir = nil
end
assert.same({
bar = {
_ = {},
name = "bar",
url = "https://github.com/foo/baz.git",
},
fee = {
_ = {},
name = "fee",
url = "https://github.com/foo/fee.git",
dependencies = { "bar" },
},
}, clean(spec.plugins))
end)
end
it("handles opt from dep", function()
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/dep1", { "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } } })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert.same(3, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar._.dep ~= true)
assert(spec.plugins.bar.lazy == false)
assert(spec.plugins.dep2._.dep == true)
assert(spec.plugins.dep2.lazy == true)
assert(spec.plugins.dep1._.dep ~= true)
assert(spec.plugins.dep1.lazy == false)
end)
it("handles defaults opt", function()
do
Config.options.defaults.lazy = true
local spec = Plugin.Spec.new({ "foo/bar" })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert(spec.plugins.bar.lazy == true)
end
do
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/bar" })
Config.plugins = spec.plugins
Plugin.update_state()
assert(spec.plugins.bar.lazy == false)
end
end)
it("handles opt from dep", function()
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/bar", event = "foo" })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert.same(1, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar._.dep ~= true)
assert(spec.plugins.bar.lazy == true)
end)
it("merges lazy loaders", function()
local tests = {
{ { "foo/bar", event = "mod1" }, { "foo/bar", event = "mod2" } },
{ { "foo/bar", event = { "mod1" } }, { "foo/bar", event = { "mod2" } } },
{ { "foo/bar", event = "mod1" }, { "foo/bar", event = { "mod2" } } },
}
for _, test in ipairs(tests) do
local spec = Plugin.Spec.new(test)
assert(#spec.notifs == 0)
assert(vim.tbl_count(spec.plugins) == 1)
Handler.resolve(spec.plugins.bar)
-- vim.print(spec.plugins.bar._.handlers)
local events = vim.tbl_keys(spec.plugins.bar._.handlers.event or {})
assert(type(events) == "table")
assert(#events == 2)
assert(vim.tbl_contains(events, "mod1"))
assert(vim.tbl_contains(events, "mod2"))
end
end)
end)
it("handles opt from dep", function()
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/dep1", { "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } } })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert.same(3, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar._.dep ~= true)
assert(spec.plugins.bar.lazy == false)
assert(spec.plugins.dep2._.dep == true)
assert(spec.plugins.dep2.lazy == true)
assert(spec.plugins.dep1._.dep ~= true)
assert(spec.plugins.dep1.lazy == false)
end)
it("handles defaults opt", function()
do
Config.options.defaults.lazy = true
local spec = Plugin.Spec.new({ "foo/bar" })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert(spec.plugins.bar.lazy == true)
end
do
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/bar" })
Config.plugins = spec.plugins
Plugin.update_state()
assert(spec.plugins.bar.lazy == false)
end
end)
it("handles opt from dep", function()
Config.options.opt = false
local spec = Plugin.Spec.new({ "foo/dep1", { "foo/bar", dependencies = { "foo/dep1", "foo/dep2" } } })
Plugin.update_state({ plugins = spec.plugins })
assert.same(3, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar.dep ~= true)
assert(spec.plugins.bar.opt == false)
assert(spec.plugins.dep2.dep == true)
assert(spec.plugins.dep2.opt == true)
assert(spec.plugins.dep1.dep ~= true)
assert(spec.plugins.dep1.opt == false)
end)
it("handles opt from dep", function()
Config.options.opt = false
local spec = Plugin.Spec.new({ "foo/bar", module = "foo" })
Plugin.update_state({ plugins = spec.plugins })
Config.options.defaults.lazy = false
local spec = Plugin.Spec.new({ "foo/bar", event = "foo" })
assert(#spec.notifs == 0)
Config.plugins = spec.plugins
Plugin.update_state()
assert.same(1, vim.tbl_count(spec.plugins))
assert(spec.plugins.bar.dep ~= true)
assert(spec.plugins.bar.opt == true)
assert(spec.plugins.bar._.dep ~= true)
assert(spec.plugins.bar.lazy == true)
end)
it("merges lazy loaders", function()
local tests = {
{ { "foo/bar", module = "mod1" }, { "foo/bar", module = "mod2" } },
{ { "foo/bar", module = { "mod1" } }, { "foo/bar", module = { "mod2" } } },
{ { "foo/bar", module = "mod1" }, { "foo/bar", module = { "mod2" } } },
{ { "foo/bar", event = "mod1" }, { "foo/bar", event = "mod2" } },
{ { "foo/bar", event = { "mod1" } }, { "foo/bar", event = { "mod2" } } },
{ { "foo/bar", event = "mod1" }, { "foo/bar", event = { "mod2" } } },
}
for _, test in ipairs(tests) do
Handler.init()
local spec = Plugin.Spec.new(test)
assert(#spec.notifs == 0)
assert(vim.tbl_count(spec.plugins) == 1)
assert(type(spec.plugins.bar.module) == "table")
assert(#spec.plugins.bar.module == 2)
assert(vim.tbl_contains(spec.plugins.bar.module, "mod1"))
assert(vim.tbl_contains(spec.plugins.bar.module, "mod2"))
Handler.resolve(spec.plugins.bar)
local events = spec.plugins.bar._.handlers.event
assert(type(events) == "table")
assert(vim.tbl_count(events) == 2)
assert(events["mod1"])
assert(events["mod2"])
end
end)
it("refuses to merge", function()
assert.has.errors(function()
Plugin.Spec.new({
{ "foo/dep1", config = 1 },
{
"foo/bar",
dependencies = { { "foo/dep1", config = 2 }, "foo/dep2" },
},
})
end)
it("handles disabled", function()
local tests = {
[{ { "foo/bar" }, { "foo/bar", enabled = false } }] = false,
[{ { "foo/bar", enabled = false }, { "foo/bar" } }] = false,
[{ { "foo/bar", enabled = false }, { "foo/bar", enabled = true } }] = true,
[{ { "foo/bar" }, { "foo/bar", enabled = true } }] = true,
}
for test, ret in pairs(tests) do
local spec = Plugin.Spec.new(test)
assert(#spec.notifs == 0)
if ret then
assert(spec.plugins.bar)
assert(not spec.disabled.bar)
else
assert(not spec.plugins.bar)
assert(spec.disabled.bar)
end
end
end)
it("handles the optional keyword", function()
local tests = {
[{ { "foo/bax" }, { "foo/bar", optional = true, dependencies = "foo/dep1" } }] = false,
[{ { "foo/bax", dependencies = "foo/dep1" }, { "foo/bar", optional = true, dependencies = "foo/dep1" } }] = true,
}
for test, ret in pairs(tests) do
local spec = Plugin.Spec.new(test)
assert(#spec.notifs == 0)
assert(spec.plugins.bax)
assert(not spec.plugins.bar)
assert(#spec.disabled == 0)
if ret then
assert(spec.plugins.dep1)
else
assert(not spec.plugins.opt1)
end
end
end)
end)
describe("plugin opts", function()
---@type {spec:LazySpec, opts:table}[]
local tests = {
{
spec = { { "foo/foo", opts = { a = 1, b = 1 } }, { "foo/foo", opts = { a = 2 } } },
opts = { a = 2, b = 1 },
},
{
spec = { { "foo/foo", config = { a = 1, b = 1 } }, { "foo/foo", opts = { a = 2 } } },
opts = { a = 2, b = 1 },
},
{
spec = { { "foo/foo", opts = { a = 1, b = 1 } }, { "foo/foo", config = { a = 2 } } },
opts = { a = 2, b = 1 },
},
{
spec = { { "foo/foo", config = { a = 1, b = 1 } }, { "foo/foo", config = { a = 2 } } },
opts = { a = 2, b = 1 },
},
{
spec = { { "foo/foo", config = { a = 1, b = 1 } }, { "foo/foo", config = { a = vim.NIL } } },
opts = { b = 1 },
},
{
spec = { { "foo/foo", config = { a = 1, b = 1 } }, { "foo/foo" } },
opts = { a = 1, b = 1 },
},
{
spec = { { "foo/foo" }, { "foo/foo" } },
opts = {},
},
}
for _, test in ipairs(tests) do
it("correctly parses opts for " .. inspect(test.spec), function()
local spec = Plugin.Spec.new(test.spec)
assert(spec.plugins.foo)
assert.same(test.opts, Plugin.values(spec.plugins.foo, "opts"))
end)
end
end)
describe("plugin spec", function()
it("only includes fragments from enabled plugins", function()
local tests = {
{
spec = {
{ "foo/disabled", enabled = false, dependencies = { "foo/bar", opts = { key_disabled = true } } },
{ "foo/disabled", dependencies = { "foo/bar", opts = { key_disabled_two = true } } },
{ "foo/conditional", cond = false, dependencies = { "foo/bar", opts = { key_cond = true } } },
{ "foo/optional", optional = true, dependencies = { "foo/bar", opts = { key_optional = true } } },
{ "foo/active", dependencies = { "foo/bar", opts = { key_active = true } } },
{
"foo/bar",
opts = { key = true },
},
},
expected_opts = { key = true, key_active = true },
}, -- for now, one test...
}
for _, test in ipairs(tests) do
local spec = Plugin.Spec.new(test.spec)
assert(#spec.notifs == 0)
assert(vim.tbl_count(spec.plugins) == 2)
assert(spec.plugins.active)
assert(spec.plugins.bar)
assert.same(test.expected_opts, Plugin.values(spec.plugins.bar, "opts"))
end
end)
end)

147
tests/core/util_spec.lua Normal file
View file

@ -0,0 +1,147 @@
local Cache = require("lazy.core.cache")
local Helpers = require("tests.helpers")
local Util = require("lazy.util")
describe("util", function()
local rtp = vim.opt.rtp:get()
before_each(function()
---@type vim.Option
vim.opt.rtp = rtp
for k, v in pairs(package.loaded) do
if k:find("^foobar") then
package.loaded[k] = nil
end
end
Helpers.fs_rm("")
assert(not vim.uv.fs_stat(Helpers.path("")), "fs root should be deleted")
end)
it("lsmod lists all mods in dir", function()
vim.opt.rtp:append(Helpers.path(""))
local tests = {
{
root = "lua/foo",
mod = "foo",
files = { "lua/foo/one.lua", "lua/foo/two.lua", "lua/foo/init.lua" },
mods = { "foo.one", "foo.two", "foo" },
},
{
root = "lua/foo",
mod = "foo",
files = { "lua/foo/one.lua", "lua/foo/two.lua", "lua/foo.lua" },
mods = { "foo.one", "foo.two", "foo" },
},
{
root = "lua/foo",
mod = "foo",
files = { "lua/foo/one.lua", "lua/foo/two.lua" },
mods = { "foo.one", "foo.two" },
},
{
root = "lua/load-plugins",
mod = "load-plugins",
files = { "lua/load-plugins.lua" },
mods = { "load-plugins" },
},
}
for t, test in ipairs(tests) do
local expected = vim.deepcopy(test.mods)
table.sort(expected)
Helpers.fs_rm("")
local files = Helpers.fs_create(test.files)
-- test with empty cache
Cache.reset()
local root = Util.find_root(test.mod)
assert(root, "no root found for " .. test.mod .. " (test " .. t .. ")")
assert.same(Helpers.path(test.root), root)
local mods = {}
Util.lsmod(test.mod, function(modname, modpath)
mods[#mods + 1] = modname
end)
table.sort(mods)
assert.same(expected, mods)
-- fill the cache
Cache.reset()
root = Util.find_root(test.mod)
assert(root, "no root found for " .. test.mod .. " (test " .. t .. ")")
assert.same(Helpers.path(test.root), root)
mods = {}
Util.lsmod(test.mod, function(modname, modpath)
mods[#mods + 1] = modname
end)
table.sort(mods)
assert.same(expected, mods)
end
end)
it("find the correct root with dels", function()
Cache.reset()
vim.opt.rtp:append(Helpers.path("old"))
Helpers.fs_create({ "old/lua/foobar/init.lua" })
local root = Util.find_root("foobar")
assert(root, "foobar root not found")
assert.same(Helpers.path("old/lua/foobar"), root)
Helpers.fs_rm("old")
assert(not vim.uv.fs_stat(Helpers.path("old/lua/foobar")), "old/lua/foobar should not exist")
-- vim.opt.rtp = rtp
vim.opt.rtp:append(Helpers.path("new"))
Helpers.fs_create({ "new/lua/foobar/init.lua" })
root = Util.find_root("foobar")
assert(root, "foobar root not found")
assert.same(Helpers.path("new/lua/foobar"), root)
end)
it("merges correctly", function()
local tests = {
{
input = { { a = 1 }, { b = 2 } },
output = { a = 1, b = 2 },
},
{
input = { nil, { a = 1 }, { b = 2 } },
output = { a = 1, b = 2 },
},
{
input = { { a = 1 }, { b = 2 }, nil },
output = { a = 1, b = 2 },
},
{
input = { { a = 1 }, nil, { b = 2 } },
output = { a = 1, b = 2 },
},
{
input = { nil, { a = 1 }, nil, { b = 2 }, nil },
output = { a = 1, b = 2 },
},
{
input = { { a = 1 }, { a = 2 } },
output = { a = 2 },
},
{
input = { { a = { 1, 2 } }, { a = { 3 } } },
output = { a = { 3 } },
},
{
input = { { b = { 1, 2 } }, { a = { 3 }, b = vim.NIL } },
output = { a = { 3 } },
},
{
input = { { a = 1 }, { b = 2, a = vim.NIL } },
output = { b = 2 },
},
}
for _, test in ipairs(tests) do
local n = 0
for i in pairs(test.input) do
n = math.max(n, i)
end
assert.same(test.output, Util.merge(unpack(test.input, 1, n)))
end
end)
end)

View file

@ -0,0 +1,18 @@
local Keys = require("lazy.core.handler.keys")
describe("keys", function()
it("parses ids correctly", function()
local tests = {
{ "<C-/>", "<c-/>", true },
{ "<C-h>", "<c-H>", true },
{ "<C-h>k", "<c-H>K", false },
}
for _, test in ipairs(tests) do
if test[3] then
assert.same(Keys.parse(test[1]).id, Keys.parse(test[2]).id)
else
assert.is_not.same(Keys.parse(test[1]).id, Keys.parse(test[2]).id)
end
end
end)
end)

37
tests/helpers.lua Normal file
View file

@ -0,0 +1,37 @@
local Util = require("lazy.util")
local M = {}
M.fs_root = vim.fn.fnamemodify("./.tests/fs", ":p")
function M.path(path)
return Util.norm(M.fs_root .. "/" .. path)
end
---@param files string[]
function M.fs_create(files)
---@type string[]
local ret = {}
for _, file in ipairs(files) do
ret[#ret + 1] = Util.norm(M.fs_root .. "/" .. file)
local parent = vim.fn.fnamemodify(ret[#ret], ":h:p")
vim.fn.mkdir(parent, "p")
Util.write_file(ret[#ret], "")
end
return ret
end
function M.fs_rm(dir)
dir = Util.norm(M.fs_root .. "/" .. dir)
Util.walk(dir, function(path, _, type)
if type == "directory" then
vim.uv.fs_rmdir(path)
else
vim.uv.fs_unlink(path)
end
end)
vim.uv.fs_rmdir(dir)
end
return M

View file

@ -1,32 +0,0 @@
local M = {}
function M.root(root)
local f = debug.getinfo(1, "S").source:sub(2)
return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "")
end
---@param plugin string
function M.load(plugin)
local name = plugin:match(".*/(.*)")
local package_root = M.root(".tests/site/pack/deps/start/")
if not vim.loop.fs_stat(package_root .. name) then
print("Installing " .. plugin)
vim.fn.mkdir(package_root, "p")
vim.fn.system({
"git",
"clone",
"--depth=1",
"https://github.com/" .. plugin .. ".git",
package_root .. "/" .. name,
})
end
end
function M.setup()
vim.cmd([[set runtimepath=$VIMRUNTIME]])
vim.opt.runtimepath:append(M.root())
vim.opt.packpath = { M.root(".tests/site") }
M.load("nvim-lua/plenary.nvim")
end
M.setup()

View file

@ -0,0 +1,19 @@
local Async = require("lazy.async")
local Process = require("lazy.manage.process")
describe("process", function()
it("runs sync", function()
local lines = Process.exec({ "echo", "-n", "hello" })
assert.are.same({ "hello" }, lines)
end)
it("runs sync from async context", function()
local lines ---@type string[]
local async = Async.new(function()
lines = Process.exec({ "echo", "-n", "hello" })
end)
async:wait()
assert.are.same({ "hello" }, lines)
end)
end)

View file

@ -1,3 +1,4 @@
local Async = require("lazy.async")
local Runner = require("lazy.manage.runner")
describe("runner", function()
@ -30,11 +31,11 @@ describe("runner", function()
end,
}
package.loaded["lazy.manage.task.test"]["async" .. i] = {
---@async
---@param task LazyTask
run = function(task)
task:schedule(function()
table.insert(runs, { plugin = task.plugin.name, task = task.name })
end)
Async.yield()
table.insert(runs, { plugin = task.plugin.name, task = task.name })
end,
}
end
@ -64,7 +65,7 @@ describe("runner", function()
local runner = Runner.new({ plugins = plugins, pipeline = { "test.test1", "test.skip", "test.test2" } })
runner:start()
runner:wait()
assert.equal(4, #runs)
assert.equal(4, #runs, runs)
end)
it("handles opts", function()

View file

@ -14,6 +14,7 @@ describe("semver version", function()
["1.2.3+build"] = { major = 1, minor = 2, patch = 3, build = "build" },
}
for input, output in pairs(tests) do
output.input = input
it("correctly parses " .. input, function()
assert.same(output, v(input))
end)

View file

@ -1,94 +1,82 @@
--# selene:allow(incorrect_standard_library_use)
local Async = require("lazy.async")
local Task = require("lazy.manage.task")
describe("task", function()
local plugin = { name = "test", _ = {} }
local done = false
local error = nil
---@type {done?:boolean, error:string?}
local task_result = {}
local opts = {
---@param task LazyTask
on_done = function(task)
done = true
error = task.error
task_result = { done = true, error = task.error }
end,
}
before_each(function()
done = false
error = nil
task_result = {}
end)
it("simple function", function()
local task = Task.new(plugin, "test", function() end, opts)
assert(not task:has_started())
assert(not task:is_running())
task:start()
assert(not task:is_running())
assert(task:is_done())
assert(done)
assert(task:running())
task:wait()
assert(not task:running())
assert(task_result.done)
end)
it("detects errors", function()
local task = Task.new(plugin, "test", function()
error("test")
end, opts)
assert(not task:has_started())
assert(not task:is_running())
task:start()
assert(task:is_done())
assert(not task:is_running())
assert(done)
assert(error)
assert(task.error and task.error:find("test"))
assert(task:running())
task:wait()
assert(not task:running())
assert(task_result.done)
assert(task_result.error)
assert(task:has_errors() and task:output(vim.log.levels.ERROR):find("test"))
end)
it("schedule", function()
local running = false
local task = Task.new(plugin, "test", function(task)
running = true
task:schedule(function()
running = false
end)
it("async", function()
local running = true
---@async
local task = Task.new(plugin, "test", function()
Async.yield()
running = false
end, opts)
assert(not task:is_running())
assert(not task:has_started())
task:start()
assert(task:running())
assert(running)
assert(#task._running == 1)
assert(task:is_running())
assert(not task:is_done())
assert(task:running())
task:wait()
assert(task:is_done())
assert(not task:is_running())
assert(done)
assert(not task.error)
assert(not running)
assert(not task:running())
assert(task_result.done)
assert(not task:has_errors())
end)
it("spawn errors", function()
local task = Task.new(plugin, "test", function(task)
local task = Task.new(plugin, "spawn_errors", function(task)
task:spawn("foobar")
end, opts)
assert(not task:is_running())
task:start()
assert(not task:is_running())
assert(done)
assert(task.error and task.error:find("Failed to spawn"))
assert(task:running())
task:wait()
assert(not task:running())
assert(task_result.done)
assert(task:has_errors() and task:output(vim.log.levels.ERROR):find("Failed to spawn"), task:output())
end)
it("spawn", function()
local task = Task.new(plugin, "test", function(task)
task:spawn("echo", { args = { "foo" } })
end, opts)
assert(not task:is_running())
assert(not task:has_started())
task:start()
assert(task:has_started())
assert(task:is_running())
assert(task:running())
assert(task:running())
task:wait()
assert(task:is_done())
assert.same(task.output, "foo\n")
assert(done)
assert(not task.error)
assert.same(task:output(), "foo")
assert(task_result.done)
assert(not task:has_errors())
end)
it("spawn 2x", function()
@ -96,12 +84,11 @@ describe("task", function()
task:spawn("echo", { args = { "foo" } })
task:spawn("echo", { args = { "bar" } })
end, opts)
assert(not task:is_running())
task:start()
assert(task:is_running())
assert(task:running())
assert(task:running())
task:wait()
assert.same(task.output, "foo\nbar\n")
assert(done)
assert(not task.error)
assert(task:output() == "foo\nbar" or task:output() == "bar\nfoo", task:output())
assert(task_result.done)
assert(not task:has_errors())
end)
end)

12
tests/minit.lua Executable file
View file

@ -0,0 +1,12 @@
#!/usr/bin/env -S nvim -l
vim.env.LAZY_STDPATH = ".tests"
vim.opt.rtp:prepend(".")
-- Setup lazy.nvim
require("lazy.minit").setup({
spec = {
{ dir = vim.uv.cwd() },
},
})

Some files were not shown because too many files have changed in this diff Show more